This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/maven-xinclude-extension.git
The following commit(s) were added to refs/heads/main by this push: new cefb0c5 Upgrade to Maven 4.0.0-rc-1 (#16) cefb0c5 is described below commit cefb0c581a9752856e7a21bb119492530198a2e1 Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Tue Dec 10 23:13:28 2024 +0100 Upgrade to Maven 4.0.0-rc-1 (#16) --- .github/workflows/maven-verify.yml | 4 +- pom.xml | 84 +++- .../org/apache/maven/xinclude/StaxLocation.java | 76 +++ .../maven/xinclude/XIncludeModelXmlFactory.java | 5 +- src/main/mdo/reader-stax.vm | 74 +-- src/main/mdo/writer-stax.vm | 523 +++++++++++++++++++++ .../org/apache/maven/xinclude/ModelXmlTest.java | 3 +- 7 files changed, 718 insertions(+), 51 deletions(-) diff --git a/.github/workflows/maven-verify.yml b/.github/workflows/maven-verify.yml index 99811aa..96bece9 100644 --- a/.github/workflows/maven-verify.yml +++ b/.github/workflows/maven-verify.yml @@ -26,6 +26,6 @@ jobs: name: Verify uses: apache/maven-gh-actions-shared/.github/workflows/maven-verify.yml@v4 with: - ff-maven: "4.0.0-beta-4" # Maven version for fail-fast-build - maven-matrix: '[ "4.0.0-beta-4" ]' + ff-maven: "4.0.0-beta-5" # Maven version for fail-fast-build + maven-matrix: '[ "4.0.0-beta-5", "4.0.0-rc-1" ]' jdk-matrix: '[ "17", "21" ]' diff --git a/pom.xml b/pom.xml index be0776c..a4f2e01 100644 --- a/pom.xml +++ b/pom.xml @@ -33,16 +33,15 @@ under the License. <properties> <javaVersion>17</javaVersion> - <maven.version>4.0.0-beta-4</maven.version> - <junit.version>5.11.3</junit.version> + <maven.version>4.0.0-rc-1</maven.version> + + <versions.junit5>5.11.3</versions.junit5> + <version.maven-dependency-plugin>3.8.1</version.maven-dependency-plugin> + <version.maven-surefire-plugin>3.5.2</version.maven-surefire-plugin> + <version.maven-invoker-plugin>3.9.0</version.maven-invoker-plugin> </properties> <dependencies> - <dependency> - <groupId>com.fasterxml.woodstox</groupId> - <artifactId>woodstox-core</artifactId> - <version>7.1.0</version> - </dependency> <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-api-core</artifactId> @@ -57,24 +56,80 @@ under the License. </dependency> <dependency> <groupId>org.apache.maven</groupId> - <artifactId>maven-api-impl</artifactId> + <artifactId>maven-api-xml</artifactId> <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-model</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-api-meta</artifactId> + <version>${maven.version}</version> + <scope>provided</scope> + </dependency> + + <dependency> + <groupId>com.fasterxml.woodstox</groupId> + <artifactId>woodstox-core</artifactId> + <version>7.1.0</version> + </dependency> + <dependency> + <groupId>org.codehaus.woodstox</groupId> + <artifactId>stax2-api</artifactId> + <version>4.2.2</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-xml</artifactId> + <version>${maven.version}</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-impl</artifactId> + <version>${maven.version}</version> + <scope>test</scope> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> - <artifactId>junit-jupiter</artifactId> - <version>${junit.version}</version> + <artifactId>junit-jupiter-api</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-enforcer-plugin</artifactId> + <!-- Use the latest version of the plugin --> + <executions> + <execution> + <id>enforce-maven</id> + <goals> + <goal>enforce</goal> + </goals> + <configuration> + <rules> + <requireMavenVersion> + <version>[4.0.0-beta-5,)</version> + <!-- Specify the required Maven version --> + <message>You need Maven 4.0.0-beta-5 or higher to build this project.</message> + </requireMavenVersion> + </rules> + </configuration> + </execution> + </executions> + </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> - <version>3.8.1</version> + <version>${version.maven-dependency-plugin}</version> <executions> <execution> <id>copy-mdo</id> @@ -109,6 +164,7 @@ under the License. </models> <templates> <template>reader-stax.vm</template> + <template>writer-stax.vm</template> </templates> <params> <param>forcedIOModelVersion=4.0.0</param> @@ -133,10 +189,14 @@ under the License. <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-invoker-plugin</artifactId> - <version>3.9.0</version> + <version>${version.maven-invoker-plugin}</version> <configuration> <showErrors>true</showErrors> <cloneProjectsTo>${project.build.directory}/its</cloneProjectsTo> + <collectedProjects> + <project>entities-xinclude/pom.xml</project> + <project>entities-xinclude/child/pom.xml</project> + </collectedProjects> <cloneClean>true</cloneClean> <localRepositoryPath>${project.build.directory}/local-repo</localRepositoryPath> <settingsFile>src/it/settings.xml</settingsFile> diff --git a/src/main/java/org/apache/maven/xinclude/StaxLocation.java b/src/main/java/org/apache/maven/xinclude/StaxLocation.java new file mode 100644 index 0000000..90b08fe --- /dev/null +++ b/src/main/java/org/apache/maven/xinclude/StaxLocation.java @@ -0,0 +1,76 @@ +/* + * 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.maven.xinclude; + +import javax.xml.stream.XMLStreamException; + +import org.apache.maven.api.services.xml.Location; + +public class StaxLocation implements Location { + + private final javax.xml.stream.Location location; + + public static Location getLocation(Exception e) { + return toLocation(e instanceof XMLStreamException xe ? xe.getLocation() : null); + } + + public static Location toLocation(javax.xml.stream.Location location) { + return location != null ? new StaxLocation(location) : null; + } + + public static String getMessage(Exception e) { + String message = e.getMessage(); + if (e instanceof XMLStreamException xe && xe.getLocation() != null) { + int idx = message.indexOf("\nMessage: "); + if (idx >= 0) { + return message.substring(idx + "\nMessage: ".length()); + } + } + return message; + } + + public StaxLocation(javax.xml.stream.Location location) { + this.location = location; + } + + @Override + public int getLineNumber() { + return location.getLineNumber(); + } + + @Override + public int getColumnNumber() { + return location.getColumnNumber(); + } + + @Override + public int getCharacterOffset() { + return location.getCharacterOffset(); + } + + @Override + public String getPublicId() { + return location.getPublicId(); + } + + @Override + public String getSystemId() { + return location.getSystemId(); + } +} diff --git a/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java b/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java index 59051f3..62c355e 100644 --- a/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java +++ b/src/main/java/org/apache/maven/xinclude/XIncludeModelXmlFactory.java @@ -40,12 +40,11 @@ import org.apache.maven.api.services.xml.XmlReaderException; import org.apache.maven.api.services.xml.XmlReaderRequest; import org.apache.maven.api.services.xml.XmlWriterException; import org.apache.maven.api.services.xml.XmlWriterRequest; -import org.apache.maven.model.v4.MavenStaxWriter; import org.apache.maven.xinclude.stax.XInclude; import org.codehaus.stax2.io.Stax2FileSource; -import static org.apache.maven.internal.impl.StaxLocation.getLocation; -import static org.apache.maven.internal.impl.StaxLocation.getMessage; +import static org.apache.maven.xinclude.StaxLocation.getLocation; +import static org.apache.maven.xinclude.StaxLocation.getMessage; import static org.apache.maven.xinclude.Utils.nonNull; @Named diff --git a/src/main/mdo/reader-stax.vm b/src/main/mdo/reader-stax.vm index 6d777aa..c0c7cec 100644 --- a/src/main/mdo/reader-stax.vm +++ b/src/main/mdo/reader-stax.vm @@ -84,6 +84,7 @@ import javax.xml.transform.stream.StreamSource; import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI; import static javax.xml.XMLConstants.XML_NS_URI; +@SuppressWarnings("deprecation") @Generated public class ${className} { @@ -356,15 +357,39 @@ public class ${className} { private boolean addLocationInformation = true; #end - private ContentTransformer contentTransformer = (s, f) -> s; - - private XMLResolver xmlResolver; + private final ContentTransformer contentTransformer; + private final XMLResolver xmlResolver; public ${className}() { + this(null, null); } public ${className}(ContentTransformer contentTransformer) { + this(contentTransformer, null); + } + + public ${className}(XMLResolver xmlResolver) { + this(null, xmlResolver); + } + + public ${className}(ContentTransformer contentTransformer, XMLResolver xmlResolver) { this.contentTransformer = contentTransformer; + this.xmlResolver = xmlResolver; + } + + /** + * Returns the {@link XMLInputFactory} used by this reader. + * + * @return the {@link XMLInputFactory} used by this reader. + */ + public XMLInputFactory getXMLInputFactory(boolean strict) { + XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory(); + factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); + factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true); + factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, false); + factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, xmlResolver); + factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, getUndeclaredXmlResolver(strict)); + return factory; } /** @@ -405,22 +430,6 @@ public class ${className} { } //-- void setAddLocationInformation(boolean) #end - public ContentTransformer getContentTransformer() { - return contentTransformer; - } - - public void setContentTransformer(ContentTransformer contentTransformer) { - this.contentTransformer = contentTransformer; - } - - public XMLResolver getXmlResolver() { - return xmlResolver; - } - - public void setXmlResolver(XMLResolver xmlResolver) { - this.xmlResolver = xmlResolver; - } - public ${root.name} read(Reader reader) throws XMLStreamException { #if ( $locationTracking ) return read(reader, true, null); @@ -441,17 +450,12 @@ public class ${className} { #else public ${root.name} read(Reader reader, boolean strict) throws XMLStreamException { #end - XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory(); - factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); - factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true); - factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, false); - factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, xmlResolver); - factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, getUndeclaredXmlResolver(strict)); #if ( $locationTracking ) StreamSource streamSource = new StreamSource(reader, source != null ? source.getLocation() : null); #else StreamSource streamSource = new StreamSource(reader); #end + XMLInputFactory factory = getXMLInputFactory(strict); XMLStreamReader parser = factory.createXMLStreamReader(streamSource); #if ( $locationTracking ) return read(parser, strict, source); @@ -482,17 +486,12 @@ public class ${className} { #else public ${root.name} read(InputStream in, boolean strict) throws XMLStreamException { #end - XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory(); - factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, true); - factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, true); - factory.setProperty(WstxInputProperties.P_TREAT_CHAR_REFS_AS_ENTS, false); - factory.setProperty(WstxInputProperties.P_ENTITY_RESOLVER, xmlResolver); - factory.setProperty(WstxInputProperties.P_UNDECLARED_ENTITY_RESOLVER, getUndeclaredXmlResolver(strict)); #if ( $locationTracking ) StreamSource streamSource = new StreamSource(in, source != null ? source.getLocation() : null); #else StreamSource streamSource = new StreamSource(in); #end + XMLInputFactory factory = getXMLInputFactory(strict); XMLStreamReader parser = factory.createXMLStreamReader(streamSource); #if ( $locationTracking ) return read(parser, strict, source); @@ -579,6 +578,9 @@ public class ${className} { #foreach ( $field in $allFields ) #if ( $Helper.xmlFieldMetadata( $field ).attribute ) #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) } else if ("$fieldTagName".equals(name)) { #if ( $locationTracking ) @@ -590,6 +592,8 @@ public class ${className} { ${classLcapName}.${field.name}(interpolatedTrimmed(value, "$fieldTagName")); #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) ${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(value, "$fieldTagName"), "$fieldTagName", parser, ${field.defaultValue})); + #elseif ( $field.type == "int" || $field.type == "Integer" ) + ${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(value, "$fieldTagName"), "$fieldTagName", parser, strict, ${field.defaultValue})); #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end @@ -690,7 +694,13 @@ public class ${className} { #end break; #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + #if ( $locationTracking ) + ${field.name}.add(parse${field.toClass.name}(parser, strict, source)); + #elseif ( $needXmlContext ) + ${field.name}.add(parse${field.toClass.name}(parser, strict, context)); + #else ${field.name}.add(parse${field.toClass.name}(parser, strict)); + #end break; #elseif ( $field.to && $field.multiplicity == "*" ) List<$field.to> ${field.name} = new ArrayList<>(); @@ -869,7 +879,7 @@ public class ${className} { * @return String */ private String interpolatedTrimmed(String value, String context) { - return getTrimmedValue(contentTransformer.transform(value, context)); + return getTrimmedValue(contentTransformer != null ? contentTransformer.transform(value, context) : value); } //-- String interpolatedTrimmed(String, String) /** diff --git a/src/main/mdo/writer-stax.vm b/src/main/mdo/writer-stax.vm new file mode 100644 index 0000000..6e9c8c6 --- /dev/null +++ b/src/main/mdo/writer-stax.vm @@ -0,0 +1,523 @@ +#* + 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. +*# +#parse ( "common.vm" ) +# +#set ( $package = "${packageToolV4}" ) +#set ( $className = "${model.name}StaxWriter" ) +# +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#set ( $xmlModelMetadata = $model.getMetadata( "org.codehaus.modello.plugins.xml.metadata.XmlModelMetadata" ) ) +#if ( $forcedIOModelVersion ) + #set ( $Version = $model.class.classLoader.loadClass( "org.codehaus.modello.model.Version" ) ) + #set ( $ioVersion = $Version.getConstructor( $package.class ).newInstance( $forcedIOModelVersion ) ) +#else + #set ( $ioVersion = $version ) +#end +#set ( $namespace = $xmlModelMetadata.getNamespace($ioVersion) ) +#set ( $schemaLocation = $xmlModelMetadata.getSchemaLocation($ioVersion) ) +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. +// ============================================================== +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import java.util.function.Function; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamWriter; +import org.apache.maven.api.annotations.Generated; +#if ( $locationTracking ) +import ${packageModelV4}.InputLocation; +import ${packageModelV4}.InputLocationTracker; +#end +import org.apache.maven.api.xml.XmlNode; +import org.apache.maven.internal.xml.XmlNodeBuilder; +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputLocation" ) +import ${packageModelV4}.${class.name}; + #end +#end +import org.codehaus.stax2.util.StreamWriterDelegate; + +import static javax.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI; + +@SuppressWarnings("deprecation") +@Generated +public class ${className} { + + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Default namespace. + */ + private static final String NAMESPACE = "${namespace}"; + + /** + * Default schemaLocation. + */ + private static final String SCHEMA_LOCATION = "${schemaLocation}"; + + /** + * Field namespace. + */ + private String namespace = NAMESPACE; + + /** + * Field schemaLocation. + */ + private String schemaLocation = SCHEMA_LOCATION; + + /** + * Field fileComment. + */ + private String fileComment = null; + +#if ( $locationTracking ) + private boolean addLocationInformation = true; + + /** + * Field stringFormatter. + */ + protected Function<InputLocation, String> stringFormatter; + +#end + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setNamespace. + * + * @param namespace the namespace to use. + */ + public void setNamespace(String namespace) { + this.namespace = Objects.requireNonNull(namespace); + } //-- void setNamespace(String) + + /** + * Method setSchemaLocation. + * + * @param schemaLocation the schema location to use. + */ + public void setSchemaLocation(String schemaLocation) { + this.schemaLocation = Objects.requireNonNull(schemaLocation); + } //-- void setSchemaLocation(String) + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment(String fileComment) { + this.fileComment = fileComment; + } //-- void setFileComment(String) + +#if ( $locationTracking ) + /** + * Method setAddLocationInformation. + */ + public void setAddLocationInformation(boolean addLocationInformation) { + this.addLocationInformation = addLocationInformation; + } //-- void setAddLocationInformation(String) + + /** + * Method setStringFormatter. + * + * @param stringFormatter + */ + public void setStringFormatter(Function<InputLocation, String> stringFormatter) { + this.stringFormatter = stringFormatter; + } //-- void setStringFormatter(Function<InputLocation, String>) + +#end + /** + * Method write. + * + * @param writer a writer object + * @param ${rootLcapName} a ${root.name} object + * @throws IOException IOException if any + */ + public void write(Writer writer, ${root.name} ${rootLcapName}) throws IOException, XMLStreamException { + XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory(); + factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false); + factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true); + factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true); + XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(writer)); + serializer.writeStartDocument(${rootLcapName}.getModelEncoding(), null); + write${root.name}("$rootTag", ${rootLcapName}, serializer); + serializer.writeEndDocument(); + } //-- void write(Writer, ${root.name}) + + /** + * Method write. + * + * @param stream a stream object + * @param ${rootLcapName} a ${root.name} object + * @throws IOException IOException if any + */ + public void write(OutputStream stream, ${root.name} ${rootLcapName}) throws IOException, XMLStreamException { + XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory(); + factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false); + factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true); + factory.setProperty(com.ctc.wstx.api.WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true); + XMLStreamWriter serializer = new IndentingXMLStreamWriter(factory.createXMLStreamWriter(stream, ${rootLcapName}.getModelEncoding())); + serializer.writeStartDocument(${rootLcapName}.getModelEncoding(), null); + write${root.name}("$rootTag", ${rootLcapName}, serializer); + serializer.writeEndDocument(); + } //-- void write(OutputStream, ${root.name}) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}(String tagName, ${classUcapName} ${classLcapName}, XMLStreamWriter serializer) + throws IOException, XMLStreamException { + if (${classLcapName} != null) { + #if ( $class == $root ) + if (this.fileComment != null) { + serializer.writeCharacters("\n"); + serializer.writeComment(this.fileComment); + serializer.writeCharacters("\n"); + } + serializer.writeStartElement("", tagName, namespace); + serializer.writeNamespace("", namespace); + serializer.writeNamespace("xsi", W3C_XML_SCHEMA_INSTANCE_NS_URI); + serializer.writeAttribute(W3C_XML_SCHEMA_INSTANCE_NS_URI, "schemaLocation", namespace + " " + schemaLocation); + #else + serializer.writeStartElement(namespace, tagName); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).format ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr("$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer); + #elseif ( $field.type == "boolean" ) + #set ( $def = ${field.defaultValue} ) + #if ( ${def} == "true" ) + writeAttr("$fieldTagName", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer); + #else + writeAttr("$fieldTagName", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer); + #end + #elseif ( $field.type == "int" || $field.type == "Integer" ) + writeAttr("$fieldTagName", Integer.toString(${classLcapName}.get${fieldCapName}()), serializer); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient + && ! $Helper.xmlFieldMetadata( $field ).format ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $locationTracking ) + #set ( $loctrac = ", ${classLcapName}" ) + #set ( $loctracnull = ", null" ) + #else + #set ( $loctrac = "" ) + #set ( $loctracnull = "" ) + #end + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag("$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer${loctrac}); + #else + writeTag("$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer${loctrac}); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag("$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer${loctrac}); + #else + writeTag("$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer${loctrac}); + #end + #elseif ( $field.type == "int" ) + writeTag("$fieldTagName", "${def}", Integer.toString(${classLcapName}.get${fieldCapName}()), serializer${loctrac}); + #elseif ( $field.type == "DOM" ) + writeDom(${classLcapName}.get${fieldCapName}(), serializer); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList("$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer${loctrac}, + t -> writeTag("$singularField", null, t, serializer${loctracnull})); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties("$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer${loctrac}); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}("$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList("$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer${loctrac}, + t -> write${field.to}("$singularField", t, serializer)); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.writeEndElement(); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter<T> { + public void write(T t) throws IOException, XMLStreamException; + } + +#if ( $locationTracking ) + private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, InputLocationTracker locationTracker, ElementWriter<T> writer) throws IOException, XMLStreamException { + writeList(tagName, false, list, serializer, locationTracker, writer); +#else + private <T> void writeList(String tagName, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException { + writeList(tagName, false, list, serializer, writer); +#end + } + +#if ( $locationTracking ) + private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, InputLocationTracker locationTracker, ElementWriter<T> writer) throws IOException, XMLStreamException { +#else + private <T> void writeList(String tagName, boolean flat, List<T> list, XMLStreamWriter serializer, ElementWriter<T> writer) throws IOException, XMLStreamException { +#end + if (list != null && !list.isEmpty()) { + if (!flat) { + serializer.writeStartElement(namespace, tagName); + } + int index = 0; +#if ( $locationTracking ) + InputLocation location = locationTracker != null ? locationTracker.getLocation(tagName) : null; +#end + for (T t : list) { + writer.write(t); +#if ( $locationTracking ) + writeLocationTracking(location, Integer.valueOf(index++), serializer); +#end + } + if (!flat) { + serializer.writeEndElement(); + } + } + } + +#if ( $locationTracking ) + private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer, InputLocationTracker locationTracker) throws IOException, XMLStreamException { +#else + private <T> void writeProperties(String tagName, Map<String, String> props, XMLStreamWriter serializer) throws IOException, XMLStreamException { +#end + if (props != null && !props.isEmpty()) { + serializer.writeStartElement(namespace, tagName); +#if ( $locationTracking ) + InputLocation location = locationTracker != null ? locationTracker.getLocation(tagName) : null; +#end + for (Map.Entry<String, String> entry : props.entrySet()) { + String key = entry.getKey(); +#if ( $locationTracking ) + writeTag(key, null, entry.getValue(), serializer, null); + writeLocationTracking(location, key, serializer); +#else + writeTag(key, null, entry.getValue(), serializer); +#end + } + serializer.writeEndElement(); + } + } + + private void writeDom(XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException { + if (dom != null) { + serializer.writeStartElement(namespace, dom.getName()); + for (Map.Entry<String, String> attr : dom.getAttributes().entrySet()) { + if (attr.getKey().startsWith("xml:")) { + serializer.writeAttribute("http://www.w3.org/XML/1998/namespace", + attr.getKey().substring(4), attr.getValue()); + } else { + serializer.writeAttribute(attr.getKey(), attr.getValue()); + } + } + for (XmlNode child : dom.getChildren()) { + writeDom(child, serializer); + } + String value = dom.getValue(); + if (value != null) { + serializer.writeCharacters(value); + } + serializer.writeEndElement(); +#if ( $locationTracking ) + if (addLocationInformation && dom.getInputLocation() instanceof InputLocation && dom.getChildren().isEmpty()) { + serializer.writeComment(toString((InputLocation) dom.getInputLocation())); + } +#end + } + } + +#if ( $locationTracking ) + private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer, InputLocationTracker locationTracker) throws IOException, XMLStreamException { +#else + private void writeTag(String tagName, String defaultValue, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException { +#end + if (value != null && !Objects.equals(defaultValue, value)) { + serializer.writeStartElement(namespace, tagName); + serializer.writeCharacters(value); + serializer.writeEndElement(); +#if ( $locationTracking ) + writeLocationTracking(locationTracker, tagName, serializer); +#end + } + } + + private void writeAttr(String attrName, String value, XMLStreamWriter serializer) throws IOException, XMLStreamException { + if (value != null) { + serializer.writeAttribute(attrName, value); + } + } +#if ( $locationTracking ) + + /** + * Method writeLocationTracking. + * + * @param locationTracker + * @param serializer + * @param key + * @throws IOException + */ + protected void writeLocationTracking(InputLocationTracker locationTracker, Object key, XMLStreamWriter serializer) throws IOException, XMLStreamException { + if (addLocationInformation) { + InputLocation location = (locationTracker == null) ? null : locationTracker.getLocation(key); + if (location != null) { + serializer.writeComment(toString(location)); + } + } + } //-- void writeLocationTracking(InputLocationTracker, Object, XMLStreamWriter) + + /** + * Method toString. + * + * @param location + * @return String + */ + protected String toString(InputLocation location) { + if (stringFormatter != null) { + return stringFormatter.apply(location); + } + if (location.getSource() != null) { + return ' ' + location.getSource().toString() + ':' + location.getLineNumber() + ' '; + } else { + return " " + location.getLineNumber() + " "; + } + } //-- String toString(InputLocation) +#end + + static class IndentingXMLStreamWriter extends StreamWriterDelegate { + + int depth = 0; + boolean hasChildren = false; + + public IndentingXMLStreamWriter(XMLStreamWriter parent) { + super(parent); + } + + @Override + public void writeEmptyElement(String localName) throws XMLStreamException { + indent(); + super.writeEmptyElement(localName); + hasChildren = true; + } + + @Override + public void writeEmptyElement(String namespaceURI, String localName) throws XMLStreamException { + indent(); + super.writeEmptyElement(namespaceURI, localName); + hasChildren = true; + } + + @Override + public void writeEmptyElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { + indent(); + super.writeEmptyElement(prefix, localName, namespaceURI); + hasChildren = true; + } + + @Override + public void writeStartElement(String localName) throws XMLStreamException { + indent(); + super.writeStartElement(localName); + depth++; + hasChildren = false; + } + + @Override + public void writeStartElement(String namespaceURI, String localName) throws XMLStreamException { + indent(); + super.writeStartElement(namespaceURI, localName); + depth++; + hasChildren = false; + } + + @Override + public void writeStartElement(String prefix, String localName, String namespaceURI) throws XMLStreamException { + indent(); + super.writeStartElement(prefix, localName, namespaceURI); + depth++; + hasChildren = false; + } + + @Override + public void writeEndElement() throws XMLStreamException { + depth--; + if (hasChildren) { + indent(); + } + super.writeEndElement(); + hasChildren = true; + } + + private void indent() throws XMLStreamException { + super.writeCharacters("\n"); + for (int i = 0; i < depth; i++) { + super.writeCharacters(" "); + } + } + } +} diff --git a/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java b/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java index 196195a..f88d1d3 100644 --- a/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java +++ b/src/test/java/org/apache/maven/xinclude/ModelXmlTest.java @@ -59,8 +59,7 @@ class ModelXmlTest { + " <version>1.0-m7-SNAPSHOT</version>\n" + " &desc;\n" + "</project>\n"; - MavenStaxReader staxReader = new MavenStaxReader(); - staxReader.setXmlResolver((publicID, systemID, baseURI, namespace) -> { + MavenStaxReader staxReader = new MavenStaxReader((publicID, systemID, baseURI, namespace) -> { if ("file:desc.xml".equals(systemID)) { return "<?xml version='1.0' encoding='UTF-8'?><description>foo</description>"; }