[MNG-7830] Switch from plexus-xml to stax / woodstox (#1185)

This commit is contained in:
Guillaume Nodet 2023-06-29 12:03:50 +02:00 committed by GitHub
parent 00e1793550
commit e39142b77a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
88 changed files with 3036 additions and 1105 deletions

View File

@ -0,0 +1,3 @@
Copyright (c) 2008 FasterXML LLC info@fasterxml.com
This source code is licensed under standard BSD license, which is compatible with all Free and Open Software (OSS) licenses.

View File

@ -23,7 +23,7 @@
import java.nio.file.Files; import java.nio.file.Files;
import org.apache.maven.api.settings.InputSource; import org.apache.maven.api.settings.InputSource;
import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.apache.maven.settings.v4.SettingsStaxReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@ -43,7 +43,7 @@ void testValidGlobalSettings() throws Exception {
assertTrue(globalSettingsFile.isFile(), globalSettingsFile.getAbsolutePath()); assertTrue(globalSettingsFile.isFile(), globalSettingsFile.getAbsolutePath());
try (InputStream is = Files.newInputStream(globalSettingsFile.toPath())) { try (InputStream is = Files.newInputStream(globalSettingsFile.toPath())) {
new SettingsXpp3ReaderEx().read(is, true, new InputSource(globalSettingsFile.getAbsolutePath())); new SettingsStaxReader().read(is, true, new InputSource(globalSettingsFile.getAbsolutePath()));
} }
} }
} }

View File

@ -147,6 +147,11 @@ under the License.
<artifactId>maven-slf4j-wrapper</artifactId> <artifactId>maven-slf4j-wrapper</artifactId>
<version>${project.version}</version> <version>${project.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-xml-impl</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>

View File

@ -18,20 +18,20 @@
*/ */
package org.apache.maven.artifact.repository.metadata; package org.apache.maven.artifact.repository.metadata;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.InputStream;
import java.io.Writer; import java.io.OutputStream;
import java.nio.file.Files;
import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.metadata.ArtifactMetadata; import org.apache.maven.artifact.metadata.ArtifactMetadata;
import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxWriter;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Shared methods of the repository metadata handling. * Shared methods of the repository metadata handling.
@ -59,15 +59,13 @@ public void storeInLocalRepository(ArtifactRepository localRepository, ArtifactR
throws RepositoryMetadataStoreException { throws RepositoryMetadataStoreException {
try { try {
updateRepositoryMetadata(localRepository, remoteRepository); updateRepositoryMetadata(localRepository, remoteRepository);
} catch (IOException | XmlPullParserException e) { } catch (IOException | XMLStreamException e) {
throw new RepositoryMetadataStoreException("Error updating group repository metadata", e); throw new RepositoryMetadataStoreException("Error updating group repository metadata", e);
} }
} }
protected void updateRepositoryMetadata(ArtifactRepository localRepository, ArtifactRepository remoteRepository) protected void updateRepositoryMetadata(ArtifactRepository localRepository, ArtifactRepository remoteRepository)
throws IOException, XmlPullParserException { throws IOException, XMLStreamException {
MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
Metadata metadata = null; Metadata metadata = null;
File metadataFile = new File( File metadataFile = new File(
@ -85,8 +83,8 @@ protected void updateRepositoryMetadata(ArtifactRepository localRepository, Arti
// to delete on exit // to delete on exit
} }
} else if (metadataFile.exists()) { } else if (metadataFile.exists()) {
try (Reader reader = ReaderFactory.newXmlReader(metadataFile)) { try (InputStream input = Files.newInputStream(metadataFile.toPath())) {
metadata = mappingReader.read(reader, false); metadata = new Metadata(new MetadataStaxReader().read(input, false));
} }
} }
@ -110,10 +108,9 @@ protected void updateRepositoryMetadata(ArtifactRepository localRepository, Arti
if (changed || !metadataFile.exists()) { if (changed || !metadataFile.exists()) {
metadataFile.getParentFile().mkdirs(); metadataFile.getParentFile().mkdirs();
try (Writer writer = WriterFactory.newXmlWriter(metadataFile)) { try (OutputStream output = Files.newOutputStream(metadataFile.toPath())) {
MetadataXpp3Writer mappingWriter = new MetadataXpp3Writer(); MetadataStaxWriter mappingWriter = new MetadataStaxWriter();
mappingWriter.write(output, metadata.getDelegate());
mappingWriter.write(writer, metadata);
} }
} else { } else {
metadataFile.setLastModified(System.currentTimeMillis()); metadataFile.setLastModified(System.currentTimeMillis());

View File

@ -21,6 +21,7 @@
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -38,14 +39,13 @@
import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy;
import org.apache.maven.artifact.repository.DefaultRepositoryRequest; import org.apache.maven.artifact.repository.DefaultRepositoryRequest;
import org.apache.maven.artifact.repository.RepositoryRequest; import org.apache.maven.artifact.repository.RepositoryRequest;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxWriter;
import org.apache.maven.repository.legacy.UpdateCheckManager; import org.apache.maven.repository.legacy.UpdateCheckManager;
import org.apache.maven.repository.legacy.WagonManager; import org.apache.maven.repository.legacy.WagonManager;
import org.apache.maven.wagon.ResourceDoesNotExistException; import org.apache.maven.wagon.ResourceDoesNotExistException;
import org.apache.maven.wagon.TransferFailedException; import org.apache.maven.wagon.TransferFailedException;
import org.codehaus.plexus.logging.AbstractLogEnabled; import org.codehaus.plexus.logging.AbstractLogEnabled;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* @author Jason van Zyl * @author Jason van Zyl
@ -270,13 +270,11 @@ private boolean loadMetadata(
*/ */
protected Metadata readMetadata(File mappingFile) throws RepositoryMetadataReadException { protected Metadata readMetadata(File mappingFile) throws RepositoryMetadataReadException {
MetadataXpp3Reader mappingReader = new MetadataXpp3Reader();
try (InputStream in = Files.newInputStream(mappingFile.toPath())) { try (InputStream in = Files.newInputStream(mappingFile.toPath())) {
Metadata result = mappingReader.read(in, false); return new Metadata(new MetadataStaxReader().read(in, false));
return result;
} catch (FileNotFoundException e) { } catch (FileNotFoundException e) {
throw new RepositoryMetadataReadException("Cannot read metadata from '" + mappingFile + "'", e); throw new RepositoryMetadataReadException("Cannot read metadata from '" + mappingFile + "'", e);
} catch (IOException | XmlPullParserException e) { } catch (IOException | XMLStreamException e) {
throw new RepositoryMetadataReadException( throw new RepositoryMetadataReadException(
"Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e); "Cannot read metadata from '" + mappingFile + "': " + e.getMessage(), e);
} }
@ -311,8 +309,8 @@ private void fixTimestamp(File metadataFile, Metadata metadata, Metadata referen
getLogger().debug("Repairing metadata in " + metadataFile); getLogger().debug("Repairing metadata in " + metadataFile);
try (OutputStream out = Files.newOutputStream(metadataFile.toPath())) { try (OutputStream out = Files.newOutputStream(metadataFile.toPath())) {
new MetadataXpp3Writer().write(out, metadata); new MetadataStaxWriter().write(out, metadata.getDelegate());
} catch (IOException e) { } catch (IOException | XMLStreamException e) {
String msg = "Could not write fixed metadata to " + metadataFile + ": " + e.getMessage(); String msg = "Could not write fixed metadata to " + metadataFile + ": " + e.getMessage();
if (getLogger().isDebugEnabled()) { if (getLogger().isDebugEnabled()) {
getLogger().warn(msg, e); getLogger().warn(msg, e);

View File

@ -19,6 +19,7 @@
package org.apache.maven.project.interpolation; package org.apache.maven.project.interpolation;
import javax.inject.Inject; import javax.inject.Inject;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -32,8 +33,8 @@
import java.util.Properties; import java.util.Properties;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader; import org.apache.maven.model.v4.MavenStaxReader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer; import org.apache.maven.model.v4.MavenStaxWriter;
import org.apache.maven.project.DefaultProjectBuilderConfiguration; import org.apache.maven.project.DefaultProjectBuilderConfiguration;
import org.apache.maven.project.ProjectBuilderConfiguration; import org.apache.maven.project.ProjectBuilderConfiguration;
import org.apache.maven.project.path.PathTranslator; import org.apache.maven.project.path.PathTranslator;
@ -52,7 +53,6 @@
import org.codehaus.plexus.logging.Logger; import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable; import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException; import org.codehaus.plexus.personality.plexus.lifecycle.phase.InitializationException;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Use a regular expression search to find and resolve expressions within the POM. * Use a regular expression search to find and resolve expressions within the POM.
@ -130,10 +130,10 @@ public Model interpolate(Model model, File projectDir, ProjectBuilderConfigurati
throws ModelInterpolationException { throws ModelInterpolationException {
StringWriter sWriter = new StringWriter(1024); StringWriter sWriter = new StringWriter(1024);
MavenXpp3Writer writer = new MavenXpp3Writer(); MavenStaxWriter writer = new MavenStaxWriter();
try { try {
writer.write(sWriter, model); writer.write(sWriter, model.getDelegate());
} catch (IOException e) { } catch (IOException | XMLStreamException e) {
throw new ModelInterpolationException("Cannot serialize project model for interpolation.", e); throw new ModelInterpolationException("Cannot serialize project model for interpolation.", e);
} }
@ -142,10 +142,10 @@ public Model interpolate(Model model, File projectDir, ProjectBuilderConfigurati
StringReader sReader = new StringReader(serializedModel); StringReader sReader = new StringReader(serializedModel);
MavenXpp3Reader modelReader = new MavenXpp3Reader(); MavenStaxReader modelReader = new MavenStaxReader();
try { try {
model = modelReader.read(sReader); model = new Model(modelReader.read(sReader));
} catch (IOException | XmlPullParserException e) { } catch (XMLStreamException e) {
throw new ModelInterpolationException( throw new ModelInterpolationException(
"Cannot read project model from interpolating filter of serialized version.", e); "Cannot read project model from interpolating filter of serialized version.", e);
} }

View File

@ -22,11 +22,11 @@
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.File; import java.io.File;
import java.io.Reader; import java.io.InputStream;
import java.nio.file.Files;
import org.apache.maven.toolchain.model.PersistedToolchains; import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.apache.maven.toolchain.v4.MavenToolchainsStaxReader;
import org.codehaus.plexus.util.ReaderFactory;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -44,8 +44,8 @@ public PersistedToolchains build(File userToolchainsFile) throws MisconfiguredTo
PersistedToolchains toolchains = null; PersistedToolchains toolchains = null;
if (userToolchainsFile != null && userToolchainsFile.isFile()) { if (userToolchainsFile != null && userToolchainsFile.isFile()) {
try (Reader in = ReaderFactory.newXmlReader(userToolchainsFile)) { try (InputStream in = Files.newInputStream(userToolchainsFile.toPath())) {
toolchains = new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in)); toolchains = new PersistedToolchains(new MavenToolchainsStaxReader().read(in));
} catch (Exception e) { } catch (Exception e) {
throw new MisconfiguredToolchainException( throw new MisconfiguredToolchainException(
"Cannot read toolchains file at " + userToolchainsFile.getAbsolutePath(), e); "Cannot read toolchains file at " + userToolchainsFile.getAbsolutePath(), e);

View File

@ -20,6 +20,7 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -29,9 +30,7 @@
import java.util.Objects; import java.util.Objects;
import org.apache.maven.artifact.repository.metadata.Metadata; import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader;
import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Handles deserialization of metadata from some kind of textual format like XML. * Handles deserialization of metadata from some kind of textual format like XML.
@ -52,9 +51,13 @@ public Metadata read(Reader input, Map<String, ?> options) throws IOException {
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) { try (Reader in = input) {
return new MetadataXpp3Reader().read(in, isStrict(options)); return new Metadata(new MetadataStaxReader().read(in, isStrict(options)));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new MetadataParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new MetadataParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }
@ -62,9 +65,13 @@ public Metadata read(InputStream input, Map<String, ?> options) throws IOExcepti
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) { try (InputStream in = input) {
return new MetadataXpp3Reader().read(in, isStrict(options)); return new Metadata(new MetadataStaxReader().read(in, isStrict(options)));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new MetadataParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new MetadataParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }

View File

@ -236,7 +236,7 @@ public DefaultRepositorySystemSession newRepositorySession(MavenExecutionRequest
authSelector.add(server.getId(), authBuilder.build()); authSelector.add(server.getId(), authBuilder.build());
if (server.getConfiguration() != null) { if (server.getConfiguration() != null) {
XmlNode dom = ((org.codehaus.plexus.util.xml.Xpp3Dom) server.getConfiguration()).getDom(); XmlNode dom = server.getDelegate().getConfiguration();
List<XmlNode> children = dom.getChildren().stream() List<XmlNode> children = dom.getChildren().stream()
.filter(c -> !"wagonProvider".equals(c.getName())) .filter(c -> !"wagonProvider".equals(c.getName()))
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -37,9 +37,8 @@
import org.apache.maven.api.services.xml.XmlReaderRequest; import org.apache.maven.api.services.xml.XmlReaderRequest;
import org.apache.maven.api.services.xml.XmlWriterException; import org.apache.maven.api.services.xml.XmlWriterException;
import org.apache.maven.api.services.xml.XmlWriterRequest; import org.apache.maven.api.services.xml.XmlWriterRequest;
import org.apache.maven.model.v4.MavenXpp3ReaderEx; import org.apache.maven.model.v4.MavenStaxReader;
import org.apache.maven.model.v4.MavenXpp3WriterEx; import org.apache.maven.model.v4.MavenStaxWriter;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import static org.apache.maven.internal.impl.Utils.nonNull; import static org.apache.maven.internal.impl.Utils.nonNull;
@ -61,16 +60,21 @@ public Model read(@Nonnull XmlReaderRequest request) throws XmlReaderException {
if (request.getModelId() != null || request.getLocation() != null) { if (request.getModelId() != null || request.getLocation() != null) {
source = new InputSource(request.getModelId(), request.getLocation()); source = new InputSource(request.getModelId(), request.getLocation());
} }
MavenXpp3ReaderEx xml = new MavenXpp3ReaderEx(); MavenStaxReader xml = new MavenStaxReader();
xml.setAddDefaultEntities(request.isAddDefaultEntities()); xml.setAddDefaultEntities(request.isAddDefaultEntities());
if (path != null) { if (inputStream != null) {
reader = new XmlStreamReader(path.toFile()); return xml.read(inputStream, request.isStrict(), source);
} else if (url != null) { } else if (reader != null) {
reader = new XmlStreamReader(url); return xml.read(reader, request.isStrict(), source);
} else if (inputStream != null) { } else if (path != null) {
reader = new XmlStreamReader(inputStream); try (InputStream is = Files.newInputStream(path)) {
return xml.read(is, request.isStrict(), source);
}
} else {
try (InputStream is = url.openStream()) {
return xml.read(is, request.isStrict(), source);
}
} }
return xml.read(reader, request.isStrict(), source);
} catch (Exception e) { } catch (Exception e) {
throw new XmlReaderException("Unable to read model", e); throw new XmlReaderException("Unable to read model", e);
} }
@ -88,12 +92,12 @@ public void write(XmlWriterRequest<Model> request) throws XmlWriterException {
} }
try { try {
if (writer != null) { if (writer != null) {
new MavenXpp3WriterEx().write(writer, content); new MavenStaxWriter().write(writer, content);
} else if (outputStream != null) { } else if (outputStream != null) {
new MavenXpp3WriterEx().write(outputStream, content); new MavenStaxWriter().write(outputStream, content);
} else { } else {
try (OutputStream os = Files.newOutputStream(path)) { try (OutputStream os = Files.newOutputStream(path)) {
new MavenXpp3WriterEx().write(outputStream, content); new MavenStaxWriter().write(outputStream, content);
} }
} }
} catch (Exception e) { } catch (Exception e) {

View File

@ -35,8 +35,8 @@
import org.apache.maven.api.services.xml.XmlWriterRequest; import org.apache.maven.api.services.xml.XmlWriterRequest;
import org.apache.maven.api.settings.InputSource; import org.apache.maven.api.settings.InputSource;
import org.apache.maven.api.settings.Settings; import org.apache.maven.api.settings.Settings;
import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.apache.maven.settings.v4.SettingsStaxReader;
import org.apache.maven.settings.v4.SettingsXpp3Writer; import org.apache.maven.settings.v4.SettingsStaxWriter;
@Named @Named
@Singleton @Singleton
@ -54,7 +54,7 @@ public Settings read(@Nonnull XmlReaderRequest request) throws XmlReaderExceptio
if (request.getModelId() != null || request.getLocation() != null) { if (request.getModelId() != null || request.getLocation() != null) {
source = new InputSource(request.getLocation()); source = new InputSource(request.getLocation());
} }
SettingsXpp3ReaderEx xml = new SettingsXpp3ReaderEx(); SettingsStaxReader xml = new SettingsStaxReader();
xml.setAddDefaultEntities(request.isAddDefaultEntities()); xml.setAddDefaultEntities(request.isAddDefaultEntities());
if (reader != null) { if (reader != null) {
return xml.read(reader, request.isStrict(), source); return xml.read(reader, request.isStrict(), source);
@ -77,9 +77,9 @@ public void write(XmlWriterRequest<Settings> request) throws XmlWriterException
} }
try { try {
if (writer != null) { if (writer != null) {
new SettingsXpp3Writer().write(writer, content); new SettingsStaxWriter().write(writer, content);
} else { } else {
new SettingsXpp3Writer().write(outputStream, content); new SettingsStaxWriter().write(outputStream, content);
} }
} catch (Exception e) { } catch (Exception e) {
throw new XmlWriterException("Unable to write settings", e); throw new XmlWriterException("Unable to write settings", e);

View File

@ -35,8 +35,8 @@
import org.apache.maven.api.services.xml.XmlWriterException; import org.apache.maven.api.services.xml.XmlWriterException;
import org.apache.maven.api.services.xml.XmlWriterRequest; import org.apache.maven.api.services.xml.XmlWriterRequest;
import org.apache.maven.api.toolchain.PersistedToolchains; import org.apache.maven.api.toolchain.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.apache.maven.toolchain.v4.MavenToolchainsStaxReader;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; import org.apache.maven.toolchain.v4.MavenToolchainsStaxWriter;
@Named @Named
@Singleton @Singleton
@ -54,7 +54,7 @@ public PersistedToolchains read(@Nonnull XmlReaderRequest request) throws XmlRea
if (request.getModelId() != null || request.getLocation() != null) { if (request.getModelId() != null || request.getLocation() != null) {
source = new InputSource(request.getModelId(), request.getLocation()); source = new InputSource(request.getModelId(), request.getLocation());
} }
MavenToolchainsXpp3Reader xml = new MavenToolchainsXpp3Reader(); MavenToolchainsStaxReader xml = new MavenToolchainsStaxReader();
xml.setAddDefaultEntities(request.isAddDefaultEntities()); xml.setAddDefaultEntities(request.isAddDefaultEntities());
if (reader != null) { if (reader != null) {
return xml.read(reader, request.isStrict()); return xml.read(reader, request.isStrict());
@ -77,9 +77,9 @@ public void write(XmlWriterRequest<PersistedToolchains> request) throws XmlWrite
} }
try { try {
if (writer != null) { if (writer != null) {
new MavenToolchainsXpp3Writer().write(writer, content); new MavenToolchainsStaxWriter().write(writer, content);
} else { } else {
new MavenToolchainsXpp3Writer().write(outputStream, content); new MavenToolchainsStaxWriter().write(outputStream, content);
} }
} catch (Exception e) { } catch (Exception e) {
throw new XmlWriterException("Unable to write toolchains", e); throw new XmlWriterException("Unable to write toolchains", e);

View File

@ -21,6 +21,8 @@
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
@ -38,15 +40,10 @@
import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory; import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
import org.apache.maven.model.building.TransformerContext; import org.apache.maven.model.building.TransformerContext;
import org.apache.maven.model.transform.RawToConsumerPomXMLFilterFactory; import org.apache.maven.model.transform.RawToConsumerPomXMLFilterFactory;
import org.apache.maven.model.transform.pull.XmlUtils; import org.apache.maven.model.transform.stax.XmlUtils;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.apache.maven.project.artifact.ProjectArtifact; import org.apache.maven.project.artifact.ProjectArtifact;
import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.stax2.XMLInputFactory2;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.artifact.DefaultArtifact;
@ -175,7 +172,7 @@ private static BiConsumer<Path, Path> transformer(RepositorySystemSession sessio
try (InputStream inputStream = transform(src, context)) { try (InputStream inputStream = transform(src, context)) {
Files.createDirectories(dest.getParent()); Files.createDirectories(dest.getParent());
Files.copy(inputStream, dest, StandardCopyOption.REPLACE_EXISTING); Files.copy(inputStream, dest, StandardCopyOption.REPLACE_EXISTING);
} catch (XmlPullParserException | IOException e) { } catch (XMLStreamException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
}; };
@ -185,13 +182,14 @@ private static BiConsumer<Path, Path> transformer(RepositorySystemSession sessio
/** /**
* The actual transformation: visible for testing. * The actual transformation: visible for testing.
*/ */
static InputStream transform(Path pomFile, TransformerContext context) throws IOException, XmlPullParserException { static InputStream transform(Path pomFile, TransformerContext context) throws IOException, XMLStreamException {
XmlStreamReader reader = ReaderFactory.newXmlReader(Files.newInputStream(pomFile)); try (InputStream input = Files.newInputStream(pomFile)) {
XmlPullParser parser = new MXParser(EntityReplacementMap.defaultEntityReplacementMap); XMLInputFactory2 factory = new com.ctc.wstx.stax.WstxInputFactory();
parser.setInput(reader); factory.configureForRoundTripping();
parser = new RawToConsumerPomXMLFilterFactory(new DefaultBuildPomXMLFilterFactory(context, true)) XMLStreamReader reader = factory.createXMLStreamReader(input);
.get(parser, pomFile); reader = new RawToConsumerPomXMLFilterFactory(new DefaultBuildPomXMLFilterFactory(context, true))
.get(reader, pomFile);
return XmlUtils.writeDocument(reader, parser); return XmlUtils.writeDocument(reader);
}
} }
} }

View File

@ -21,6 +21,7 @@
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
@ -60,7 +61,6 @@
import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.plugin.version.PluginVersionResolutionException;
import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice. * <strong>NOTE:</strong> This class is not part of any public api and can be changed or deleted without prior notice.
@ -290,8 +290,9 @@ private Map<String, List<MojoExecution>> calculateLifecycleMappings(
private void finalizeMojoConfiguration(MojoExecution mojoExecution) { private void finalizeMojoConfiguration(MojoExecution mojoExecution) {
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
org.codehaus.plexus.util.xml.Xpp3Dom config = mojoExecution.getConfiguration(); XmlNode executionConfiguration = mojoExecution.getConfiguration() != null
XmlNode executionConfiguration = config != null ? config.getDom() : null; ? mojoExecution.getConfiguration().getDom()
: null;
if (executionConfiguration == null) { if (executionConfiguration == null) {
executionConfiguration = new XmlNodeImpl("configuration"); executionConfiguration = new XmlNodeImpl("configuration");
} }
@ -462,7 +463,7 @@ private void injectLifecycleOverlay(
try { try {
lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle); lifecycleOverlay = pluginDescriptor.getLifecycleMapping(forkedLifecycle);
} catch (IOException | XmlPullParserException e) { } catch (IOException | XMLStreamException e) {
throw new PluginDescriptorParsingException(pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e); throw new PluginDescriptorParsingException(pluginDescriptor.getPlugin(), pluginDescriptor.getSource(), e);
} }

View File

@ -18,20 +18,21 @@
*/ */
package org.apache.maven.project; package org.apache.maven.project;
import java.io.BufferedInputStream; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.internal.xml.XmlNodeBuilder; import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Creates an extension descriptor from some XML stream. * Creates an extension descriptor from some XML stream.
@ -71,7 +72,7 @@ public ExtensionDescriptor build(File extensionJar) throws IOException {
File pluginXml = new File(extensionJar, getExtensionDescriptorLocation()); File pluginXml = new File(extensionJar, getExtensionDescriptorLocation());
if (pluginXml.canRead()) { if (pluginXml.canRead()) {
try (InputStream is = new BufferedInputStream(new FileInputStream(pluginXml))) { try (InputStream is = Files.newInputStream(pluginXml.toPath())) {
extensionDescriptor = build(is); extensionDescriptor = build(is);
} }
} }
@ -88,8 +89,9 @@ public ExtensionDescriptor build(InputStream is) throws IOException {
XmlNode dom; XmlNode dom;
try { try {
dom = XmlNodeBuilder.build(ReaderFactory.newXmlReader(is)); XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(is);
} catch (XmlPullParserException e) { dom = XmlNodeBuilder.build(reader);
} catch (XMLStreamException e) {
throw new IOException(e.getMessage(), e); throw new IOException(e.getMessage(), e);
} }

View File

@ -144,6 +144,9 @@ under the License.
<exportedArtifact>org.apache.maven:maven-api-toolchain</exportedArtifact> <exportedArtifact>org.apache.maven:maven-api-toolchain</exportedArtifact>
<exportedArtifact>org.apache.maven:maven-api-xml</exportedArtifact> <exportedArtifact>org.apache.maven:maven-api-xml</exportedArtifact>
<exportedArtifact>com.fasterxml:aalto-xml</exportedArtifact>
<exportedArtifact>org.codehaus.woodstox:stax2-api</exportedArtifact>
<exportedArtifact>classworlds:classworlds</exportedArtifact> <exportedArtifact>classworlds:classworlds</exportedArtifact>
<exportedArtifact>org.codehaus.plexus:plexus-classworlds</exportedArtifact> <exportedArtifact>org.codehaus.plexus:plexus-classworlds</exportedArtifact>
<exportedArtifact>org.codehaus.plexus:plexus-component-api</exportedArtifact> <exportedArtifact>org.codehaus.plexus:plexus-component-api</exportedArtifact>

View File

@ -18,8 +18,9 @@
*/ */
package org.apache.maven.configuration; package org.apache.maven.configuration;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -27,7 +28,6 @@
import org.apache.maven.configuration.internal.DefaultBeanConfigurator; import org.apache.maven.configuration.internal.DefaultBeanConfigurator;
import org.apache.maven.internal.xml.XmlNodeBuilder; import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -53,8 +53,10 @@ void tearDown() throws Exception {
private Xpp3Dom toConfig(String xml) { private Xpp3Dom toConfig(String xml) {
try { try {
return new Xpp3Dom(XmlNodeBuilder.build(new StringReader("<configuration>" + xml + "</configuration>"))); return new Xpp3Dom(XmlNodeBuilder.build(
} catch (XmlPullParserException | IOException e) { new StringReader("<configuration>" + xml + "</configuration>"),
(XmlNodeBuilder.InputLocationBuilderStax) null));
} catch (XMLStreamException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
} }

View File

@ -18,14 +18,14 @@
*/ */
package org.apache.maven.configuration; package org.apache.maven.configuration;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import org.apache.maven.configuration.internal.DefaultBeanConfigurator; import org.apache.maven.configuration.internal.DefaultBeanConfigurator;
import org.apache.maven.internal.xml.XmlNodeBuilder; import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -51,8 +51,10 @@ void tearDown() throws Exception {
private Xpp3Dom toConfig(String xml) { private Xpp3Dom toConfig(String xml) {
try { try {
return new Xpp3Dom(XmlNodeBuilder.build(new StringReader("<configuration>" + xml + "</configuration>"))); return new Xpp3Dom(XmlNodeBuilder.build(
} catch (XmlPullParserException | IOException e) { new StringReader("<configuration>" + xml + "</configuration>"),
(XmlNodeBuilder.InputLocationBuilderStax) null));
} catch (XMLStreamException e) {
throw new IllegalArgumentException(e); throw new IllegalArgumentException(e);
} }
} }

View File

@ -105,7 +105,7 @@ void testVersionlessManagedDependency() throws Exception {
e.getResults(), e.getResults(),
contains(projectBuildingResultWithProblemMessage( contains(projectBuildingResultWithProblemMessage(
"'dependencies.dependency.version' for org.apache.maven.its:a:jar is missing"))); "'dependencies.dependency.version' for org.apache.maven.its:a:jar is missing")));
assertThat(e.getResults(), contains(projectBuildingResultWithLocation(17, 9))); assertThat(e.getResults(), contains(projectBuildingResultWithLocation(5, 9)));
} }
@Test @Test
@ -234,7 +234,7 @@ void testReadInvalidPom() throws Exception {
// single project build entry point // single project build entry point
Exception ex = assertThrows(Exception.class, () -> projectBuilder.build(pomFile, configuration)); Exception ex = assertThrows(Exception.class, () -> projectBuilder.build(pomFile, configuration));
assertThat(ex.getMessage(), containsString("expected START_TAG or END_TAG not TEXT")); assertThat(ex.getMessage(), containsString("Received non-all-whitespace CHARACTERS or CDATA event"));
// multi projects build entry point // multi projects build entry point
ProjectBuildingException pex = assertThrows( ProjectBuildingException pex = assertThrows(
@ -245,7 +245,7 @@ void testReadInvalidPom() throws Exception {
assertThat(pex.getResults().get(0).getProblems().size(), greaterThan(0)); assertThat(pex.getResults().get(0).getProblems().size(), greaterThan(0));
assertThat( assertThat(
pex.getResults(), pex.getResults(),
contains(projectBuildingResultWithProblemMessage("expected START_TAG or END_TAG not TEXT"))); contains(projectBuildingResultWithProblemMessage("expected START_TAG or END_TAG not CHARACTERS")));
} }
@Test @Test

View File

@ -178,14 +178,22 @@ under the License.
<models> <models>
<model>src/main/mdo/core-extensions.mdo</model> <model>src/main/mdo/core-extensions.mdo</model>
</models> </models>
<templates>
<template>model.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
<params>
<param>packageModelV4=org.apache.maven.cli.internal.extension.model</param>
<param>packageToolV4=org.apache.maven.cli.internal.extension.io</param>
</params>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>modello</id> <id>modello</id>
<goals> <goals>
<goal>java</goal> <goal>velocity</goal>
<goal>xpp3-reader</goal>
<goal>xpp3-writer</goal>
</goals> </goals>
</execution> </execution>
</executions> </executions>

View File

@ -18,10 +18,10 @@
*/ */
package org.apache.maven.cli; package org.apache.maven.cli;
import java.io.BufferedInputStream; import javax.xml.stream.XMLStreamException;
import java.io.Console; import java.io.Console;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
@ -56,8 +56,8 @@
import org.apache.maven.cli.event.DefaultEventSpyContext; import org.apache.maven.cli.event.DefaultEventSpyContext;
import org.apache.maven.cli.event.ExecutionEventLogger; import org.apache.maven.cli.event.ExecutionEventLogger;
import org.apache.maven.cli.internal.BootstrapCoreExtensionManager; import org.apache.maven.cli.internal.BootstrapCoreExtensionManager;
import org.apache.maven.cli.internal.extension.io.CoreExtensionsStaxReader;
import org.apache.maven.cli.internal.extension.model.CoreExtension; import org.apache.maven.cli.internal.extension.model.CoreExtension;
import org.apache.maven.cli.internal.extension.model.io.xpp3.CoreExtensionsXpp3Reader;
import org.apache.maven.cli.jansi.JansiMessageBuilderFactory; import org.apache.maven.cli.jansi.JansiMessageBuilderFactory;
import org.apache.maven.cli.jansi.MessageUtils; import org.apache.maven.cli.jansi.MessageUtils;
import org.apache.maven.cli.logging.Slf4jConfiguration; import org.apache.maven.cli.logging.Slf4jConfiguration;
@ -108,7 +108,6 @@
import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.codehaus.plexus.interpolation.StringSearchInterpolator;
import org.codehaus.plexus.logging.LoggerManager; import org.codehaus.plexus.logging.LoggerManager;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.DefaultRepositoryCache; import org.eclipse.aether.DefaultRepositoryCache;
import org.eclipse.aether.transfer.TransferListener; import org.eclipse.aether.transfer.TransferListener;
import org.slf4j.ILoggerFactory; import org.slf4j.ILoggerFactory;
@ -795,12 +794,11 @@ protected void configure() {
} }
private List<CoreExtension> readCoreExtensionsDescriptor(File extensionsFile) private List<CoreExtension> readCoreExtensionsDescriptor(File extensionsFile)
throws IOException, XmlPullParserException { throws IOException, XMLStreamException {
CoreExtensionsXpp3Reader parser = new CoreExtensionsXpp3Reader(); CoreExtensionsStaxReader parser = new CoreExtensionsStaxReader();
try (InputStream is = new BufferedInputStream(new FileInputStream(extensionsFile))) { try (InputStream is = Files.newInputStream(extensionsFile.toPath())) {
return parser.read(is, true).getExtensions();
return parser.read(is).getExtensions();
} }
} }

View File

@ -20,12 +20,12 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory; import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* ModelSourceTransformer for the build pom * ModelSourceTransformer for the build pom
@ -37,7 +37,7 @@
@Singleton @Singleton
class BuildModelSourceTransformer implements ModelSourceTransformer { class BuildModelSourceTransformer implements ModelSourceTransformer {
@Override @Override
public XmlPullParser transform(XmlPullParser parser, Path pomFile, TransformerContext context) public XMLStreamReader transform(XMLStreamReader parser, Path pomFile, TransformerContext context)
throws IOException, TransformerException { throws IOException, TransformerException {
BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new DefaultBuildPomXMLFilterFactory(context, false); BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new DefaultBuildPomXMLFilterFactory(context, false);

View File

@ -18,11 +18,11 @@
*/ */
package org.apache.maven.model.building; package org.apache.maven.model.building;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Default ModelSourceTransformer, provides pomFile as inputStream and ignores the context * Default ModelSourceTransformer, provides pomFile as inputStream and ignores the context
* *
@ -32,7 +32,7 @@
public class DefaultModelSourceTransformer implements ModelSourceTransformer { public class DefaultModelSourceTransformer implements ModelSourceTransformer {
@Override @Override
public XmlPullParser transform(XmlPullParser parser, Path pomFile, TransformerContext context) public XMLStreamReader transform(XMLStreamReader parser, Path pomFile, TransformerContext context)
throws IOException, TransformerException { throws IOException, TransformerException {
return parser; return parser;
} }

View File

@ -18,15 +18,15 @@
*/ */
package org.apache.maven.model.building; package org.apache.maven.model.building;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* The ModelSourceTransformer is a way to transform the local pom while streaming the input. * The ModelSourceTransformer is a way to transform the local pom while streaming the input.
* *
* The {@link #transform(XmlPullParser, Path, TransformerContext)} method uses a Path on purpose, to ensure the * The {@link #transform(XMLStreamReader, Path, TransformerContext)} method uses a Path on purpose, to ensure the
* local pom is the original source. * local pom is the original source.
* *
* @author Robert Scholte * @author Robert Scholte
@ -42,6 +42,6 @@ public interface ModelSourceTransformer {
* @throws IOException if an I/O error occurs * @throws IOException if an I/O error occurs
* @throws TransformerException if the transformation fails * @throws TransformerException if the transformation fails
*/ */
XmlPullParser transform(XmlPullParser parser, Path pomFile, TransformerContext context) XMLStreamReader transform(XMLStreamReader parser, Path pomFile, TransformerContext context)
throws IOException, TransformerException; throws IOException, TransformerException;
} }

View File

@ -21,11 +21,16 @@
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.Location;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
@ -34,14 +39,7 @@
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelSourceTransformer; import org.apache.maven.model.building.ModelSourceTransformer;
import org.apache.maven.model.building.TransformerContext; import org.apache.maven.model.building.TransformerContext;
import org.apache.maven.model.v4.MavenXpp3Reader; import org.apache.maven.model.v4.MavenStaxReader;
import org.apache.maven.model.v4.MavenXpp3ReaderEx;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Handles deserialization of a model from some kind of textual format like XML. * Handles deserialization of a model from some kind of textual format like XML.
@ -62,7 +60,7 @@ public DefaultModelReader(ModelSourceTransformer transformer) {
public Model read(File input, Map<String, ?> options) throws IOException { public Model read(File input, Map<String, ?> options) throws IOException {
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (XmlStreamReader in = ReaderFactory.newXmlReader(input)) { try (InputStream in = Files.newInputStream(input.toPath())) {
Model model = read(in, input.toPath(), options); Model model = read(in, input.toPath(), options);
model.setPomFile(input); model.setPomFile(input);
@ -84,8 +82,8 @@ public Model read(Reader input, Map<String, ?> options) throws IOException {
public Model read(InputStream input, Map<String, ?> options) throws IOException { public Model read(InputStream input, Map<String, ?> options) throws IOException {
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (XmlStreamReader in = ReaderFactory.newXmlReader(input)) { try (InputStream in = input) {
return read(in, null, options); return read(input, null, options);
} }
} }
@ -104,13 +102,14 @@ private TransformerContext getTransformerContext(Map<String, ?> options) {
return (TransformerContext) value; return (TransformerContext) value;
} }
private Model read(Reader reader, Path pomFile, Map<String, ?> options) throws IOException { private Model read(InputStream input, Path pomFile, Map<String, ?> options) throws IOException {
try { try {
XmlPullParser parser = new MXParser(EntityReplacementMap.defaultEntityReplacementMap); XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
parser.setInput(reader); factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
XMLStreamReader parser = factory.createXMLStreamReader(input);
TransformerContext context = getTransformerContext(options); TransformerContext context = getTransformerContext(options);
XmlPullParser transformingParser = XMLStreamReader transformingParser =
context != null ? transformer.transform(parser, pomFile, context) : parser; context != null ? transformer.transform(parser, pomFile, context) : parser;
InputSource source = getSource(options); InputSource source = getSource(options);
@ -120,8 +119,13 @@ private Model read(Reader reader, Path pomFile, Map<String, ?> options) throws I
} else { } else {
return readModel(transformingParser, strict); return readModel(transformingParser, strict);
} }
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new ModelParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); Location location = e.getLocation();
throw new ModelParseException(
e.getMessage(),
location != null ? location.getLineNumber() : -1,
location != null ? location.getColumnNumber() : -1,
e);
} catch (IOException e) { } catch (IOException e) {
throw e; throw e;
} catch (Exception e) { } catch (Exception e) {
@ -129,14 +133,46 @@ private Model read(Reader reader, Path pomFile, Map<String, ?> options) throws I
} }
} }
private Model readModel(XmlPullParser parser, boolean strict) throws XmlPullParserException, IOException { private Model read(Reader reader, Path pomFile, Map<String, ?> options) throws IOException {
MavenXpp3Reader mr = new MavenXpp3Reader(); try {
return new Model(mr.read(parser, strict)); XMLInputFactory factory = new com.ctc.wstx.stax.WstxInputFactory();
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false);
XMLStreamReader parser = factory.createXMLStreamReader(reader);
TransformerContext context = getTransformerContext(options);
XMLStreamReader transformingParser =
context != null ? transformer.transform(parser, pomFile, context) : parser;
InputSource source = getSource(options);
boolean strict = isStrict(options);
if (source != null) {
return readModelEx(transformingParser, source, strict);
} else {
return readModel(transformingParser, strict);
}
} catch (XMLStreamException e) {
Location location = e.getLocation();
throw new ModelParseException(
e.getMessage(),
location != null ? location.getLineNumber() : -1,
location != null ? location.getColumnNumber() : -1,
e);
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IOException("Unable to transform pom", e);
}
} }
private Model readModelEx(XmlPullParser parser, InputSource source, boolean strict) private Model readModel(XMLStreamReader parser, boolean strict) throws XMLStreamException, IOException {
throws XmlPullParserException, IOException { MavenStaxReader mr = new MavenStaxReader();
MavenXpp3ReaderEx mr = new MavenXpp3ReaderEx(); mr.setAddLocationInformation(false);
return new Model(mr.read(parser, strict, null));
}
private Model readModelEx(XMLStreamReader parser, InputSource source, boolean strict)
throws XMLStreamException, IOException {
MavenStaxReader mr = new MavenStaxReader();
return new Model(mr.read( return new Model(mr.read(
parser, strict, new org.apache.maven.api.model.InputSource(source.getModelId(), source.getLocation()))); parser, strict, new org.apache.maven.api.model.InputSource(source.getModelId(), source.getLocation())));
} }

View File

@ -23,6 +23,7 @@
import java.util.List; import java.util.List;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.model.Build; import org.apache.maven.model.Build;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
@ -30,7 +31,6 @@
import org.apache.maven.model.PluginManagement; import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollector;
import org.codehaus.plexus.util.xml.Xpp3Dom;
/** /**
* Handles expansion of general build plugin configuration into individual executions. * Handles expansion of general build plugin configuration into individual executions.
@ -58,16 +58,13 @@ public void expandPluginConfiguration(Model model, ModelBuildingRequest request,
private void expand(List<Plugin> plugins) { private void expand(List<Plugin> plugins) {
for (Plugin plugin : plugins) { for (Plugin plugin : plugins) {
Xpp3Dom pluginConfiguration = (Xpp3Dom) plugin.getConfiguration(); XmlNode pluginConfiguration = plugin.getDelegate().getConfiguration();
if (pluginConfiguration != null) { if (pluginConfiguration != null) {
for (PluginExecution execution : plugin.getExecutions()) { for (PluginExecution execution : plugin.getExecutions()) {
Xpp3Dom executionConfiguration = (Xpp3Dom) execution.getConfiguration(); XmlNode executionConfiguration = execution.getDelegate().getConfiguration();
executionConfiguration = XmlNode.merge(executionConfiguration, pluginConfiguration);
executionConfiguration = execution.update(execution.getDelegate().withConfiguration(executionConfiguration));
Xpp3Dom.mergeXpp3Dom(executionConfiguration, new Xpp3Dom(pluginConfiguration));
execution.setConfiguration(executionConfiguration);
} }
} }
} }

View File

@ -21,13 +21,13 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.apache.maven.api.xml.XmlNode;
import org.apache.maven.model.Model; import org.apache.maven.model.Model;
import org.apache.maven.model.ReportPlugin; import org.apache.maven.model.ReportPlugin;
import org.apache.maven.model.ReportSet; import org.apache.maven.model.ReportSet;
import org.apache.maven.model.Reporting; import org.apache.maven.model.Reporting;
import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollector;
import org.codehaus.plexus.util.xml.Xpp3Dom;
/** /**
* Handles expansion of general report plugin configuration into individual report sets. * Handles expansion of general report plugin configuration into individual report sets.
@ -44,13 +44,13 @@ public void expandPluginConfiguration(Model model, ModelBuildingRequest request,
if (reporting != null) { if (reporting != null) {
for (ReportPlugin reportPlugin : reporting.getPlugins()) { for (ReportPlugin reportPlugin : reporting.getPlugins()) {
Xpp3Dom parentDom = (Xpp3Dom) reportPlugin.getConfiguration(); XmlNode parentDom = reportPlugin.getDelegate().getConfiguration();
if (parentDom != null) { if (parentDom != null) {
for (ReportSet execution : reportPlugin.getReportSets()) { for (ReportSet execution : reportPlugin.getReportSets()) {
Xpp3Dom childDom = (Xpp3Dom) execution.getConfiguration(); XmlNode childDom = execution.getDelegate().getConfiguration();
childDom = Xpp3Dom.mergeXpp3Dom(childDom, new Xpp3Dom(parentDom)); childDom = XmlNode.merge(childDom, parentDom);
execution.setConfiguration(childDom); execution.update(execution.getDelegate().withConfiguration(childDom));
} }
} }
} }

View File

@ -19,14 +19,15 @@
package org.apache.maven.model.root; package org.apache.maven.model.root;
import javax.inject.Named; import javax.inject.Named;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import org.codehaus.plexus.util.xml.pull.MXParser; import com.ctc.wstx.stax.WstxInputFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Named @Named
public class DefaultRootLocator implements RootLocator { public class DefaultRootLocator implements RootLocator {
@ -38,16 +39,16 @@ public boolean isRootDirectory(Path dir) {
// we're too early to use the modelProcessor ... // we're too early to use the modelProcessor ...
Path pom = dir.resolve("pom.xml"); Path pom = dir.resolve("pom.xml");
try (InputStream is = Files.newInputStream(pom)) { try (InputStream is = Files.newInputStream(pom)) {
MXParser parser = new MXParser(); XMLStreamReader parser = new WstxInputFactory().createXMLStreamReader(is);
parser.setInput(is, null); if (parser.nextTag() == XMLStreamReader.START_ELEMENT
if (parser.nextTag() == MXParser.START_TAG && parser.getName().equals("project")) { && parser.getLocalName().equals("project")) {
for (int i = 0; i < parser.getAttributeCount(); i++) { for (int i = 0; i < parser.getAttributeCount(); i++) {
if ("root".equals(parser.getAttributeName(i))) { if ("root".equals(parser.getAttributeLocalName(i))) {
return Boolean.parseBoolean(parser.getAttributeValue(i)); return Boolean.parseBoolean(parser.getAttributeValue(i));
} }
} }
} }
} catch (IOException | XmlPullParserException e) { } catch (IOException | XMLStreamException e) {
// The root locator can be used very early during the setup of Maven, // The root locator can be used very early during the setup of Maven,
// even before the arguments from the command line are parsed. Any exception // even before the arguments from the command line are parsed. Any exception
// that would happen here should cause the build to fail at a later stage // that would happen here should cause the build to fail at a later stage

View File

@ -18,6 +18,8 @@
*/ */
package org.apache.maven.model.inheritance; package org.apache.maven.model.inheritance;
import javax.xml.stream.XMLStreamReader;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
@ -30,7 +32,6 @@
import org.apache.maven.model.io.DefaultModelReader; import org.apache.maven.model.io.DefaultModelReader;
import org.apache.maven.model.io.DefaultModelWriter; import org.apache.maven.model.io.DefaultModelWriter;
import org.apache.maven.model.io.ModelWriter; import org.apache.maven.model.io.ModelWriter;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.xmlunit.matchers.CompareMatcher; import org.xmlunit.matchers.CompareMatcher;
@ -53,7 +54,7 @@ class DefaultInheritanceAssemblerTest {
void setUp() throws Exception { void setUp() throws Exception {
reader = new DefaultModelReader(new AbstractModelSourceTransformer() { reader = new DefaultModelReader(new AbstractModelSourceTransformer() {
@Override @Override
public XmlPullParser transform(XmlPullParser parser, Path pomFile, TransformerContext context) public XMLStreamReader transform(XMLStreamReader parser, Path pomFile, TransformerContext context)
throws IOException, TransformerException { throws IOException, TransformerException {
return null; return null;
} }

View File

@ -32,6 +32,14 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId> <artifactId>junit-jupiter-params</artifactId>

View File

@ -18,13 +18,13 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Base implementation for providing the BuildToRawPomXML. * Base implementation for providing the BuildToRawPomXML.
* *
@ -46,10 +46,10 @@ public BuildToRawPomXMLFilterFactory(boolean consume) {
* *
* @param projectFile will be used by ConsumerPomXMLFilter to get the right filter * @param projectFile will be used by ConsumerPomXMLFilter to get the right filter
*/ */
public final XmlPullParser get(XmlPullParser orgParser, Path projectFile) { public final XMLStreamReader get(XMLStreamReader orgParser, Path projectFile) {
// Ensure that xs:any elements aren't touched by next filters // Ensure that xs:any elements aren't touched by next filters
XmlPullParser parser = orgParser instanceof FastForwardFilter ? orgParser : new FastForwardFilter(orgParser); XMLStreamReader parser = orgParser instanceof FastForwardFilter ? orgParser : new FastForwardFilter(orgParser);
if (getDependencyKeyToVersionMapper() != null) { if (getDependencyKeyToVersionMapper() != null) {
parser = new ReactorDependencyXMLFilter(parser, getDependencyKeyToVersionMapper()); parser = new ReactorDependencyXMLFilter(parser, getDependencyKeyToVersionMapper());

View File

@ -18,11 +18,12 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.List; import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Resolves all ci-friendly properties occurrences between version-tags * Resolves all ci-friendly properties occurrences between version-tags
@ -36,8 +37,8 @@ class CiFriendlyXMLFilter extends NodeBufferingParser {
private Function<String, String> replaceChain = Function.identity(); private Function<String, String> replaceChain = Function.identity();
CiFriendlyXMLFilter(XmlPullParser xmlPullParser, boolean replace) { CiFriendlyXMLFilter(XMLStreamReader delegate, boolean replace) {
super(xmlPullParser, "version"); super(delegate, "version");
this.replace = replace; this.replace = replace;
} }
@ -66,7 +67,7 @@ public boolean isSet() {
@Override @Override
protected void process(List<Event> buffer) { protected void process(List<Event> buffer) {
for (Event event : buffer) { for (Event event : buffer) {
if (event.event == TEXT && replace && event.text.contains("${")) { if (event.event == CHARACTERS && replace && event.text.contains("${")) {
event.text = replaceChain.apply(event.text); event.text = replaceChain.apply(event.text);
} }
pushEvent(event); pushEvent(event);

View File

@ -18,13 +18,13 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import java.io.IOException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayDeque; import java.util.ArrayDeque;
import java.util.Deque; import java.util.Deque;
import org.apache.maven.model.transform.pull.BufferingParser; import org.apache.maven.model.transform.stax.BufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* This filter will bypass all following filters and write directly to the output. * This filter will bypass all following filters and write directly to the output.
@ -52,27 +52,20 @@ class FastForwardFilter extends BufferingParser {
private int domDepth = 0; private int domDepth = 0;
FastForwardFilter(XmlPullParser xmlPullParser) { FastForwardFilter(XMLStreamReader delegate) {
super(xmlPullParser); super(delegate);
} }
@Override @Override
public int next() throws XmlPullParserException, IOException { public int next() throws XMLStreamException {
int event = super.next(); int event = super.next();
filter(); filter();
return event; return event;
} }
@Override protected void filter() throws XMLStreamException {
public int nextToken() throws XmlPullParserException, IOException { if (delegate.getEventType() == START_ELEMENT) {
int event = super.nextToken(); String localName = delegate.getLocalName();
filter();
return event;
}
protected void filter() throws XmlPullParserException, IOException {
if (xmlPullParser.getEventType() == START_TAG) {
String localName = xmlPullParser.getName();
if (domDepth > 0) { if (domDepth > 0) {
domDepth++; domDepth++;
} else { } else {
@ -94,7 +87,7 @@ protected void filter() throws XmlPullParserException, IOException {
} }
} }
state.add(localName); state.add(localName);
} else if (xmlPullParser.getEventType() == END_TAG) { } else if (delegate.getEventType() == END_ELEMENT) {
if (domDepth > 0) { if (domDepth > 0) {
if (--domDepth == 0) { if (--domDepth == 0) {
bypass(false); bypass(false);

View File

@ -18,57 +18,63 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
public class ModelVersionXMLFilter extends NodeBufferingParser { public class ModelVersionXMLFilter extends NodeBufferingParser {
private static final Pattern S_FILTER = Pattern.compile("\\s+"); private static final Pattern S_FILTER = Pattern.compile("\\s+");
public static final String NAMESPACE_PREFIX = "http://maven.apache.org/POM/"; public static final String NAMESPACE_PREFIX = "http://maven.apache.org/POM/";
public ModelVersionXMLFilter(XmlPullParser xmlPullParser) { public ModelVersionXMLFilter(XMLStreamReader delegate) {
super(xmlPullParser, "project"); super(delegate, "project");
} }
@Override @Override
protected void process(List<Event> buffer) { protected void process(List<Event> buffer) {
if (buffer.stream().noneMatch(e -> e.event == XmlPullParser.START_TAG && "modelVersion".equals(e.name))) { if (buffer.stream().noneMatch(e -> e.event == START_ELEMENT && "modelVersion".equals(e.name))) {
String namespace = null; String namespace = null;
String prefix = null;
for (int pos = 0; pos < buffer.size(); pos++) { for (int pos = 0; pos < buffer.size(); pos++) {
Event e = buffer.get(pos); Event e = buffer.get(pos);
if (namespace != null) { if (namespace != null) {
if (e.event == XmlPullParser.START_TAG) { if (e.event == START_ELEMENT) {
Event prev = buffer.get(pos - 1); Event prev = buffer.get(pos - 1);
if (prev.event != TEXT || !S_FILTER.matcher(prev.text).matches()) { if (prev.event != CHARACTERS
|| !S_FILTER.matcher(prev.text).matches()) {
prev = null; prev = null;
} }
Event pmse = new Event(); Event pmse = new Event();
pmse.event = START_TAG; pmse.event = START_ELEMENT;
pmse.name = "modelVersion"; pmse.name = "modelVersion";
pmse.namespace = namespace; pmse.namespace = namespace;
pmse.prefix = prefix;
buffer.add(pos++, pmse); buffer.add(pos++, pmse);
Event pmve = new Event(); Event pmve = new Event();
pmve.event = TEXT; pmve.event = CHARACTERS;
pmve.text = namespace.substring(NAMESPACE_PREFIX.length()); pmve.text = namespace.substring(NAMESPACE_PREFIX.length());
buffer.add(pos++, pmve); buffer.add(pos++, pmve);
Event pmee = new Event(); Event pmee = new Event();
pmee.event = END_TAG; pmee.event = END_ELEMENT;
pmee.name = "modelVersion"; pmee.name = "modelVersion";
pmee.namespace = namespace; pmee.namespace = namespace;
pmee.prefix = prefix;
buffer.add(pos++, pmee); buffer.add(pos++, pmee);
if (prev != null) { if (prev != null) {
buffer.add(pos++, prev); buffer.add(pos++, prev);
} }
break; break;
} }
} else if (e.event == XmlPullParser.START_TAG } else if (e.event == START_ELEMENT
&& "project".equals(e.name) && "project".equals(e.name)
&& e.namespace != null && e.namespace != null
&& e.namespace.startsWith(NAMESPACE_PREFIX)) { && e.namespace.startsWith(NAMESPACE_PREFIX)) {
namespace = e.namespace; namespace = e.namespace;
prefix = e.prefix;
} }
} }
} }

View File

@ -18,10 +18,11 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.List; import java.util.List;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Remove all modules, this is just buildtime information * Remove all modules, this is just buildtime information
@ -31,8 +32,8 @@
* @since 4.0.0 * @since 4.0.0
*/ */
class ModulesXMLFilter extends NodeBufferingParser { class ModulesXMLFilter extends NodeBufferingParser {
ModulesXMLFilter(XmlPullParser xmlPullParser) { ModulesXMLFilter(XMLStreamReader delegate) {
super(xmlPullParser, "modules"); super(delegate, "modules");
} }
protected void process(List<Event> buffer) { protected void process(List<Event> buffer) {

View File

@ -18,6 +18,8 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
@ -27,8 +29,7 @@
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* <p> * <p>
@ -54,8 +55,8 @@ class ParentXMLFilter extends NodeBufferingParser {
* @param relativePathMapper * @param relativePathMapper
*/ */
ParentXMLFilter( ParentXMLFilter(
XmlPullParser parser, Function<Path, Optional<RelativeProject>> relativePathMapper, Path projectPath) { XMLStreamReader delegate, Function<Path, Optional<RelativeProject>> relativePathMapper, Path projectPath) {
super(parser, "parent"); super(delegate, "parent");
this.relativePathMapper = relativePathMapper; this.relativePathMapper = relativePathMapper;
this.projectPath = projectPath; this.projectPath = projectPath;
} }
@ -71,11 +72,11 @@ protected void process(List<Event> buffer) {
boolean hasRelativePath = false; boolean hasRelativePath = false;
for (int i = 0; i < buffer.size(); i++) { for (int i = 0; i < buffer.size(); i++) {
Event event = buffer.get(i); Event event = buffer.get(i);
if (event.event == START_TAG) { if (event.event == START_ELEMENT) {
tagName = event.name; tagName = event.name;
hasVersion |= "version".equals(tagName); hasVersion |= "version".equals(tagName);
hasRelativePath |= "relativePath".equals(tagName); hasRelativePath |= "relativePath".equals(tagName);
} else if (event.event == TEXT) { } else if (event.event == CHARACTERS) {
if (S_FILTER.matcher(event.text).matches()) { if (S_FILTER.matcher(event.text).matches()) {
if (whitespaceAfterParentStart.isEmpty()) { if (whitespaceAfterParentStart.isEmpty()) {
whitespaceAfterParentStart = event.text; whitespaceAfterParentStart = event.text;
@ -89,7 +90,7 @@ protected void process(List<Event> buffer) {
} else if ("version".equals(tagName)) { } else if ("version".equals(tagName)) {
version = nullSafeAppend(version, event.text); version = nullSafeAppend(version, event.text);
} }
} else if (event.event == END_TAG && "parent".equals(event.name)) { } else if (event.event == END_ELEMENT && "parent".equals(event.name)) {
Optional<RelativeProject> resolvedParent; Optional<RelativeProject> resolvedParent;
if (!hasVersion && (!hasRelativePath || relativePath != null)) { if (!hasVersion && (!hasRelativePath || relativePath != null)) {
Path relPath = Paths.get(Objects.toString(relativePath, "../pom.xml")); Path relPath = Paths.get(Objects.toString(relativePath, "../pom.xml"));
@ -98,23 +99,23 @@ protected void process(List<Event> buffer) {
resolvedParent = Optional.empty(); resolvedParent = Optional.empty();
} }
if (!hasVersion && resolvedParent.isPresent()) { if (!hasVersion && resolvedParent.isPresent()) {
int pos = buffer.get(i - 1).event == TEXT ? i - 1 : i; int pos = buffer.get(i - 1).event == CHARACTERS ? i - 1 : i;
Event e = new Event(); Event e = new Event();
e.event = TEXT; e.event = CHARACTERS;
e.text = whitespaceAfterParentStart; e.text = whitespaceAfterParentStart;
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = START_TAG; e.event = START_ELEMENT;
e.namespace = buffer.get(0).namespace; e.namespace = buffer.get(0).namespace;
e.prefix = buffer.get(0).prefix; e.prefix = buffer.get(0).prefix;
e.name = "version"; e.name = "version";
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = TEXT; e.event = CHARACTERS;
e.text = resolvedParent.get().getVersion(); e.text = resolvedParent.get().getVersion();
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = END_TAG; e.event = END_ELEMENT;
e.name = "version"; e.name = "version";
e.namespace = buffer.get(0).namespace; e.namespace = buffer.get(0).namespace;
e.prefix = buffer.get(0).prefix; e.prefix = buffer.get(0).prefix;

View File

@ -18,9 +18,9 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import java.nio.file.Path; import javax.xml.stream.XMLStreamReader;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import java.nio.file.Path;
/** /**
* @author Guillaume Nodet * @author Guillaume Nodet
@ -34,9 +34,9 @@ public RawToConsumerPomXMLFilterFactory(BuildToRawPomXMLFilterFactory buildPomXM
this.buildPomXMLFilterFactory = buildPomXMLFilterFactory; this.buildPomXMLFilterFactory = buildPomXMLFilterFactory;
} }
public final XmlPullParser get(XmlPullParser orgParser, Path projectPath) { public final XMLStreamReader get(XMLStreamReader orgParser, Path projectPath) {
// Ensure that xs:any elements aren't touched by next filters // Ensure that xs:any elements aren't touched by next filters
XmlPullParser parser = orgParser instanceof FastForwardFilter ? orgParser : new FastForwardFilter(orgParser); XMLStreamReader parser = orgParser instanceof FastForwardFilter ? orgParser : new FastForwardFilter(orgParser);
parser = buildPomXMLFilterFactory.get(parser, projectPath); parser = buildPomXMLFilterFactory.get(parser, projectPath);

View File

@ -18,12 +18,13 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.List; import java.util.List;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Will apply the version if the dependency is part of the reactor * Will apply the version if the dependency is part of the reactor
@ -38,8 +39,8 @@ public class ReactorDependencyXMLFilter extends NodeBufferingParser {
private static final Pattern S_FILTER = Pattern.compile("\\s+"); private static final Pattern S_FILTER = Pattern.compile("\\s+");
public ReactorDependencyXMLFilter( public ReactorDependencyXMLFilter(
XmlPullParser xmlPullParser, BiFunction<String, String, String> reactorVersionMapper) { XMLStreamReader delegate, BiFunction<String, String, String> reactorVersionMapper) {
super(xmlPullParser, "dependency"); super(delegate, "dependency");
this.reactorVersionMapper = reactorVersionMapper; this.reactorVersionMapper = reactorVersionMapper;
} }
@ -52,10 +53,10 @@ protected void process(List<Event> buffer) {
String tagName = null; String tagName = null;
for (int i = 0; i < buffer.size(); i++) { for (int i = 0; i < buffer.size(); i++) {
Event event = buffer.get(i); Event event = buffer.get(i);
if (event.event == START_TAG) { if (event.event == START_ELEMENT) {
tagName = event.name; tagName = event.name;
hasVersion |= "version".equals(tagName); hasVersion |= "version".equals(tagName);
} else if (event.event == TEXT) { } else if (event.event == CHARACTERS) {
if (S_FILTER.matcher(event.text).matches()) { if (S_FILTER.matcher(event.text).matches()) {
if (dependencyWhitespace.isEmpty()) { if (dependencyWhitespace.isEmpty()) {
dependencyWhitespace = event.text; dependencyWhitespace = event.text;
@ -65,26 +66,26 @@ protected void process(List<Event> buffer) {
} else if ("artifactId".equals(tagName)) { } else if ("artifactId".equals(tagName)) {
artifactId = nullSafeAppend(artifactId, event.text); artifactId = nullSafeAppend(artifactId, event.text);
} }
} else if (event.event == END_TAG && "dependency".equals(event.name)) { } else if (event.event == END_ELEMENT && "dependency".equals(event.name)) {
String version = reactorVersionMapper.apply(groupId, artifactId); String version = reactorVersionMapper.apply(groupId, artifactId);
if (!hasVersion && version != null) { if (!hasVersion && version != null) {
int pos = buffer.get(i - 1).event == TEXT ? i - 1 : i; int pos = buffer.get(i - 1).event == CHARACTERS ? i - 1 : i;
Event e = new Event(); Event e = new Event();
e.event = TEXT; e.event = CHARACTERS;
e.text = dependencyWhitespace; e.text = dependencyWhitespace;
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = START_TAG; e.event = START_ELEMENT;
e.namespace = buffer.get(0).namespace; e.namespace = buffer.get(0).namespace;
e.prefix = buffer.get(0).prefix; e.prefix = buffer.get(0).prefix;
e.name = "version"; e.name = "version";
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = TEXT; e.event = CHARACTERS;
e.text = version; e.text = version;
buffer.add(pos++, e); buffer.add(pos++, e);
e = new Event(); e = new Event();
e.event = END_TAG; e.event = END_ELEMENT;
e.name = "version"; e.name = "version";
e.namespace = buffer.get(0).namespace; e.namespace = buffer.get(0).namespace;
e.prefix = buffer.get(0).prefix; e.prefix = buffer.get(0).prefix;

View File

@ -18,11 +18,12 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.List; import java.util.List;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.maven.model.transform.pull.NodeBufferingParser; import org.apache.maven.model.transform.stax.NodeBufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/** /**
* Remove relativePath element, has no value for consumer pom * Remove relativePath element, has no value for consumer pom
@ -35,23 +36,23 @@ public class RelativePathXMLFilter extends NodeBufferingParser {
private static final Pattern S_FILTER = Pattern.compile("\\s+"); private static final Pattern S_FILTER = Pattern.compile("\\s+");
public RelativePathXMLFilter(XmlPullParser xmlPullParser) { public RelativePathXMLFilter(XMLStreamReader delegate) {
super(xmlPullParser, "parent"); super(delegate, "parent");
} }
protected void process(List<Event> buffer) { protected void process(List<Event> buffer) {
boolean skip = false; boolean skip = false;
Event prev = null; Event prev = null;
for (Event event : buffer) { for (Event event : buffer) {
if (event.event == START_TAG && "relativePath".equals(event.name)) { if (event.event == START_ELEMENT && "relativePath".equals(event.name)) {
skip = true; skip = true;
if (prev != null if (prev != null
&& prev.event == TEXT && prev.event == CHARACTERS
&& S_FILTER.matcher(prev.text).matches()) { && S_FILTER.matcher(prev.text).matches()) {
prev = null; prev = null;
} }
event = null; event = null;
} else if (event.event == END_TAG && "relativePath".equals(event.name)) { } else if (event.event == END_ELEMENT && "relativePath".equals(event.name)) {
skip = false; skip = false;
event = null; event = null;
} else if (skip) { } else if (skip) {

View File

@ -18,12 +18,14 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import java.io.IOException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.apache.maven.model.transform.pull.BufferingParser; import org.apache.maven.model.transform.stax.BufferingParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Remove the root attribute on the model * Remove the root attribute on the model
@ -32,14 +34,18 @@
* @since 4.0.0 * @since 4.0.0
*/ */
class RootXMLFilter extends BufferingParser { class RootXMLFilter extends BufferingParser {
RootXMLFilter(XmlPullParser xmlPullParser) {
super(xmlPullParser); final Deque<String> elements = new ArrayDeque<>();
RootXMLFilter(XMLStreamReader delegate) {
super(delegate);
} }
@Override @Override
protected boolean accept() throws XmlPullParserException, IOException { protected boolean accept() throws XMLStreamException {
if (xmlPullParser.getEventType() == XmlPullParser.START_TAG) { if (delegate.getEventType() == START_ELEMENT) {
if (xmlPullParser.getDepth() == 1 && "project".equals(xmlPullParser.getName())) { elements.push(delegate.getLocalName());
if (elements.size() == 1 && "project".equals(delegate.getLocalName())) {
Event event = bufferEvent(); Event event = bufferEvent();
event.attributes = Stream.of(event.attributes) event.attributes = Stream.of(event.attributes)
.filter(a -> !"root".equals(a.name)) .filter(a -> !"root".equals(a.name))
@ -47,6 +53,8 @@ protected boolean accept() throws XmlPullParserException, IOException {
pushEvent(event); pushEvent(event);
return false; return false;
} }
} else if (delegate.getEventType() == END_ELEMENT) {
elements.pop();
} }
return true; return true;
} }

View File

@ -1,509 +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.maven.model.transform.pull;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Objects;
import java.util.regex.Pattern;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* An xml pull parser filter base implementation.
*
* @author Guillaume Nodet
* @since 4.0.0
*/
public class BufferingParser implements XmlPullParser {
private static final Pattern WHITESPACE_REGEX = Pattern.compile("[ \r\t\n]+");
protected XmlPullParser xmlPullParser;
protected Deque<Event> events;
protected Event current;
protected boolean bypass;
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Event {
public int event;
public String name;
public String prefix;
public String namespace;
public boolean empty;
public String text;
public Attribute[] attributes;
public Namespace[] namespaces;
public int columnNumber;
public int lineNumber;
public String positionDescription() {
return " " + TYPES[event] + " @" + lineNumber + ":" + columnNumber;
}
@Override
public String toString() {
switch (event) {
case START_DOCUMENT:
case END_DOCUMENT:
return "Event{event=" + TYPES[event] + "'}";
case PROCESSING_INSTRUCTION:
case TEXT:
case CDSECT:
case ENTITY_REF:
case COMMENT:
case IGNORABLE_WHITESPACE:
return "Event{event=" + TYPES[event] + ", text='" + text + "'}";
case START_TAG:
return "Event{" + "event=START_TAG"
+ ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", attributes="
+ Arrays.toString(attributes) + ", namespaces="
+ Arrays.toString(namespaces) + '}';
case END_TAG:
return "Event{" + "event=END_TAG"
+ ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", namespaces="
+ Arrays.toString(namespaces) + '}';
default:
return "Event{" + "event="
+ TYPES[event] + ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", text='"
+ text + '\'' + ", attributes="
+ Arrays.toString(attributes) + ", namespaces="
+ Arrays.toString(namespaces) + '}';
}
}
}
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Namespace {
public String prefix;
public String uri;
}
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Attribute {
public String name;
public String prefix;
public String namespace;
public String type;
public String value;
public boolean isDefault;
}
public BufferingParser(XmlPullParser xmlPullParser) {
this.xmlPullParser = xmlPullParser;
}
@Override
public void setFeature(String name, boolean state) throws XmlPullParserException {
xmlPullParser.setFeature(name, state);
}
@Override
public boolean getFeature(String name) {
return xmlPullParser.getFeature(name);
}
@Override
public void setProperty(String name, Object value) throws XmlPullParserException {
xmlPullParser.setProperty(name, value);
}
@Override
public Object getProperty(String name) {
return xmlPullParser.getProperty(name);
}
@Override
public void setInput(Reader in) throws XmlPullParserException {
xmlPullParser.setInput(in);
}
@Override
public void setInput(InputStream inputStream, String inputEncoding) throws XmlPullParserException {
xmlPullParser.setInput(inputStream, inputEncoding);
}
@Override
public String getInputEncoding() {
return xmlPullParser.getInputEncoding();
}
@Override
public void defineEntityReplacementText(String entityName, String replacementText) throws XmlPullParserException {
xmlPullParser.defineEntityReplacementText(entityName, replacementText);
}
@Override
public int getNamespaceCount(int depth) throws XmlPullParserException {
// TODO: if (current != null) throw new IllegalStateException("Not supported during events replay");
return xmlPullParser.getNamespaceCount(depth);
}
@Override
public String getNamespacePrefix(int pos) throws XmlPullParserException {
// TODO: if (current != null) throw new IllegalStateException("Not supported during events replay");
return xmlPullParser.getNamespacePrefix(pos);
}
@Override
public String getNamespaceUri(int pos) throws XmlPullParserException {
// TODO: if (current != null) throw new IllegalStateException("Not supported during events replay");
return xmlPullParser.getNamespaceUri(pos);
}
@Override
public String getNamespace(String prefix) {
// TODO: if (current != null) throw new IllegalStateException("Not supported during events replay");
return xmlPullParser.getNamespace(prefix);
}
@Override
public int getDepth() {
// TODO: if (current != null) throw new IllegalStateException("Not supported during events replay");
return xmlPullParser.getDepth();
}
@Override
public String getPositionDescription() {
if (current != null) {
return current.positionDescription();
}
return xmlPullParser.getPositionDescription();
}
@Override
public int getLineNumber() {
if (current != null) {
return current.lineNumber;
}
return xmlPullParser.getLineNumber();
}
@Override
public int getColumnNumber() {
if (current != null) {
return current.columnNumber;
}
return xmlPullParser.getColumnNumber();
}
@Override
public boolean isWhitespace() throws XmlPullParserException {
if (current != null) {
if (current.event == TEXT || current.event == CDSECT) {
return WHITESPACE_REGEX.matcher(current.text).matches();
} else if (current.event == IGNORABLE_WHITESPACE) {
return true;
} else {
throw new XmlPullParserException("no content available to check for whitespaces");
}
}
return xmlPullParser.isWhitespace();
}
@Override
public String getText() {
return current != null ? current.text : xmlPullParser.getText();
}
@Override
public char[] getTextCharacters(int[] holderForStartAndLength) {
if (current != null) {
throw new IllegalStateException("Not supported during events replay");
}
return xmlPullParser.getTextCharacters(holderForStartAndLength);
}
@Override
public String getNamespace() {
return current != null ? current.namespace : xmlPullParser.getNamespace();
}
@Override
public String getName() {
return current != null ? current.name : xmlPullParser.getName();
}
@Override
public String getPrefix() {
return current != null ? current.prefix : xmlPullParser.getPrefix();
}
@Override
public boolean isEmptyElementTag() throws XmlPullParserException {
return current != null ? current.empty : xmlPullParser.isEmptyElementTag();
}
@Override
public int getAttributeCount() {
if (current != null) {
return current.attributes != null ? current.attributes.length : 0;
} else {
return xmlPullParser.getAttributeCount();
}
}
@Override
public String getAttributeNamespace(int index) {
if (current != null) {
return current.attributes[index].namespace;
} else {
return xmlPullParser.getAttributeNamespace(index);
}
}
@Override
public String getAttributeName(int index) {
if (current != null) {
return current.attributes[index].name;
} else {
return xmlPullParser.getAttributeName(index);
}
}
@Override
public String getAttributePrefix(int index) {
if (current != null) {
return current.attributes[index].prefix;
} else {
return xmlPullParser.getAttributePrefix(index);
}
}
@Override
public String getAttributeType(int index) {
if (current != null) {
return current.attributes[index].type;
} else {
return xmlPullParser.getAttributeType(index);
}
}
@Override
public boolean isAttributeDefault(int index) {
if (current != null) {
return current.attributes[index].isDefault;
} else {
return xmlPullParser.isAttributeDefault(index);
}
}
@Override
public String getAttributeValue(int index) {
if (current != null) {
return current.attributes[index].value;
} else {
return xmlPullParser.getAttributeValue(index);
}
}
@Override
public String getAttributeValue(String namespace, String name) {
if (current != null) {
if (current.attributes != null) {
for (Attribute attr : current.attributes) {
if (Objects.equals(namespace, attr.namespace) && Objects.equals(name, attr.name)) {
return attr.value;
}
}
}
return null;
} else {
return xmlPullParser.getAttributeValue(namespace, name);
}
}
@Override
public void require(int type, String namespace, String name) throws XmlPullParserException, IOException {
if (current != null) {
throw new IllegalStateException("Not supported during events replay");
}
xmlPullParser.require(type, namespace, name);
}
@Override
public int getEventType() throws XmlPullParserException {
return current != null ? current.event : xmlPullParser.getEventType();
}
@Override
public int next() throws XmlPullParserException, IOException {
while (true) {
if (events != null && !events.isEmpty()) {
current = events.removeFirst();
return current.event;
} else {
current = null;
}
if (getEventType() == END_DOCUMENT) {
throw new XmlPullParserException("already reached end of XML input", this, null);
}
int currentEvent = xmlPullParser.next();
if (bypass() || accept()) {
return currentEvent;
}
}
}
@Override
public int nextToken() throws XmlPullParserException, IOException {
while (true) {
if (events != null && !events.isEmpty()) {
current = events.removeFirst();
return current.event;
} else {
current = null;
}
if (getEventType() == END_DOCUMENT) {
throw new XmlPullParserException("already reached end of XML input", this, null);
}
int currentEvent = xmlPullParser.nextToken();
if (bypass() || accept()) {
return currentEvent;
}
}
}
@Override
public int nextTag() throws XmlPullParserException, IOException {
int eventType = next();
if (eventType == TEXT && isWhitespace()) { // skip whitespace
eventType = next();
}
if (eventType != START_TAG && eventType != END_TAG) {
throw new XmlPullParserException("expected START_TAG or END_TAG not " + TYPES[getEventType()], this, null);
}
return eventType;
}
@Override
public String nextText() throws XmlPullParserException, IOException {
int eventType = getEventType();
if (eventType != START_TAG) {
throw new XmlPullParserException("parser must be on START_TAG to read next text", this, null);
}
eventType = next();
if (eventType == TEXT) {
final String result = getText();
eventType = next();
if (eventType != END_TAG) {
throw new XmlPullParserException(
"TEXT must be immediately followed by END_TAG and not " + TYPES[getEventType()], this, null);
}
return result;
} else if (eventType == END_TAG) {
return "";
} else {
throw new XmlPullParserException("parser must be on START_TAG or TEXT to read text", this, null);
}
}
protected Event bufferEvent() throws XmlPullParserException {
Event event = new Event();
XmlPullParser pp = xmlPullParser;
event.event = xmlPullParser.getEventType();
event.columnNumber = xmlPullParser.getColumnNumber();
event.lineNumber = xmlPullParser.getLineNumber();
switch (event.event) {
case START_DOCUMENT:
case END_DOCUMENT:
break;
case START_TAG:
event.name = pp.getName();
event.namespace = pp.getNamespace();
event.prefix = pp.getPrefix();
event.empty = pp.isEmptyElementTag();
event.text = pp.getText();
event.attributes = new Attribute[pp.getAttributeCount()];
for (int i = 0; i < pp.getAttributeCount(); i++) {
Attribute attr = new Attribute();
attr.name = pp.getAttributeName(i);
attr.namespace = pp.getAttributeNamespace(i);
attr.value = pp.getAttributeValue(i);
attr.type = pp.getAttributeType(i);
attr.isDefault = pp.isAttributeDefault(i);
event.attributes[i] = attr;
}
break;
case END_TAG:
event.name = pp.getName();
event.namespace = pp.getNamespace();
event.prefix = pp.getPrefix();
event.text = pp.getText();
break;
case TEXT:
case COMMENT:
case IGNORABLE_WHITESPACE:
case CDSECT:
case ENTITY_REF:
event.text = pp.getText();
break;
default:
break;
}
return event;
}
protected void pushEvent(Event event) {
if (events == null) {
events = new ArrayDeque<>();
}
events.add(event);
}
protected boolean accept() throws XmlPullParserException, IOException {
return true;
}
public void bypass(boolean bypass) {
if (bypass && events != null && !events.isEmpty()) {
throw new IllegalStateException("Can not disable filter while processing");
}
this.bypass = bypass;
}
public boolean bypass() {
return bypass || (xmlPullParser instanceof BufferingParser && ((BufferingParser) xmlPullParser).bypass());
}
protected static String nullSafeAppend(String originalValue, String charSegment) {
if (originalValue == null) {
return charSegment;
} else {
return originalValue + charSegment;
}
}
}

View File

@ -1,118 +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.maven.model.transform.pull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.pull.MXSerializer;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.util.xml.pull.XmlSerializer;
public class XmlUtils {
public static ByteArrayInputStream writeDocument(XmlStreamReader reader, XmlPullParser parser)
throws IOException, XmlPullParserException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Writer writer = newWriter(reader, baos);
writeDocument(parser, writer);
return new ByteArrayInputStream(baos.toByteArray());
}
public static void writeDocument(XmlPullParser parser, Writer writer) throws IOException, XmlPullParserException {
XmlSerializer serializer = new MXSerializer();
serializer.setOutput(writer);
while (parser.nextToken() != XmlPullParser.END_DOCUMENT) {
switch (parser.getEventType()) {
case XmlPullParser.START_DOCUMENT:
serializer.startDocument(parser.getInputEncoding(), true);
break;
case XmlPullParser.END_DOCUMENT:
serializer.endDocument();
case XmlPullParser.START_TAG:
int nsStart = parser.getNamespaceCount(parser.getDepth() - 1);
int nsEnd = parser.getNamespaceCount(parser.getDepth());
for (int i = nsStart; i < nsEnd; i++) {
String prefix = parser.getNamespacePrefix(i);
String ns = parser.getNamespaceUri(i);
serializer.setPrefix(prefix, ns);
}
serializer.startTag(parser.getNamespace(), parser.getName());
for (int i = 0; i < parser.getAttributeCount(); i++) {
serializer.attribute(
parser.getAttributeNamespace(i),
parser.getAttributeName(i),
parser.getAttributeValue(i));
}
break;
case XmlPullParser.END_TAG:
serializer.endTag(parser.getNamespace(), parser.getName());
break;
case XmlPullParser.TEXT:
serializer.text(normalize(parser.getText()));
break;
case XmlPullParser.CDSECT:
serializer.cdsect(parser.getText());
break;
case XmlPullParser.ENTITY_REF:
serializer.entityRef(parser.getName());
break;
case XmlPullParser.IGNORABLE_WHITESPACE:
serializer.ignorableWhitespace(normalize(parser.getText()));
break;
case XmlPullParser.PROCESSING_INSTRUCTION:
serializer.processingInstruction(parser.getText());
break;
case XmlPullParser.COMMENT:
serializer.comment(normalize(parser.getText()));
break;
case XmlPullParser.DOCDECL:
serializer.docdecl(normalize(parser.getText()));
break;
default:
break;
}
}
serializer.endDocument();
}
private static OutputStreamWriter newWriter(XmlStreamReader reader, ByteArrayOutputStream baos)
throws UnsupportedEncodingException {
if (reader.getEncoding() != null) {
return new OutputStreamWriter(baos, reader.getEncoding());
} else {
return new OutputStreamWriter(baos);
}
}
private static String normalize(String input) {
if (input.indexOf('\n') >= 0 && !"\n".equals(System.lineSeparator())) {
return input.replace("\n", System.lineSeparator());
}
return input;
}
}

View File

@ -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.
*/
package org.apache.maven.model.transform.stax;
import javax.xml.namespace.NamespaceContext;
import javax.xml.namespace.QName;
import javax.xml.stream.Location;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
import java.util.Objects;
import java.util.regex.Pattern;
import org.codehaus.stax2.XMLStreamReader2;
public class BufferingParser implements XMLStreamReader {
private static final Pattern WHITESPACE_REGEX = Pattern.compile("[ \r\t\n]+");
private static final String[] TYPES = new String[] {
"",
"START_ELEMENT",
"END_ELEMENT",
"PROCESSING_INSTRUCTION",
"CHARACTERS",
"COMMENT",
"SPACE",
"START_DOCUMENT",
"END_DOCUMENT",
"ENTITY_REFERENCE",
"ATTRIBUTE",
"DTD",
"CDATA",
"NAMESPACE",
"NOTATION_DECLARATION",
"ENTITY_DECLARATION"
};
protected XMLStreamReader delegate;
protected Deque<Event> events;
protected Event current;
protected boolean bypass;
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Event {
public int event;
public String name;
public String prefix;
public String namespace;
public boolean empty;
public String text;
public Attribute[] attributes;
public Namespace[] namespaces;
public int columnNumber;
public int lineNumber;
public String positionDescription() {
return " " + TYPES[event] + " @" + lineNumber + ":" + columnNumber;
}
@Override
public String toString() {
switch (event) {
case START_DOCUMENT:
case END_DOCUMENT:
return "Event{event=" + TYPES[event] + "'}";
case PROCESSING_INSTRUCTION:
case CHARACTERS:
case CDATA:
case ENTITY_REFERENCE:
case COMMENT:
case SPACE:
return "Event{event=" + TYPES[event] + ", text='" + text + "'}";
case START_ELEMENT:
return "Event{" + "event=START_TAG"
+ ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", attributes="
+ Arrays.toString(attributes) + ", namespaces="
+ Arrays.toString(namespaces) + '}';
case END_ELEMENT:
return "Event{" + "event=END_TAG"
+ ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", namespaces="
+ Arrays.toString(namespaces) + '}';
default:
return "Event{" + "event="
+ TYPES[event] + ", name='"
+ name + '\'' + ", prefix='"
+ prefix + '\'' + ", namespace='"
+ namespace + '\'' + ", empty="
+ empty + ", text='"
+ text + '\'' + ", attributes="
+ Arrays.toString(attributes) + ", namespaces="
+ Arrays.toString(namespaces) + '}';
}
}
}
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Namespace {
public String prefix;
public String uri;
}
@SuppressWarnings("checkstyle:VisibilityModifier")
public static class Attribute {
public String name;
public String prefix;
public String namespace;
public String type;
public String value;
}
public BufferingParser(XMLStreamReader delegate) {
this.delegate = delegate;
}
@Override
public Object getProperty(String name) throws IllegalArgumentException {
return delegate.getProperty(name);
}
@Override
public String getElementText() throws XMLStreamException {
return delegate.getElementText();
}
@Override
public boolean hasNext() throws XMLStreamException {
return delegate.hasNext();
}
@Override
public void close() throws XMLStreamException {
delegate.close();
}
@Override
public String getNamespaceURI(String prefix) {
return delegate.getNamespaceURI(prefix);
}
@Override
public boolean isStartElement() {
return delegate.isStartElement();
}
@Override
public boolean isEndElement() {
return delegate.isEndElement();
}
@Override
public boolean isCharacters() {
return delegate.isCharacters();
}
@Override
public boolean isWhiteSpace() {
return delegate.isWhiteSpace();
}
@Override
public QName getAttributeName(int index) {
return delegate.getAttributeName(index);
}
@Override
public boolean isAttributeSpecified(int index) {
return delegate.isAttributeSpecified(index);
}
@Override
public int getNamespaceCount() {
return current != null
? current.namespaces != null ? current.namespaces.length : 0
: delegate.getNamespaceCount();
}
@Override
public String getNamespacePrefix(int index) {
return current != null ? current.namespaces[index].prefix : delegate.getNamespacePrefix(index);
}
@Override
public String getNamespaceURI(int index) {
return current != null ? current.namespaces[index].uri : delegate.getNamespaceURI(index);
}
@Override
public NamespaceContext getNamespaceContext() {
return delegate.getNamespaceContext();
}
@Override
public char[] getTextCharacters() {
return delegate.getTextCharacters();
}
@Override
public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length)
throws XMLStreamException {
return delegate.getTextCharacters(sourceStart, target, targetStart, length);
}
@Override
public int getTextStart() {
return delegate.getTextStart();
}
@Override
public int getTextLength() {
return delegate.getTextLength();
}
@Override
public String getEncoding() {
return delegate.getEncoding();
}
@Override
public boolean hasText() {
return delegate.hasText();
}
@Override
public Location getLocation() {
return delegate.getLocation();
}
@Override
public QName getName() {
return delegate.getName();
}
@Override
public boolean hasName() {
return delegate.hasName();
}
@Override
public String getVersion() {
return delegate.getVersion();
}
@Override
public boolean isStandalone() {
return delegate.isStandalone();
}
@Override
public boolean standaloneSet() {
return delegate.standaloneSet();
}
@Override
public String getCharacterEncodingScheme() {
return delegate.getCharacterEncodingScheme();
}
@Override
public String getPITarget() {
return delegate.getPITarget();
}
@Override
public String getPIData() {
return delegate.getPIData();
}
@Override
public String getText() {
return current != null ? current.text : delegate.getText();
}
@Override
public String getNamespaceURI() {
return current != null ? current.namespace : delegate.getNamespaceURI();
}
@Override
public String getLocalName() {
return current != null ? current.name : delegate.getLocalName();
}
@Override
public String getPrefix() {
return current != null ? current.prefix : delegate.getPrefix();
}
@Override
public int getAttributeCount() {
if (current != null) {
return current.attributes != null ? current.attributes.length : 0;
} else {
return delegate.getAttributeCount();
}
}
@Override
public String getAttributeNamespace(int index) {
if (current != null) {
return current.attributes[index].namespace;
} else {
return delegate.getAttributeNamespace(index);
}
}
@Override
public String getAttributeLocalName(int index) {
if (current != null) {
return current.attributes[index].name;
} else {
return delegate.getAttributeLocalName(index);
}
}
@Override
public String getAttributePrefix(int index) {
if (current != null) {
return current.attributes[index].prefix;
} else {
return delegate.getAttributePrefix(index);
}
}
@Override
public String getAttributeType(int index) {
if (current != null) {
return current.attributes[index].type;
} else {
return delegate.getAttributeType(index);
}
}
@Override
public String getAttributeValue(int index) {
if (current != null) {
return current.attributes[index].value;
} else {
return delegate.getAttributeValue(index);
}
}
@Override
public String getAttributeValue(String namespace, String name) {
if (current != null) {
if (current.attributes != null) {
for (Attribute attr : current.attributes) {
if (Objects.equals(namespace, attr.namespace) && Objects.equals(name, attr.name)) {
return attr.value;
}
}
}
return null;
} else {
return delegate.getAttributeValue(namespace, name);
}
}
@Override
public void require(int type, String namespace, String name) throws XMLStreamException {
if (current != null) {
throw new IllegalStateException("Not supported during events replay");
}
delegate.require(type, namespace, name);
}
@Override
public int getEventType() {
return current != null ? current.event : delegate.getEventType();
}
@Override
public int next() throws XMLStreamException {
while (true) {
if (events != null && !events.isEmpty()) {
current = events.removeFirst();
return current.event;
} else {
current = null;
}
if (getEventType() == END_DOCUMENT) {
throw new XMLStreamException("already reached end of XML input", getLocation(), null);
}
int currentEvent = delegate.next();
if (bypass() || accept()) {
return currentEvent;
}
}
}
@Override
public int nextTag() throws XMLStreamException {
int eventType = next();
while (eventType == CHARACTERS && isWhitespace() // skip whitespace
|| eventType == COMMENT) { // skip comments
eventType = next();
}
if (eventType != START_ELEMENT && eventType != END_ELEMENT) {
throw new XMLStreamException(
"expected START_TAG or END_TAG not " + TYPES[getEventType()], getLocation(), null);
}
return eventType;
}
public boolean isWhitespace() throws XMLStreamException {
if (getEventType() == CHARACTERS || getEventType() == CDATA) {
return WHITESPACE_REGEX.matcher(getText()).matches();
} else if (getEventType() == SPACE) {
return true;
} else {
throw new XMLStreamException("no content available to check for whitespaces");
}
}
protected Event bufferEvent() throws XMLStreamException {
Event event = new Event();
XMLStreamReader pp = delegate;
event.event = delegate.getEventType();
event.columnNumber = delegate.getLocation().getColumnNumber();
event.lineNumber = delegate.getLocation().getLineNumber();
switch (event.event) {
case START_DOCUMENT:
case END_DOCUMENT:
break;
case START_ELEMENT:
event.name = pp.getLocalName();
event.namespace = pp.getNamespaceURI();
event.prefix = pp.getPrefix();
event.empty = (pp instanceof XMLStreamReader2) && ((XMLStreamReader2) pp).isEmptyElement();
// event.text = pp.getText();
event.attributes = new Attribute[pp.getAttributeCount()];
for (int i = 0; i < pp.getAttributeCount(); i++) {
Attribute attr = new Attribute();
attr.name = pp.getAttributeLocalName(i);
attr.namespace = pp.getAttributeNamespace(i);
attr.value = pp.getAttributeValue(i);
attr.type = pp.getAttributeType(i);
event.attributes[i] = attr;
}
event.namespaces = new Namespace[pp.getNamespaceCount()];
for (int i = 0; i < pp.getNamespaceCount(); i++) {
Namespace ns = new Namespace();
ns.uri = pp.getNamespaceURI(i);
ns.prefix = pp.getNamespacePrefix(i);
event.namespaces[i] = ns;
}
break;
case END_ELEMENT:
event.name = pp.getLocalName();
event.namespace = pp.getNamespaceURI();
event.prefix = pp.getPrefix();
// event.text = pp.getText();
break;
case CHARACTERS:
case COMMENT:
case SPACE:
case CDATA:
case ENTITY_REFERENCE:
event.text = pp.getText();
break;
default:
break;
}
return event;
}
protected void pushEvent(Event event) {
if (events == null) {
events = new ArrayDeque<>();
}
events.add(event);
}
protected boolean accept() throws XMLStreamException {
return true;
}
public void bypass(boolean bypass) {
if (bypass && events != null && !events.isEmpty()) {
throw new IllegalStateException("Can not disable filter while processing");
}
this.bypass = bypass;
}
public boolean bypass() {
return bypass || (delegate instanceof BufferingParser && ((BufferingParser) delegate).bypass());
}
protected static String nullSafeAppend(String originalValue, String charSegment) {
if (originalValue == null) {
return charSegment;
} else {
return originalValue + charSegment;
}
}
}

View File

@ -16,16 +16,15 @@
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*/ */
package org.apache.maven.model.transform.pull; package org.apache.maven.model.transform.stax;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Buffer events while parsing a given element to allow some post-processing. * Buffer events while parsing a given element to allow some post-processing.
* *
@ -40,31 +39,29 @@ public abstract class NodeBufferingParser extends BufferingParser {
private boolean buffering; private boolean buffering;
public NodeBufferingParser(XmlPullParser xmlPullParser, String nodeName) { public NodeBufferingParser(XMLStreamReader xmlPullParser, String nodeName) {
super(xmlPullParser); super(xmlPullParser);
this.nodeName = Objects.requireNonNull(nodeName); this.nodeName = Objects.requireNonNull(nodeName);
} }
@Override @Override
protected boolean accept() throws XmlPullParserException, IOException { protected boolean accept() throws XMLStreamException {
if (nodeName.equals(xmlPullParser.getName())) { if (!buffering && delegate.getEventType() == START_ELEMENT && nodeName.equals(delegate.getLocalName())) {
if (xmlPullParser.getEventType() == START_TAG && !buffering) { buffer.add(bufferEvent());
buffer.add(bufferEvent()); buffering = true;
buffering = true; return false;
return false; } else if (buffering && delegate.getEventType() == END_ELEMENT && nodeName.equals(delegate.getLocalName())) {
} buffer.add(bufferEvent());
if (xmlPullParser.getEventType() == END_TAG && buffering) { process(buffer);
buffer.add(bufferEvent()); buffering = false;
process(buffer); buffer.clear();
buffering = false; return false;
buffer.clear();
return false;
}
} else if (buffering) { } else if (buffering) {
buffer.add(bufferEvent()); buffer.add(bufferEvent());
return false; return false;
} else {
return true;
} }
return true;
} }
@Override @Override

View File

@ -0,0 +1,187 @@
/*
* 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.model.transform.stax;
import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayDeque;
import java.util.Deque;
import com.ctc.wstx.api.WstxOutputProperties;
public class XmlUtils {
public static InputStream writeDocument(XMLStreamReader parser) throws XMLStreamException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
writeDocument(parser, baos);
return new ByteArrayInputStream(baos.toByteArray());
}
public static void writeDocument(XMLStreamReader parser, OutputStream output) throws XMLStreamException {
XMLOutputFactory factory = new com.ctc.wstx.stax.WstxOutputFactory();
factory.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, false);
factory.setProperty(WstxOutputProperties.P_USE_DOUBLE_QUOTES_IN_XML_DECL, true);
factory.setProperty(WstxOutputProperties.P_ADD_SPACE_AFTER_EMPTY_ELEM, true);
XMLStreamWriter serializer = factory.createXMLStreamWriter(output, parser.getCharacterEncodingScheme());
copy(parser, serializer);
}
private static String normalize(String input) {
if (input != null) {
return input.replace("\r\n", "\n");
}
return input;
}
/**
* Copies the reader to the writer. The start and end document methods must
* be handled on the writer manually.
*/
public static void copy(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
copy(reader, writer, false, false);
}
public static void copy(XMLStreamReader reader, XMLStreamWriter writer, boolean fragment)
throws XMLStreamException {
copy(reader, writer, fragment, false);
}
public static void copy(XMLStreamReader reader, XMLStreamWriter writer, boolean fragment, boolean isThreshold)
throws XMLStreamException {
// number of elements read in
int read = 0;
int elementCount = 0;
final Deque<Integer> countStack = new ArrayDeque<>();
int event = reader.getEventType();
while (true) {
switch (event) {
case XMLStreamConstants.START_ELEMENT:
read++;
if (isThreshold) {
elementCount++;
countStack.push(elementCount);
elementCount = 0;
}
writeStartElement(reader, writer);
break;
case XMLStreamConstants.END_ELEMENT:
if (read > 0) {
writer.writeEndElement();
}
read--;
if (read < 0 && fragment) {
return;
}
if (isThreshold && !countStack.isEmpty()) {
elementCount = countStack.pop();
}
break;
case XMLStreamConstants.CHARACTERS:
writer.writeCharacters(normalize(reader.getText()));
break;
case XMLStreamConstants.SPACE:
writer.writeCharacters(normalize(reader.getText()));
break;
case XMLStreamConstants.ENTITY_REFERENCE:
writer.writeEntityRef(reader.getLocalName());
break;
case XMLStreamConstants.COMMENT:
writer.writeComment(normalize(reader.getText()));
break;
case XMLStreamConstants.CDATA:
writer.writeCData(normalize(reader.getText()));
break;
case XMLStreamConstants.START_DOCUMENT:
if (reader.getVersion() != null) {
writer.writeStartDocument(reader.getCharacterEncodingScheme(), reader.getVersion());
}
break;
case XMLStreamConstants.END_DOCUMENT:
writer.writeEndDocument();
return;
default:
break;
}
event = reader.next();
}
}
private static void writeStartElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException {
String uri = reader.getNamespaceURI();
String prefix = reader.getPrefix();
String local = reader.getLocalName();
if (prefix == null) {
prefix = "";
}
// Write out the element name
if (uri != null) {
if (prefix.isEmpty() && isEmpty(uri)) {
writer.writeStartElement(local);
} else {
writer.writeStartElement(prefix, local, uri);
}
} else {
writer.writeStartElement(local);
}
// Write out the namespaces
for (int i = 0; i < reader.getNamespaceCount(); i++) {
String nsURI = reader.getNamespaceURI(i);
String nsPrefix = reader.getNamespacePrefix(i);
if (nsURI == null) {
nsURI = "";
}
writer.writeNamespace(nsPrefix, nsURI);
writer.setPrefix(nsPrefix, nsURI);
}
// Write out attributes
for (int i = 0; i < reader.getAttributeCount(); i++) {
String ns = reader.getAttributeNamespace(i);
String nsPrefix = reader.getAttributePrefix(i);
if (ns == null || ns.isEmpty()) {
writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i));
} else if (nsPrefix == null || nsPrefix.isEmpty()) {
writer.writeAttribute(
reader.getAttributeNamespace(i), reader.getAttributeLocalName(i), reader.getAttributeValue(i));
} else {
writer.writeAttribute(
reader.getAttributePrefix(i),
reader.getAttributeNamespace(i),
reader.getAttributeLocalName(i),
reader.getAttributeValue(i));
}
}
}
private static boolean isEmpty(String s) {
return s == null || s.isEmpty();
}
}

View File

@ -18,34 +18,32 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter;
import org.apache.maven.model.transform.pull.XmlUtils; import org.apache.maven.model.transform.stax.XmlUtils;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
public abstract class AbstractXMLFilterTests { public abstract class AbstractXMLFilterTests {
protected XmlPullParser getFilter(XmlPullParser parser) { protected XMLStreamReader getFilter(XMLStreamReader parser) {
throw new UnsupportedOperationException("Override one of the getFilter() methods"); throw new UnsupportedOperationException("Override one of the getFilter() methods");
} }
protected String transform(String input) throws XmlPullParserException, IOException { protected String transform(String input) throws XMLStreamException, IOException {
return transform(new StringReader(input)); return transform(new StringReader(input));
} }
protected String transform(Reader input) throws XmlPullParserException, IOException { protected String transform(Reader input) throws XMLStreamException, IOException {
XMLStreamReader parser = XMLInputFactory.newFactory().createXMLStreamReader(input);
XMLStreamReader filter = getFilter(parser);
MXParser parser = new MXParser(); ByteArrayOutputStream baos = new ByteArrayOutputStream();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); XmlUtils.writeDocument(filter, baos);
parser.setInput(input); return baos.toString();
XmlPullParser filter = getFilter(parser);
StringWriter writer = new StringWriter();
XmlUtils.writeDocument(filter, writer);
return writer.toString();
} }
} }

View File

@ -18,14 +18,15 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import javax.xml.stream.XMLStreamReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
class CiFriendlyXMLFilterTest extends AbstractXMLFilterTests { class CiFriendlyXMLFilterTest extends AbstractXMLFilterTests {
@Override @Override
protected CiFriendlyXMLFilter getFilter(XmlPullParser parser) { protected CiFriendlyXMLFilter getFilter(XMLStreamReader parser) {
CiFriendlyXMLFilter filter = new CiFriendlyXMLFilter(parser, true); CiFriendlyXMLFilter filter = new CiFriendlyXMLFilter(parser, true);
filter.setChangelist("CHANGELIST"); filter.setChangelist("CHANGELIST");

View File

@ -18,20 +18,21 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import java.util.function.Function; import java.util.function.Function;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.xmlunit.assertj.XmlAssert.assertThat; import static org.xmlunit.assertj.XmlAssert.assertThat;
class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests { class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests {
@Override @Override
protected XmlPullParser getFilter(XmlPullParser orgParser) { protected XMLStreamReader getFilter(XMLStreamReader orgParser) {
final BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new BuildToRawPomXMLFilterFactory(true) { final BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new BuildToRawPomXMLFilterFactory(true) {
@Override @Override
protected Function<Path, Optional<RelativeProject>> getRelativePathMapper() { protected Function<Path, Optional<RelativeProject>> getRelativePathMapper() {
@ -59,7 +60,7 @@ protected Optional<String> getChangelist() {
} }
}; };
XmlPullParser parser = XMLStreamReader parser =
new RawToConsumerPomXMLFilterFactory(buildPomXMLFilterFactory).get(orgParser, Paths.get("pom.xml")); new RawToConsumerPomXMLFilterFactory(buildPomXMLFilterFactory).get(orgParser, Paths.get("pom.xml"));
return parser; return parser;
} }

View File

@ -18,14 +18,15 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import javax.xml.stream.XMLStreamReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
class ModelVersionXMLFilterTest extends AbstractXMLFilterTests { class ModelVersionXMLFilterTest extends AbstractXMLFilterTests {
@Override @Override
protected XmlPullParser getFilter(XmlPullParser parser) { protected XMLStreamReader getFilter(XMLStreamReader parser) {
return new ModelVersionXMLFilter(parser); return new ModelVersionXMLFilter(parser);
} }

View File

@ -18,7 +18,8 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import javax.xml.stream.XMLStreamReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.xmlunit.assertj.XmlAssert.assertThat; import static org.xmlunit.assertj.XmlAssert.assertThat;
@ -26,7 +27,7 @@
class ModulesXMLFilterTest extends AbstractXMLFilterTests { class ModulesXMLFilterTest extends AbstractXMLFilterTests {
@Override @Override
protected ModulesXMLFilter getFilter(XmlPullParser parser) { protected ModulesXMLFilter getFilter(XMLStreamReader parser) {
return new ModulesXMLFilter(parser); return new ModulesXMLFilter(parser);
} }

View File

@ -18,19 +18,20 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function; import java.util.function.Function;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
class ParentXMLFilterTest extends AbstractXMLFilterTests { class ParentXMLFilterTest extends AbstractXMLFilterTests {
private Function<XmlPullParser, XmlPullParser> filterCreator; private Function<XMLStreamReader, XMLStreamReader> filterCreator;
@BeforeEach @BeforeEach
void reset() { void reset() {
@ -38,21 +39,21 @@ void reset() {
} }
@Override @Override
protected XmlPullParser getFilter(XmlPullParser parser) { protected XMLStreamReader getFilter(XMLStreamReader parser) {
Function<XmlPullParser, XmlPullParser> filterCreator = Function<XMLStreamReader, XMLStreamReader> filterCreator =
(this.filterCreator != null ? this.filterCreator : this::createFilter); (this.filterCreator != null ? this.filterCreator : this::createFilter);
return filterCreator.apply(parser); return filterCreator.apply(parser);
} }
protected XmlPullParser createFilter(XmlPullParser parser) { protected XMLStreamReader createFilter(XMLStreamReader parser) {
return createFilter( return createFilter(
parser, parser,
x -> Optional.of(new RelativeProject("GROUPID", "ARTIFACTID", "1.0.0")), x -> Optional.of(new RelativeProject("GROUPID", "ARTIFACTID", "1.0.0")),
Paths.get("pom.xml").toAbsolutePath()); Paths.get("pom.xml").toAbsolutePath());
} }
protected XmlPullParser createFilter( protected XMLStreamReader createFilter(
XmlPullParser parser, Function<Path, Optional<RelativeProject>> pathMapper, Path projectPath) { XMLStreamReader parser, Function<Path, Optional<RelativeProject>> pathMapper, Path projectPath) {
return new ParentXMLFilter(new FastForwardFilter(parser), pathMapper, projectPath); return new ParentXMLFilter(new FastForwardFilter(parser), pathMapper, projectPath);
} }
@ -154,12 +155,12 @@ void testDefaultRelativePath() throws Exception {
+ " <artifactId>ARTIFACTID</artifactId>\n" + " <artifactId>ARTIFACTID</artifactId>\n"
+ " </parent>\n" + " </parent>\n"
+ "</project>"; + "</project>";
String expected = "<project>" + System.lineSeparator() String expected = "<project>\n"
+ " <parent>" + System.lineSeparator() + " <parent>\n"
+ " <groupId>GROUPID</groupId>" + System.lineSeparator() + " <groupId>GROUPID</groupId>\n"
+ " <artifactId>ARTIFACTID</artifactId>" + System.lineSeparator() + " <artifactId>ARTIFACTID</artifactId>\n"
+ " <version>1.0.0</version>" + System.lineSeparator() + " <version>1.0.0</version>\n"
+ " </parent>" + System.lineSeparator() + " </parent>\n"
+ "</project>"; + "</project>";
String actual = transform(input); String actual = transform(input);
@ -299,13 +300,13 @@ void testIndent() throws Exception {
+ " <!--version here-->\n" + " <!--version here-->\n"
+ " </parent>\n" + " </parent>\n"
+ "</project>"; + "</project>";
String expected = "<project>" + System.lineSeparator() String expected = "<project>\n"
+ " <parent>" + System.lineSeparator() + " <parent>\n"
+ " <groupId>GROUPID</groupId>" + System.lineSeparator() + " <groupId>GROUPID</groupId>\n"
+ " <artifactId>ARTIFACTID</artifactId>" + System.lineSeparator() + " <artifactId>ARTIFACTID</artifactId>\n"
+ " <!--version here-->" + System.lineSeparator() + " <!--version here-->\n"
+ " <version>1.0.0</version>" + System.lineSeparator() + " <version>1.0.0</version>\n"
+ " </parent>" + System.lineSeparator() + " </parent>\n"
+ "</project>"; + "</project>";
String actual = transform(input); String actual = transform(input);

View File

@ -18,9 +18,10 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import javax.xml.stream.XMLStreamReader;
import java.util.function.BiFunction; import java.util.function.BiFunction;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -35,7 +36,7 @@ protected void reset() {
} }
@Override @Override
protected ReactorDependencyXMLFilter getFilter(XmlPullParser parser) { protected ReactorDependencyXMLFilter getFilter(XMLStreamReader parser) {
return new ReactorDependencyXMLFilter( return new ReactorDependencyXMLFilter(
parser, reactorVersionMapper != null ? reactorVersionMapper : (g, a) -> "1.0.0"); parser, reactorVersionMapper != null ? reactorVersionMapper : (g, a) -> "1.0.0");
} }

View File

@ -18,14 +18,15 @@
*/ */
package org.apache.maven.model.transform; package org.apache.maven.model.transform;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import javax.xml.stream.XMLStreamReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.xmlunit.assertj.XmlAssert.assertThat; import static org.xmlunit.assertj.XmlAssert.assertThat;
class RelativePathXMLFilterTest extends AbstractXMLFilterTests { class RelativePathXMLFilterTest extends AbstractXMLFilterTests {
@Override @Override
protected RelativePathXMLFilter getFilter(XmlPullParser parser) { protected RelativePathXMLFilter getFilter(XMLStreamReader parser) {
return new RelativePathXMLFilter(parser); return new RelativePathXMLFilter(parser);
} }

View File

@ -46,6 +46,22 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.36</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -61,6 +77,7 @@ under the License.
<model>src/main/mdo/maven.mdo</model> <model>src/main/mdo/maven.mdo</model>
</models> </models>
<params> <params>
<param>forcedIOModelVersion=4.0.0</param>
<param>packageModelV3=org.apache.maven.model</param> <param>packageModelV3=org.apache.maven.model</param>
<param>packageModelV4=org.apache.maven.api.model</param> <param>packageModelV4=org.apache.maven.api.model</param>
<param>packageToolV4=org.apache.maven.model.v4</param> <param>packageToolV4=org.apache.maven.model.v4</param>
@ -104,6 +121,8 @@ under the License.
<template>reader-ex.vm</template> <template>reader-ex.vm</template>
<template>writer.vm</template> <template>writer.vm</template>
<template>writer-ex.vm</template> <template>writer-ex.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates> </templates>
</configuration> </configuration>
</execution> </execution>

View File

@ -18,6 +18,8 @@
*/ */
package org.apache.maven.model.v4; package org.apache.maven.model.v4;
import javax.xml.stream.XMLStreamException;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.io.StringWriter; import java.io.StringWriter;
@ -25,7 +27,6 @@
import java.util.Map; import java.util.Map;
import org.apache.maven.api.model.Model; import org.apache.maven.api.model.Model;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -55,7 +56,7 @@ String toXml(Model model) throws IOException {
return sw.toString(); return sw.toString();
} }
Model fromXml(String xml) throws IOException, XmlPullParserException { Model fromXml(String xml) throws XMLStreamException {
return new MavenXpp3Reader().read(new StringReader(xml)); return new MavenStaxReader().read(new StringReader(xml));
} }
} }

View File

@ -0,0 +1,117 @@
/*
* 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.model.v4;
/*
* Copyright The Codehaus Foundation.
*
* Licensed 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.
*/
import javax.xml.stream.XMLStreamException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import org.apache.maven.api.model.InputSource;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
/**
* <p>Xpp3DomPerfTest class.</p>
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Warmup(iterations = 3)
@Measurement(time = 10)
public class Xpp3DomPerfTest {
@State(Scope.Benchmark)
public static class AdditionState {
List<Path> poms;
@Setup(Level.Iteration)
public void setUp() throws IOException {
Path userHome = Paths.get(System.getProperty("user.home"));
poms = Files.walk(userHome.resolve(".m2/repository/org/apache/maven"))
.filter(p -> p.getFileName().toString().endsWith(".pom"))
.collect(Collectors.toList());
}
}
@Benchmark
public int readWithXpp3(AdditionState state) throws IOException, XmlPullParserException {
int i = 0;
for (Path pom : state.poms) {
try (InputStream is = Files.newInputStream(pom)) {
new MavenXpp3ReaderEx().read(is, true, new InputSource("id", pom.toString()));
i++;
} catch (XmlPullParserException e) {
throw new RuntimeException("Error parsing: " + pom, e);
}
}
return i;
}
@Benchmark
public int readWithStax(AdditionState state) throws IOException, XMLStreamException {
int i = 0;
for (Path pom : state.poms) {
try (InputStream is = Files.newInputStream(pom)) {
MavenStaxReader reader = new MavenStaxReader();
reader.setAddLocationInformation(false);
reader.read(is, true, new InputSource("id", pom.toString()));
i++;
} catch (XMLStreamException e) {
throw new RuntimeException("Error parsing: " + pom, e);
}
}
return i;
}
/**
* <p>main.</p>
*
* @param args a {@link String} object.
* @throws org.openjdk.jmh.runner.RunnerException if any.
*/
public static void main(String... args) throws RunnerException {
Options opts = new OptionsBuilder().forks(1).build();
new Runner(opts).run();
}
}

View File

@ -78,11 +78,14 @@ under the License.
<template>model.vm</template> <template>model.vm</template>
<template>reader.vm</template> <template>reader.vm</template>
<template>writer.vm</template> <template>writer.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates> </templates>
<params> <params>
<param>packageModelV3=org.apache.maven.plugin.lifecycle</param> <param>packageModelV3=org.apache.maven.plugin.lifecycle</param>
<param>packageModelV4=org.apache.maven.plugin.lifecycle</param> <param>packageModelV4=org.apache.maven.plugin.lifecycle</param>
<param>packageToolV4=org.apache.maven.plugin.lifecycle.io.xpp3</param> <param>packageToolV4=org.apache.maven.plugin.lifecycle.io</param>
<param>packageToolV4Xpp3=org.apache.maven.plugin.lifecycle.io.xpp3</param>
</params> </params>
</configuration> </configuration>
</execution> </execution>

View File

@ -18,13 +18,14 @@
*/ */
package org.apache.maven.plugin.descriptor; package org.apache.maven.plugin.descriptor;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.nio.file.Files;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -37,11 +38,9 @@
import org.apache.maven.model.Plugin; import org.apache.maven.model.Plugin;
import org.apache.maven.plugin.lifecycle.Lifecycle; import org.apache.maven.plugin.lifecycle.Lifecycle;
import org.apache.maven.plugin.lifecycle.LifecycleConfiguration; import org.apache.maven.plugin.lifecycle.LifecycleConfiguration;
import org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader; import org.apache.maven.plugin.lifecycle.io.LifecycleMappingsStaxReader;
import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.codehaus.plexus.classworlds.realm.ClassRealm;
import org.codehaus.plexus.component.repository.ComponentSetDescriptor; import org.codehaus.plexus.component.repository.ComponentSetDescriptor;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* @author Jason van Zyl * @author Jason van Zyl
@ -327,12 +326,12 @@ public void setPluginArtifact(Artifact pluginArtifact) {
this.pluginArtifact = pluginArtifact; this.pluginArtifact = pluginArtifact;
} }
public Lifecycle getLifecycleMapping(String lifecycleId) throws IOException, XmlPullParserException { public Lifecycle getLifecycleMapping(String lifecycleId) throws IOException, XMLStreamException {
if (lifecycleMappings == null) { if (lifecycleMappings == null) {
LifecycleConfiguration lifecycleConfiguration; LifecycleConfiguration lifecycleConfiguration;
try (Reader reader = ReaderFactory.newXmlReader(getDescriptorStream(LIFECYCLE_DESCRIPTOR))) { try (InputStream input = getDescriptorStream(LIFECYCLE_DESCRIPTOR)) {
lifecycleConfiguration = new LifecycleMappingsXpp3Reader().read(reader); lifecycleConfiguration = new LifecycleMappingsStaxReader().read(input);
} }
lifecycleMappings = new HashMap<>(); lifecycleMappings = new HashMap<>();
@ -358,7 +357,7 @@ private InputStream getDescriptorStream(String descriptor) throws IOException {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
} else { } else {
return new FileInputStream(new File(pluginFile, descriptor)); return Files.newInputStream(new File(pluginFile, descriptor).toPath());
} }
} }

View File

@ -18,20 +18,22 @@
*/ */
package org.apache.maven.plugin.descriptor; package org.apache.maven.plugin.descriptor;
import java.io.IOException; import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.internal.xml.XmlNodeBuilder; import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.apache.maven.internal.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.component.repository.ComponentDependency;
import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.component.repository.ComponentRequirement;
import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration;
import org.codehaus.plexus.configuration.PlexusConfigurationException; import org.codehaus.plexus.configuration.PlexusConfigurationException;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* @author Jason van Zyl * @author Jason van Zyl
@ -374,16 +376,18 @@ public MojoDescriptor buildComponentDescriptor(PlexusConfiguration c, PluginDesc
public PlexusConfiguration buildConfiguration(Reader configuration) throws PlexusConfigurationException { public PlexusConfiguration buildConfiguration(Reader configuration) throws PlexusConfigurationException {
try { try {
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(configuration)); XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(configuration);
} catch (IOException | XmlPullParserException e) { return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(reader, true, null));
} catch (XMLStreamException e) {
throw new PlexusConfigurationException(e.getMessage(), e); throw new PlexusConfigurationException(e.getMessage(), e);
} }
} }
public PlexusConfiguration buildConfiguration(InputStream configuration) throws PlexusConfigurationException { public PlexusConfiguration buildConfiguration(InputStream configuration) throws PlexusConfigurationException {
try { try {
return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(configuration, null)); XMLStreamReader reader = WstxInputFactory.newFactory().createXMLStreamReader(configuration);
} catch (IOException | XmlPullParserException e) { return XmlPlexusConfiguration.toPlexusConfiguration(XmlNodeBuilder.build(reader, true, null));
} catch (XMLStreamException e) {
throw new PlexusConfigurationException(e.getMessage(), e); throw new PlexusConfigurationException(e.getMessage(), e);
} }
} }

View File

@ -36,6 +36,14 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-xml-impl</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.apache.maven.resolver</groupId> <groupId>org.apache.maven.resolver</groupId>
<artifactId>maven-resolver-api</artifactId> <artifactId>maven-resolver-api</artifactId>
@ -49,19 +57,50 @@ under the License.
<groupId>org.codehaus.modello</groupId> <groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId> <artifactId>modello-maven-plugin</artifactId>
<configuration> <configuration>
<version>1.1.0</version> <version>1.2.0</version>
<models> <models>
<model>src/main/mdo/metadata.mdo</model> <model>src/main/mdo/metadata.mdo</model>
</models> </models>
<params>
<param>forcedIOModelVersion=1.1.0</param>
<param>packageModelV3=org.apache.maven.artifact.repository.metadata</param>
<param>packageModelV4=org.apache.maven.artifact.repository.metadata.v4</param>
<param>packageToolV4=org.apache.maven.artifact.repository.metadata.io</param>
</params>
<velocityBasedir>${project.basedir}/../src/mdo</velocityBasedir>
</configuration> </configuration>
<executions> <executions>
<execution> <execution>
<id>modello</id> <id>modello</id>
<goals> <goals>
<goal>java</goal> <goal>velocity</goal>
<goal>xpp3-reader</goal>
<goal>xpp3-writer</goal>
</goals> </goals>
<configuration>
<version>1.2.0</version>
<models>
<model>src/main/mdo/metadata.mdo</model>
</models>
<templates>
<template>model.vm</template>
<template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates>
</configuration>
</execution>
<execution>
<id>modello-v3</id>
<goals>
<goal>velocity</goal>
</goals>
<configuration>
<version>1.1.0</version>
<models>
<model>src/main/mdo/metadata.mdo</model>
</models>
<templates>
<template>model-v3.vm</template>
</templates>
</configuration>
</execution> </execution>
</executions> </executions>
</plugin> </plugin>

View File

@ -0,0 +1,61 @@
/*
* 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.artifact.repository.metadata;
import java.io.Serializable;
public abstract class BaseObject implements Serializable, Cloneable {
protected transient ChildrenTracking childrenTracking;
protected Object delegate;
public BaseObject() {}
public BaseObject(Object delegate, BaseObject parent) {
this.delegate = delegate;
this.childrenTracking = parent != null ? parent::replace : null;
}
public BaseObject(Object delegate, ChildrenTracking parent) {
this.delegate = delegate;
this.childrenTracking = parent;
}
public Object getDelegate() {
return delegate;
}
public void update(Object newDelegate) {
if (delegate != newDelegate) {
if (childrenTracking != null) {
childrenTracking.replace(delegate, newDelegate);
}
delegate = newDelegate;
}
}
protected boolean replace(Object oldDelegate, Object newDelegate) {
return false;
}
@FunctionalInterface
protected interface ChildrenTracking {
boolean replace(Object oldDelegate, Object newDelegate);
}
}

View File

@ -19,7 +19,7 @@ under the License.
<model xmlns="http://codehaus-plexus.github.io/MODELLO/1.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <model xmlns="http://codehaus-plexus.github.io/MODELLO/1.4.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.4.0 http://codehaus-plexus.github.io/modello/xsd/modello-1.4.0.xsd" xsi:schemaLocation="http://codehaus-plexus.github.io/MODELLO/1.4.0 http://codehaus-plexus.github.io/modello/xsd/modello-1.4.0.xsd"
xsd.namespace="http://maven.apache.org/METADATA/${version}" xml.namespace="http://maven.apache.org/METADATA/${version}"
xml.schemaLocation="https://maven.apache.org/xsd/repository-metadata-${version}.xsd"> xml.schemaLocation="https://maven.apache.org/xsd/repository-metadata-${version}.xsd">
<id>repository-metadata</id> <id>repository-metadata</id>
<name>Metadata</name> <name>Metadata</name>
@ -35,11 +35,11 @@ under the License.
</default> </default>
</defaults> </defaults>
<classes> <classes>
<class rootElement="true" java.clone="deep"> <class rootElement="true" xml.tagName="metadata" java.clone="deep">
<name>Metadata</name> <name>Metadata</name>
<version>1.0.0+</version> <version>1.0.0+</version>
<fields> <fields>
<field xml.attribute="true"> <field xml.attribute="true" xml.tagName="modelVersion">
<name>modelVersion</name> <name>modelVersion</name>
<version>1.1.0+</version> <version>1.1.0+</version>
<type>String</type> <type>String</type>
@ -86,7 +86,7 @@ under the License.
</fields> </fields>
<codeSegments> <codeSegments>
<codeSegment> <codeSegment>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<code><![CDATA[ <code><![CDATA[
private String getSnapshotVersionKey( SnapshotVersion sv ) private String getSnapshotVersionKey( SnapshotVersion sv )
{ {
@ -299,7 +299,7 @@ under the License.
</fields> </fields>
<codeSegments> <codeSegments>
<codeSegment> <codeSegment>
<version>1.0.0+</version> <version>1.0.0/1.1.0</version>
<code><![CDATA[ <code><![CDATA[
public void updateTimestamp() public void updateTimestamp()
{ {

View File

@ -18,12 +18,21 @@
*/ */
package org.apache.maven.artifact.repository.metadata; package org.apache.maven.artifact.repository.metadata;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLOutputFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.text.DateFormat; import java.text.DateFormat;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.GregorianCalendar; import java.util.GregorianCalendar;
import java.util.TimeZone; import java.util.TimeZone;
import com.ctc.wstx.stax.WstxInputFactory;
import com.ctc.wstx.stax.WstxOutputFactory;
import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.apache.maven.artifact.repository.metadata.io.MetadataStaxWriter;
import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.artifact.DefaultArtifact;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
@ -31,6 +40,7 @@
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
class MetadataTest { class MetadataTest {
@ -209,6 +219,22 @@ void mergeWithSnapshotLegacy() {
} }
/*-- END test "groupId/artifactId/version" metadata ---*/ /*-- END test "groupId/artifactId/version" metadata ---*/
@Test
void testRoundtrip() throws Exception {
System.setProperty(XMLInputFactory.class.getName(), WstxInputFactory.class.getName());
System.setProperty(XMLOutputFactory.class.getName(), WstxOutputFactory.class.getName());
Metadata source = new Metadata(org.apache.maven.artifact.repository.metadata.v4.Metadata.newBuilder(
createMetadataFromArtifact(artifact).getDelegate(), true)
.modelEncoding("UTF-16")
.build());
ByteArrayOutputStream baos = new ByteArrayOutputStream();
new MetadataStaxWriter().write(baos, source.getDelegate());
Metadata source2 =
new Metadata(new MetadataStaxReader().read(new ByteArrayInputStream(baos.toByteArray()), true));
assertNotNull(source2);
}
/*-- START helper methods to populate metadata objects ---*/ /*-- START helper methods to populate metadata objects ---*/
private static final String SNAPSHOT = "SNAPSHOT"; private static final String SNAPSHOT = "SNAPSHOT";

View File

@ -22,8 +22,8 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.FileInputStream;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -33,7 +33,7 @@
import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.repository.metadata.Versioning; import org.apache.maven.artifact.repository.metadata.Versioning;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.eclipse.aether.RepositoryEvent; import org.eclipse.aether.RepositoryEvent;
import org.eclipse.aether.RepositoryEvent.EventType; import org.eclipse.aether.RepositoryEvent.EventType;
import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.RepositorySystemSession;
@ -202,9 +202,10 @@ private Versioning readVersions(
syncContext.acquire(null, Collections.singleton(metadata)); syncContext.acquire(null, Collections.singleton(metadata));
if (metadata.getFile() != null && metadata.getFile().exists()) { if (metadata.getFile() != null && metadata.getFile().exists()) {
try (InputStream in = new FileInputStream(metadata.getFile())) { try (InputStream in =
versioning = Files.newInputStream(metadata.getFile().toPath())) {
new MetadataXpp3Reader().read(in, false).getVersioning(); versioning = new Versioning(
new MetadataStaxReader().read(in, false).getVersioning());
} }
} }
} }

View File

@ -23,9 +23,9 @@
import javax.inject.Singleton; import javax.inject.Singleton;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.file.Files;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
@ -36,7 +36,7 @@
import org.apache.maven.artifact.repository.metadata.Snapshot; import org.apache.maven.artifact.repository.metadata.Snapshot;
import org.apache.maven.artifact.repository.metadata.SnapshotVersion; import org.apache.maven.artifact.repository.metadata.SnapshotVersion;
import org.apache.maven.artifact.repository.metadata.Versioning; import org.apache.maven.artifact.repository.metadata.Versioning;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.StringUtils;
import org.eclipse.aether.RepositoryCache; import org.eclipse.aether.RepositoryCache;
import org.eclipse.aether.RepositoryEvent; import org.eclipse.aether.RepositoryEvent;
@ -245,9 +245,10 @@ private Versioning readVersions(
syncContext.acquire(null, Collections.singleton(metadata)); syncContext.acquire(null, Collections.singleton(metadata));
if (metadata.getFile() != null && metadata.getFile().exists()) { if (metadata.getFile() != null && metadata.getFile().exists()) {
try (InputStream in = new FileInputStream(metadata.getFile())) { try (InputStream in =
versioning = Files.newInputStream(metadata.getFile().toPath())) {
new MetadataXpp3Reader().read(in, false).getVersioning(); versioning = new Versioning(
new MetadataStaxReader().read(in, false).getVersioning());
/* /*
NOTE: Users occasionally misuse the id "local" for remote repos which screws up the metadata NOTE: Users occasionally misuse the id "local" for remote repos which screws up the metadata

View File

@ -18,20 +18,20 @@
*/ */
package org.apache.maven.repository.internal; package org.apache.maven.repository.internal;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.InputStream;
import java.io.Writer; import java.io.OutputStream;
import java.nio.file.Files;
import java.util.Collections; import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.Map; import java.util.Map;
import org.apache.maven.artifact.repository.metadata.Metadata; import org.apache.maven.artifact.repository.metadata.Metadata;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Reader; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxReader;
import org.apache.maven.artifact.repository.metadata.io.xpp3.MetadataXpp3Writer; import org.apache.maven.artifact.repository.metadata.io.MetadataStaxWriter;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.WriterFactory;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.RepositoryException; import org.eclipse.aether.RepositoryException;
import org.eclipse.aether.metadata.AbstractMetadata; import org.eclipse.aether.metadata.AbstractMetadata;
import org.eclipse.aether.metadata.MergeableMetadata; import org.eclipse.aether.metadata.MergeableMetadata;
@ -86,20 +86,18 @@ static Metadata read(File metadataFile) throws RepositoryException {
return new Metadata(); return new Metadata();
} }
try (Reader reader = ReaderFactory.newXmlReader(metadataFile)) { try (InputStream input = Files.newInputStream(metadataFile.toPath())) {
return new MetadataXpp3Reader().read(reader, false); return new Metadata(new MetadataStaxReader().read(input, false));
} catch (IOException e) { } catch (IOException | XMLStreamException e) {
throw new RepositoryException("Could not read metadata " + metadataFile + ": " + e.getMessage(), e);
} catch (XmlPullParserException e) {
throw new RepositoryException("Could not parse metadata " + metadataFile + ": " + e.getMessage(), e); throw new RepositoryException("Could not parse metadata " + metadataFile + ": " + e.getMessage(), e);
} }
} }
private void write(File metadataFile, Metadata metadata) throws RepositoryException { private void write(File metadataFile, Metadata metadata) throws RepositoryException {
metadataFile.getParentFile().mkdirs(); metadataFile.getParentFile().mkdirs();
try (Writer writer = WriterFactory.newXmlWriter(metadataFile)) { try (OutputStream output = Files.newOutputStream(metadataFile.toPath())) {
new MetadataXpp3Writer().write(writer, metadata); new MetadataStaxWriter().write(output, metadata.getDelegate());
} catch (IOException e) { } catch (IOException | XMLStreamException e) {
throw new RepositoryException("Could not write metadata " + metadataFile + ": " + e.getMessage(), e); throw new RepositoryException("Could not write metadata " + metadataFile + ": " + e.getMessage(), e);
} }
} }

View File

@ -20,6 +20,7 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -31,8 +32,7 @@
import org.apache.maven.api.settings.InputSource; import org.apache.maven.api.settings.InputSource;
import org.apache.maven.settings.Settings; import org.apache.maven.settings.Settings;
import org.apache.maven.settings.v4.SettingsXpp3ReaderEx; import org.apache.maven.settings.v4.SettingsStaxReader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Handles deserialization of settings from the default textual format. * Handles deserialization of settings from the default textual format.
@ -49,9 +49,13 @@ public Settings read(File input, Map<String, ?> options) throws IOException {
try (InputStream in = Files.newInputStream(input.toPath())) { try (InputStream in = Files.newInputStream(input.toPath())) {
InputSource source = new InputSource(input.toString()); InputSource source = new InputSource(input.toString());
return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); return new Settings(new SettingsStaxReader().read(in, isStrict(options), source));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new SettingsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }
@ -61,9 +65,13 @@ public Settings read(Reader input, Map<String, ?> options) throws IOException {
try (Reader in = input) { try (Reader in = input) {
InputSource source = (InputSource) options.get(InputSource.class.getName()); InputSource source = (InputSource) options.get(InputSource.class.getName());
return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); return new Settings(new SettingsStaxReader().read(in, isStrict(options), source));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new SettingsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }
@ -73,9 +81,13 @@ public Settings read(InputStream input, Map<String, ?> options) throws IOExcepti
try (InputStream in = input) { try (InputStream in = input) {
InputSource source = (InputSource) options.get(InputSource.class.getName()); InputSource source = (InputSource) options.get(InputSource.class.getName());
return new Settings(new SettingsXpp3ReaderEx().read(in, isStrict(options), source)); return new Settings(new SettingsStaxReader().read(in, isStrict(options), source));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new SettingsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }

View File

@ -20,18 +20,18 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer; import java.io.Writer;
import java.nio.file.Files;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import org.apache.maven.settings.Settings; import org.apache.maven.settings.Settings;
import org.apache.maven.settings.v4.SettingsXpp3Writer; import org.apache.maven.settings.v4.SettingsStaxWriter;
import org.codehaus.plexus.util.xml.XmlStreamWriter;
/** /**
* Handles serialization of settings into the default textual format. * Handles serialization of settings into the default textual format.
@ -49,7 +49,7 @@ public void write(File output, Map<String, Object> options, Settings settings) t
output.getParentFile().mkdirs(); output.getParentFile().mkdirs();
write(new XmlStreamWriter(output), options, settings); write(Files.newOutputStream(output.toPath()), options, settings);
} }
@Override @Override
@ -58,7 +58,9 @@ public void write(Writer output, Map<String, Object> options, Settings settings)
Objects.requireNonNull(settings, "settings cannot be null"); Objects.requireNonNull(settings, "settings cannot be null");
try (Writer out = output) { try (Writer out = output) {
new SettingsXpp3Writer().write(out, settings.getDelegate()); new SettingsStaxWriter().write(out, settings.getDelegate());
} catch (XMLStreamException e) {
throw new IOException("Error writing settings", e);
} }
} }
@ -67,14 +69,10 @@ public void write(OutputStream output, Map<String, Object> options, Settings set
Objects.requireNonNull(output, "output cannot be null"); Objects.requireNonNull(output, "output cannot be null");
Objects.requireNonNull(settings, "settings cannot be null"); Objects.requireNonNull(settings, "settings cannot be null");
String encoding = settings.getModelEncoding(); try (OutputStream out = output) {
// TODO Use StringUtils here new SettingsStaxWriter().write(out, settings.getDelegate());
if (encoding == null || encoding.length() <= 0) { } catch (XMLStreamException e) {
encoding = "UTF-8"; throw new IOException("Error writing settings", e);
}
try (Writer out = new OutputStreamWriter(output, encoding)) {
write(out, options, settings);
} }
} }
} }

View File

@ -46,6 +46,10 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -61,6 +65,7 @@ under the License.
<model>src/main/mdo/settings.mdo</model> <model>src/main/mdo/settings.mdo</model>
</models> </models>
<params> <params>
<param>forcedIOModelVersion=1.2.0</param>
<param>packageModelV3=org.apache.maven.settings</param> <param>packageModelV3=org.apache.maven.settings</param>
<param>packageModelV4=org.apache.maven.api.settings</param> <param>packageModelV4=org.apache.maven.api.settings</param>
<param>packageToolV4=org.apache.maven.settings.v4</param> <param>packageToolV4=org.apache.maven.settings.v4</param>
@ -78,9 +83,9 @@ under the License.
<template>merger.vm</template> <template>merger.vm</template>
<template>transformer.vm</template> <template>transformer.vm</template>
<template>reader.vm</template> <template>reader.vm</template>
<template>reader-ex.vm</template>
<template>writer.vm</template> <template>writer.vm</template>
<template>writer-ex.vm</template> <template>reader-stax.vm</template>
<template>writer-stax.vm</template>
</templates> </templates>
<params combine.children="append"> <params combine.children="append">
<param>locationTracking=true</param> <param>locationTracking=true</param>

View File

@ -28,6 +28,7 @@
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Deprecated
public class SettingsXpp3Reader { public class SettingsXpp3Reader {
private boolean addDefaultEntities = true; private boolean addDefaultEntities = true;

View File

@ -24,6 +24,7 @@
import org.apache.maven.settings.Settings; import org.apache.maven.settings.Settings;
@Deprecated
public class SettingsXpp3Writer { public class SettingsXpp3Writer {
// --------------------------/ // --------------------------/
// - Class/Member Variables -/ // - Class/Member Variables -/

View File

@ -20,6 +20,7 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@ -30,8 +31,7 @@
import java.util.Objects; import java.util.Objects;
import org.apache.maven.toolchain.model.PersistedToolchains; import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.apache.maven.toolchain.v4.MavenToolchainsStaxReader;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/** /**
* Handles deserialization of toolchains from the default textual format. * Handles deserialization of toolchains from the default textual format.
@ -48,9 +48,13 @@ public PersistedToolchains read(File input, Map<String, ?> options) throws IOExc
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = Files.newInputStream(input.toPath())) { try (InputStream in = Files.newInputStream(input.toPath())) {
return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options))); return new PersistedToolchains(new MavenToolchainsStaxReader().read(in, isStrict(options)));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new ToolchainsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }
@ -59,9 +63,13 @@ public PersistedToolchains read(Reader input, Map<String, ?> options) throws IOE
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (Reader in = input) { try (Reader in = input) {
return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options))); return new PersistedToolchains(new MavenToolchainsStaxReader().read(in, isStrict(options)));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new ToolchainsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }
@ -70,9 +78,13 @@ public PersistedToolchains read(InputStream input, Map<String, ?> options) throw
Objects.requireNonNull(input, "input cannot be null"); Objects.requireNonNull(input, "input cannot be null");
try (InputStream in = input) { try (InputStream in = input) {
return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options))); return new PersistedToolchains(new MavenToolchainsStaxReader().read(in, isStrict(options)));
} catch (XmlPullParserException e) { } catch (XMLStreamException e) {
throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); throw new ToolchainsParseException(
e.getMessage(),
e.getLocation().getLineNumber(),
e.getLocation().getColumnNumber(),
e);
} }
} }

View File

@ -20,6 +20,7 @@
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Singleton; import javax.inject.Singleton;
import javax.xml.stream.XMLStreamException;
import java.io.IOException; import java.io.IOException;
import java.io.Writer; import java.io.Writer;
@ -27,7 +28,7 @@
import java.util.Objects; import java.util.Objects;
import org.apache.maven.toolchain.model.PersistedToolchains; import org.apache.maven.toolchain.model.PersistedToolchains;
import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; import org.apache.maven.toolchain.v4.MavenToolchainsStaxWriter;
/** /**
* Handles serialization of toolchains into the default textual format. * Handles serialization of toolchains into the default textual format.
@ -45,7 +46,9 @@ public void write(Writer output, Map<String, Object> options, PersistedToolchain
Objects.requireNonNull(toolchains, "toolchains cannot be null"); Objects.requireNonNull(toolchains, "toolchains cannot be null");
try (Writer out = output) { try (Writer out = output) {
new MavenToolchainsXpp3Writer().write(out, toolchains.getDelegate()); new MavenToolchainsStaxWriter().write(out, toolchains.getDelegate());
} catch (XMLStreamException e) {
throw new IOException("Error writing toolchains", e);
} }
} }
} }

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one

View File

@ -45,6 +45,10 @@ under the License.
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -71,8 +75,8 @@ under the License.
<templates> <templates>
<template>model-v3.vm</template> <template>model-v3.vm</template>
<template>merger.vm</template> <template>merger.vm</template>
<template>reader.vm</template> <template>reader-stax.vm</template>
<template>writer.vm</template> <template>writer-stax.vm</template>
</templates> </templates>
<params> <params>
<param>packageModelV3=org.apache.maven.toolchain.model</param> <param>packageModelV3=org.apache.maven.toolchain.model</param>

View File

@ -39,6 +39,10 @@ under the License.
<groupId>org.eclipse.sisu</groupId> <groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.plexus</artifactId> <artifactId>org.eclipse.sisu.plexus</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-xml</artifactId> <artifactId>plexus-xml</artifactId>

View File

@ -18,6 +18,9 @@
*/ */
package org.apache.maven.internal.xml; package org.apache.maven.internal.xml;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Reader; import java.io.Reader;
@ -26,6 +29,7 @@
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import com.ctc.wstx.stax.WstxInputFactory;
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.codehaus.plexus.util.xml.pull.MXParser; import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser;
@ -39,7 +43,7 @@ public class XmlNodeBuilder {
private static final boolean DEFAULT_TRIM = true; private static final boolean DEFAULT_TRIM = true;
public static XmlNodeImpl build(Reader reader) throws XmlPullParserException, IOException { public static XmlNodeImpl build(Reader reader) throws XmlPullParserException, IOException {
return build(reader, null); return build(reader, (InputLocationBuilder) null);
} }
/** /**
@ -155,6 +159,90 @@ public static XmlNodeImpl build(XmlPullParser parser, boolean trim, InputLocatio
throw new IllegalStateException("End of document found before returning to 0 depth"); throw new IllegalStateException("End of document found before returning to 0 depth");
} }
public static XmlNodeImpl build(Reader reader, InputLocationBuilderStax locationBuilder) throws XMLStreamException {
XMLStreamReader parser = WstxInputFactory.newFactory().createXMLStreamReader(reader);
return build(parser, DEFAULT_TRIM, locationBuilder);
}
public static XmlNodeImpl build(XMLStreamReader parser) throws XMLStreamException {
return build(parser, DEFAULT_TRIM, null);
}
public static XmlNodeImpl build(XMLStreamReader parser, InputLocationBuilderStax locationBuilder)
throws XMLStreamException {
return build(parser, DEFAULT_TRIM, locationBuilder);
}
public static XmlNodeImpl build(XMLStreamReader parser, boolean trim, InputLocationBuilderStax locationBuilder)
throws XMLStreamException {
boolean spacePreserve = false;
String name = null;
String value = null;
Object location = null;
Map<String, String> attrs = null;
List<XmlNode> children = null;
int eventType = parser.getEventType();
int lastStartTag = -1;
while (eventType != XMLStreamReader.END_DOCUMENT) {
if (eventType == XMLStreamReader.START_ELEMENT) {
lastStartTag = parser.getLocation().getLineNumber() * 1000
+ parser.getLocation().getColumnNumber();
if (name == null) {
int namespacesSize = parser.getNamespaceCount();
name = parser.getLocalName();
String pfx = parser.getPrefix();
if (pfx != null && !pfx.isEmpty()) {
name = pfx + ":" + name;
}
location = locationBuilder != null ? locationBuilder.toInputLocation(parser) : null;
int attributesSize = parser.getAttributeCount();
if (attributesSize > 0 || namespacesSize > 0) {
attrs = new HashMap<>();
for (int i = 0; i < namespacesSize; i++) {
String prefix = parser.getNamespacePrefix(i);
String namespace = parser.getNamespaceURI(i);
attrs.put("xmlns:" + prefix, namespace);
}
for (int i = 0; i < attributesSize; i++) {
String aname = parser.getAttributeLocalName(i);
String avalue = parser.getAttributeValue(i);
String apfx = parser.getAttributePrefix(i);
if (apfx != null && !apfx.isEmpty()) {
aname = apfx + ":" + aname;
}
attrs.put(aname, avalue);
spacePreserve = spacePreserve || ("xml:space".equals(aname) && "preserve".equals(avalue));
}
}
} else {
if (children == null) {
children = new ArrayList<>();
}
XmlNode child = build(parser, trim, locationBuilder);
children.add(child);
}
} else if (eventType == XMLStreamReader.CHARACTERS || eventType == XMLStreamReader.CDATA) {
String text = parser.getText();
value = value != null ? value + text : text;
} else if (eventType == XMLStreamReader.END_ELEMENT) {
boolean emptyTag = lastStartTag
== parser.getLocation().getLineNumber() * 1000
+ parser.getLocation().getColumnNumber();
if (value != null && trim && !spacePreserve) {
value = value.trim();
}
return new XmlNodeImpl(
name,
children == null ? (value != null ? value : emptyTag ? null : "") : null,
attrs,
children,
location);
}
eventType = parser.next();
}
throw new IllegalStateException("End of document found before returning to 0 depth");
}
/** /**
* Input location builder interface, to be implemented to choose how to store data. * Input location builder interface, to be implemented to choose how to store data.
* *
@ -163,4 +251,8 @@ public static XmlNodeImpl build(XmlPullParser parser, boolean trim, InputLocatio
public interface InputLocationBuilder { public interface InputLocationBuilder {
Object toInputLocation(XmlPullParser parser); Object toInputLocation(XmlPullParser parser);
} }
public interface InputLocationBuilderStax {
Object toInputLocation(XMLStreamReader parser);
}
} }

View File

@ -18,7 +18,11 @@
*/ */
package org.apache.maven.internal.xml; package org.apache.maven.internal.xml;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.IOException; import java.io.IOException;
import java.io.Reader;
import java.io.StringReader; import java.io.StringReader;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -29,8 +33,6 @@
import org.apache.maven.api.xml.XmlNode; import org.apache.maven.api.xml.XmlNode;
import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.Xpp3Dom;
import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.Xpp3DomBuilder;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
@ -241,7 +243,7 @@ void testCombineKeys() throws Exception {
} }
@Test @Test
void testPreserveDominantBlankValue() throws XmlPullParserException, IOException { void testPreserveDominantBlankValue() throws XMLStreamException, IOException {
String lhs = "<parameter xml:space=\"preserve\"> </parameter>"; String lhs = "<parameter xml:space=\"preserve\"> </parameter>";
String rhs = "<parameter>recessive</parameter>"; String rhs = "<parameter>recessive</parameter>";
@ -254,7 +256,7 @@ void testPreserveDominantBlankValue() throws XmlPullParserException, IOException
} }
@Test @Test
void testPreserveDominantEmptyNode() throws XmlPullParserException, IOException { void testPreserveDominantEmptyNode() throws XMLStreamException, IOException {
String lhs = "<parameter></parameter>"; String lhs = "<parameter></parameter>";
String rhs = "<parameter>recessive</parameter>"; String rhs = "<parameter>recessive</parameter>";
@ -267,7 +269,7 @@ void testPreserveDominantEmptyNode() throws XmlPullParserException, IOException
} }
@Test @Test
void testPreserveDominantEmptyNode2() throws XmlPullParserException, IOException { void testPreserveDominantEmptyNode2() throws XMLStreamException, IOException {
String lhs = "<parameter/>"; String lhs = "<parameter/>";
String rhs = "<parameter>recessive</parameter>"; String rhs = "<parameter>recessive</parameter>";
@ -442,14 +444,11 @@ void testEquals() {
/** /**
* <p>testEqualsIsNullSafe.</p> * <p>testEqualsIsNullSafe.</p>
*
* @throws org.codehaus.plexus.util.xml.pull.XmlPullParserException if any.
* @throws java.io.IOException if any.
*/ */
@Test @Test
void testEqualsIsNullSafe() throws XmlPullParserException, IOException { void testEqualsIsNullSafe() throws XMLStreamException, IOException {
String testDom = "<configuration><items thing='blah'><item>one</item><item>two</item></items></configuration>"; String testDom = "<configuration><items thing='blah'><item>one</item><item>two</item></items></configuration>";
Xpp3Dom dom = Xpp3DomBuilder.build(new StringReader(testDom)); XmlNode dom = toXmlNode(testDom);
Map<String, String> attributes = new HashMap<>(); Map<String, String> attributes = new HashMap<>();
attributes.put("nullValue", null); attributes.put("nullValue", null);
@ -464,19 +463,14 @@ void testEqualsIsNullSafe() throws XmlPullParserException, IOException {
/** /**
* <p>testShouldOverwritePluginConfigurationSubItemsByDefault.</p> * <p>testShouldOverwritePluginConfigurationSubItemsByDefault.</p>
*
* @throws org.codehaus.plexus.util.xml.pull.XmlPullParserException if any.
* @throws java.io.IOException if any.
*/ */
@Test @Test
void testShouldOverwritePluginConfigurationSubItemsByDefault() throws XmlPullParserException, IOException { void testShouldOverwritePluginConfigurationSubItemsByDefault() throws XMLStreamException, IOException {
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>"; String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
XmlNode parentConfig = XmlNode parentConfig = toXmlNode(parentConfigStr, new FixedInputLocationBuilder("parent"));
XmlNodeBuilder.build(new StringReader(parentConfigStr), new FixedInputLocationBuilder("parent"));
String childConfigStr = "<configuration><items><item>three</item></items></configuration>"; String childConfigStr = "<configuration><items><item>three</item></items></configuration>";
XmlNode childConfig = XmlNode childConfig = toXmlNode(childConfigStr, new FixedInputLocationBuilder("child"));
XmlNodeBuilder.build(new StringReader(childConfigStr), new FixedInputLocationBuilder("child"));
XmlNode result = XmlNode.merge(childConfig, parentConfig); XmlNode result = XmlNode.merge(childConfig, parentConfig);
XmlNode items = result.getChild("items"); XmlNode items = result.getChild("items");
@ -490,20 +484,15 @@ void testShouldOverwritePluginConfigurationSubItemsByDefault() throws XmlPullPar
/** /**
* <p>testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet.</p> * <p>testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet.</p>
*
* @throws org.codehaus.plexus.util.xml.pull.XmlPullParserException if any.
* @throws java.io.IOException if any.
*/ */
@Test @Test
void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet() throws XmlPullParserException, IOException { void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet() throws XMLStreamException, IOException {
String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>"; String parentConfigStr = "<configuration><items><item>one</item><item>two</item></items></configuration>";
XmlNode parentConfig = XmlNode parentConfig = toXmlNode(parentConfigStr, new FixedInputLocationBuilder("parent"));
XmlNodeBuilder.build(new StringReader(parentConfigStr), new FixedInputLocationBuilder("parent"));
String childConfigStr = String childConfigStr =
"<configuration><items combine.children=\"append\"><item>three</item></items></configuration>"; "<configuration><items combine.children=\"append\"><item>three</item></items></configuration>";
XmlNode childConfig = XmlNode childConfig = toXmlNode(childConfigStr, new FixedInputLocationBuilder("child"));
XmlNodeBuilder.build(new StringReader(childConfigStr), new FixedInputLocationBuilder("child"));
XmlNode result = XmlNode.merge(childConfig, parentConfig); XmlNode result = XmlNode.merge(childConfig, parentConfig);
XmlNode items = result.getChild("items"); XmlNode items = result.getChild("items");
@ -562,14 +551,11 @@ void testShouldCopyRecessiveChildrenNotPresentInTarget() throws Exception {
/** /**
* <p>testDupeChildren.</p> * <p>testDupeChildren.</p>
*
* @throws java.io.IOException if any.
* @throws org.codehaus.plexus.util.xml.pull.XmlPullParserException if any.
*/ */
@Test @Test
void testDupeChildren() throws IOException, XmlPullParserException { void testDupeChildren() throws IOException, XMLStreamException {
String dupes = "<configuration><foo>x</foo><foo>y</foo></configuration>"; String dupes = "<configuration><foo>x</foo><foo>y</foo></configuration>";
Xpp3Dom dom = Xpp3DomBuilder.build(new StringReader(dupes)); XmlNode dom = toXmlNode(new StringReader(dupes));
assertNotNull(dom); assertNotNull(dom);
assertEquals("y", dom.getChild("foo").getValue()); assertEquals("y", dom.getChild("foo").getValue());
} }
@ -611,7 +597,7 @@ void testShouldRemoveDoNotRemoveTagWhenSwappedInputDOMs() throws Exception {
} }
@Test @Test
void testMergeCombineChildrenAppendOnRecessive() throws XmlPullParserException, IOException { void testMergeCombineChildrenAppendOnRecessive() throws XMLStreamException, IOException {
String dominant = "<relocations>\n" + " <relocation>\n" String dominant = "<relocations>\n" + " <relocation>\n"
+ " <pattern>org.apache.shiro.crypto.CipherService</pattern>\n" + " <pattern>org.apache.shiro.crypto.CipherService</pattern>\n"
+ " <shadedPattern>org.apache.shiro.crypto.cipher.CipherService</shadedPattern>\n" + " <shadedPattern>org.apache.shiro.crypto.cipher.CipherService</shadedPattern>\n"
@ -634,8 +620,8 @@ void testMergeCombineChildrenAppendOnRecessive() throws XmlPullParserException,
+ " </relocation>\n" + " </relocation>\n"
+ "</relocations>"; + "</relocations>";
XmlNodeImpl d = XmlNodeBuilder.build(new StringReader(dominant)); XmlNode d = toXmlNode(dominant);
XmlNodeImpl r = XmlNodeBuilder.build(new StringReader(recessive)); XmlNode r = toXmlNode(recessive);
XmlNode m = d.merge(r); XmlNode m = d.merge(r);
assertEquals(expected, m.toString().replaceAll("\r\n", "\n")); assertEquals(expected, m.toString().replaceAll("\r\n", "\n"));
} }
@ -652,23 +638,32 @@ private static XmlNode getNthChild(XmlNode node, String name, int nth) {
.orElse(null); .orElse(null);
} }
private static XmlNode toXmlNode(String xml) throws XmlPullParserException, IOException { private static XmlNode toXmlNode(String xml) throws XMLStreamException, IOException {
return toXmlNode(xml, null); return toXmlNode(xml, null);
} }
private static XmlNode toXmlNode(String xml, XmlNodeBuilder.InputLocationBuilder locationBuilder) private static XmlNode toXmlNode(String xml, XmlNodeBuilder.InputLocationBuilderStax locationBuilder)
throws XmlPullParserException, IOException { throws XMLStreamException, IOException {
return XmlNodeBuilder.build(new StringReader(xml), locationBuilder); return toXmlNode(new StringReader(xml), locationBuilder);
} }
private static class FixedInputLocationBuilder implements XmlNodeBuilder.InputLocationBuilder { private static XmlNode toXmlNode(Reader reader) throws XMLStreamException, IOException {
return toXmlNode(reader, null);
}
private static XmlNode toXmlNode(Reader reader, XmlNodeBuilder.InputLocationBuilderStax locationBuilder)
throws XMLStreamException, IOException {
return XmlNodeBuilder.build(reader, locationBuilder);
}
private static class FixedInputLocationBuilder implements XmlNodeBuilder.InputLocationBuilderStax {
private final Object location; private final Object location;
public FixedInputLocationBuilder(Object location) { public FixedInputLocationBuilder(Object location) {
this.location = location; this.location = location;
} }
public Object toInputLocation(XmlPullParser parser) { public Object toInputLocation(XMLStreamReader parser) {
return location; return location;
} }
} }

10
pom.xml
View File

@ -404,6 +404,16 @@ under the License.
<artifactId>plexus-cipher</artifactId> <artifactId>plexus-cipher</artifactId>
<version>${cipherVersion}</version> <version>${cipherVersion}</version>
</dependency> </dependency>
<dependency>
<groupId>com.fasterxml.woodstox</groupId>
<artifactId>woodstox-core</artifactId>
<version>6.5.1</version>
</dependency>
<dependency>
<groupId>org.codehaus.woodstox</groupId>
<artifactId>stax2-api</artifactId>
<version>4.2.1</version>
</dependency>
<dependency> <dependency>
<groupId>org.xmlunit</groupId> <groupId>org.xmlunit</groupId>
<artifactId>xmlunit-assertj</artifactId> <artifactId>xmlunit-assertj</artifactId>

View File

@ -18,7 +18,11 @@
*# *#
#parse ( "common.vm" ) #parse ( "common.vm" )
# #
#set ( $package = "${packageToolV4}" ) #if( ${packageToolV4Xpp3} )
#set ( $package = "${packageToolV4Xpp3}" )
#else
#set ( $package = "${packageToolV4}" )
#end
#set ( $className = "${model.name}Xpp3ReaderEx" ) #set ( $className = "${model.name}Xpp3ReaderEx" )
# #
#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) )
@ -59,6 +63,7 @@ import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Deprecated
@Generated @Generated
public class ${className} { public class ${className} {

View File

@ -18,7 +18,11 @@
*# *#
#parse ( "common.vm" ) #parse ( "common.vm" )
# #
#set ( $package = "${packageToolV4}" ) #if( ${packageToolV4Xpp3} )
#set ( $package = "${packageToolV4Xpp3}" )
#else
#set ( $package = "${packageToolV4}" )
#end
#set ( $className = "${model.name}Xpp3Reader" ) #set ( $className = "${model.name}Xpp3Reader" )
# #
#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) )
@ -57,6 +61,7 @@ import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Deprecated
@Generated @Generated
public class ${className} { public class ${className} {

918
src/mdo/reader-stax.vm Normal file
View File

@ -0,0 +1,918 @@
#*
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}StaxReader" )
#
#set ( $root = $model.getClass( $model.getRoot($version), $version ) )
#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.Reader;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.maven.api.annotations.Generated;
#if ( $locationTracking )
import ${packageModelV4}.InputSource;
import ${packageModelV4}.InputLocation;
#end
#foreach ( $class in $model.allClasses )
import ${packageModelV4}.${class.name};
#end
import org.apache.maven.internal.xml.XmlNodeBuilder;
import org.apache.maven.api.xml.XmlNode;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
@Generated
public class ${className} {
private static final Map<String, String> DEFAULT_ENTITIES;
static {
Map<String, String> entities = new HashMap<>();
entities.put("nbsp", "\u00a0");
entities.put("iexcl", "\u00a1");
entities.put("cent", "\u00a2");
entities.put("pound", "\u00a3");
entities.put("curren", "\u00a4");
entities.put("yen", "\u00a5");
entities.put("brvbar", "\u00a6");
entities.put("sect", "\u00a7");
entities.put("uml", "\u00a8");
entities.put("copy", "\u00a9");
entities.put("ordf", "\u00aa");
entities.put("laquo", "\u00ab");
entities.put("not", "\u00ac");
entities.put("shy", "\u00ad");
entities.put("reg", "\u00ae");
entities.put("macr", "\u00af");
entities.put("deg", "\u00b0");
entities.put("plusmn", "\u00b1");
entities.put("sup2", "\u00b2");
entities.put("sup3", "\u00b3");
entities.put("acute", "\u00b4");
entities.put("micro", "\u00b5");
entities.put("para", "\u00b6");
entities.put("middot", "\u00b7");
entities.put("cedil", "\u00b8");
entities.put("sup1", "\u00b9");
entities.put("ordm", "\u00ba");
entities.put("raquo", "\u00bb");
entities.put("frac14", "\u00bc");
entities.put("frac12", "\u00bd");
entities.put("frac34", "\u00be");
entities.put("iquest", "\u00bf");
entities.put("Agrave", "\u00c0");
entities.put("Aacute", "\u00c1");
entities.put("Acirc", "\u00c2");
entities.put("Atilde", "\u00c3");
entities.put("Auml", "\u00c4");
entities.put("Aring", "\u00c5");
entities.put("AElig", "\u00c6");
entities.put("Ccedil", "\u00c7");
entities.put("Egrave", "\u00c8");
entities.put("Eacute", "\u00c9");
entities.put("Ecirc", "\u00ca");
entities.put("Euml", "\u00cb");
entities.put("Igrave", "\u00cc");
entities.put("Iacute", "\u00cd");
entities.put("Icirc", "\u00ce");
entities.put("Iuml", "\u00cf");
entities.put("ETH", "\u00d0");
entities.put("Ntilde", "\u00d1");
entities.put("Ograve", "\u00d2");
entities.put("Oacute", "\u00d3");
entities.put("Ocirc", "\u00d4");
entities.put("Otilde", "\u00d5");
entities.put("Ouml", "\u00d6");
entities.put("times", "\u00d7");
entities.put("Oslash", "\u00d8");
entities.put("Ugrave", "\u00d9");
entities.put("Uacute", "\u00da");
entities.put("Ucirc", "\u00db");
entities.put("Uuml", "\u00dc");
entities.put("Yacute", "\u00dd");
entities.put("THORN", "\u00de");
entities.put("szlig", "\u00df");
entities.put("agrave", "\u00e0");
entities.put("aacute", "\u00e1");
entities.put("acirc", "\u00e2");
entities.put("atilde", "\u00e3");
entities.put("auml", "\u00e4");
entities.put("aring", "\u00e5");
entities.put("aelig", "\u00e6");
entities.put("ccedil", "\u00e7");
entities.put("egrave", "\u00e8");
entities.put("eacute", "\u00e9");
entities.put("ecirc", "\u00ea");
entities.put("euml", "\u00eb");
entities.put("igrave", "\u00ec");
entities.put("iacute", "\u00ed");
entities.put("icirc", "\u00ee");
entities.put("iuml", "\u00ef");
entities.put("eth", "\u00f0");
entities.put("ntilde", "\u00f1");
entities.put("ograve", "\u00f2");
entities.put("oacute", "\u00f3");
entities.put("ocirc", "\u00f4");
entities.put("otilde", "\u00f5");
entities.put("ouml", "\u00f6");
entities.put("divide", "\u00f7");
entities.put("oslash", "\u00f8");
entities.put("ugrave", "\u00f9");
entities.put("uacute", "\u00fa");
entities.put("ucirc", "\u00fb");
entities.put("uuml", "\u00fc");
entities.put("yacute", "\u00fd");
entities.put("thorn", "\u00fe");
entities.put("yuml", "\u00ff");
// ----------------------------------------------------------------------
// Special entities
// ----------------------------------------------------------------------
entities.put("OElig", "\u0152");
entities.put("oelig", "\u0153");
entities.put("Scaron", "\u0160");
entities.put("scaron", "\u0161");
entities.put("Yuml", "\u0178");
entities.put("circ", "\u02c6");
entities.put("tilde", "\u02dc");
entities.put("ensp", "\u2002");
entities.put("emsp", "\u2003");
entities.put("thinsp", "\u2009");
entities.put("zwnj", "\u200c");
entities.put("zwj", "\u200d");
entities.put("lrm", "\u200e");
entities.put("rlm", "\u200f");
entities.put("ndash", "\u2013");
entities.put("mdash", "\u2014");
entities.put("lsquo", "\u2018");
entities.put("rsquo", "\u2019");
entities.put("sbquo", "\u201a");
entities.put("ldquo", "\u201c");
entities.put("rdquo", "\u201d");
entities.put("bdquo", "\u201e");
entities.put("dagger", "\u2020");
entities.put("Dagger", "\u2021");
entities.put("permil", "\u2030");
entities.put("lsaquo", "\u2039");
entities.put("rsaquo", "\u203a");
entities.put("euro", "\u20ac");
// ----------------------------------------------------------------------
// Symbol entities
// ----------------------------------------------------------------------
entities.put("fnof", "\u0192");
entities.put("Alpha", "\u0391");
entities.put("Beta", "\u0392");
entities.put("Gamma", "\u0393");
entities.put("Delta", "\u0394");
entities.put("Epsilon", "\u0395");
entities.put("Zeta", "\u0396");
entities.put("Eta", "\u0397");
entities.put("Theta", "\u0398");
entities.put("Iota", "\u0399");
entities.put("Kappa", "\u039a");
entities.put("Lambda", "\u039b");
entities.put("Mu", "\u039c");
entities.put("Nu", "\u039d");
entities.put("Xi", "\u039e");
entities.put("Omicron", "\u039f");
entities.put("Pi", "\u03a0");
entities.put("Rho", "\u03a1");
entities.put("Sigma", "\u03a3");
entities.put("Tau", "\u03a4");
entities.put("Upsilon", "\u03a5");
entities.put("Phi", "\u03a6");
entities.put("Chi", "\u03a7");
entities.put("Psi", "\u03a8");
entities.put("Omega", "\u03a9");
entities.put("alpha", "\u03b1");
entities.put("beta", "\u03b2");
entities.put("gamma", "\u03b3");
entities.put("delta", "\u03b4");
entities.put("epsilon", "\u03b5");
entities.put("zeta", "\u03b6");
entities.put("eta", "\u03b7");
entities.put("theta", "\u03b8");
entities.put("iota", "\u03b9");
entities.put("kappa", "\u03ba");
entities.put("lambda", "\u03bb");
entities.put("mu", "\u03bc");
entities.put("nu", "\u03bd");
entities.put("xi", "\u03be");
entities.put("omicron", "\u03bf");
entities.put("pi", "\u03c0");
entities.put("rho", "\u03c1");
entities.put("sigmaf", "\u03c2");
entities.put("sigma", "\u03c3");
entities.put("tau", "\u03c4");
entities.put("upsilon", "\u03c5");
entities.put("phi", "\u03c6");
entities.put("chi", "\u03c7");
entities.put("psi", "\u03c8");
entities.put("omega", "\u03c9");
entities.put("thetasym", "\u03d1");
entities.put("upsih", "\u03d2");
entities.put("piv", "\u03d6");
entities.put("bull", "\u2022");
entities.put("hellip", "\u2026");
entities.put("prime", "\u2032");
entities.put("Prime", "\u2033");
entities.put("oline", "\u203e");
entities.put("frasl", "\u2044");
entities.put("weierp", "\u2118");
entities.put("image", "\u2111");
entities.put("real", "\u211c");
entities.put("trade", "\u2122");
entities.put("alefsym", "\u2135");
entities.put("larr", "\u2190");
entities.put("uarr", "\u2191");
entities.put("rarr", "\u2192");
entities.put("darr", "\u2193");
entities.put("harr", "\u2194");
entities.put("crarr", "\u21b5");
entities.put("lArr", "\u21d0");
entities.put("uArr", "\u21d1");
entities.put("rArr", "\u21d2");
entities.put("dArr", "\u21d3");
entities.put("hArr", "\u21d4");
entities.put("forall", "\u2200");
entities.put("part", "\u2202");
entities.put("exist", "\u2203");
entities.put("empty", "\u2205");
entities.put("nabla", "\u2207");
entities.put("isin", "\u2208");
entities.put("notin", "\u2209");
entities.put("ni", "\u220b");
entities.put("prod", "\u220f");
entities.put("sum", "\u2211");
entities.put("minus", "\u2212");
entities.put("lowast", "\u2217");
entities.put("radic", "\u221a");
entities.put("prop", "\u221d");
entities.put("infin", "\u221e");
entities.put("ang", "\u2220");
entities.put("and", "\u2227");
entities.put("or", "\u2228");
entities.put("cap", "\u2229");
entities.put("cup", "\u222a");
entities.put("int", "\u222b");
entities.put("there4", "\u2234");
entities.put("sim", "\u223c");
entities.put("cong", "\u2245");
entities.put("asymp", "\u2248");
entities.put("ne", "\u2260");
entities.put("equiv", "\u2261");
entities.put("le", "\u2264");
entities.put("ge", "\u2265");
entities.put("sub", "\u2282");
entities.put("sup", "\u2283");
entities.put("nsub", "\u2284");
entities.put("sube", "\u2286");
entities.put("supe", "\u2287");
entities.put("oplus", "\u2295");
entities.put("otimes", "\u2297");
entities.put("perp", "\u22a5");
entities.put("sdot", "\u22c5");
entities.put("lceil", "\u2308");
entities.put("rceil", "\u2309");
entities.put("lfloor", "\u230a");
entities.put("rfloor", "\u230b");
entities.put("lang", "\u2329");
entities.put("rang", "\u232a");
entities.put("loz", "\u25ca");
entities.put("spades", "\u2660");
entities.put("clubs", "\u2663");
entities.put("hearts", "\u2665");
entities.put("diams", "\u2666");
DEFAULT_ENTITIES = Collections.unmodifiableMap(entities);
}
private boolean addDefaultEntities = true;
#if ( $locationTracking )
private boolean addLocationInformation = true;
#end
private final ContentTransformer contentTransformer;
public ${className}() {
this((s, f) -> s);
}
public ${className}(ContentTransformer contentTransformer) {
this.contentTransformer = contentTransformer;
}
/**
* Returns the state of the "add default entities" flag.
*
* @return boolean
*/
public boolean getAddDefaultEntities() {
return addDefaultEntities;
} //-- boolean getAddDefaultEntities()
/**
* Sets the state of the "add default entities" flag.
*
* @param addDefaultEntities a addDefaultEntities object.
*/
public void setAddDefaultEntities(boolean addDefaultEntities) {
this.addDefaultEntities = addDefaultEntities;
} //-- void setAddDefaultEntities(boolean)
#if ( $locationTracking )
/**
* Returns the state of the "add location information" flag.
*
* @return boolean
*/
public boolean getAddLocationInformation() {
return addLocationInformation;
} //-- boolean getAddLocationInformation()
/**
* Sets the state of the "add location information" flag.
*
* @param addLocationInformation a addLocationInformation object.
*/
public void setAddLocationInformation(boolean addLocationInformation) {
this.addLocationInformation = addLocationInformation;
} //-- void setAddLocationInformation(boolean)
#end
public ${root.name} read(Reader reader) throws XMLStreamException {
#if ( $locationTracking )
return read(reader, true, null);
#else
return read(reader, true);
#end
}
/**
* @param reader a reader object.
* @param strict a strict object.
* @throws XMLStreamException XMLStreamException if
* any.
* @return ${root.name}
*/
#if ( $locationTracking )
public ${root.name} read(Reader reader, boolean strict, InputSource source) throws XMLStreamException {
#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, false);
#if ( $locationTracking )
StreamSource streamSource = new StreamSource(reader, source != null ? source.getLocation() : null);
#else
StreamSource streamSource = new StreamSource(reader);
#end
XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
#if ( $locationTracking )
return read(parser, strict, source);
#else
return read(parser, strict);
#end
} //-- ${root.name} read(Reader, boolean)
public ${root.name} read(InputStream in) throws XMLStreamException {
#if ( $locationTracking )
return read(in, true, null);
#else
return read(in, true);
#end
}
/**
* Method read.
*
* @param in a in object.
* @param strict a strict object.
* @throws XMLStreamException XMLStreamException if
* any.
* @return ${root.name}
*/
#if ( $locationTracking )
public ${root.name} read(InputStream in, boolean strict, InputSource source) throws XMLStreamException {
#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, false);
#if ( $locationTracking )
StreamSource streamSource = new StreamSource(in, source != null ? source.getLocation() : null);
#else
StreamSource streamSource = new StreamSource(in);
#end
XMLStreamReader parser = factory.createXMLStreamReader(streamSource);
#if ( $locationTracking )
return read(parser, strict, source);
#else
return read(parser, strict);
#end
} //-- ${root.name} read(InputStream, boolean)
/**
* Method read.
*
* @param parser a parser object.
* @param strict a strict object.
* @throws XMLStreamException XMLStreamException if
* any.
* @return ${root.name}
*/
#if ( $locationTracking )
public ${root.name} read(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException {
#else
public ${root.name} read(XMLStreamReader parser, boolean strict) throws XMLStreamException {
#end
$rootUcapName $rootLcapName = null;
int eventType = parser.getEventType();
boolean parsed = false;
while (eventType != XMLStreamReader.END_DOCUMENT) {
if (eventType == XMLStreamReader.START_ELEMENT) {
if (strict && ! "${rootTag}".equals(parser.getLocalName())) {
throw new XMLStreamException("Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser.getLocation(), null);
} else if (parsed) {
// fallback, already expected a XMLStreamException due to invalid XML
throw new XMLStreamException("Duplicated tag: '${rootTag}'", parser.getLocation(), null);
}
#if ( $locationTracking )
$rootLcapName = parse${rootUcapName}(parser, strict, source);
#else
$rootLcapName = parse${rootUcapName}(parser, strict);
#end
parsed = true;
}
eventType = parser.next();
}
if (parsed) {
return $rootLcapName;
}
throw new XMLStreamException("Expected root element '${rootTag}' but found no element at all: invalid XML document", parser.getLocation(), null);
} //-- ${root.name} read(XMLStreamReader, boolean)
#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 ( $ancestors = $Helper.ancestors( $class ) )
#set ( $allFields = $Helper.xmlFields( $class ) )
#if ( $locationTracking )
private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict, InputSource source) throws XMLStreamException {
#else
private ${classUcapName} parse${classUcapName}(XMLStreamReader parser, boolean strict) throws XMLStreamException {
#end
String tagName = parser.getLocalName();
${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder(true);
#if ( $locationTracking )
if (addLocationInformation){
${classLcapName}.location("", new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source));
}
#end
for (int i = parser.getAttributeCount() - 1; i >= 0; i--) {
String name = parser.getAttributeLocalName(i);
String ns = parser.getAttributeNamespace(i);
String value = parser.getAttributeValue(i);
if ("http://www.w3.org/2001/XMLSchema-instance".equals(ns)) {
// just ignore attributes with non-default namespace (for example: xmlns:xsi)
#if ( $class == $root )
} else if ("xmlns".equals(name)) {
// ignore xmlns attribute in root class, which is a reserved attribute name
#end
#foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).attribute )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#set ( $fieldCapName = $Helper.capitalise( $field.name ) )
} else if ("$fieldTagName".equals(name)) {
#if ( $locationTracking )
if (addLocationInformation) {
${classLcapName}.location(name, new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source));
}
#end
#if ( $field.type == "String" )
${classLcapName}.${field.name}(interpolatedTrimmed(value, "$fieldTagName"));
#elseif ( $field.type == "boolean" || $field.type == "Boolean" )
${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(value, "$fieldTagName"), "$fieldTagName", parser, ${field.defaultValue}));
#else
// TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
#end
#end
#end
} else {
checkUnknownAttribute(parser, name, tagName, strict);
}
}
Set<String> parsed = new HashSet<>();
#foreach ( $field in $allFields )
#if ( $Helper.isFlatItems( $field ) )
List<$field.to> ${field.name} = new ArrayList<>();
#end
#end
while ((strict ? parser.nextTag() : nextTag(parser)) == XMLStreamReader.START_ELEMENT) {
String childName = checkDuplicate(parser.getLocalName(), parser, parsed);
#if ( $locationTracking )
int line = addLocationInformation ? parser.getLocation().getLineNumber() : -1;
int column = addLocationInformation ? parser.getLocation().getColumnNumber() : -1;
Map<Object, InputLocation> locations = null;
#end
switch (childName) {
#set( $ift = "if" )
#foreach ( $field in $allFields )
#if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name )
#end
#if ( $Helper.isFlatItems( $field ) )
#set ( $fieldTagName = $Helper.singular( $fieldTagName ) )
#end
#set ( $fieldCapName = $Helper.capitalise($field.name))
case "${fieldTagName}": {
#if ( $field.type == "String" )
${classLcapName}.${field.name}(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"));
break;
#elseif ( $field.type == "boolean" || $field.type == "Boolean" )
${classLcapName}.${field.name}(getBooleanValue(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"), "${fieldTagName}", parser, ${field.defaultValue}));
break;
#elseif ( $field.type == "int" )
${classLcapName}.${field.name}(getIntegerValue(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"), "${fieldTagName}", parser, strict, ${field.defaultValue}));
break;
#elseif ( $field.type == "DOM" )
${classLcapName}.${field.name}(buildXmlNode(parser));
break;
#elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" )
List<String> ${field.name} = new ArrayList<>();
#if ( $locationTracking )
locations = new HashMap<>();
#end
while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) {
#if ( $locationTracking )
if (addLocationInformation) {
locations.put(Integer.valueOf(locations.size()), new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source));
}
#end
${field.name}.add(interpolatedTrimmed(nextText(parser, strict), "${fieldTagName}"));
} else {
checkUnknownElement(parser, strict);
}
}
${classLcapName}.${field.name}(${field.name});
break;
#elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" )
Map<String, String> ${field.name} = new LinkedHashMap<>();
#if ( $locationTracking )
locations = new HashMap<>();
#end
while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
String key = parser.getLocalName();
String value = nextText(parser, strict).trim();
#if ( $locationTracking )
if (addLocationInformation) {
locations.put(key, new InputLocation(parser.getLocation().getLineNumber(), parser.getLocation().getColumnNumber(), source));
}
#end
${field.name}.put(key, value);
}
${classLcapName}.${field.name}(${field.name});
break;
#elseif ( $field.to && $field.multiplicity == "1" )
#if ( $locationTracking )
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict, source));
#else
${classLcapName}.${field.name}(parse${field.toClass.name}(parser, strict));
#end
break;
#elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) )
${field.name}.add(parse${field.toClass.name}(parser, strict));
break;
#elseif ( $field.to && $field.multiplicity == "*" )
List<$field.to> ${field.name} = new ArrayList<>();
while (parser.nextTag() == XMLStreamReader.START_ELEMENT) {
if ("${Helper.singular($fieldTagName)}".equals(parser.getLocalName())) {
#if ( $locationTracking )
${field.name}.add(parse${field.toClass.name}(parser, strict, source));
#else
${field.name}.add(parse${field.toClass.name}(parser, strict));
#end
} else {
checkUnknownElement(parser, strict);
}
}
${classLcapName}.${field.name}(${field.name});
break;
#else
// TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity}
break;
#end
}
#set( $ift = "else if" )
#end
#end
default: {
checkUnknownElement(parser, strict);
break;
}
}
#if ( $locationTracking )
if (addLocationInformation) {
${classLcapName}.location(childName, new InputLocation(line, column, source, locations));
}
#end
}
#foreach ( $field in $allFields )
#if ( $Helper.isFlatItems( $field ) )
${classLcapName}.${field.name}(${field.name});
#end
#end
#if ( $class == $root )
${classLcapName}.modelEncoding(parser.getEncoding());
#end
return ${classLcapName}.build();
}
#end
#end
private String checkDuplicate(String tagName, XMLStreamReader parser, Set<String> parsed) throws XMLStreamException {
#set( $aliases = { } )
#set( $flats = { } )
#foreach( $class in $model.allClasses )
#foreach ( $field in $class.getFields($version) )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#if ( ! $fieldTagName )
#set ( $fieldTagName = $field.name )
#end
#if ( $field.alias )
#set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) )
#end
#if ( $Helper.isFlatItems( $field ) )
#set ( $fieldTagName = $Helper.singular($fieldTagName) )
#set ( $dummy = $flats.put( $fieldTagName, "" ) )
#end
#end
#end
#if ( ! ${aliases.isEmpty()} )
switch (tagName) {
#foreach( $entry in $aliases.entrySet() )
case "${entry.key}":
tagName = "${entry.value}";
break;
#end
}
#end
#if ( ! ${flats.isEmpty()} )
switch (tagName) {
#foreach( $entry in $flats.entrySet() )
case "${entry.key}":
#end
break;
default:
if (!parsed.add(tagName)) {
throw new XMLStreamException("Duplicated tag: '" + tagName + "'", parser.getLocation(), null);
}
}
#end
return tagName;
}
/**
* Method checkUnknownAttribute.
*
* @param parser a parser object.
* @param strict a strict object.
* @param tagName a tagName object.
* @param attribute a attribute object.
* @throws XMLStreamException XMLStreamException if
* any.
* @throws IOException IOException if any.
*/
private void checkUnknownAttribute(XMLStreamReader parser, String attribute, String tagName, boolean strict) throws XMLStreamException {
// strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too
if (strict) {
throw new XMLStreamException("Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser.getLocation(), null);
}
} //-- void checkUnknownAttribute(XMLStreamReader, String, String, boolean)
/**
* Method checkUnknownElement.
*
* @param parser a parser object.
* @param strict a strict object.
* @throws XMLStreamException XMLStreamException if
* any.
* @throws IOException IOException if any.
*/
private void checkUnknownElement(XMLStreamReader parser, boolean strict) throws XMLStreamException {
if (strict) {
throw new XMLStreamException("Unrecognised tag: '" + parser.getName() + "'", parser.getLocation(), null);
}
for (int unrecognizedTagCount = 1; unrecognizedTagCount > 0;) {
int eventType = nextTag(parser);
if (eventType == XMLStreamReader.START_ELEMENT) {
unrecognizedTagCount++;
} else if (eventType == XMLStreamReader.END_ELEMENT) {
unrecognizedTagCount--;
}
}
} //-- void checkUnknownElement(XMLStreamReader, boolean)
/**
* Method getTrimmedValue.
*
* @param s a s object.
* @return String
*/
private String getTrimmedValue(String s) {
if (s != null) {
s = s.trim();
}
return s;
} //-- String getTrimmedValue(String)
/**
* Method interpolatedTrimmed.
*
* @param value a value object.
* @param context a context object.
* @return String
*/
private String interpolatedTrimmed(String value, String context) {
return getTrimmedValue(contentTransformer.transform(value, context));
} //-- String interpolatedTrimmed(String, String)
/**
* Method nextTag.
*
* @param parser a parser object.
* @throws IOException IOException if any.
* @throws XMLStreamException XMLStreamException if
* any.
* @return int
*/
private int nextTag(XMLStreamReader parser) throws XMLStreamException {
while (true) {
int next = parser.next();
switch (next) {
case XMLStreamReader.SPACE:
case XMLStreamReader.COMMENT:
case XMLStreamReader.PROCESSING_INSTRUCTION:
case XMLStreamReader.CDATA:
case XMLStreamReader.CHARACTERS:
continue;
case XMLStreamReader.START_ELEMENT:
case XMLStreamReader.END_ELEMENT:
return next;
}
}
} //-- int nextTag(XMLStreamReader)
private String nextText(XMLStreamReader parser, boolean strict) throws XMLStreamException {
int eventType = parser.getEventType();
if (eventType != XMLStreamReader.START_ELEMENT) {
throw new XMLStreamException("parser must be on START_ELEMENT to read next text", parser.getLocation(), null);
}
eventType = parser.next();
StringBuilder result = new StringBuilder();
while (true) {
if (eventType == XMLStreamReader.CHARACTERS || eventType == XMLStreamReader.CDATA) {
result.append(parser.getText());
} else if (eventType == XMLStreamReader.ENTITY_REFERENCE) {
String val = null;
if (strict) {
throw new XMLStreamException("Entities are not supported in strict mode", parser.getLocation(), null);
} else if (addDefaultEntities) {
val = DEFAULT_ENTITIES.get(parser.getLocalName());
}
if (val != null) {
result.append(val);
} else {
result.append("&").append(parser.getLocalName()).append(";");
}
} else if (eventType != XMLStreamReader.COMMENT) {
break;
}
eventType = parser.next();
}
if (eventType != XMLStreamReader.END_ELEMENT) {
throw new XMLStreamException(
"TEXT must be immediately followed by END_ELEMENT and not " + eventType /*TODO: TYPES[eventType]*/, parser.getLocation(), null);
}
return result.toString();
}
private XmlNode buildXmlNode(XMLStreamReader parser) throws XMLStreamException {
return XmlNodeBuilder.build(parser);
}
#foreach ( $class in $model.allClasses )
#foreach ( $field in $class.getFields($version) )
#if ( $field.type == "boolean" || $field.type == "Boolean" )
#set ( $hasBooleanField = true )
#elseif ( $field.type == "int" || $field.type == "Integer" )
#set ( $hasIntegerField = true )
#end
#end
#end
#if ( $hasBooleanField )
/**
* Method getBooleanValue.
*
* @param s a s object.
* @param defaultValue a defaultValue object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XMLStreamException XMLStreamException if
* any.
* @return boolean
*/
private boolean getBooleanValue(String s, String attribute, XMLStreamReader parser, boolean defaultValue) throws XMLStreamException {
if (s != null && s.length() != 0) {
return Boolean.valueOf(s).booleanValue();
}
return defaultValue;
} //-- boolean getBooleanValue(String, String, XMLStreamReader, String)
#end
#if ( $hasIntegerField )
/**
* Method getIntegerValue.
*
* @param s a s object.
* @param strict a strict object.
* @param parser a parser object.
* @param attribute a attribute object.
* @throws XMLStreamException XMLStreamException if
* any.
* @return int
*/
private int getIntegerValue(String s, String attribute, XMLStreamReader parser, boolean strict, int defaultValue) throws XMLStreamException {
if (s != null) {
try {
return Integer.valueOf(s).intValue();
} catch (NumberFormatException nfe) {
if (strict) {
throw new XMLStreamException("Unable to parse element '" + attribute + "', must be an integer", parser.getLocation(), nfe);
}
}
}
return defaultValue;
} //-- int getIntegerValue(String, String, XMLStreamReader, boolean)
#end
public static interface ContentTransformer {
/**
* Interpolate the value read from the xpp3 document
* @param source The source value
* @param fieldName A description of the field being interpolated. The implementation may use this to
* log stuff.
* @return The interpolated value.
*/
String transform(String source, String fieldName);
}
}

View File

@ -18,7 +18,11 @@
*# *#
#parse ( "common.vm" ) #parse ( "common.vm" )
# #
#set ( $package = "${packageToolV4}" ) #if( ${packageToolV4Xpp3} )
#set ( $package = "${packageToolV4Xpp3}" )
#else
#set ( $package = "${packageToolV4}" )
#end
#set ( $className = "${model.name}Xpp3Reader" ) #set ( $className = "${model.name}Xpp3Reader" )
# #
#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) )
@ -58,6 +62,7 @@ import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
@Deprecated
@Generated @Generated
public class ${className} { public class ${className} {

View File

@ -18,7 +18,11 @@
*# *#
#parse ( "common.vm" ) #parse ( "common.vm" )
# #
#set ( $package = "${packageToolV4}" ) #if( ${packageToolV4Xpp3} )
#set ( $package = "${packageToolV4Xpp3}" )
#else
#set ( $package = "${packageToolV4}" )
#end
#set ( $className = "${model.name}Xpp3WriterEx" ) #set ( $className = "${model.name}Xpp3WriterEx" )
# #
#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) )
@ -66,6 +70,7 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.util.xml.pull.XmlSerializer; import org.codehaus.plexus.util.xml.pull.XmlSerializer;
@Deprecated
@Generated @Generated
public class ${className} { public class ${className} {

414
src/mdo/writer-stax.vm Normal file
View File

@ -0,0 +1,414 @@
#*
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 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
@Generated
public class ${className} {
//--------------------------/
//- Class/Member Variables -/
//--------------------------/
/**
* Field NAMESPACE.
*/
private static final String NAMESPACE = "${namespace}";
/**
* XSI namespace
*/
private static final String XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance";
/**
* Field fileComment.
*/
private String fileComment = null;
#if ( $locationTracking )
/**
* Field stringFormatter.
*/
protected InputLocation.StringFormatter stringFormatter;
#end
//-----------/
//- Methods -/
//-----------/
/**
* Method setFileComment.
*
* @param fileComment a fileComment object.
*/
public void setFileComment(String fileComment) {
this.fileComment = fileComment;
} //-- void setFileComment(String)
#if ( $locationTracking )
/**
* Method setStringFormatter.
*
* @param stringFormatter
*/
public void setStringFormatter(InputLocation.StringFormatter stringFormatter) {
this.stringFormatter = stringFormatter;
} //-- void setStringFormatter(InputLocation.StringFormatter)
#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);
XMLStreamWriter serializer = 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);
XMLStreamWriter serializer = factory.createXMLStreamWriter(stream, ${rootLcapName}.getModelEncoding());
serializer.writeStartDocument(${rootLcapName}.getModelEncoding(), null);
write${root.name}("$rootTag", ${rootLcapName}, serializer);
serializer.writeEndDocument();
} //-- void write(OutputStream, ${root.name})
/**
* Method writeDomToSerializer.
*
* @param dom a dom object.
* @param serializer a serializer object.
* @throws IOException IOException if any.
*/
protected void writeDomToSerializer(org.apache.maven.api.xml.XmlNode dom, XMLStreamWriter serializer) throws IOException, XMLStreamException {
serializer.writeStartElement(NAMESPACE, dom.getName());
for (Map.Entry<String, String> attribute : dom.getAttributes().entrySet()) {
serializer.writeAttribute(NAMESPACE, attribute.getKey(), attribute.getValue());
}
for (XmlNode aChild : dom.getChildren()) {
writeDomToSerializer(aChild, serializer);
}
String value = dom.getValue();
if (value != null) {
serializer.writeCharacters(value);
}
serializer.writeEndElement();
} //-- void writeDomToSerializer(org.apache.maven.api.xml.XmlNode, XMLStreamWriter)
#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.writeComment(this.fileComment);
}
serializer.writeStartElement("", tagName, NAMESPACE);
serializer.writeNamespace("", NAMESPACE);
serializer.writeNamespace("xsi", XSI_NAMESPACE);
serializer.writeAttribute(XSI_NAMESPACE, "schemaLocation", NAMESPACE + " ${schemaLocation}");
#else
serializer.writeStartElement(NAMESPACE, tagName);
#end
#foreach ( $field in $allFields )
#if ( $Helper.xmlFieldMetadata( $field ).attribute )
#set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName )
#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
#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 )
#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();
#if ( $locationTracking )
writeLocationTracking(${classLcapName}, "", serializer);
#end
}
}
#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 )
writeLocationTracking(locationTracker, tagName, serializer);
#end
}
}
}
#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();
#if ( $locationTracking )
writeLocationTracking(locationTracker, tagName, serializer);
#end
}
}
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()) {
serializer.writeAttribute(NAMESPACE, 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 )
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 {
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.toString(location);
}
return ' ' + location.getSource().toString() + ':' + location.getLineNumber() + ' ';
} //-- String toString(InputLocation)
#end
}

View File

@ -18,7 +18,11 @@
*# *#
#parse ( "common.vm" ) #parse ( "common.vm" )
# #
#set ( $package = "${packageToolV4}" ) #if( ${packageToolV4Xpp3} )
#set ( $package = "${packageToolV4Xpp3}" )
#else
#set ( $package = "${packageToolV4}" )
#end
#set ( $className = "${model.name}Xpp3Writer" ) #set ( $className = "${model.name}Xpp3Writer" )
# #
#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) )
@ -62,6 +66,7 @@ import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.codehaus.plexus.util.xml.pull.XmlSerializer; import org.codehaus.plexus.util.xml.pull.XmlSerializer;
@Deprecated
@Generated @Generated
public class ${className} { public class ${className} {