This is an automated email from the ASF dual-hosted git repository.
Claudenw pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
The following commit(s) were added to refs/heads/master by this push:
new 0c08080b RAT-561: Cleanup XmlWriter resource issues (#683)
0c08080b is described below
commit 0c08080b9d0abe4c699a4261bbe7603cef29bdd0
Author: Claude Warren <[email protected]>
AuthorDate: Wed Jun 24 16:30:45 2026 +0200
RAT-561: Cleanup XmlWriter resource issues (#683)
* Cleanup XmlWriter resource issues
Remove IXmlWriter
Replace simple RatReport implementations with anonymous implementations.
Rework tests to ensure that XmlWriter is closed properly.
* update javadoc
---------
Co-authored-by: P. Ottlinger <[email protected]>
---
.../src/main/java/org/apache/rat/Reporter.java | 3 +-
.../rat/configuration/XMLConfigurationWriter.java | 295 +++++-----
.../org/apache/rat/report/ConfigurationReport.java | 53 --
.../rat/report/claim/ClaimReporterMultiplexer.java | 90 ---
.../rat/report/claim/ClaimValidatorReport.java | 77 ---
.../rat/report/claim/SimpleXmlClaimReporter.java | 58 --
.../org/apache/rat/report/xml/XmlElements.java | 472 ++++++++--------
.../apache/rat/report/xml/XmlReportFactory.java | 130 ++++-
.../apache/rat/report/xml/writer/IXmlWriter.java | 159 ------
.../xml/writer/OperationNotAllowedException.java | 2 +-
.../apache/rat/report/xml/writer/XmlWriter.java | 94 +++-
.../apache/rat/analysis/AnalyserFactoryTest.java | 20 +-
.../apache/rat/report/ConfigurationReportTest.java | 27 +-
.../rat/report/xml/XmlReportFactoryTest.java | 3 +-
.../rat/report/xml/writer/XmlWriterUtilsTest.java | 27 +-
.../report/xml/writer/impl/base/XmlWriterTest.java | 621 ++++++++++-----------
.../java/org/apache/rat/testhelpers/XmlUtils.java | 4 +-
.../java/org/apache/rat/tools/xsd/XsdWriter.java | 6 +-
src/changes/changes.xml | 3 +
19 files changed, 924 insertions(+), 1220 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
index d387dd44..6ca704ca 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/Reporter.java
@@ -42,7 +42,6 @@ import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.apache.rat.report.RatReport;
import org.apache.rat.report.claim.ClaimStatistic;
import org.apache.rat.report.xml.XmlReportFactory;
-import org.apache.rat.report.xml.writer.IXmlWriter;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.utils.StandardXmlFactory;
import org.w3c.dom.Document;
@@ -88,7 +87,7 @@ public class Reporter {
if (configuration.hasSource()) {
ByteArrayOutputStream outputStream = new
ByteArrayOutputStream();
Writer outputWriter = new OutputStreamWriter(outputStream,
StandardCharsets.UTF_8);
- try (IXmlWriter writer = new XmlWriter(outputWriter)) {
+ try (XmlWriter writer = new XmlWriter(outputWriter)) {
statistic = new ClaimStatistic();
RatReport report =
XmlReportFactory.createStandardReport(writer, statistic, configuration);
report.startReport();
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationWriter.java
b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationWriter.java
index 79e7da99..11ee840f 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationWriter.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/configuration/XMLConfigurationWriter.java
@@ -41,18 +41,17 @@ import
org.apache.rat.configuration.builders.MatcherRefBuilder;
import org.apache.rat.license.ILicense;
import org.apache.rat.license.ILicenseFamily;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
-import org.apache.rat.report.xml.writer.IXmlWriter;
import org.apache.rat.report.xml.writer.XmlWriter;
/**
* Writes the XML configuration file format.
*/
public class XMLConfigurationWriter {
- /** The configuration that is being written */
+ /** The configuration that is being written. */
private final ReportConfiguration configuration;
- /** The set of defined matcher IDs */
+ /** The set of defined matcher IDs. */
private final Set<String> matchers;
- /** The set of defined license IDs */
+ /** The set of defined license IDs. */
private final Set<String> licenseChildren;
/**
@@ -87,52 +86,59 @@ public class XMLConfigurationWriter {
write(new XmlWriter(plainWriter));
}
+ private void writeFamilies(final XmlWriter writer, final
SortedSet<ILicenseFamily> families) throws IOException, RatException {
+ if (!families.isEmpty()) {
+ writer.startElement(XMLConfig.FAMILIES);
+ for (ILicenseFamily family : families) {
+ writeFamily(writer, family);
+ }
+ writer.closeElement(); // FAMILIES
+ }
+ }
+
+ private void writeLicenses(final XmlWriter writer, final
SortedSet<ILicense> licenses) throws IOException, RatException {
+ if (!licenses.isEmpty()) {
+ writer.startElement(XMLConfig.LICENSES);
+ for (ILicense license : licenses) {
+ writeDescription(writer, license.getDescription(), license);
+ }
+ writer.closeElement(); // LICENSES
+ }
+ }
+
+ private void writeApproved(final XmlWriter writer) throws IOException {
+ writer.startElement(XMLConfig.APPROVED);
+ for (String family :
configuration.getLicenseCategories(LicenseFilter.APPROVED)) {
+
writer.startElement(XMLConfig.APPROVED).attribute(XMLConfig.ATT_LICENSE_REF,
family.trim())
+ .closeElement();
+ }
+ writer.closeElement(); // APPROVED
+ }
+
+ private void writeMatchers(final XmlWriter writer) throws IOException {
+ MatcherBuilderTracker tracker = MatcherBuilderTracker.instance();
+ writer.startElement(XMLConfig.MATCHERS);
+ for (Class<?> clazz : tracker.getClasses()) {
+
writer.startElement(XMLConfig.MATCHER).attribute(XMLConfig.ATT_CLASS_NAME,
clazz.getCanonicalName())
+ .closeElement();
+ }
+ writer.closeElement(); // MATCHERS
+ }
+
/**
- * Writes the configuration to an IXmlWriter instance.
- * @param writer the IXmlWriter to write to.
+ * Writes the configuration to an XmlWriter instance.
+ * @param writer the XmlWriter to write to.
* @throws RatException on error.
*/
- public void write(final IXmlWriter writer) throws RatException {
+ public void write(final XmlWriter writer) throws RatException {
if (configuration.listFamilies() != LicenseFilter.NONE ||
configuration.listLicenses() != LicenseFilter.NONE) {
try {
- writer.openElement(XMLConfig.ROOT);
+ writer.startElement(XMLConfig.ROOT);
- // Families section
- SortedSet<ILicenseFamily> families =
configuration.getLicenseFamilies(configuration.listFamilies());
- if (!families.isEmpty()) {
- writer.openElement(XMLConfig.FAMILIES);
- for (ILicenseFamily family : families) {
- writeFamily(writer, family);
- }
- writer.closeElement(); // FAMILIES
- }
-
- // licenses section
- SortedSet<ILicense> licenses =
configuration.getLicenses(configuration.listLicenses());
- if (!licenses.isEmpty()) {
- writer.openElement(XMLConfig.LICENSES);
- for (ILicense license : licenses) {
- writeDescription(writer, license.getDescription(),
license);
- }
- writer.closeElement(); // LICENSES
- }
-
- // approved section
- writer.openElement(XMLConfig.APPROVED);
- for (String family :
configuration.getLicenseCategories(LicenseFilter.APPROVED)) {
-
writer.openElement(XMLConfig.APPROVED).attribute(XMLConfig.ATT_LICENSE_REF,
family.trim())
- .closeElement();
- }
- writer.closeElement(); // APPROVED
-
- // matchers section
- MatcherBuilderTracker tracker =
MatcherBuilderTracker.instance();
- writer.openElement(XMLConfig.MATCHERS);
- for (Class<?> clazz : tracker.getClasses()) {
-
writer.openElement(XMLConfig.MATCHER).attribute(XMLConfig.ATT_CLASS_NAME,
clazz.getCanonicalName())
- .closeElement();
- }
- writer.closeElement(); // MATCHERS
+ writeFamilies(writer,
configuration.getLicenseFamilies(configuration.listFamilies()));
+ writeLicenses(writer,
configuration.getLicenses(configuration.listLicenses()));
+ writeApproved(writer);
+ writeMatchers(writer);
writer.closeElement(); // ROOT
} catch (IOException e) {
@@ -141,9 +147,9 @@ public class XMLConfigurationWriter {
}
}
- private void writeFamily(final IXmlWriter writer, final ILicenseFamily
family) throws RatException {
+ private void writeFamily(final XmlWriter writer, final ILicenseFamily
family) throws RatException {
try {
- writer.openElement(XMLConfig.FAMILY).attribute(XMLConfig.ATT_ID,
family.getFamilyCategory().trim())
+ writer.startElement(XMLConfig.FAMILY).attribute(XMLConfig.ATT_ID,
family.getFamilyCategory().trim())
.attribute(XMLConfig.ATT_NAME, family.getFamilyName());
writer.closeElement();
} catch (IOException e) {
@@ -151,21 +157,21 @@ public class XMLConfigurationWriter {
}
}
- private void writeDescriptions(final IXmlWriter writer, final
Collection<Description> descriptions, final IHeaderMatcher component)
+ private void writeDescriptions(final XmlWriter writer, final
Collection<Description> descriptions, final IHeaderMatcher component)
throws RatException {
for (Description description : descriptions) {
writeDescription(writer, description, component);
}
}
- private void writeChildren(final IXmlWriter writer, final Description
description, final IHeaderMatcher component)
+ private void writeChildren(final XmlWriter writer, final Description
description, final IHeaderMatcher component)
throws RatException {
writeAttributes(writer,
description.filterChildren(attributeFilter(component.getDescription())),
component);
writeDescriptions(writer,
description.filterChildren(attributeFilter(component.getDescription()).negate()),
component);
}
- private void writeAttributes(final IXmlWriter writer, final
Collection<Description> descriptions, final IHeaderMatcher component)
+ private void writeAttributes(final XmlWriter writer, final
Collection<Description> descriptions, final IHeaderMatcher component)
throws RatException {
for (Description d : descriptions) {
try {
@@ -176,13 +182,13 @@ public class XMLConfigurationWriter {
}
}
- private void writeComment(final IXmlWriter writer, final Description
description) throws IOException {
+ private void writeComment(final XmlWriter writer, final Description
description) throws IOException {
if (StringUtils.isNotBlank(description.getDescription())) {
writer.comment(description.getDescription().replace("-->",
"-–>"));
}
}
- private void writeAttribute(final IXmlWriter writer, final Description
description, final IHeaderMatcher component)
+ private void writeAttribute(final XmlWriter writer, final Description
description, final IHeaderMatcher component)
throws IOException {
String paramValue = description.getParamValue(component);
if (paramValue != null) {
@@ -190,102 +196,121 @@ public class XMLConfigurationWriter {
}
}
- /* package private for testing */
+ private boolean hasUUIDId(final Description desc, final IHeaderMatcher
comp) {
+ if ("id".equals(desc.getCommonName())) {
+ try {
+ String paramId = desc.getParamValue(comp);
+ // if a UUID skip it.
+ if (paramId != null) {
+ UUID.fromString(paramId);
+ return true;
+ }
+ } catch (IllegalArgumentException expected) {
+ // do nothing.
+ }
+ }
+ return false;
+ }
+
+ private void writeChildParameter(final XmlWriter writer, final Description
description, final IHeaderMatcher component) throws IOException {
+ boolean inline =
XMLConfig.isInlineNode(component.getDescription().getCommonName(),
+ description.getCommonName());
+ String s = description.getParamValue(component);
+ if (StringUtils.isNotBlank(s)) {
+ if (!inline) {
+ writer.startElement(description.getCommonName());
+ }
+ writer.content(description.getParamValue(component));
+ if (!inline) {
+ writer.closeElement();
+ }
+ }
+
+ }
@SuppressWarnings("unchecked")
- void writeDescription(final IXmlWriter writer, final Description desc,
final IHeaderMatcher comp) throws RatException {
- Description description = desc;
- IHeaderMatcher component = comp;
- try {
- switch (description.getType()) {
- case MATCHER:
- // see if id was registered
- Optional<Description> id =
description.childrenOfType(ComponentType.PARAMETER).stream()
- .filter(i ->
XMLConfig.ATT_ID.equals(i.getCommonName())).findFirst();
+ private void writeParameterDescription(final XmlWriter writer, final
Description description, final IHeaderMatcher component) throws IOException {
+ if (hasUUIDId(description, component)) {
+ return;
+ }
- // id will not be present in matcherRef
- if (id.isPresent()) {
- String matcherId = id.get().getParamValue(component);
- // if we have seen the ID before, put a reference to the
other one.
- if (matchers.contains(matcherId)) {
- component = new
MatcherRefBuilder.IHeaderMatcherProxy(matcherId, null);
- description = component.getDescription();
- } else {
- matchers.add(matcherId);
- }
- // remove the matcher id if it is a UUID
- try {
- UUID.fromString(matcherId);
- description.getChildren().remove(XMLConfig.ATT_ID);
- } catch (IllegalArgumentException expected) {
- if (description.getCommonName().equals("spdx")) {
- description.getChildren().remove(XMLConfig.ATT_ID);
- }
+ if (description.getChildType() == String.class) {
+ writeChildParameter(writer, description, component);
+ } else {
+ try {
+ if (description.isCollection()) {
+ for (IHeaderMatcher matcher : (Collection<IHeaderMatcher>)
description
+ .getter(component.getClass()).invoke(component)) {
+ writeDescription(writer, matcher.getDescription(),
matcher);
}
+ } else {
+ IHeaderMatcher matcher = (IHeaderMatcher)
description.getter(component.getClass())
+ .invoke(component);
+ writeDescription(writer, matcher.getDescription(),
matcher);
}
+ } catch (IllegalAccessException | IllegalArgumentException |
InvocationTargetException
+ | NoSuchMethodException | SecurityException |
RatException e) {
+ throw new ImplementationException(e);
+ }
+ }
+ }
- // if only a resource, list the resource not the contents of
the matcher
- Optional<Description> resource =
description.childrenOfType(ComponentType.PARAMETER).stream()
- .filter(i ->
XMLConfig.ATT_RESOURCE.equals(i.getCommonName())).findFirst();
- if (resource.isPresent()) {
- String resourceStr =
resource.get().getParamValue(component);
- if (StringUtils.isNotBlank(resourceStr)) {
- description.getChildren().remove("enclosed");
- }
+ private void writeMatcherDescription(final XmlWriter writer, final
Description desc, final IHeaderMatcher comp) throws IOException, RatException {
+ Description description = desc;
+ IHeaderMatcher component = comp;
+ // see if id was registered
+ Optional<Description> id =
description.childrenOfType(ComponentType.PARAMETER).stream()
+ .filter(i ->
XMLConfig.ATT_ID.equals(i.getCommonName())).findFirst();
+
+ // id will not be present in matcherRef
+ if (id.isPresent()) {
+ String matcherId = id.get().getParamValue(component);
+ // if we have seen the id before, put a reference to the other one.
+ if (matchers.contains(matcherId)) {
+ component = new
MatcherRefBuilder.IHeaderMatcherProxy(matcherId, null);
+ description = component.getDescription();
+ } else {
+ matchers.add(matcherId);
+ }
+ // remove the matcher id if it is a UUID
+ try {
+ UUID.fromString(matcherId);
+ description.getChildren().remove(XMLConfig.ATT_ID);
+ } catch (IllegalArgumentException expected) {
+ if (description.getCommonName().equals("spdx")) {
+ description.getChildren().remove(XMLConfig.ATT_ID);
}
- writeComment(writer, description);
- writer.openElement(description.getCommonName());
- writeChildren(writer, description, component);
- writer.closeElement();
+ }
+ }
+
+ // if only a resource, list the resource not the contents of the
matcher
+ Optional<Description> resource =
description.childrenOfType(ComponentType.PARAMETER).stream()
+ .filter(i ->
XMLConfig.ATT_RESOURCE.equals(i.getCommonName())).findFirst();
+ if (resource.isPresent()) {
+ String resourceStr = resource.get().getParamValue(component);
+ if (StringUtils.isNotBlank(resourceStr)) {
+ description.getChildren().remove("enclosed");
+ }
+ }
+ writeComment(writer, description);
+ writer.startElement(description.getCommonName());
+ writeChildren(writer, description, component);
+ writer.closeElement();
+ }
+
+ /* package private for testing */
+ void writeDescription(final XmlWriter writer, final Description
description, final IHeaderMatcher component) throws RatException {
+ try {
+ switch (description.getType()) {
+ case MATCHER:
+ writeMatcherDescription(writer, description, component);
break;
case LICENSE:
- writer.openElement(XMLConfig.LICENSE);
+ writer.startElement(XMLConfig.LICENSE);
writeChildren(writer, description, component);
writer.closeElement();
break;
case PARAMETER:
- if ("id".equals(description.getCommonName())) {
- try {
- String paramId = description.getParamValue(component);
- // if a UUID skip it.
- if (paramId != null) {
- UUID.fromString(paramId);
- return;
- }
- } catch (IllegalArgumentException expected) {
- // do nothing.
- }
- }
- if (description.getChildType() == String.class) {
-
- boolean inline =
XMLConfig.isInlineNode(component.getDescription().getCommonName(),
- description.getCommonName());
- String s = description.getParamValue(component);
- if (StringUtils.isNotBlank(s)) {
- if (!inline) {
- writer.openElement(description.getCommonName());
- }
- writer.content(description.getParamValue(component));
- if (!inline) {
- writer.closeElement();
- }
- }
- } else {
- try {
- if (description.isCollection()) {
- for (IHeaderMatcher matcher :
(Collection<IHeaderMatcher>) description
-
.getter(component.getClass()).invoke(component)) {
- writeDescription(writer,
matcher.getDescription(), matcher);
- }
- } else {
- IHeaderMatcher matcher = (IHeaderMatcher)
description.getter(component.getClass())
- .invoke(component);
- writeDescription(writer, matcher.getDescription(),
matcher);
- }
- } catch (IllegalAccessException | IllegalArgumentException
| InvocationTargetException
- | NoSuchMethodException | SecurityException |
RatException e) {
- throw new ImplementationException(e);
- }
- }
+ writeParameterDescription(writer, description, component);
break;
case BUILD_PARAMETER:
// ignore;
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java
b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java
deleted file mode 100644
index 66ed7629..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- */
-package org.apache.rat.report;
-
-import org.apache.rat.ReportConfiguration;
-import org.apache.rat.api.RatException;
-import org.apache.rat.configuration.XMLConfigurationWriter;
-import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
-import org.apache.rat.report.xml.writer.IXmlWriter;
-
-/**
- * A report that dumps the ReportConfiguration into the XML output.
- */
-public class ConfigurationReport implements RatReport {
- /** The report configuration to report on. */
- private final ReportConfiguration configuration;
- /** The XML writer to write the report with. */
- private final IXmlWriter writer;
-
- /**
- * Constructor.
- *
- * @param writer The writer to write the XML data to.
- * @param configuration the configuration to dump
- */
- public ConfigurationReport(final IXmlWriter writer, final
ReportConfiguration configuration) {
- this.configuration = configuration;
- this.writer = writer;
- }
-
- @Override
- public void startReport() throws RatException {
- if (configuration.listFamilies() != LicenseFilter.NONE ||
configuration.listLicenses() != LicenseFilter.NONE) {
- new XMLConfigurationWriter(configuration).write(writer);
- }
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimReporterMultiplexer.java
b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimReporterMultiplexer.java
deleted file mode 100644
index 5f60284a..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimReporterMultiplexer.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- */
-package org.apache.rat.report.claim;
-
-
-import java.util.List;
-
-import org.apache.rat.api.Document;
-import org.apache.rat.api.RatException;
-import org.apache.rat.document.DocumentAnalyser;
-import org.apache.rat.document.RatDocumentAnalysisException;
-import org.apache.rat.report.RatReport;
-import org.apache.rat.report.xml.XmlElements;
-import org.apache.rat.report.xml.writer.IXmlWriter;
-
-/**
- * Executes a RatReport that multiplexes the running of multiple RatReports
- */
-public class ClaimReporterMultiplexer implements RatReport {
- /** The document analyser to use */
- private final DocumentAnalyser analyser;
- /** A list of reports that are being updated */
- private final List<? extends RatReport> reporters;
- /** If {@code true} this is a dry run do not generate report */
- private final boolean dryRun;
- /** The XML Writer this multiplexer writes to */
- private final IXmlWriter writer;
-
- /**
- * A multiplexer to run multiple claim reports.
- * @param dryRun true if this is a dry run.
- * @param analyser the analyser to use.
- * @param reporters the reports to execute.
- */
- public ClaimReporterMultiplexer(final IXmlWriter writer, final boolean
dryRun, final DocumentAnalyser analyser,
- final List<? extends RatReport> reporters)
{
- this.analyser = analyser;
- this.reporters = reporters;
- this.dryRun = dryRun;
- this.writer = writer;
- }
-
- @Override
- public void report(final Document document) throws RatException {
- if (!dryRun) {
- if (analyser != null) {
- try {
- analyser.analyse(document);
- } catch (RatDocumentAnalysisException e) {
- throw new RatException(e.getMessage(), e);
- }
- }
- for (RatReport report : reporters) {
- report.report(document);
- }
- }
- }
-
- @Override
- public void startReport() throws RatException {
- new XmlElements(writer).ratReport();
- for (RatReport report : reporters) {
- report.startReport();
- }
- }
-
- @Override
- public void endReport() throws RatException {
- for (RatReport report : reporters) {
- report.endReport();
- }
- new XmlElements(writer).closeElement();
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimValidatorReport.java
b/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimValidatorReport.java
deleted file mode 100644
index ad955a61..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/ClaimValidatorReport.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.rat.report.claim;
-
-import org.apache.rat.ReportConfiguration;
-import org.apache.rat.api.Document;
-import org.apache.rat.api.RatException;
-import org.apache.rat.config.results.ClaimValidator;
-import org.apache.rat.report.RatReport;
-import org.apache.rat.report.xml.XmlElements;
-import org.apache.rat.report.xml.writer.IXmlWriter;
-
-/**
- * A RatReport that publishes the results of the ClaimValidator.
- */
-public class ClaimValidatorReport implements RatReport {
- /**
- * The XmlElements tool to work with.
- */
- private final XmlElements elements;
- /**
- * The claim statistics to report.
- */
- private final ClaimStatistic statistic;
- /**
- * The validator for the statistics.
- */
- private final ClaimValidator validator;
-
- /**
- * Constructor.
- * @param writer the XMLWriter to write with.
- * @param statistic the Claim statistics to report.
- * @param configuration the configuration for the run.
- */
- public ClaimValidatorReport(final IXmlWriter writer, final ClaimStatistic
statistic, final ReportConfiguration configuration) {
- this.elements = new XmlElements(writer);
- this.statistic = statistic;
- this.validator = configuration.getClaimValidator();
- }
-
- @Override
- public void endReport() throws RatException {
- elements.statistics();
- for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values())
{
- int count = statistic.getCounter(counter);
- elements.statistic(counter.displayName(), count,
counter.getDescription(), validator.isValid(counter, count));
- }
- for (String category : statistic.getLicenseFamilyCategories()) {
- elements.licenseCategory(category,
statistic.getLicenseCategoryCount(category));
- }
- for (String category : statistic.getLicenseNames()) {
- elements.licenseName(category,
statistic.getLicenseNameCount(category));
- }
- for (Document.Type type : statistic.getDocumentTypes()) {
- elements.documentType(type.name(), statistic.getCounter(type));
- }
-
- elements.closeElement();
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/SimpleXmlClaimReporter.java
b/apache-rat-core/src/main/java/org/apache/rat/report/claim/SimpleXmlClaimReporter.java
deleted file mode 100644
index cf9228f6..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/report/claim/SimpleXmlClaimReporter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- */
-package org.apache.rat.report.claim;
-
-import java.util.Iterator;
-
-import org.apache.rat.api.Document;
-import org.apache.rat.api.MetaData;
-import org.apache.rat.api.RatException;
-import org.apache.rat.license.ILicense;
-import org.apache.rat.report.RatReport;
-import org.apache.rat.report.xml.XmlElements;
-import org.apache.rat.report.xml.writer.IXmlWriter;
-
-/**
- * A claim reporter to write the XML document.
- */
-public class SimpleXmlClaimReporter implements RatReport {
-
-
- /** the writer to write to */
- private final XmlElements xmlElements;
-
- /**
- * Constructor.
- * @param writer The writer to write the report to.
- */
- public SimpleXmlClaimReporter(final IXmlWriter writer) {
- this.xmlElements = new XmlElements(writer);
- }
-
- @Override
- public void report(final Document document) throws RatException {
- final MetaData metaData = document.getMetaData();
- xmlElements.document(document);
- for (Iterator<ILicense> iter = metaData.licenses().iterator();
iter.hasNext();) {
- final ILicense license = iter.next();
- xmlElements.license(license, metaData.isApproved(license));
- }
- xmlElements.closeElement();
- }
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
index 35d14b10..922b1d92 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlElements.java
@@ -28,309 +28,345 @@ import org.apache.rat.VersionInfo;
import org.apache.rat.api.Document;
import org.apache.rat.api.MetaData;
import org.apache.rat.api.RatException;
+import org.apache.rat.config.results.ClaimValidator;
import org.apache.rat.license.ILicense;
-import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.claim.ClaimStatistic;
+import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.utils.CasedString;
/**
* Creates the elements in the XML report.
*/
-public class XmlElements {
- /**
- * Converts an enum name to snake case.
- * @param name the enum name to convert.
- * @return a camel cased name.
- */
- private static String normalizeName(final String name) {
- CasedString casedName = new CasedString(CasedString.StringCase.SNAKE,
name.toLowerCase(Locale.ROOT));
- return casedName.toCase(CasedString.StringCase.PASCAL);
- }
-
- /**
- * The elements in the report.
- */
- public enum Elements {
- /** The start of the RAT report */
- RAT_REPORT("rat-report"),
- /** The version of RAT being run */
- VERSION(),
- /** A resource element */
- RESOURCE(),
- /** A license element */
- LICENSE(),
- /** A notes element */
- NOTES(),
- /** A statistics element */
- STATISTICS(),
- /** A statistic entry */
- STATISTIC(),
- /** A license name entry */
- LICENSE_NAME(),
- /** A license category entry */
- LICENSE_CATEGORY(),
- /** A document type entry */
- DOCUMENT_TYPE();
-
- /** The XML name for the element */
- private final String elementName;
-
- /**
- * Constructor.
- * @param elementName the XML name for the element.
- */
- Elements(final String elementName) {
- this.elementName = elementName;
- }
-
- Elements() {
- this.elementName = normalizeName(name());
- }
-
- /**
- * Gets the XML element name.
- * @return the XML element name.
- */
- public String getElementName() {
- return elementName;
- }
- }
-
- /**
- * The attributes of elements in the report.
- */
- public enum Attributes {
- /** A timestamp */
- TIMESTAMP,
- /** A version string */
- VERSION,
- /** The product identifier */
- PRODUCT,
- /** The vendor identifier */
- VENDOR,
- /** The approval flag */
- APPROVAL,
- /** The family category */
- FAMILY,
- /** The document type */
- TYPE,
- /** The id */
- ID,
- /** The name */
- NAME,
- /** A counter */
- COUNT,
- /** A description */
- DESCRIPTION,
- /** The media type for a document */
- MEDIA_TYPE,
- /** The encoding for a text document */
- ENCODING,
- /** Denotes a skipped directory */
- IS_DIRECTORY
+public final class XmlElements {
+ private XmlElements() {
+ // do not instantiate
}
- /** The XMLWriter that we write to */
- private final IXmlWriter writer;
-
/**
- * Constructor.
- * @param xmlWriter The writer to use.
+ * Converts an enum name to pascal case.
+ *
+ * @param name the attribute to normalize
+ * @return a pascal cased name.
*/
- public XmlElements(final IXmlWriter xmlWriter) {
- this.writer = xmlWriter;
+ private static String normalizeName(final String name) {
+ CasedString casedName = new CasedString(CasedString.StringCase.SNAKE,
name.toLowerCase(Locale.ROOT));
+ return casedName.toCase(CasedString.StringCase.PASCAL);
}
/**
* Create the RAT report element. Includes the timestamp and the version
element.
- * @return this.
+ * Does not close the report.
+ *
* @throws RatException on error
*/
- public XmlElements ratReport() throws RatException {
- return write(Elements.RAT_REPORT).
- write(Attributes.TIMESTAMP,
DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(Calendar.getInstance()))
- .version();
+ public static void ratReport(final XmlWriter writer) throws RatException {
+ try {
+ writer.startElement(Elements.RAT_REPORT.elementName)
+ .attribute(Attributes.TIMESTAMP.attributeName(),
+
DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(Calendar.getInstance()));
+ version(writer);
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
* Creates the version element with all version attributes populated.
Closes the version element.
- * @return this.
+ *
* @throws RatException on error
*/
- public XmlElements version() throws RatException {
+ public static void version(final XmlWriter writer) throws RatException {
VersionInfo versionInfo = new VersionInfo();
- return write(Elements.VERSION)
- .write(Attributes.PRODUCT, versionInfo.getTitle())
- .write(Attributes.VENDOR, versionInfo.getVendor())
- .write(Attributes.VERSION, versionInfo.getVersion())
- .closeElement();
+ try {
+ writer.startElement(Elements.VERSION.elementName)
+ .attribute(Attributes.PRODUCT.attributeName(),
versionInfo.getTitle())
+ .attribute(Attributes.VENDOR.attributeName(),
versionInfo.getVendor())
+ .attribute(Attributes.VERSION.attributeName(),
versionInfo.getVersion())
+ .closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
* Creates a license element. Closes the element before exit.
- * @param license the license for the element.
+ *
+ * @param license the license for the element.
* @param approved {@code true} if the license is approved.
- * @return this
* @throws RatException on error.
*/
- public XmlElements license(final ILicense license, final boolean approved)
throws RatException {
- write(Elements.LICENSE).write(Attributes.ID, license.getId())
- .write(Attributes.NAME, license.getName())
- .write(Attributes.APPROVAL,
Boolean.valueOf(approved).toString())
- .write(Attributes.FAMILY,
license.getLicenseFamily().getFamilyCategory());
- if (StringUtils.isNotBlank(license.getNote())) {
- try {
- write(Elements.NOTES).cdata(license.getNote()).closeElement();
- } catch (IOException e) {
- throw new RatException("Can not write CDATA for 'notes'
element", e);
+ public static void license(final XmlWriter writer, final ILicense license,
final boolean approved) throws RatException {
+ try {
+ writer.startElement(Elements.LICENSE.elementName)
+ .attribute(Attributes.ID.attributeName(), license.getId())
+ .attribute(Attributes.NAME.attributeName(),
license.getName())
+ .attribute(Attributes.APPROVAL.attributeName(),
Boolean.toString(approved))
+ .attribute(Attributes.FAMILY.attributeName(),
license.getLicenseFamily().getFamilyCategory());
+
+ if (StringUtils.isNotBlank(license.getNote())) {
+
writer.startElement(Elements.NOTES.elementName).cdata(license.getNote()).closeElement();
}
+ writer.closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
}
- return closeElement();
}
/**
- * Writes a CDATA block
- * @param data the data to write.
- * @return this
- * @throws IOException on error.
- */
- private XmlElements cdata(final String data) throws IOException {
- writer.cdata(data);
- return this;
- }
-
- /**
- * Creates a document element with attributes. Does NOT close the document
element.
+ * Creates a document element with attributes. Does <strong>NOT</strong>
close the document element.
+ *
* @param document the document to write.
- * @return this
* @throws RatException on error.
*/
- public XmlElements document(final Document document) throws RatException {
+ public static void document(final XmlWriter writer, final Document
document) throws RatException {
final MetaData metaData = document.getMetaData();
- XmlElements result = write(Elements.RESOURCE)
- .write(Attributes.NAME, document.getName().localized("/"))
- .write(Attributes.TYPE, metaData.getDocumentType().toString())
- .write(Attributes.MEDIA_TYPE,
metaData.getMediaType().toString());
- if (Document.Type.STANDARD == metaData.getDocumentType() ||
metaData.hasCharset()) {
- result = result.write(Attributes.ENCODING,
metaData.getCharset().displayName());
- }
- if (document.isIgnored()) {
- result = result.write(Attributes.IS_DIRECTORY,
Boolean.toString(document.isDirectory()));
+ try {
+ writer.startElement(Elements.RESOURCE.elementName)
+ .attribute(Attributes.NAME.attributeName(),
document.getName().localized("/"))
+ .attribute(Attributes.TYPE.attributeName(),
metaData.getDocumentType().toString())
+ .attribute(Attributes.MEDIA_TYPE.attributeName(),
metaData.getMediaType().toString());
+ if (Document.Type.STANDARD == metaData.getDocumentType() ||
metaData.hasCharset()) {
+ writer.attribute(Attributes.ENCODING.attributeName(),
metaData.getCharset().displayName());
+ }
+ if (document.isIgnored()) {
+ writer.attribute(Attributes.IS_DIRECTORY.attributeName(),
Boolean.toString(document.isDirectory()));
+ }
+ } catch (IOException e) {
+ throw new RatException(e);
}
- return result;
}
/**
* Creates a statistics element.
- * @return this
+ *
* @throws RatException on error.
*/
- public XmlElements statistics() throws RatException {
- return write(Elements.STATISTICS);
+ public static void statistics(final XmlWriter writer, final ClaimStatistic
statistic, final ClaimValidator validator) throws RatException {
+ try {
+ writer.startElement(Elements.STATISTICS.elementName);
+ for (ClaimStatistic.Counter counter :
ClaimStatistic.Counter.values()) {
+ int count = statistic.getCounter(counter);
+ XmlElements.statistic(writer, counter.displayName(), count,
counter.getDescription(), validator.isValid(counter, count));
+ }
+ for (String category : statistic.getLicenseFamilyCategories()) {
+ XmlElements.licenseCategory(writer, category,
statistic.getLicenseCategoryCount(category));
+ }
+ for (String category : statistic.getLicenseNames()) {
+ XmlElements.licenseName(writer, category,
statistic.getLicenseNameCount(category));
+ }
+ for (Document.Type type : statistic.getDocumentTypes()) {
+ XmlElements.documentType(writer, type.name(),
statistic.getCounter(type));
+ }
+
+ writer.closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
* Creates a statistic element. Closes the element before returning.
- * @param name the name of the statistics element.
- * @param count the count for the element.
+ *
+ * @param name the name of the statistics element.
+ * @param count the count for the element.
* @param description description of this statistic.
- * @param isOk if {@code true} the count is within limits.
- * @return this
+ * @param isOk if {@code true} the count is within limits.
* @throws RatException on error.
*/
- public XmlElements statistic(final String name, final int count, final
String description, final boolean isOk) throws RatException {
- return write(Elements.STATISTIC)
- .write(Attributes.NAME, name)
- .write(Attributes.COUNT, Integer.toString(count))
- .write(Attributes.APPROVAL, Boolean.toString(isOk))
- .write(Attributes.DESCRIPTION, description)
- .closeElement();
+ public static void statistic(final XmlWriter writer, final String name,
final int count, final String description, final boolean isOk) throws
RatException {
+ try {
+ writer.startElement(Elements.STATISTIC.elementName)
+ .attribute(Attributes.NAME.attributeName(), name)
+ .attribute(Attributes.COUNT.attributeName(),
Integer.toString(count))
+ .attribute(Attributes.APPROVAL.attributeName(),
Boolean.toString(isOk))
+ .attribute(Attributes.DESCRIPTION.attributeName(),
description)
+ .closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
* Creates a statistic element. Closes the element before returning.
- * @param name the name of the statistics element.
+ *
+ * @param name the name of the statistics element.
* @param count the count for the element.
- * @return this
* @throws RatException on error.
*/
- public XmlElements licenseCategory(final String name, final int count)
throws RatException {
- return write(Elements.LICENSE_CATEGORY)
- .write(Attributes.NAME, name)
- .write(Attributes.COUNT, Integer.toString(count))
- .closeElement();
+ public static void licenseCategory(final XmlWriter writer, final String
name, final int count) throws RatException {
+ try {
+ writer.startElement(Elements.LICENSE_CATEGORY.elementName)
+ .attribute(Attributes.NAME.attributeName(), name)
+ .attribute(Attributes.COUNT.attributeName(),
Integer.toString(count))
+ .closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
* Creates a statistic element. Closes the element before returning.
- * @param name the name of the statistics element.
+ *
+ * @param name the name of the statistics element.
* @param count the count for the element.
- * @return this
* @throws RatException on error.
*/
- public XmlElements licenseName(final String name, final int count) throws
RatException {
- return write(Elements.LICENSE_NAME)
- .write(Attributes.NAME, name)
- .write(Attributes.COUNT, Integer.toString(count))
- .closeElement();
+ public static void licenseName(final XmlWriter writer, final String name,
final int count) throws RatException {
+ try {
+ writer.startElement(Elements.LICENSE_NAME.elementName)
+ .attribute(Attributes.NAME.attributeName(), name)
+ .attribute(Attributes.COUNT.attributeName(),
Integer.toString(count))
+ .closeElement();
+ } catch (IOException e) {
+ throw new RatException(e);
+ }
}
/**
- * Creates a statistic element. Closes the element before returning.
- * @param name the name of the statistics element.
+ * Creates a document type element. Closes the element before returning.
+ *
+ * @param name the name of the document type element.
* @param count the count for the element.
- * @return this
* @throws RatException on error.
*/
- public XmlElements documentType(final String name, final int count) throws
RatException {
- return write(Elements.DOCUMENT_TYPE)
- .write(Attributes.NAME, name)
- .write(Attributes.COUNT, Integer.toString(count))
- .closeElement();
- }
-
- /**
- * Closes the currently open element.
- * @return this
- * @throws RatException on error.
- */
- public XmlElements closeElement() throws RatException {
+ public static void documentType(final XmlWriter writer, final String name,
final int count) throws RatException {
try {
- writer.closeElement();
- return this;
+ writer.startElement(Elements.DOCUMENT_TYPE.elementName)
+ .attribute(Attributes.NAME.attributeName(), name)
+ .attribute(Attributes.COUNT.attributeName(),
Integer.toString(count))
+ .closeElement();
} catch (IOException e) {
- throw new RatException("Cannot close currently open element", e);
+ throw new RatException(e);
}
-
}
/**
- * Write an element. The element is not closed.
- * @param element the element to write.
- * @return this
- * @throws RatException on error.
+ * The elements in the report.
*/
- private XmlElements write(final Elements element) throws RatException {
- try {
- writer.openElement(element.getElementName());
- return this;
- } catch (IOException e) {
- throw new RatException("Cannot open start element: " +
element.elementName, e);
+ public enum Elements {
+ /**
+ * The start of the RAT report.
+ */
+ RAT_REPORT("rat-report"),
+ /**
+ * The version of RAT being run.
+ */
+ VERSION(),
+ /**
+ * A resource element.
+ */
+ RESOURCE(),
+ /**
+ * A license element.
+ */
+ LICENSE(),
+ /**
+ * A notes element.
+ */
+ NOTES(),
+ /**
+ * A statistics element.
+ */
+ STATISTICS(),
+ /**
+ * A statistic entry.
+ */
+ STATISTIC(),
+ /**
+ * A license name entry.
+ */
+ LICENSE_NAME(),
+ /**
+ * A license category entry.
+ */
+ LICENSE_CATEGORY(),
+ /**
+ * A document type entry.
+ */
+ DOCUMENT_TYPE();
+
+ /**
+ * The XML name for the element
+ */
+ private final String elementName;
+
+ /**
+ * Constructor.
+ *
+ * @param elementName the XML name for the element.
+ */
+ Elements(final String elementName) {
+ this.elementName = elementName;
+ }
+
+ Elements() {
+ this.elementName = normalizeName(name());
}
}
/**
- * Write an attribute.
- * @param attribute the attribute name.
- * @param value the attribute value.
- * @return this
- * @throws RatException on error.
+ * The attributes of elements in the report.
*/
- public XmlElements write(final Attributes attribute, final String value)
throws RatException {
- try {
- writer.attribute(normalizeName(attribute.name()), value);
- return this;
- } catch (IOException e) {
- throw new RatException("Cannot open add attribute: " + attribute,
e);
+ public enum Attributes {
+ /**
+ * A timestamp.
+ */
+ TIMESTAMP,
+ /**
+ * A version string.
+ */
+ VERSION,
+ /**
+ * The product identifier.
+ */
+ PRODUCT,
+ /**
+ * The vendor identifier.
+ */
+ VENDOR,
+ /**
+ * The approval flag.
+ */
+ APPROVAL,
+ /**
+ * The family category.
+ */
+ FAMILY,
+ /**
+ * The document type.
+ */
+ TYPE,
+ /**
+ * The id.
+ */
+ ID,
+ /**
+ * The name.
+ */
+ NAME,
+ /**
+ * A counter.
+ */
+ COUNT,
+ /**
+ * A description.
+ */
+ DESCRIPTION,
+ /**
+ * The media type for a document.
+ */
+ MEDIA_TYPE,
+ /**
+ * The encoding for a text document.
+ */
+ ENCODING,
+ /**
+ * Denotes a skipped directory.
+ */
+ IS_DIRECTORY;
+
+ String attributeName() {
+ return normalizeName(this.name());
}
}
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
index 2bdce3b0..4214b4fb 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java
@@ -18,21 +18,26 @@
*/
package org.apache.rat.report.xml;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import org.apache.rat.ReportConfiguration;
import org.apache.rat.analysis.AnalyserFactory;
+import org.apache.rat.api.Document;
+import org.apache.rat.api.MetaData;
+import org.apache.rat.api.RatException;
+import org.apache.rat.configuration.XMLConfigurationWriter;
+import org.apache.rat.document.DocumentAnalyser;
+import org.apache.rat.document.RatDocumentAnalysisException;
+import org.apache.rat.license.ILicense;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
-import org.apache.rat.report.ConfigurationReport;
import org.apache.rat.report.RatReport;
import org.apache.rat.report.claim.ClaimAggregator;
-import org.apache.rat.report.claim.ClaimReporterMultiplexer;
import org.apache.rat.report.claim.ClaimStatistic;
-import org.apache.rat.report.claim.ClaimValidatorReport;
import org.apache.rat.report.claim.LicenseAddingReport;
-import org.apache.rat.report.claim.SimpleXmlClaimReporter;
-import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.xml.writer.XmlWriter;
/**
* A factory to create reports from a writer and a configuration.
@@ -53,7 +58,7 @@ public final class XmlReportFactory {
* @param configuration The report configuration.
* @return a RatReport instance.
*/
- public static RatReport createStandardReport(final IXmlWriter writer,
final ClaimStatistic statistic, final ReportConfiguration configuration) {
+ public static RatReport createStandardReport(final XmlWriter writer, final
ClaimStatistic statistic, final ReportConfiguration configuration) {
final List<RatReport> reporters = new ArrayList<>();
if (statistic != null) {
reporters.add(new ClaimAggregator(statistic));
@@ -63,13 +68,116 @@ public final class XmlReportFactory {
}
if (configuration.listFamilies() != LicenseFilter.NONE ||
configuration.listLicenses() != LicenseFilter.NONE) {
-
- reporters.add(new ConfigurationReport(writer, configuration));
+ reporters.add(configuration(writer, configuration));
}
- reporters.add(new SimpleXmlClaimReporter(writer));
- reporters.add(new ClaimValidatorReport(writer, statistic,
configuration));
+ reporters.add(simple(writer));
+ reporters.add(validator(writer, statistic, configuration));
+
+ return multiplexer(writer, configuration.isDryRun(),
AnalyserFactory.createConfiguredAnalyser(configuration), reporters);
+ }
+
+ /**
+ * Creates a simple claim reporter.
+ * @param writer The XmlWriter to use
+ * @return the RatReport that will write to the writer.
+ */
+ public static RatReport simple(final XmlWriter writer) {
+ return new RatReport() {
+ @Override
+ public void report(final Document document) throws RatException {
+ final MetaData metaData = document.getMetaData();
+ XmlElements.document(writer, document);
+ for (Iterator<ILicense> iter = metaData.licenses().iterator();
iter.hasNext();) {
+ final ILicense license = iter.next();
+ XmlElements.license(writer, license,
metaData.isApproved(license));
+ }
+ try {
+ writer.closeElement();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ };
+ }
+
+ /**
+ * Creates a simple claim validator reporter
+ * @param writer The XmlWriter to use
+ * @return the RatReport that will write to the writer.
+ */
+ public static RatReport validator(final XmlWriter writer, final
ClaimStatistic statistic, final ReportConfiguration configuration) {
+ return new RatReport() {
+ @Override
+ public void endReport() throws RatException {
+ XmlElements.statistics(writer, statistic,
configuration.getClaimValidator());
+ }
+ };
+ }
+
+ /**
+ * Creates a configuration report
+ *
+ * @param writer The writer to write the XML data to.
+ * @param configuration the configuration to write
+ */
+ public static RatReport configuration(final XmlWriter writer, final
ReportConfiguration configuration) {
+ return new RatReport() {
+ @Override
+ public void startReport() throws RatException {
+ if (configuration.listFamilies() != LicenseFilter.NONE ||
configuration.listLicenses() != LicenseFilter.NONE) {
+ new XMLConfigurationWriter(configuration).write(writer);
+ }
+ }
+ };
+ }
+
- return new ClaimReporterMultiplexer(writer, configuration.isDryRun(),
AnalyserFactory.createConfiguredAnalyser(configuration), reporters);
+ /**
+ * Creates a RatReport that multiplexes the running of multiple RatReports
+ */
+ public static RatReport multiplexer(final XmlWriter writer, final boolean
dryRun, final DocumentAnalyser analyser,
+ final List<? extends RatReport>
reporters) {
+ return new MultiplexerReport(writer, dryRun, analyser, reporters);
}
+
+ private record MultiplexerReport(XmlWriter writer, boolean dryRun,
DocumentAnalyser analyser,
+ List<? extends RatReport> reporters)
implements RatReport {
+
+ @Override
+ public void report(final Document document) throws RatException {
+ if (!dryRun) {
+ if (analyser != null) {
+ try {
+ analyser.analyse(document);
+ } catch (RatDocumentAnalysisException e) {
+ throw new RatException(e.getMessage(), e);
+ }
+ }
+ for (RatReport report : reporters) {
+ report.report(document);
+ }
+ }
+ }
+
+ @Override
+ public void startReport() throws RatException {
+ XmlElements.ratReport(writer);
+ for (RatReport report : reporters) {
+ report.startReport();
+ }
+ }
+
+ @Override
+ public void endReport() throws RatException {
+ for (RatReport report : reporters) {
+ report.endReport();
+ }
+ try {
+ writer.closeElement();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
deleted file mode 100644
index a227b9c5..00000000
---
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one *
- * or more contributor license agreements. See the NOTICE file *
- * distributed with this work for additional information *
- * regarding copyright ownership. The ASF licenses this file *
- * to you under the Apache License, Version 2.0 (the *
- * "License"); you may not use this file except in compliance *
- * with the License. You may obtain a copy of the License at *
- * *
- * http://www.apache.org/licenses/LICENSE-2.0 *
- * *
- * Unless required by applicable law or agreed to in writing, *
- * software distributed under the License is distributed on an *
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
- * KIND, either express or implied. See the License for the *
- * specific language governing permissions and limitations *
- * under the License. *
- */
-package org.apache.rat.report.xml.writer;
-
-import java.io.IOException;
-
-import org.apache.rat.report.xml.XmlElements;
-import org.w3c.dom.Document;
-
-/**
- * Simple interface for creating basic XML documents.
- * Performs basic validation and escaping.
- * Not namespace aware.
- */
-public interface IXmlWriter extends AutoCloseable {
-
- /**
- * Starts a document by writing a prologue.
- * Calling this method is optional.
- * When writing a document fragment, it should <em>not</em> be called.
- * @return this object
- * @throws OperationNotAllowedException
- * if called after the first element has been written
- * or once a prolog has already been written
- */
- IXmlWriter startDocument() throws IOException;
-
- /**
- * Writes the start of an element.
- *
- * @param elementName the name of the element, not null
- * @return this object
- * @throws InvalidXmlException if the name is not valid for a xml element
- * @throws OperationNotAllowedException
- * if called after the first element has been closed
- */
- IXmlWriter openElement(CharSequence elementName) throws IOException;
-
- /**
- * Writes the start of an element.
- *
- * @param element the element, not null
- * @return this object
- * @throws InvalidXmlException if the name is not valid for a xml element
- * @throws OperationNotAllowedException
- * if called after the first element has been closed
- */
- default IXmlWriter openElement(XmlElements.Elements element) throws
IOException {
- return openElement(element.getElementName());
- }
-
- /**
- * Writes a comment.
- *
- * @param text the comment text
- * @return this object
- * @throws OperationNotAllowedException
- * if called after the first element has been closed
- */
- IXmlWriter comment(CharSequence text) throws IOException;
-
- /**
- * Writes an attribute of an element.
- * Note that this is only allowed directly after {@link
#openElement(CharSequence)}
- * or this method.
- *
- * @param name the attribute name, not null
- * @param value the attribute value, not null
- * @return this object
- * @throws InvalidXmlException if the name is not valid for a xml attribute
- * or if a value for the attribute has already been written
- * @throws OperationNotAllowedException if called after {@link
#content(CharSequence)}
- * or {@link #closeElement()} or before any call to {@link
#openElement(CharSequence)}
- */
- IXmlWriter attribute(CharSequence name, CharSequence value) throws
IOException;
-
- /**
- * Writes content.
- * Note that this method does not support CDATA.
- * This method automatically escapes characters.
- *
- * @param content the content to write
- * @return this object
- * @throws OperationNotAllowedException
- * if called before any call to {@link #openElement(CharSequence)}
- * or after the first element has been closed
- */
- IXmlWriter content(CharSequence content) throws IOException;
-
- /**
- * Writes CDATA content.
- * This method DOES NOT automatically escape characters.
- * It will remove enclosed CDATA closing strings (e.g. {@code ]]>})
- *
- * @param content the content to write
- * @return this object
- * @throws OperationNotAllowedException
- * if called before any call to {@link #openElement(CharSequence)}
- * or after the first element has been closed
- */
- IXmlWriter cdata(CharSequence content) throws IOException;
-
- /**
- * Closes the last element written.
- *
- * @return this object
- * @throws OperationNotAllowedException
- * if called before any call to {@link #openElement(CharSequence)}
- * or after the first element has been closed
- */
- IXmlWriter closeElement() throws IOException;
-
- /**
- * Closes all open elements back to and including the named element.
- *
- * @param name the last element to close
- * @return this object
- * @throws OperationNotAllowedException
- * if called before any call to {@link #openElement(CharSequence)}
- * or after the first element has been closed
- */
- IXmlWriter closeElement(CharSequence name) throws IOException;
-
- /**
- * Closes all pending elements.
- * When appropriate, resources are also flushed and closed.
- * No exception is raised when called upon a document whose
- * root element has already been closed.
- *
- * @return this object
- * @throws OperationNotAllowedException
- * if called before any call to {@link #openElement(CharSequence)}
- */
- IXmlWriter closeDocument() throws IOException;
-
- /**
- * Append an XML document into this one.
- * @param document the document to append
- * @return this object
- * @throws IOException on error.
- */
- IXmlWriter append(Document document) throws IOException;
-}
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/OperationNotAllowedException.java
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/OperationNotAllowedException.java
index df248bac..943abe6a 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/OperationNotAllowedException.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/OperationNotAllowedException.java
@@ -21,7 +21,7 @@ package org.apache.rat.report.xml.writer;
import java.io.IOException;
/**
- * Thrown by {@link IXmlWriter} implementations when the current
+ * Thrown by {@link XmlWriter} implementations when the current
* state does not allow the requested operation.
*/
public class OperationNotAllowedException extends IOException {
diff --git
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
index 9a49fbdd..c9c0c16d 100644
---
a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
+++
b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
@@ -36,9 +36,6 @@ import org.apache.rat.utils.StandardXmlFactory;
import org.w3c.dom.Document;
/**
- * <p>
- * Lightweight {@link IXmlWriter} implementation.
- * </p>
* <p>
* Requires a wrapper to be used safely in a multithreaded environment.
* </p>
@@ -47,7 +44,7 @@ import org.w3c.dom.Document;
* </p>
*/
@SuppressWarnings({"checkstyle:MagicNumber", "checkstyle:JavadocVariable"})
-public final class XmlWriter implements IXmlWriter {
+public final class XmlWriter implements AutoCloseable {
private final Appendable appendable;
private final ArrayDeque<CharSequence> elementNames;
private final Set<CharSequence> currentAttributes = new HashSet<>();
@@ -86,8 +83,7 @@ public final class XmlWriter implements IXmlWriter {
* @throws OperationNotAllowedException if called after the first element
has
* been written or once a prolog has already been written
*/
- @Override
- public IXmlWriter startDocument() throws IOException {
+ public XmlWriter startDocument() throws IOException {
if (elementsWritten) {
throw new OperationNotAllowedException("Document already started");
}
@@ -108,8 +104,7 @@ public final class XmlWriter implements IXmlWriter {
* @throws OperationNotAllowedException if called after the first element
has
* been closed
*/
- @Override
- public IXmlWriter openElement(final CharSequence elementName) throws
IOException {
+ public XmlWriter startElement(final CharSequence elementName) throws
IOException {
validateRootOpen();
if (!XMLChar.isValidName(elementName.toString())) {
throw new InvalidXmlException("'" + elementName + "' is not a
valid element name");
@@ -124,8 +119,15 @@ public final class XmlWriter implements IXmlWriter {
return this;
}
- @Override
- public IXmlWriter comment(final CharSequence text) throws IOException {
+ /**
+ * Writes a comment.
+ *
+ * @param text the comment text
+ * @return this object
+ * @throws OperationNotAllowedException
+ * if called after the first element has been closed
+ */
+ public XmlWriter comment(final CharSequence text) throws IOException {
maybeCloseElement();
appendable.append("<!-- ");
writeEscaped(text, false);
@@ -135,7 +137,7 @@ public final class XmlWriter implements IXmlWriter {
/**
* Writes an attribute of an element. Note that this is only allowed
directly
- * after {@link #openElement(CharSequence)} or a previous {@code
attribute} call.
+ * after {@link #startElement(CharSequence)} or a previous {@code
attribute} call.
*
* @param name the attribute name, not null
* @param value the attribute value, not null
@@ -144,10 +146,9 @@ public final class XmlWriter implements IXmlWriter {
* if a value for the attribute has already been written
* @throws OperationNotAllowedException if called after
* {@link #content(CharSequence)} or {@link #closeElement()} or before any
call
- * to {@link #openElement(CharSequence)}
+ * to {@link #startElement(CharSequence)}
*/
- @Override
- public IXmlWriter attribute(final CharSequence name, final CharSequence
value) throws IOException {
+ public XmlWriter attribute(final CharSequence name, final CharSequence
value) throws IOException {
if (elementNames.isEmpty()) {
validateRootOpen();
throw new OperationNotAllowedException("Close called before an
element has been opened.");
@@ -182,15 +183,34 @@ public final class XmlWriter implements IXmlWriter {
maybeCloseElement();
}
- @Override
- public IXmlWriter content(final CharSequence content) throws IOException {
+ /**
+ * Writes content.
+ * Note that this method does not support CDATA.
+ * This method automatically escapes characters.
+ *
+ * @param content the content to write
+ * @return this object
+ * @throws OperationNotAllowedException
+ * if called before any call to {@link #startElement(CharSequence)}
+ * or after the first element has been closed
+ */public XmlWriter content(final CharSequence content) throws IOException
{
prepareForData();
writeEscaped(content, false);
return this;
}
- @Override
- public IXmlWriter cdata(final CharSequence content) throws IOException {
+ /**
+ * Writes CDATA content.
+ * This method DOES NOT automatically escape characters.
+ * It will remove enclosed CDATA closing strings (e.g. {@code ]]>})
+ *
+ * @param content the content to write
+ * @return this object
+ * @throws OperationNotAllowedException
+ * if called before any call to {@link #startElement(CharSequence)}
+ * or after the first element has been closed
+ */
+ public XmlWriter cdata(final CharSequence content) throws IOException {
prepareForData();
StringBuilder sb = new StringBuilder(content);
int found;
@@ -240,10 +260,9 @@ public final class XmlWriter implements IXmlWriter {
*
* @return this object
* @throws OperationNotAllowedException if called before any call to
- * {@link #openElement} or after the first element has been closed
+ * {@link #startElement} or after the first element has been closed
*/
- @Override
- public IXmlWriter closeElement() throws IOException {
+ public XmlWriter closeElement() throws IOException {
if (elementNames.isEmpty()) {
validateRootOpen();
throw new OperationNotAllowedException("Close called before an
element has been opened.");
@@ -265,10 +284,9 @@ public final class XmlWriter implements IXmlWriter {
* @param name The name of the element to close. Must not be {@code null}.
* @return this object
* @throws OperationNotAllowedException if called before any call to
- * {@link #openElement} or after the first element has been closed
+ * {@link #startElement} or after the first element has been closed
*/
- @Override
- public IXmlWriter closeElement(final CharSequence name) throws IOException
{
+ public XmlWriter closeElement(final CharSequence name) throws IOException {
Objects.requireNonNull(name);
if (elementNames.isEmpty()) {
validateRootOpen();
@@ -296,10 +314,9 @@ public final class XmlWriter implements IXmlWriter {
*
* @return this object
* @throws OperationNotAllowedException if called before any call to
- * {@link #openElement}
+ * {@link #startElement}
*/
- @Override
- public IXmlWriter closeDocument() throws IOException {
+ public XmlWriter closeDocument() throws IOException {
if (elementNames.isEmpty() && !elementsWritten) {
throw new OperationNotAllowedException("Close called before an
element has been opened.");
}
@@ -311,13 +328,28 @@ public final class XmlWriter implements IXmlWriter {
@Override
public void close() throws IOException {
- closeDocument();
- if (appendable instanceof Closeable closeable) {
- closeable.close();
+ IOException thrown = null;
+ try {
+ closeDocument();
+ } catch (IOException e) {
+ thrown = e;
+ } finally {
+ if (appendable instanceof Closeable closeable) {
+ try {
+ closeable.close();
+ } catch (IOException e) {
+ if (thrown == null) {
+ thrown = e;
+ }
+ }
+ }
+ }
+ if (thrown != null) {
+ throw thrown;
}
}
- public IXmlWriter append(final Document document) throws IOException {
+ public XmlWriter append(final Document document) throws IOException {
validateRootOpen();
elementsWritten = true;
maybeCloseElement();
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
index 13319f35..22a4945f 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java
@@ -36,7 +36,7 @@ import org.apache.rat.document.DocumentAnalyser;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.FileDocument;
import org.apache.rat.document.RatDocumentAnalysisException;
-import org.apache.rat.report.claim.SimpleXmlClaimReporter;
+import org.apache.rat.report.xml.XmlReportFactory;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.test.utils.Resources;
import org.apache.rat.testhelpers.TestingDocument;
@@ -53,8 +53,6 @@ public class AnalyserFactoryTest {
private final DocumentName basedir;
- private StringWriter out;
- private SimpleXmlClaimReporter reporter;
private DocumentAnalyser analyser;
AnalyserFactoryTest() {
@@ -63,8 +61,6 @@ public class AnalyserFactoryTest {
@BeforeEach
public void setUp() {
- out = new StringWriter();
- reporter = new SimpleXmlClaimReporter(new XmlWriter(out));
ReportConfiguration config = new ReportConfiguration();
config.addLicense(UnknownLicense.INSTANCE);
analyser = AnalyserFactory.createConfiguredAnalyser(config);
@@ -175,13 +171,20 @@ public class AnalyserFactoryTest {
assertThat(document.getMetaData().getMediaType().toString()).isEqualTo("application/gzip");
}
+ private String buildReport(final Document document) throws Exception {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ XmlReportFactory.simple(writer).report(document);
+ }
+ return out.toString();
+ }
+
@Test
public void RAT147_unix_Test() throws Exception {
final Document document = new FileDocument(basedir,
Resources.getResourceFile("/jira/RAT147/unix-newlines.txt.bin"),
DocumentNameMatcher.MATCHES_ALL);
analyser.analyse(document);
- reporter.report(document);
- String result = out.toString();
+ String result = buildReport(document);
TextUtils.assertPatternInTarget(
"<resource name='/jira/RAT147/unix-newlines.txt.bin'
type='STANDARD'",
result);
@@ -192,8 +195,7 @@ public class AnalyserFactoryTest {
final Document document = new FileDocument(basedir,
Resources.getResourceFile("/jira/RAT147/windows-newlines.txt.bin"),
DocumentNameMatcher.MATCHES_ALL);
analyser.analyse(document);
- reporter.report(document);
- String result = out.toString();
+ String result = buildReport(document);
TextUtils.assertPatternInTarget(
"<resource name='/jira/RAT147/windows-newlines.txt.bin'
type='STANDARD'",
result);
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java
b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java
index af0d1333..cc964ffe 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java
@@ -35,7 +35,7 @@ import org.apache.rat.ReportConfiguration;
import org.apache.rat.configuration.MatcherBuilderTracker;
import org.apache.rat.license.ILicenseFamily;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
-import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.xml.XmlReportFactory;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.testhelpers.XmlUtils;
import org.junit.jupiter.api.BeforeEach;
@@ -45,30 +45,31 @@ import org.w3c.dom.Node;
public class ConfigurationReportTest {
- private ConfigurationReport report;
- private StringWriter sw;
- private IXmlWriter writer;
-
+ private ReportConfiguration reportConfiguration;
private final String[] FAMILY_IDS = { "AL", "BSD-3", "CDDL1", "GPL",
"MIT", "OASIS", "W3C", "W3CD", };
@BeforeEach
public void setup() {
- ReportConfiguration reportConfiguration = new ReportConfiguration();
+ reportConfiguration = new ReportConfiguration();
reportConfiguration.listFamilies(LicenseFilter.ALL);
reportConfiguration.listLicenses(LicenseFilter.ALL);
reportConfiguration.setFrom(Defaults.builder().build());
+ }
- sw = new StringWriter();
- writer = new XmlWriter(sw);
- report = new ConfigurationReport(writer, reportConfiguration);
+ private String executeReport() throws Exception {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startDocument();
+ RatReport report = XmlReportFactory.configuration(writer,
reportConfiguration);
+ report.startReport();
+ report.endReport();
+ }
+ return out.toString();
}
@Test
public void testAllFamiliesAndMatchers() throws Exception {
- report.startReport();
- report.endReport();
- writer.closeDocument();
- String result = sw.toString();
+ String result = executeReport();
assertTrue(XmlUtils.isWellFormedXml(result), "Is well formed");
XPath xPath = XPathFactory.newInstance().newXPath();
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java
index 3de15b01..fb041648 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java
@@ -38,7 +38,6 @@ import org.apache.rat.license.ILicense;
import org.apache.rat.license.ILicenseFamily;
import org.apache.rat.report.RatReport;
import org.apache.rat.report.claim.ClaimStatistic;
-import org.apache.rat.report.xml.writer.IXmlWriter;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.test.utils.Resources;
import org.apache.rat.testhelpers.TestingLicense;
@@ -54,7 +53,7 @@ public class XmlReportFactoryTest {
.setLicenseFamilyName("Testing family").build();
private StringWriter out;
- private IXmlWriter writer;
+ private XmlWriter writer;
@BeforeEach
public void setUp() throws Exception {
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterUtilsTest.java
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterUtilsTest.java
index f0c8c921..27eab5fb 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterUtilsTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterUtilsTest.java
@@ -19,7 +19,6 @@
package org.apache.rat.report.xml.writer;
import org.apache.rat.testhelpers.XmlUtils;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.StringWriter;
@@ -28,25 +27,23 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
public class XmlWriterUtilsTest {
- private StringWriter out;
- private IXmlWriter writer;
-
- @BeforeEach
- public void setUp() throws Exception {
- out = new StringWriter();
- writer = new XmlWriter(out);
- writer.openElement("alpha");
- }
-
@Test
public void writeTrue() throws Exception {
- XmlUtils.writeAttribute(writer, "name", true);
- assertEquals("<alpha name='true'", out.toString(), "Attribute written
as True");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ XmlUtils.writeAttribute(writer, "name", true);
+ assertEquals("<alpha name='true'", out.toString(), "Attribute
written as True");
+ }
}
@Test
public void writeFalse() throws Exception {
- XmlUtils.writeAttribute(writer, "name", false);
- assertEquals("<alpha name='false'", out.toString(), "Attribute written
as False");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ XmlUtils.writeAttribute(writer, "name", false);
+ assertEquals("<alpha name='false'", out.toString(), "Attribute
written as False");
+ }
}
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java
index 4f5ea5a0..287db767 100644
---
a/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java
+++
b/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java
@@ -7,7 +7,7 @@
* "License"); you may not use this file except in compliance *
* with the License. You may obtain a copy of the License at *
* *
- * http://www.apache.org/licenses/LICENSE-2.0 *
+ * https://www.apache.org/licenses/LICENSE-2.0 *
* *
* Unless required by applicable law or agreed to in writing, *
* software distributed under the License is distributed on an *
@@ -18,12 +18,10 @@
*/
package org.apache.rat.report.xml.writer.impl.base;
-import org.apache.rat.report.xml.writer.IXmlWriter;
import org.apache.rat.report.xml.writer.InvalidXmlException;
import org.apache.rat.report.xml.writer.OperationNotAllowedException;
import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.testhelpers.XmlUtils;
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
@@ -33,73 +31,61 @@ import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.NoSuchElementException;
-import static org.assertj.core.api.Assertions.fail;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
class XmlWriterTest {
- private XmlWriter writer;
- private StringWriter out;
-
- @BeforeEach
- public void setUp() {
- out = new StringWriter();
- writer = new XmlWriter(out);
- }
-
@Test
void returnValues() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals(
- writer, writer.attribute("beta", "b"), "XmlWriters should
always return themselves");
- assertEquals(
- writer, writer.content("gamma"), "XmlWriters should always
return themselves");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ assertThat(writer.startElement("alpha")).as("XmlWriters should always
return themselves").isEqualTo(writer);
+ assertThat(writer.attribute("beta", "b")).as("XmlWriters should
always return themselves").isEqualTo(writer);
+ assertThat(writer.content("gamma")).as("XmlWriters should always
return themselves").isEqualTo(writer);
+ assertThat(writer.closeElement()).as("XmlWriters should always
return themselves").isEqualTo(writer);
+ }
}
@Test
- void openElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta", out.toString(), "Alpha element tag closed
and beta started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/>", out.toString(), "Beta tag ended");
- assertEquals(
- writer, writer.openElement("gamma"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/><gamma", out.toString(), "Gamma tag
started");
+ void startElement() throws Exception {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.startElement("beta");
+ assertThat(out).hasToString("<alpha><beta");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha><beta/>");
+ writer.startElement("gamma");
+ assertThat(out).hasToString("<alpha><beta/><gamma");
+ }
}
@Test
void invalidElementName() throws Exception {
- assertTrue( isValidElementName("alpha"), "All strings ok");
- assertTrue(isValidElementName("alpha77"), "Strings and digits ok");
- assertFalse(isValidElementName("5alpha77"), "Must no start with
digit");
- assertFalse(isValidElementName("alph<a77"), "Greater than not ok");
- assertFalse(isValidElementName("alph<a77"), "Less than not ok");
- assertFalse(isValidElementName("alph'a77"), "Quote not ok");
- assertTrue(isValidElementName("alph-a77"), "Dash ok");
- assertTrue(isValidElementName("alph_a77"), "Underscore ok");
- assertTrue(isValidElementName("alph.a77"), "Dot ok");
- assertTrue(isValidElementName("alpha:77"), "Colon ok");
- assertFalse(isValidElementName("-a77"), "Start with dash not ok");
- assertTrue(isValidElementName("_a77"), "Start with underscore ok");
- assertFalse(isValidElementName(".a77"), "Start with dot not ok");
- assertTrue(isValidElementName(":a77"), "Start with colon ok");
+ assertThat(isValidElementName("alpha")).as("All strings ok").isTrue();
+ assertThat(isValidElementName("alpha77")).as("Strings and digits
ok").isTrue();
+ assertThat(isValidElementName("5alpha77")).as("Must no start with
digit").isFalse();
+ assertThat(isValidElementName("alph<a77")).as("Greater than not
ok").isFalse();
+ assertThat(isValidElementName("alph<a77")).as("Less than not
ok").isFalse();
+ assertThat(isValidElementName("alph'a77")).as("Quote not
ok").isFalse();
+ assertThat(isValidElementName("alph-a77")).as("Dash ok").isTrue();
+ assertThat(isValidElementName("alph_a77")).as("Underscore
ok").isTrue();
+ assertThat(isValidElementName("alph.a77")).as("Dot ok").isTrue();
+ assertThat(isValidElementName("alpha:77")).as("Colon ok").isTrue();
+ assertThat(isValidElementName("-a77")).as("Start with dash not
ok").isFalse();
+ assertThat(isValidElementName("_a77")).as("Start with underscore
ok").isTrue();
+ assertThat(isValidElementName(".a77")).as("Start with dot not
ok").isFalse();
+ assertThat(isValidElementName(":a77")).as("Start with colon
ok").isTrue();
}
private boolean isValidElementName(String elementName) throws Exception {
boolean result = true;
- try {
- writer.openElement(elementName);
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement(elementName);
} catch (InvalidXmlException e) {
result = false;
}
@@ -107,191 +93,177 @@ class XmlWriterTest {
}
@Test
- void callOpenElementAfterLastElementClosed() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString(), "Element alpha is closed");
- try {
- writer.openElement("delta");
- fail("Cannot open new elements once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ void callStartElementAfterLastElementClosed() throws Exception {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha/>");
+ assertThatThrownBy(() -> writer.startElement("delta"))
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void callCloseElementAfterLastElementClosed() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString(), "Element alpha is closed");
- try {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
writer.closeElement();
- fail("Cannot close elements once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ assertThat(out).hasToString("<alpha/>");
+ assertThatThrownBy(writer::closeElement)
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void closeFirstElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString(), "Element alpha is closed");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha/>");
+ }
}
@Test
void closeElementWithContent() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta", out.toString(), "Beta element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/>", out.toString(), "Element beta is
closed");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/></alpha>", out.toString(), "Element beta
is closed");
- try {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").startElement("beta");
+ assertThat(out).hasToString("<alpha><beta");
+
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha><beta/>");
writer.closeElement();
- fail("Cannot close elements once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ assertThat(out).hasToString("<alpha><beta/></alpha>");
+ assertThatThrownBy(writer::closeElement)
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void closeElementBeforeFirstElement() throws Exception {
- try {
- writer.closeElement();
- fail("Cannot close elements before the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements before the first element has been
closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ assertThatThrownBy(writer::closeElement)
+ .hasMessageContaining("Close called before an element has
been opened.")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
}
+
}
@Test
void contentAfterElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.content("foo bar"), "XmlWriters should always
return themselves");
- assertEquals("<alpha>foo bar", out.toString(), "Alpha tag closed.
Content written");
- assertEquals(
- writer, writer.content(" and more foo bar"), "XmlWriters
should always return themselves");
- assertEquals("<alpha>foo bar and more foo bar", out.toString(), "Alpha
tag closed. Content written");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha>foo bar and more foo bar<beta", out.toString());
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha>foo bar and more foo bar<beta/>", out.toString(),
"Element beta is closed");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha>foo bar and more foo bar<beta/></alpha>",
out.toString(), "Element beta is closed");
- try {
- writer.content("A Sentence Too far");
- fail("Cannot write content once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.content("foo bar");
+ assertThat(out).hasToString("<alpha>foo bar");
+ writer.content(" and more foo bar");
+ assertThat(out).hasToString("<alpha>foo bar and more foo bar");
+ writer.startElement("beta");
+ assertThat(out).hasToString("<alpha>foo bar and more foo
bar<beta");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha>foo bar and more foo
bar<beta/>");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha>foo bar and more foo
bar<beta/></alpha>");
+ assertThatThrownBy(() -> writer.content("A Sentence Too far"))
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void contentAfterLastElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString(), "Element alpha is closed");
- try {
- writer.content("A Sentence Too far");
- fail("Cannot write content once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.closeElement();
+ assertThat(out).hasToString("<alpha/>");
+ assertThatThrownBy(() -> writer.content("A Sentence Too far"))
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void writeContentBeforeFirstElement() throws Exception {
- try {
- writer.content("Too early");
- fail("Cannot close elements before the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements before the first element has been
closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ assertThatThrownBy(() -> writer.content("Too early"))
+ .hasMessageContaining("An element must be opened before
content can be written.")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
}
}
@Test
void contentEscaping() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.content("this&that"), "XmlWriters should always
return themselves");
- assertEquals("<alpha>this&that", out.toString(), "Amphersands must
be escaped");
- assertEquals(
- writer, writer.content("small<large"), "XmlWriters should
always return themselves");
- assertEquals("<alpha>this&thatsmall<large", out.toString(),
"Left angle brackets must be escaped");
- assertEquals(
- writer, writer.content("12>1"), "XmlWriters should always
return themselves");
- assertEquals("<alpha>this&thatsmall<large12>1",
out.toString(), "Choose to escape right angle brackets");
-
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+ assertThat(out).hasToString("<alpha");
+ writer.content("this&that");
+ assertThat(out).hasToString("<alpha>this&that");
+ writer.content("small<large");
+ assertThat(out).hasToString("<alpha>this&thatsmall<large");
+ writer.content("12>1");
+
assertThat(out).hasToString("<alpha>this&thatsmall<large12>1");
+ }
}
@Test
void attributeAfterLastElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString(), "Element alpha is closed");
- try {
- writer.attribute("foo", "bar");
- fail("Cannot write content once the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements once the first element has been closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").closeElement();
+ assertThat(out).hasToString("<alpha/>");
+ assertThatThrownBy(() -> writer.attribute("foo", "bar"))
+ .hasMessageContaining("Root element already closed. Cannot
open new element.")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
void attributeContentBeforeFirstElement() throws Exception {
- try {
- writer.attribute("foo", "bar");
- fail("Cannot close elements before the first element has been
closed");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements before the first element has been
closed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ assertThatThrownBy(() -> writer.attribute("foo", "bar"))
+ .hasMessageContaining("Close called before an element has
been opened.")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
}
}
@Test
void invalidAttributeName() throws Exception {
- writer.openElement("alpha");
- assertTrue(isValidAttributeName("alpha"), "All string ok");
- assertTrue(isValidAttributeName("alpha77"), "Strings and digits ok");
- assertFalse(isValidAttributeName("5alpha77"), "Must not start with
digit");
- assertTrue(isValidAttributeName("alpha:77"), "Colon ok");
- assertFalse(isValidAttributeName("alph<a77"),"Greater than not ok");
- assertFalse(isValidAttributeName("alph<a77"), "Less than not ok");
- assertFalse(isValidAttributeName("alph'a77"), "Quote not ok");
+ assertThat(isValidAttributeName("alpha")).as("All string ok").isTrue();
+ assertThat(isValidAttributeName("alpha77")).as("Strings and digits
ok").isTrue();
+ assertThat(isValidAttributeName("5alpha77")).as("Must not start with
digit").isFalse();
+ assertThat(isValidAttributeName("alpha:77")).as("Colon ok").isTrue();
+ assertThat(isValidAttributeName("alph<a77")).as("Greater than not
ok").isFalse();
+ assertThat(isValidAttributeName("alph<a77")).as("Less than not
ok").isFalse();
+ assertThat(isValidAttributeName("alph'a77")).as("Quote not
ok").isFalse();
}
private boolean isValidAttributeName(String name) throws Exception {
boolean result = true;
- try {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
writer.attribute(name, "");
} catch (InvalidXmlException e) {
result = false;
@@ -301,235 +273,199 @@ class XmlWriterTest {
@Test
void escapeAttributeContent() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.attribute("one", "this&that"), "XmlWriters
should always return themselves");
- assertEquals("<alpha one='this&that'", out.toString(),
"Amphersands must be escaped");
- assertEquals(
- writer, writer.attribute("two", "small<large"), "XmlWriters
should always return themselves");
- assertEquals("<alpha one='this&that' two='small<large'",
out.toString(), "Left angle brackets must be escaped");
- assertEquals(
- writer, writer.attribute("three", "12>1"), "XmlWriters should
always return themselves");
- assertEquals("<alpha one='this&that' two='small<large'
three='12>1'", out.toString(), "Choose to escape right angle brackets");
- assertEquals(
- writer, writer.attribute("four", "'quote'"), "XmlWriters
should always return themselves");
- assertEquals("<alpha one='this&that' two='small<large'
three='12>1' four=''quote''", out.toString(), "Apostrophes must be
escape");
- assertEquals(
- writer, writer.attribute("five", "\"quote\""), "XmlWriters
should always return themselves");
- assertEquals("<alpha one='this&that' two='small<large'
three='12>1' four=''quote'' five='"quote"'",
out.toString(), "Double quotes must be escape");
-
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").attribute("one",
"this&that").attribute("two", "small<large")
+ .attribute("three", "12>1").attribute("four",
"'quote'").attribute("five", "\"quote\"");
+ assertThat(out).hasToString("<alpha one='this&that'
two='small<large' three='12>1' four=''quote''
five='"quote"'");
+ }
}
@Test
void attributeInContent() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.content("foo bar"), "XmlWriters should always
return themselves");
- try {
- writer.attribute("name", "value");
- fail("attributes after body content are not allowed");
- } catch (InvalidXmlException e) {
- // attributes after body content are not allowed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").content("foo bar");
+ assertThatThrownBy(() -> writer.attribute("name", "value"))
+ .hasMessageContaining("Attributes can only be written in
elements")
+ .isInstanceOf(InvalidXmlException.class);
}
}
@Test
void outOfRangeCharacter() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- CharSequence cs = new CharSequence() {
- @Override
- public int length() {
- return 1;
- }
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ CharSequence cs = new CharSequence() {
+ @Override
+ public int length() {
+ return 1;
+ }
- @Override
- public char charAt(int index) {
- return Character.highSurrogate(0x110000);
- }
+ @Override
+ public char charAt(int index) {
+ return Character.highSurrogate(0x110000);
+ }
- @Override
- public CharSequence subSequence(int start, int end) {
- return null;
- }
- };
-
- assertEquals(writer, writer.content(cs), "XmlWriters should always
return themselves");
- assertEquals("<alpha>\\uDC00", this.out.toString(), "Replace illegal
characters with \\u encoding");
+ @Override
+ public CharSequence subSequence(int start, int end) {
+ return null;
+ }
+ };
+ writer.startElement("alpha").content(cs);
+ assertThat(out).hasToString("<alpha>\\uDC00");
+ }
}
@Test
void attributeAfterElementClosed() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta", out.toString(), "Beta element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/>", out.toString(), "Beta element closed");
- try {
- writer.attribute("name", "value");
- fail("attributes after closed element are not allowed");
- } catch (InvalidXmlException e) {
- // attributes after body content are not allowed
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").startElement("beta").closeElement();
+ assertThat(out).hasToString("<alpha><beta/>");
+ assertThatThrownBy(() -> writer.attribute("name", "value"))
+ .hasMessageContaining("Attributes can only be written in
elements")
+ .isInstanceOf(InvalidXmlException.class);
}
}
@Test
void closeDocumentBeforeOpen() throws Exception {
- try {
- writer.closeDocument();
- fail("Cannot close document before the first element has been
opened");
- } catch (OperationNotAllowedException e) {
- // Cannot open new elements before the first element has been
opened
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ assertThatThrownBy(writer::closeDocument)
+ .hasMessageContaining("Close called before an element has
been opened.")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
}
+
}
@Test
void closeDocumentAfterRootElementClosed() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha/>", out.toString());
- try {
- writer.closeDocument();
- } catch (OperationNotAllowedException e) {
- fail("No exception should be thrown when called after the root
element is closed.");
- }
- }
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").closeElement();
+ assertThatNoException().isThrownBy(writer::closeDocument);
+ }
+ }
@Test
void closeSimpleDocument() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta", out.toString(), "Beta element started");
- assertEquals(
- writer, writer.closeDocument(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta/></alpha>", out.toString(), "Beta element
started");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").startElement("beta").closeDocument();
+ assertThat(out).hasToString("<alpha><beta/></alpha>");
+ }
}
@Test
void closeComplexDocument() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta", out.toString(), "Beta element started");
- assertEquals(
- writer, writer.attribute("name", "value"), "XmlWriters should
always return themselves");
- assertEquals("<alpha><beta name='value'", out.toString(), "Beta
element started");
- assertEquals(
- writer, writer.closeElement(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta name='value'/>", out.toString(), "Beta
element started");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta name='value'/><beta", out.toString(), "Beta
element started");
- assertEquals(
- writer, writer.attribute("name", "value"), "XmlWriters should
always return themselves");
- assertEquals("<alpha><beta name='value'/><beta name='value'",
out.toString(), "Beta element started");
- assertEquals(
- writer, writer.openElement("gamma"), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta name='value'/><beta name='value'><gamma",
out.toString(), "Beta element started");
- assertEquals(
- writer, writer.closeDocument(), "XmlWriters should always
return themselves");
- assertEquals("<alpha><beta name='value'/><beta
name='value'><gamma/></beta></alpha>", out.toString(), "Beta element started");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+
writer.startElement("alpha").startElement("beta").attribute("name",
"value").closeElement()
+ .startElement("beta")
+ .attribute("name", "value")
+ .startElement("gamma").closeDocument();
+ assertThat(out).hasToString("<alpha><beta name='value'/><beta
name='value'><gamma/></beta></alpha>");
+ }
}
@Test
void writeProlog() throws Exception {
- assertEquals(
- writer, writer.startDocument(), "XmlWriters should always
return themselves");
- assertEquals("<?xml version='1.0'?>", out.toString(), "Prolog
written");
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startDocument();
+ assertThat(out).hasToString("<?xml version='1.0'?>");
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
+ }
}
@Test
void writeAfterElement() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- try {
- writer.startDocument();
- fail("Operation not allowed once an element has been written");
- } catch (OperationNotAllowedException e) {
- // Operation not allowed once an element has been written
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha");
+
assertThatThrownBy(writer::startDocument).hasMessageContaining("Document
already started")
+ .isInstanceOf(OperationNotAllowedException.class);
}
}
@Test
- void writePrologTwo() throws Exception {
- assertEquals(
- writer, writer.startDocument(), "XmlWriters should always
return themselves");
- assertEquals("<?xml version='1.0'?>", out.toString(), "Prolog
written");
- try {
+ void writePrologTwice() throws Exception {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
writer.startDocument();
- fail("Operation not allow once a prolog has been written");
- } catch (OperationNotAllowedException e) {
- // Operation not allowed once a prolog has been written
+ assertThat(out).hasToString("<?xml version='1.0'?>");
+
assertThatThrownBy(writer::startDocument).hasMessageContaining("Only one prolog
allowed")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
}
}
@Test
void duplicateAttributes() throws Exception {
- assertEquals(
- writer, writer.openElement("alpha"), "XmlWriters should always
return themselves");
- assertEquals("<alpha", out.toString(), "Alpha element started");
- assertEquals(
- writer, writer.attribute("one", "1"), "XmlWriters should
always return themselves");
- assertEquals("<alpha one='1'", out.toString(), "Attribute written");
- assertEquals(
- writer, writer.openElement("beta"), "XmlWriters should always
return themselves");
- assertEquals("<alpha one='1'><beta", out.toString(), "Beta element
started");
- assertEquals(
- writer, writer.attribute("one", "1"), "XmlWriters should
always return themselves");
- assertEquals("<alpha one='1'><beta one='1'", out.toString(), "Beta
element started");
- try {
- writer.attribute("one", "2");
- fail("Each attribute may only be written once");
- } catch (InvalidXmlException e) {
- // Each attribute may only be written once
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startElement("alpha").attribute("one",
"1").startElement("beta").attribute("one", "1");
+ assertThat(out).hasToString("<alpha one='1'><beta one='1'");
+ assertThatThrownBy(() -> writer.attribute("one", "2"))
+ .hasMessageContaining("Each attribute can only be written
once")
+ .isInstanceOf(InvalidXmlException.class);
}
}
@Test
- void writeCDataBeforeElement() {
- assertThrows(OperationNotAllowedException.class, () ->
writer.startDocument().cdata("Just cdata").closeDocument());
+ void writeCDataBeforeElement() throws IOException {
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startDocument();
+ assertThatThrownBy(() -> writer.cdata("Just cdata"))
+ .hasMessageContaining("An element must be opened before
content can be written.")
+ .isInstanceOf(OperationNotAllowedException.class);
+ } catch (OperationNotAllowedException expected) {
+ assertThat(expected).hasMessageContaining("Close called before an
element has been opened.");
+ }
}
@Test
void writeCData() throws Exception {
- writer.startDocument().openElement("test").cdata("Just
cdata").closeDocument();
- assertEquals("<?xml version='1.0'?><test><![CDATA[ Just cdata
]]></test>", out.toString());
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startDocument().startElement("test").cdata("Just
cdata").closeDocument();
+ assertThat(out).hasToString("<?xml version='1.0'?><test><![CDATA[
Just cdata ]]></test>");
+ }
}
@Test
void writeCDataEmbeddedCData() throws Exception {
- writer.startDocument().openElement("test").cdata("Some <![CDATA[ cdata
]]> text").closeDocument();
- assertEquals("<?xml version='1.0'?><test><![CDATA[ Some \\u3C![CDATA[
cdata {rat:CDATA close} text ]]></test>", out.toString());
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ writer.startDocument().startElement("test").cdata("Some <![CDATA[
cdata ]]> text").closeDocument();
+ assertThat(out).hasToString("<?xml version='1.0'?><test><![CDATA[
Some \\u3C![CDATA[ cdata {rat:CDATA close} text ]]></test>");
+ }
}
@Test
void closeElementBeforeOpened() throws IOException {
- IXmlWriter underTest = writer.startDocument().openElement("test");
- assertThrows(NoSuchElementException.class, () ->
underTest.closeElement("missing"));
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+ XmlWriter underTest = writer.startDocument().startElement("test");
+ assertThatThrownBy(() -> underTest.closeElement("missing"))
+ .isInstanceOf(NoSuchElementException.class);
+ }
}
@Test
void closeElement() throws Exception {
-
writer.startDocument().openElement("root").openElement("hello").openElement("world").content("hello
world").closeElement("hello").openElement("test").closeDocument();
- assertEquals("<?xml version='1.0'?><root><hello><world>hello
world</world></hello><test/></root>", out.toString());
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+
writer.startDocument().startElement("root").startElement("hello").startElement("world").content("hello
world").closeElement("hello").startElement("test").closeDocument();
+ assertThat(out).hasToString("<?xml
version='1.0'?><root><hello><world>hello world</world></hello><test/></root>");
+ }
}
@Test
@@ -545,7 +481,10 @@ class XmlWriterTest {
"</base>");
byte[] rawDocument = "<?xml version='1.0'?><root><hello><world>hello
world</world></hello><test/></root>".getBytes(StandardCharsets.UTF_8);
Document document = XmlUtils.toDom(new
ByteArrayInputStream(rawDocument));
-
writer.startDocument().openElement("base").append(document).closeDocument();
- assertEquals(expected, out.toString());
+ StringWriter out = new StringWriter();
+ try (XmlWriter writer = new XmlWriter(out)) {
+
writer.startDocument().startElement("base").append(document).closeDocument();
+ }
+ assertThat(out).hasToString(expected);
}
}
diff --git
a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java
b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java
index c7e3cfcc..7f53c9a6 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java
@@ -46,7 +46,7 @@ import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
-import org.apache.rat.report.xml.writer.IXmlWriter;
+import org.apache.rat.report.xml.writer.XmlWriter;
import org.apache.rat.utils.DefaultLog;
import org.apache.rat.utils.StandardXmlFactory;
import org.w3c.dom.Document;
@@ -143,7 +143,7 @@ public final class XmlUtils {
return StandardXmlFactory.documentBuilder().parse(inputStream);
}
- public static void writeAttribute(final IXmlWriter writer, final String
name, final boolean booleanValue)
+ public static void writeAttribute(final XmlWriter writer, final String
name, final boolean booleanValue)
throws IOException {
final String value = Boolean.toString(booleanValue);
writer.attribute(name, value);
diff --git
a/apache-rat-tools/src/main/java/org/apache/rat/tools/xsd/XsdWriter.java
b/apache-rat-tools/src/main/java/org/apache/rat/tools/xsd/XsdWriter.java
index 56b97b02..ccbc583b 100644
--- a/apache-rat-tools/src/main/java/org/apache/rat/tools/xsd/XsdWriter.java
+++ b/apache-rat-tools/src/main/java/org/apache/rat/tools/xsd/XsdWriter.java
@@ -76,7 +76,7 @@ public class XsdWriter {
*/
public XsdWriter init() throws IOException {
writer.startDocument()
- .openElement("xs:schema")
+ .startElement("xs:schema")
.attribute("attributeFormDefault", "unqualified")
.attribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema");
return this;
@@ -111,7 +111,7 @@ public class XsdWriter {
* @throws IOException on error.
*/
public XsdWriter open(final Type type, final String... attributeMap)
throws IOException {
- writer.openElement(type.elementName);
+ writer.startElement(type.elementName);
writeAttributes(attributeMap);
return this;
}
@@ -124,7 +124,7 @@ public class XsdWriter {
* @throws IOException on error.
*/
public XsdWriter attribute(final String name, final String...
attributeMap) throws IOException {
- writer.openElement("xs:attribute").attribute("name", name);
+ writer.startElement("xs:attribute").attribute("name", name);
writeAttributes(attributeMap);
writer.closeElement();
return this;
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index cd8a80e5..33009c05 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -68,6 +68,9 @@ in order to be properly linked in site reports.
</release>
-->
<release version="1.0.0-SNAPSHOT" date="xxxx-yy-zz" description="Current
SNAPSHOT - release to be done">
+ <action issue="RAT-561" type="add" dev="claudenw">
+ Remove IXmlWriter and simplify RatReport XML writer implementations
while ensuring all resources are closed in tests.
+ </action>
<action issue="RAT-560" type="add" dev="claudenw">
Disallowed DOCTYPE declarations in the Xerces2 XML parser to mitigate
XXE attacks, and centralised XML parser initialisation within RAT.
</action>