You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sl...@apache.org on 2021/10/10 11:26:35 UTC
[maven] 01/01: [MNG-7182] Use the MX xpp parser instead of a STAX
transformation
This is an automated email from the ASF dual-hosted git repository.
slachiewicz pushed a commit to branch MNG-7182
in repository https://gitbox.apache.org/repos/asf/maven.git
commit 0775a4343181d34f316ac371816d3e97215c497a
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Thu Jul 8 07:54:01 2021 +0200
[MNG-7182] Use the MX xpp parser instead of a STAX transformation
Closes #486
---
.../aether/ConsumerModelSourceTransformer.java | 97 +---
.../DefaultRepositorySystemSessionFactory.java | 30 +-
.../building/AbstractModelSourceTransformer.java | 205 --------
.../building/BuildModelSourceTransformer.java | 53 +-
.../building/DefaultBuildPomXMLFilterFactory.java | 6 +-
.../building/DefaultModelSourceTransformer.java | 10 +-
.../model/building/ModelSourceTransformer.java | 8 +-
.../apache/maven/model/io/DefaultModelReader.java | 105 ++--
.../DefaultInheritanceAssemblerTest.java | 15 +-
maven-model-transform/pom.xml | 4 +
.../model/transform/AbstractEventXMLFilter.java | 285 -----------
.../model/transform/BuildToRawPomXMLFilter.java | 58 ---
.../transform/BuildToRawPomXMLFilterFactory.java | 64 +--
.../transform/BuildToRawPomXMLFilterListener.java | 42 --
.../maven/model/transform/CiFriendlyXMLFilter.java | 70 +--
.../maven/model/transform/DependencyKey.java | 87 ----
.../maven/model/transform/FastForwardFilter.java | 96 ++--
.../maven/model/transform/ModulesXMLFilter.java | 82 +--
.../maven/model/transform/ParentXMLFilter.java | 226 ++++-----
.../model/transform/RawToConsumerPomXMLFilter.java | 62 ---
.../RawToConsumerPomXMLFilterFactory.java | 22 +-
.../transform/ReactorDependencyXMLFilter.java | 186 +++----
.../model/transform/RelativePathXMLFilter.java | 99 ++--
.../model/transform/pull/BufferingParser.java | 563 +++++++++++++++++++++
.../maven/model/transform/pull/XmlUtils.java | 132 +++++
.../model/transform/sax/AbstractSAXFilter.java | 143 ------
.../model/transform/sax/CommentRenormalizer.java | 108 ----
.../maven/model/transform/sax/Factories.java | 79 ---
.../apache/maven/model/transform/sax/SAXEvent.java | 34 --
.../maven/model/transform/sax/SAXEventFactory.java | 144 ------
.../maven/model/transform/sax/SAXEventUtils.java | 49 --
.../model/transform/AbstractXMLFilterTests.java | 180 +------
.../model/transform/CiFriendlyXMLFilterTest.java | 24 +-
.../model/transform/ConsumerPomXMLFilterTest.java | 29 +-
.../model/transform/ModulesXMLFilterTest.java | 14 +-
.../maven/model/transform/ParentXMLFilterTest.java | 115 +++--
.../transform/ReactorDependencyXMLFilterTest.java | 32 +-
.../model/transform/RelativePathXMLFilterTest.java | 9 +-
.../model/transform/sax/ChainedFilterTest.java | 148 ------
.../transform/sax/CommentRenormalizerTest.java | 64 ---
.../model/transform/sax/SAXEventUtilsTest.java | 41 --
41 files changed, 1213 insertions(+), 2607 deletions(-)
diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java b/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
index b720acb..c1e1144 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
@@ -23,91 +23,30 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.function.Consumer;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.stream.XMLInputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamReader;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-
-import org.apache.maven.model.building.AbstractModelSourceTransformer;
import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
import org.apache.maven.model.building.TransformerContext;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.apache.maven.xml.internal.DefaultConsumerPomXMLFilterFactory;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-
-class ConsumerModelSourceTransformer extends AbstractModelSourceTransformer
+import org.apache.maven.model.transform.RawToConsumerPomXMLFilterFactory;
+import org.apache.maven.model.transform.pull.XmlUtils;
+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;
+
+class ConsumerModelSourceTransformer
{
- @Override
- protected AbstractSAXFilter getSAXFilter( Path pomFile,
- TransformerContext context,
- Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerConfigurationException, SAXException, ParserConfigurationException
- {
- return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context,
- lexicalHandlerConsumer, true ) ).get( pomFile );
- }
-
- /**
- * This transformer will ensure that encoding and version are kept.
- * However, it cannot prevent:
- * <ul>
- * <li>attributes will be on one line</li>
- * <li>Unnecessary whitespace before the rootelement will be removed</li>
- * </ul>
- */
- @Override
- protected TransformerHandler getTransformerHandler( Path pomFile )
- throws IOException, org.apache.maven.model.building.TransformerException
+ public InputStream transform( Path pomFile, TransformerContext context )
+ throws IOException, XmlPullParserException
{
- final TransformerHandler transformerHandler;
-
- final SAXTransformerFactory transformerFactory = getTransformerFactory();
-
- // Keep same encoding+version
- try ( InputStream input = Files.newInputStream( pomFile ) )
- {
- XMLStreamReader streamReader =
- XMLInputFactory.newFactory().createXMLStreamReader( input );
-
- transformerHandler = transformerFactory.newTransformerHandler();
-
- final String encoding = streamReader.getCharacterEncodingScheme();
- final String version = streamReader.getVersion();
-
- Transformer transformer = transformerHandler.getTransformer();
- transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
- if ( encoding == null && version == null )
- {
- transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
- }
- else
- {
- transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
+ XmlStreamReader reader = ReaderFactory.newXmlReader( Files.newInputStream( pomFile ) );
+ XmlPullParser parser = new MXParser( EntityReplacementMap.defaultEntityReplacementMap );
+ parser.setInput( reader );
+ parser = new RawToConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context, true ) )
+ .get( parser, pomFile );
- if ( encoding != null )
- {
- transformer.setOutputProperty( OutputKeys.ENCODING, encoding );
- }
- if ( version != null )
- {
- transformer.setOutputProperty( OutputKeys.VERSION, version );
- }
- }
- }
- catch ( XMLStreamException | TransformerConfigurationException e )
- {
- throw new org.apache.maven.model.building.TransformerException(
- "Failed to detect XML encoding and version", e );
- }
- return transformerHandler;
+ return XmlUtils.writeDocument( reader, parser );
}
}
diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
index c0ab9da..a642bec 100644
--- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
+++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java
@@ -19,6 +19,19 @@ package org.apache.maven.internal.aether;
* under the License.
*/
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
import org.apache.maven.RepositoryUtils;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.bridge.MavenRepositorySystem;
@@ -26,7 +39,6 @@ import org.apache.maven.eventspy.internal.EventSpyDispatcher;
import org.apache.maven.execution.MavenExecutionRequest;
import org.apache.maven.feature.Features;
import org.apache.maven.model.building.TransformerContext;
-import org.apache.maven.model.building.TransformerException;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.apache.maven.settings.Mirror;
import org.apache.maven.settings.Proxy;
@@ -37,6 +49,7 @@ import org.apache.maven.settings.crypto.SettingsDecrypter;
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration;
import org.codehaus.plexus.util.xml.Xpp3Dom;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.eclipse.aether.ConfigurationProperties;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
@@ -59,19 +72,6 @@ import org.eclipse.sisu.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Properties;
-
/**
* @since 3.3.0
*/
@@ -310,7 +310,7 @@ public class DefaultRepositorySystemSessionFactory
{
return new ConsumerModelSourceTransformer().transform( pomFile.toPath(), context );
}
- catch ( TransformerException e )
+ catch ( XmlPullParserException e )
{
throw new TransformException( e );
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/AbstractModelSourceTransformer.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/AbstractModelSourceTransformer.java
index dba9294..3ea1dbf 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/AbstractModelSourceTransformer.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/AbstractModelSourceTransformer.java
@@ -19,35 +19,6 @@ package org.apache.maven.model.building;
* under the License.
*/
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.function.Consumer;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.apache.maven.model.transform.sax.CommentRenormalizer;
-import org.apache.maven.model.transform.sax.Factories;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.ext.LexicalHandler;
-
/**
* Offers a transformation implementation based on PipelineStreams.
* Subclasses are responsible for providing the right SAXFilter.
@@ -58,181 +29,5 @@ import org.xml.sax.ext.LexicalHandler;
public abstract class AbstractModelSourceTransformer
implements ModelSourceTransformer
{
- private static final AtomicInteger TRANSFORM_THREAD_COUNTER = new AtomicInteger();
-
- private final TransformerFactory transformerFactory = Factories.newTransformerFactory();
-
- protected abstract AbstractSAXFilter getSAXFilter( Path pomFile,
- TransformerContext context,
- Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerConfigurationException, SAXException, ParserConfigurationException;
-
- protected OutputStream filterOutputStream( OutputStream outputStream, Path pomFile )
- {
- return outputStream;
- }
-
- public SAXTransformerFactory getTransformerFactory()
- {
- return ( SAXTransformerFactory ) transformerFactory;
- }
-
- protected TransformerHandler getTransformerHandler( Path pomFile )
- throws IOException, org.apache.maven.model.building.TransformerException
- {
- return null;
- }
-
- @Override
- public final InputStream transform( Path pomFile, TransformerContext context )
- throws IOException, org.apache.maven.model.building.TransformerException
- {
- final TransformerHandler transformerHandler = getTransformerHandler( pomFile );
-
- final PipedOutputStream pout = new PipedOutputStream();
- OutputStream out = filterOutputStream( pout, pomFile );
-
- final javax.xml.transform.Result result;
- final Consumer<LexicalHandler> lexConsumer;
- if ( transformerHandler == null )
- {
- result = new StreamResult( out );
- lexConsumer = null;
- }
- else
- {
- result = new SAXResult( transformerHandler );
- lexConsumer = l -> ( (SAXResult) result ).setLexicalHandler( new CommentRenormalizer( l ) );
- transformerHandler.setResult( new StreamResult( out ) );
- }
-
- final AbstractSAXFilter filter;
- try
- {
- filter = getSAXFilter( pomFile, context, lexConsumer );
- filter.setLexicalHandler( transformerHandler );
- // By default errors are written to stderr.
- // Hence set custom errorHandler to reduce noice
- filter.setErrorHandler( new ErrorHandler()
- {
- @Override
- public void warning( SAXParseException exception )
- throws SAXException
- {
- throw exception;
- }
-
- @Override
- public void fatalError( SAXParseException exception )
- throws SAXException
- {
- throw exception;
- }
-
- @Override
- public void error( SAXParseException exception )
- throws SAXException
- {
- throw exception;
- }
- } );
- }
- catch ( TransformerConfigurationException | SAXException | ParserConfigurationException e )
- {
- throw new org.apache.maven.model.building.TransformerException( e );
- }
-
- final SAXSource transformSource =
- new SAXSource( filter, new org.xml.sax.InputSource( Files.newInputStream( pomFile ) ) );
-
- IOExceptionHandler eh = new IOExceptionHandler();
-
- // Ensure pipedStreams are connected before the transformThread starts!!
- final PipedInputStream pipedInputStream = new PipedInputStream( pout );
-
- Thread transformThread = new Thread( () ->
- {
- try ( PipedOutputStream pos = pout )
- {
- transformerFactory.newTransformer().transform( transformSource, result );
- }
- catch ( TransformerException | IOException e )
- {
- eh.uncaughtException( Thread.currentThread(), e );
- }
- }, "TransformThread-" + TRANSFORM_THREAD_COUNTER.incrementAndGet() );
- transformThread.setUncaughtExceptionHandler( eh );
- transformThread.setDaemon( true );
- transformThread.start();
-
- return new ThreadAwareInputStream( pipedInputStream, eh );
- }
-
- private static class IOExceptionHandler
- implements Thread.UncaughtExceptionHandler, AutoCloseable
- {
- private volatile Throwable cause;
-
- @Override
- public void uncaughtException( Thread t, Throwable e )
- {
- try
- {
- throw e;
- }
- catch ( TransformerException | IOException | RuntimeException | Error allGood )
- {
- // all good
- this.cause = e;
- }
- catch ( Throwable notGood )
- {
- throw new AssertionError( "Unexpected Exception", e );
- }
- }
-
- @Override
- public void close()
- throws IOException
- {
- if ( cause != null )
- {
- try
- {
- throw cause;
- }
- catch ( IOException | RuntimeException | Error e )
- {
- throw e;
- }
- catch ( Throwable t )
- {
- // Any checked exception
- throw new RuntimeException( "Failed to transform pom", t );
- }
- }
- }
- }
-
- private class ThreadAwareInputStream
- extends FilterInputStream
- {
- final IOExceptionHandler h;
-
- protected ThreadAwareInputStream( InputStream in, IOExceptionHandler h )
- {
- super( in );
- this.h = h;
- }
- @Override
- public void close()
- throws IOException
- {
- try ( IOExceptionHandler eh = h )
- {
- super.close();
- }
- }
- }
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
index 699a009..9da284b 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/BuildModelSourceTransformer.java
@@ -19,24 +19,14 @@ package org.apache.maven.model.building;
* under the License.
*/
-import java.io.FilterOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.nio.file.Path;
-import java.util.function.Consumer;
-import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory;
-import org.apache.maven.model.transform.BuildToRawPomXMLFilterListener;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.eclipse.sisu.Nullable;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* ModelSourceTransformer for the build pom
@@ -46,44 +36,15 @@ import org.xml.sax.ext.LexicalHandler;
*/
@Named
@Singleton
-class BuildModelSourceTransformer extends AbstractModelSourceTransformer
+class BuildModelSourceTransformer implements ModelSourceTransformer
{
- @Inject
- @Nullable
- private BuildToRawPomXMLFilterListener xmlFilterListener;
-
- protected AbstractSAXFilter getSAXFilter( Path pomFile,
- TransformerContext context,
- Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerConfigurationException, SAXException, ParserConfigurationException
+ @Override
+ public XmlPullParser transform( XmlPullParser parser, Path pomFile, TransformerContext context )
+ throws IOException, TransformerException
{
BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory =
- new DefaultBuildPomXMLFilterFactory( context, lexicalHandlerConsumer, false );
-
- return buildPomXMLFilterFactory.get( pomFile );
- }
+ new DefaultBuildPomXMLFilterFactory( context, false );
- @Override
- protected OutputStream filterOutputStream( OutputStream outputStream, Path pomFile )
- {
- OutputStream out;
- if ( xmlFilterListener != null )
- {
- out = new FilterOutputStream( outputStream )
- {
- @Override
- public void write( byte[] b, int off, int len )
- throws IOException
- {
- super.write( b, off, len );
- xmlFilterListener.write( pomFile, b, off, len );
- }
- };
- }
- else
- {
- out = outputStream;
- }
- return out;
+ return buildPomXMLFilterFactory.get( parser, pomFile );
}
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
index d22eaac..e415461 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java
@@ -23,13 +23,11 @@ package org.apache.maven.model.building;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.BiFunction;
-import java.util.function.Consumer;
import java.util.function.Function;
import org.apache.maven.model.Model;
import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory;
import org.apache.maven.model.transform.RelativeProject;
-import org.xml.sax.ext.LexicalHandler;
/**
* A BuildPomXMLFilterFactory which is context aware
@@ -44,14 +42,12 @@ public class DefaultBuildPomXMLFilterFactory extends BuildToRawPomXMLFilterFacto
/**
*
* @param context a set of data to extract values from as required for the build pom
- * @param lexicalHandlerConsumer the lexical handler consumer
* @param consume {@code true} if this factory is being used for creating the consumer pom, otherwise {@code false}
*/
public DefaultBuildPomXMLFilterFactory( TransformerContext context,
- Consumer<LexicalHandler> lexicalHandlerConsumer,
boolean consume )
{
- super( lexicalHandlerConsumer, consume );
+ super( consume );
this.context = context;
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelSourceTransformer.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelSourceTransformer.java
index 7c57f30..e6e4073 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelSourceTransformer.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelSourceTransformer.java
@@ -20,10 +20,10 @@ package org.apache.maven.model.building;
*/
import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
import java.nio.file.Path;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+
/**
* Default ModelSourceTransformer, provides pomFile as inputStream and ignores the context
*
@@ -34,10 +34,10 @@ public class DefaultModelSourceTransformer implements ModelSourceTransformer
{
@Override
- public InputStream transform( Path pomFile, TransformerContext context )
- throws IOException, TransformerException
+ public XmlPullParser transform( XmlPullParser parser, Path pomFile, TransformerContext context )
+ throws IOException, TransformerException
{
- return Files.newInputStream( pomFile );
+ return parser;
}
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelSourceTransformer.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelSourceTransformer.java
index a2556ce..a2504ef 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelSourceTransformer.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelSourceTransformer.java
@@ -20,16 +20,18 @@ package org.apache.maven.model.building;
*/
import java.io.IOException;
-import java.io.InputStream;
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 {@link #transform(Path, TransformerContext)} method uses a Path on purpose, to ensure the
+ * The {@link #transform(XmlPullParser, Path, TransformerContext)} method uses a Path on purpose, to ensure the
* local pom is the the original source.
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
public interface ModelSourceTransformer
@@ -42,6 +44,6 @@ public interface ModelSourceTransformer
* @throws IOException if an I/O error occurs
* @throws TransformerException if the transformation fails
*/
- InputStream transform( Path pomFile, TransformerContext context )
+ XmlPullParser transform( XmlPullParser parser, Path pomFile, TransformerContext context )
throws IOException, TransformerException;
}
diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java
index eeafabe..3501df9 100644
--- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java
+++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java
@@ -20,10 +20,12 @@ package org.apache.maven.model.io;
*/
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Path;
import java.util.Map;
import java.util.Objects;
@@ -35,11 +37,13 @@ import org.apache.maven.model.InputSource;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelSourceTransformer;
import org.apache.maven.model.building.TransformerContext;
-import org.apache.maven.model.building.TransformerException;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.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;
/**
@@ -54,6 +58,10 @@ public class DefaultModelReader
{
private final ModelSourceTransformer transformer;
+ private Method readMethod;
+
+ private Method readMethodEx;
+
@Inject
public DefaultModelReader( ModelSourceTransformer transformer )
{
@@ -66,28 +74,9 @@ public class DefaultModelReader
{
Objects.requireNonNull( input, "input cannot be null" );
- TransformerContext context = getTransformerContext( options );
-
- final InputStream is;
- if ( context == null )
- {
- is = new FileInputStream( input );
- }
- else
- {
- try
- {
- is = transformer.transform( input.toPath(), context );
- }
- catch ( TransformerException e )
- {
- throw new IOException( "Failed to transform " + input, e );
- }
- }
-
- try ( InputStream in = is )
+ try ( XmlStreamReader in = ReaderFactory.newXmlReader( input ) )
{
- Model model = read( is, options );
+ Model model = read( in, input.toPath(), options );
model.setPomFile( input );
@@ -103,7 +92,7 @@ public class DefaultModelReader
try ( Reader in = input )
{
- return read( in, isStrict( options ), getSource( options ) );
+ return read( in, null, options );
}
}
@@ -115,7 +104,7 @@ public class DefaultModelReader
try ( XmlStreamReader in = ReaderFactory.newXmlReader( input ) )
{
- return read( in, isStrict( options ), getSource( options ) );
+ return read( in, null, options );
}
}
@@ -137,24 +126,80 @@ public class DefaultModelReader
return (TransformerContext) value;
}
- private Model read( Reader reader, boolean strict, InputSource source )
+ private Model read( Reader reader, Path pomFile, Map<String, ?> options )
throws IOException
{
try
{
- if ( source != null )
+ XmlPullParser parser = new MXParser( EntityReplacementMap.defaultEntityReplacementMap );
+ parser.setInput( reader );
+
+ TransformerContext context = getTransformerContext( options );
+ XmlPullParser transformingParser = context != null
+ ? transformer.transform( parser, pomFile, context ) : parser;
+
+ InputSource source = getSource( options );
+ boolean strict = isStrict( options );
+ try
{
- return new MavenXpp3ReaderEx().read( reader, strict, source );
+ if ( source != null )
+ {
+ return readModelEx( transformingParser, source, strict );
+ }
+ else
+ {
+ return readModel( transformingParser, strict );
+ }
}
- else
+ catch ( InvocationTargetException e )
{
- return new MavenXpp3Reader().read( reader, strict );
+ Throwable cause = e.getCause();
+ if ( cause instanceof Exception )
+ {
+ throw ( Exception ) cause;
+ }
+ throw e;
}
}
catch ( XmlPullParserException e )
{
throw new ModelParseException( e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e );
}
+ catch ( IOException e )
+ {
+ throw e;
+ }
+ catch ( Exception e )
+ {
+ throw new IOException( "Unable to transform pom", e );
+ }
+ }
+
+ private Model readModel( XmlPullParser parser, boolean strict )
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
+ {
+ if ( readMethod == null )
+ {
+ readMethod = MavenXpp3Reader.class.getDeclaredMethod( "read", XmlPullParser.class, boolean.class );
+ readMethod.setAccessible( true );
+ }
+ MavenXpp3Reader mr = new MavenXpp3Reader();
+ Object model = readMethod.invoke( mr, parser, strict );
+ return ( Model ) model;
+ }
+
+ private Model readModelEx( XmlPullParser parser, InputSource source, boolean strict )
+ throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
+ {
+ if ( readMethodEx == null )
+ {
+ readMethodEx = MavenXpp3ReaderEx.class.getDeclaredMethod( "read",
+ XmlPullParser.class, boolean.class, InputSource.class );
+ readMethodEx.setAccessible( true );
+ }
+ MavenXpp3ReaderEx mr = new MavenXpp3ReaderEx();
+ Object model = readMethodEx.invoke( mr, parser, strict, source );
+ return ( Model ) model;
}
}
diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java
index 52400d8..b573ad1 100644
--- a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java
+++ b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java
@@ -22,22 +22,16 @@ package org.apache.maven.model.inheritance;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
-import java.util.function.Consumer;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.AbstractModelSourceTransformer;
import org.apache.maven.model.building.SimpleProblemCollector;
import org.apache.maven.model.building.TransformerContext;
+import org.apache.maven.model.building.TransformerException;
import org.apache.maven.model.io.DefaultModelReader;
import org.apache.maven.model.io.DefaultModelWriter;
import org.apache.maven.model.io.ModelWriter;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.xmlunit.matchers.CompareMatcher;
@@ -64,9 +58,8 @@ public class DefaultInheritanceAssemblerTest
reader = new DefaultModelReader( new AbstractModelSourceTransformer()
{
@Override
- protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context,
- Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerConfigurationException, SAXException, ParserConfigurationException
+ public XmlPullParser transform( XmlPullParser parser, Path pomFile, TransformerContext context )
+ throws IOException, TransformerException
{
return null;
}
diff --git a/maven-model-transform/pom.xml b/maven-model-transform/pom.xml
index 2839d52..5024085 100644
--- a/maven-model-transform/pom.xml
+++ b/maven-model-transform/pom.xml
@@ -33,6 +33,10 @@ under the License.
<dependencies>
<dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ </dependency>
+ <dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<scope>test</scope>
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/AbstractEventXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/AbstractEventXMLFilter.java
deleted file mode 100644
index 711845f..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/AbstractEventXMLFilter.java
+++ /dev/null
@@ -1,285 +0,0 @@
-package org.apache.maven.model.transform;
-
-/*
- * 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.
- */
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Queue;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.apache.maven.model.transform.sax.SAXEvent;
-import org.apache.maven.model.transform.sax.SAXEventFactory;
-import org.xml.sax.Attributes;
-import org.xml.sax.Locator;
-import org.xml.sax.SAXException;
-
-/**
- * Builds up a list of SAXEvents, which will be executed with {@link #executeEvents()}
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-abstract class AbstractEventXMLFilter extends AbstractSAXFilter
-{
- private Queue<SAXEvent> saxEvents = new ArrayDeque<>();
-
- private SAXEventFactory eventFactory;
-
- // characters BEFORE startElement must get state of startingElement
- // this way removing based on state keeps correct formatting
- private List<SAXEvent> charactersSegments = new ArrayList<>();
-
- private boolean lockCharacters = false;
-
- protected abstract boolean isParsing();
-
- protected abstract String getState();
-
- protected boolean acceptEvent( String state )
- {
- return true;
- }
-
- AbstractEventXMLFilter()
- {
- super();
- }
-
- AbstractEventXMLFilter( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- private SAXEventFactory getEventFactory()
- {
- if ( eventFactory == null )
- {
- eventFactory = SAXEventFactory.newInstance( getContentHandler(), getLexicalHandler() );
- }
- return eventFactory;
- }
-
- private void processEvent( final SAXEvent event )
- throws SAXException
- {
- if ( isParsing() )
- {
- final String eventState = getState();
-
- if ( !lockCharacters )
- {
- charactersSegments.forEach( e ->
- saxEvents.add( () ->
- {
- if ( acceptEvent( eventState ) )
- {
- e.execute();
- }
- } ) );
- charactersSegments.clear();
- }
-
- saxEvents.add( () ->
- {
- if ( acceptEvent( eventState ) )
- {
- event.execute();
- }
- } );
- }
- else
- {
- event.execute();
- }
- }
-
- /**
- * Should be used to include extra events before a closing element.
- * This is a lightweight solution to keep the correct indentation.
- */
- protected Includer include()
- {
- this.lockCharacters = true;
-
- return () -> lockCharacters = false;
- }
-
- protected final void executeEvents() throws SAXException
- {
- final String eventState = getState();
- charactersSegments.forEach( e ->
- saxEvents.add( () ->
- {
- if ( acceptEvent( eventState ) )
- {
- e.execute();
- }
- } ) );
- charactersSegments.clear();
-
- // not with streams due to checked SAXException
- while ( !saxEvents.isEmpty() )
- {
- saxEvents.poll().execute();
- }
- }
-
- @Override
- public void setDocumentLocator( Locator locator )
- {
- try
- {
- processEvent( getEventFactory().setDocumentLocator( locator ) );
- }
- catch ( SAXException e )
- {
- // noop, setDocumentLocator can never throw a SAXException
- }
- }
-
- @Override
- public void startDocument() throws SAXException
- {
- processEvent( getEventFactory().startDocument() );
- }
-
- @Override
- public void endDocument() throws SAXException
- {
- processEvent( getEventFactory().endDocument() );
- }
-
- @Override
- public void startPrefixMapping( String prefix, String uri ) throws SAXException
- {
- processEvent( getEventFactory().startPrefixMapping( prefix, uri ) );
- }
-
- @Override
- public void endPrefixMapping( String prefix ) throws SAXException
- {
- processEvent( getEventFactory().endPrefixMapping( prefix ) );
- }
-
- @Override
- public void startElement( String uri, String localName, String qName, Attributes atts ) throws SAXException
- {
- processEvent( getEventFactory().startElement( uri, localName, qName, atts ) );
- }
-
- @Override
- public void endElement( String uri, String localName, String qName ) throws SAXException
- {
- processEvent( getEventFactory().endElement( uri, localName, qName ) );
- }
-
- @Override
- public void characters( char[] ch, int start, int length ) throws SAXException
- {
- if ( lockCharacters )
- {
- processEvent( getEventFactory().characters( ch, start, length ) );
- }
- else if ( isParsing() )
- {
- this.charactersSegments.add( getEventFactory().characters( ch, start, length ) );
- }
- else
- {
- super.characters( ch, start, length );
- }
- }
-
- @Override
- public void ignorableWhitespace( char[] ch, int start, int length ) throws SAXException
- {
- processEvent( getEventFactory().ignorableWhitespace( ch, start, length ) );
- }
-
- @Override
- public void processingInstruction( String target, String data ) throws SAXException
- {
- processEvent( getEventFactory().processingInstruction( target, data ) );
- }
-
- @Override
- public void skippedEntity( String name ) throws SAXException
- {
- processEvent( getEventFactory().skippedEntity( name ) );
- }
-
- @Override
- public void startDTD( String name, String publicId, String systemId ) throws SAXException
- {
- processEvent( getEventFactory().startCDATA() );
- }
-
- @Override
- public void endDTD() throws SAXException
- {
- processEvent( getEventFactory().endDTD() );
- }
-
- @Override
- public void startEntity( String name ) throws SAXException
- {
- processEvent( getEventFactory().startEntity( name ) );
- }
-
- @Override
- public void endEntity( String name ) throws SAXException
- {
- processEvent( getEventFactory().endEntity( name ) );
- }
-
- @Override
- public void startCDATA()
- throws SAXException
- {
- processEvent( getEventFactory().startCDATA() );
- }
-
- @Override
- public void endCDATA()
- throws SAXException
- {
- processEvent( getEventFactory().endCDATA() );
- }
-
- @Override
- public void comment( char[] ch, int start, int length )
- throws SAXException
- {
- processEvent( getEventFactory().comment( ch, start, length ) );
- }
-
- /**
- * AutoCloseable with a close method that doesn't throw an exception
- *
- * @author Robert Scholte
- *
- */
- @FunctionalInterface
- protected interface Includer extends AutoCloseable
- {
- void close();
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilter.java
deleted file mode 100644
index 8cc392f..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilter.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package org.apache.maven.model.transform;
-
-/*
- * 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.
- */
-
-import org.xml.sax.XMLReader;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-
-/**
- * Filter to adjust pom on filesystem before being processed for effective pom.
- * There should only be 1 BuildToRawPomXMLFilter, so the same is being used by both
- * org.apache.maven.model.building.DefaultModelBuilder.transformData(InputStream) and
- * org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory.newFileTransformerManager()
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class BuildToRawPomXMLFilter extends AbstractSAXFilter
-{
- BuildToRawPomXMLFilter()
- {
- super();
- }
-
- BuildToRawPomXMLFilter( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- /**
- * Don't allow overwriting parent
- */
- @Override
- public final void setParent( XMLReader parent )
- {
- if ( getParent() == null )
- {
- super.setParent( parent );
- }
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterFactory.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterFactory.java
index 3531e2b..3d1f1a2 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterFactory.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterFactory.java
@@ -22,17 +22,9 @@ package org.apache.maven.model.transform;
import java.nio.file.Path;
import java.util.Optional;
import java.util.function.BiFunction;
-import java.util.function.Consumer;
import java.util.function.Function;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.apache.maven.model.transform.sax.Factories;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.LexicalHandler;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* Base implementation for providing the BuildToRawPomXML.
@@ -44,74 +36,42 @@ public class BuildToRawPomXMLFilterFactory
{
private final boolean consume;
- private final Consumer<LexicalHandler> lexicalHandlerConsumer;
-
- public BuildToRawPomXMLFilterFactory( Consumer<LexicalHandler> lexicalHandlerConsumer )
+ public BuildToRawPomXMLFilterFactory()
{
- this( lexicalHandlerConsumer, false );
+ this( false );
}
- public BuildToRawPomXMLFilterFactory( Consumer<LexicalHandler> lexicalHandlerConsumer, boolean consume )
+ public BuildToRawPomXMLFilterFactory( boolean consume )
{
- this.lexicalHandlerConsumer = lexicalHandlerConsumer;
this.consume = consume;
}
/**
*
* @param projectFile will be used by ConsumerPomXMLFilter to get the right filter
- * @throws SAXException
- * @throws ParserConfigurationException
- * @throws TransformerConfigurationException
*/
- public final BuildToRawPomXMLFilter get( Path projectFile )
- throws SAXException, ParserConfigurationException, TransformerConfigurationException
+ public final XmlPullParser get( XmlPullParser orgParser, Path projectFile )
+
{
- AbstractSAXFilter parent = new AbstractSAXFilter();
- parent.setParent( getXMLReader() );
- if ( lexicalHandlerConsumer != null )
- {
- lexicalHandlerConsumer.accept( parent );
- }
+ XmlPullParser parser = orgParser;
if ( getDependencyKeyToVersionMapper() != null )
{
- ReactorDependencyXMLFilter reactorDependencyXMLFilter =
- new ReactorDependencyXMLFilter( getDependencyKeyToVersionMapper() );
- reactorDependencyXMLFilter.setParent( parent );
- parent.setLexicalHandler( reactorDependencyXMLFilter );
- parent = reactorDependencyXMLFilter;
+ parser = new ReactorDependencyXMLFilter( parser, getDependencyKeyToVersionMapper() );
}
if ( getRelativePathMapper() != null )
{
- ParentXMLFilter parentFilter = new ParentXMLFilter( getRelativePathMapper() );
- parentFilter.setProjectPath( projectFile.getParent() );
- parentFilter.setParent( parent );
- parent.setLexicalHandler( parentFilter );
- parent = parentFilter;
+ parser = new ParentXMLFilter( parser, getRelativePathMapper(), projectFile.getParent() );
}
- CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter( consume );
+ CiFriendlyXMLFilter ciFriendlyFilter = new CiFriendlyXMLFilter( parser, consume );
getChangelist().ifPresent( ciFriendlyFilter::setChangelist );
getRevision().ifPresent( ciFriendlyFilter::setRevision );
getSha1().ifPresent( ciFriendlyFilter::setSha1 );
+ parser = ciFriendlyFilter;
- if ( ciFriendlyFilter.isSet() )
- {
- ciFriendlyFilter.setParent( parent );
- parent.setLexicalHandler( ciFriendlyFilter );
- parent = ciFriendlyFilter;
- }
-
- return new BuildToRawPomXMLFilter( parent );
- }
-
- private XMLReader getXMLReader() throws SAXException, ParserConfigurationException
- {
- XMLReader xmlReader = Factories.newXMLReader();
- xmlReader.setFeature( "http://xml.org/sax/features/namespaces", true );
- return xmlReader;
+ return parser;
}
/**
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterListener.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterListener.java
deleted file mode 100644
index ff9cfb6..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/BuildToRawPomXMLFilterListener.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package org.apache.maven.model.transform;
-
-/*
- * 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.
- */
-
-import java.nio.file.Path;
-
-/**
- * Listener can be used to capture the result of the transformation of build to raw POM.
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-@FunctionalInterface
-public interface BuildToRawPomXMLFilterListener
-{
- /**
- * Captures the result of the XML transformation
- *
- * @param pomFile the original to being transformed
- * @param b the byte array
- * @param off the offset
- * @param len the length
- */
- void write( Path pomFile, byte[] b, int off, int len );
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/CiFriendlyXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/CiFriendlyXMLFilter.java
index 1a38a98..f981a8f 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/CiFriendlyXMLFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/CiFriendlyXMLFilter.java
@@ -19,37 +19,29 @@ package org.apache.maven.model.transform;
* under the License.
*/
+import java.util.List;
import java.util.function.Function;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.apache.maven.model.transform.pull.NodeBufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* Resolves all ci-friendly properties occurrences between version-tags
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
class CiFriendlyXMLFilter
- extends AbstractSAXFilter
+ extends NodeBufferingParser
{
private final boolean replace;
private Function<String, String> replaceChain = Function.identity();
- private String characters;
-
- private boolean parseVersion;
-
- CiFriendlyXMLFilter( boolean replace )
+ CiFriendlyXMLFilter( XmlPullParser xmlPullParser, boolean replace )
{
- this.replace = replace;
- }
-
- CiFriendlyXMLFilter( AbstractSAXFilter parent, boolean replace )
- {
- super( parent );
+ super( xmlPullParser, "version" );
this.replace = replace;
}
@@ -80,52 +72,16 @@ class CiFriendlyXMLFilter
}
@Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
+ protected void process( List<Event> buffer )
{
- if ( parseVersion )
+ for ( Event event : buffer )
{
- this.characters = nullSafeAppend( characters, new String( ch, start, length ) );
- }
- else
- {
- super.characters( ch, start, length );
- }
- }
-
- @Override
- public void startElement( String uri, String localName, String qName, Attributes atts )
- throws SAXException
- {
- if ( !parseVersion && "version".equals( localName ) )
- {
- parseVersion = true;
- }
-
- super.startElement( uri, localName, qName, atts );
- }
-
- @Override
- public void endElement( String uri, String localName, String qName )
- throws SAXException
- {
- if ( parseVersion )
- {
- // assuming this has the best performance
- if ( replace && characters != null && characters.contains( "${" ) )
- {
- char[] ch = replaceChain.apply( characters ).toCharArray();
- super.characters( ch, 0, ch.length );
- }
- else
+ if ( event.event == TEXT && replace && event.text.contains( "${" ) )
{
- char[] ch = characters.toCharArray();
- super.characters( ch, 0, ch.length );
+ event.text = replaceChain.apply( event.text );
}
- characters = null;
- parseVersion = false;
+ pushEvent( event );
}
-
- super.endElement( uri, localName, qName );
}
+
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/DependencyKey.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/DependencyKey.java
deleted file mode 100644
index 95c40e0..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/DependencyKey.java
+++ /dev/null
@@ -1,87 +0,0 @@
-package org.apache.maven.model.transform;
-
-/*
- * 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.
- */
-
-import java.util.Objects;
-
-/**
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class DependencyKey
-{
- private final String groupId;
-
- private final String artifactId;
-
- private final int hashCode;
-
- public DependencyKey( String groupId, String artifactId )
- {
- this.groupId = groupId;
- this.artifactId = artifactId;
-
- this.hashCode = Objects.hash( artifactId, groupId );
- }
-
- public String getGroupId()
- {
- return groupId;
- }
-
- public String getArtifactId()
- {
- return artifactId;
- }
-
- @Override
- public int hashCode()
- {
- return hashCode;
- }
-
- @Override
- public boolean equals( Object obj )
- {
- if ( this == obj )
- {
- return true;
- }
- if ( obj == null )
- {
- return false;
- }
- if ( getClass() != obj.getClass() )
- {
- return false;
- }
-
- DependencyKey other = (DependencyKey) obj;
-
- if ( !Objects.equals( artifactId, other.artifactId ) )
- {
- return false;
- }
- return Objects.equals( groupId, other.groupId );
- }
-
-
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/FastForwardFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/FastForwardFilter.java
index ea0eb9f..91977c0 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/FastForwardFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/FastForwardFilter.java
@@ -19,23 +19,23 @@ package org.apache.maven.model.transform;
* under the License.
*/
+import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLFilter;
+import org.apache.maven.model.transform.pull.BufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
/**
* This filter will skip all following filters and write directly to the output.
- * Should be used in case of a DOM that should not be effected by other filters, even though the elements match
+ * Should be used in case of a DOM that should not be effected by other filters, even though the elements match.
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
-class FastForwardFilter extends AbstractSAXFilter
+class FastForwardFilter extends BufferingParser
{
/**
* DOM elements of pom
@@ -53,75 +53,51 @@ class FastForwardFilter extends AbstractSAXFilter
private int domDepth = 0;
- private ContentHandler originalHandler;
-
- FastForwardFilter()
+ FastForwardFilter( XmlPullParser xmlPullParser )
{
- super();
- }
-
- FastForwardFilter( AbstractSAXFilter parent )
- {
- super( parent );
+ super( xmlPullParser );
}
@Override
- public void startElement( String uri, String localName, String qName, Attributes atts )
- throws SAXException
+ protected boolean accept() throws XmlPullParserException, IOException
{
- super.startElement( uri, localName, qName, atts );
- if ( domDepth > 0 )
+ if ( xmlPullParser.getEventType() == START_TAG )
{
- domDepth++;
- }
- else
- {
- final String key = state.peek() + '.' + localName;
- switch ( key )
+ String localName = xmlPullParser.getName();
+ if ( domDepth > 0 )
{
- case "execution.configuration":
- case "plugin.configuration":
- case "plugin.goals":
- case "profile.reports":
- case "project.reports":
- case "reportSet.configuration":
- domDepth++;
-
- originalHandler = getContentHandler();
-
- ContentHandler outputContentHandler = getContentHandler();
- while ( outputContentHandler instanceof XMLFilter )
- {
- outputContentHandler = ( (XMLFilter) outputContentHandler ).getContentHandler();
- }
- setContentHandler( outputContentHandler );
- break;
- default:
- break;
+ domDepth++;
+ }
+ else
+ {
+ final String key = state.peek() + '/' + localName;
+ switch ( key )
+ {
+ case "execution/configuration":
+ case "plugin/configuration":
+ case "plugin/goals":
+ case "profile/reports":
+ case "project/reports":
+ case "reportSet/configuration":
+ domDepth++;
+ disable();
+ break;
+ default:
+ break;
+ }
}
- state.push( localName );
+ state.add( localName );
}
- }
-
- @Override
- public void endElement( String uri, String localName, String qName )
- throws SAXException
- {
- if ( domDepth > 0 )
+ else if ( xmlPullParser.getEventType() == END_TAG )
{
domDepth--;
-
if ( domDepth == 0 )
{
- setContentHandler( originalHandler );
+ enable();
}
- }
- else
- {
state.pop();
}
- super.endElement( uri, localName, qName );
+ return true;
}
-
}
\ No newline at end of file
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ModulesXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ModulesXMLFilter.java
index 187fc78..4d3f94a 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ModulesXMLFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ModulesXMLFilter.java
@@ -19,93 +19,29 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import java.util.List;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
+import org.apache.maven.model.transform.pull.NodeBufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* Remove all modules, this is just buildtime information
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
class ModulesXMLFilter
- extends AbstractEventXMLFilter
+ extends NodeBufferingParser
{
- private boolean parsingModules;
-
- private String state;
-
- ModulesXMLFilter()
- {
- super();
- }
-
- ModulesXMLFilter( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- @Override
- public void startElement( String uri, String localName, String qName, Attributes atts )
- throws SAXException
- {
- if ( !parsingModules && "modules".equals( localName ) )
- {
- parsingModules = true;
- }
-
- if ( parsingModules )
- {
- state = localName;
- }
-
- super.startElement( uri, localName, qName, atts );
- }
-
- @Override
- public void endElement( String uri, String localName, String qName )
- throws SAXException
- {
- if ( parsingModules )
- {
- switch ( localName )
- {
- case "modules":
- executeEvents();
-
- parsingModules = false;
- break;
- default:
- super.endElement( uri, localName, qName );
- break;
- }
- }
- else
- {
- super.endElement( uri, localName, qName );
- }
-
- // for this simple structure resetting to modules it sufficient
- state = "modules";
- }
-
- @Override
- protected boolean isParsing()
+ ModulesXMLFilter( XmlPullParser xmlPullParser )
{
- return parsingModules;
+ super( xmlPullParser, "modules" );
}
- @Override
- protected String getState()
+ protected void process( List<Event> buffer )
{
- return state;
+ // Do nothing, as we want to delete those nodes completely
}
- @Override
- protected boolean acceptEvent( String state )
- {
- return false;
- }
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ParentXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ParentXMLFilter.java
index 926222c..37ac28b 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ParentXMLFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ParentXMLFilter.java
@@ -22,14 +22,13 @@ package org.apache.maven.model.transform;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-
+import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
-import org.apache.maven.model.transform.sax.SAXEventUtils;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.apache.maven.model.transform.pull.NodeBufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* <p>
@@ -40,167 +39,117 @@ import org.xml.sax.SAXException;
* </p>
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
class ParentXMLFilter
- extends AbstractEventXMLFilter
+ extends NodeBufferingParser
{
- private boolean parsingParent;
-
- // states
- private String state;
-
- // whiteSpace after <parent>, to be used to position <version>
- private String parentWhitespace = "";
-
- private String groupId;
-
- private String artifactId;
-
- private String relativePath;
-
- private boolean hasVersion;
-
- private boolean hasRelativePath;
-
- private Optional<RelativeProject> resolvedParent;
private final Function<Path, Optional<RelativeProject>> relativePathMapper;
- private Path projectPath;
+ private final Path projectPath;
/**
* @param relativePathMapper
*/
- ParentXMLFilter( Function<Path, Optional<RelativeProject>> relativePathMapper )
+ ParentXMLFilter( XmlPullParser parser,
+ Function<Path, Optional<RelativeProject>> relativePathMapper, Path projectPath )
{
+ super( parser, "parent" );
this.relativePathMapper = relativePathMapper;
- }
-
- public void setProjectPath( Path projectPath )
- {
this.projectPath = projectPath;
}
- @Override
- protected boolean isParsing()
- {
- return parsingParent;
- }
-
- @Override
- protected String getState()
- {
- return state;
- }
-
- @Override
- public void startElement( String uri, final String localName, String qName, Attributes atts )
- throws SAXException
- {
- if ( !parsingParent && "parent".equals( localName ) )
- {
- parsingParent = true;
- }
-
- if ( parsingParent )
- {
- state = localName;
-
- hasVersion |= "version".equals( localName );
-
- // can be set to empty on purpose to enforce repository download
- hasRelativePath |= "relativePath".equals( localName );
- }
-
- super.startElement( uri, localName, qName, atts );
- }
-
- @Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
+ protected void process( List<Event> buffer )
{
- if ( parsingParent )
+ String tagName = null;
+ String groupId = null;
+ String artifactId = null;
+ String version = null;
+ String relativePath = null;
+ String whitespaceAfterParentStart = "";
+ boolean hasVersion = false;
+ boolean hasRelativePath = false;
+ for ( int i = 0; i < buffer.size(); i++ )
{
- final String eventState = state;
-
- final String charSegment = new String( ch, start, length );
-
- switch ( eventState )
+ Event event = buffer.get( i );
+ if ( event.event == START_TAG )
{
- case "parent":
- parentWhitespace = nullSafeAppend( parentWhitespace, charSegment );
- break;
- case "relativePath":
- relativePath = nullSafeAppend( relativePath, charSegment );
- break;
- case "groupId":
- groupId = nullSafeAppend( groupId, charSegment );
- break;
- case "artifactId":
- artifactId = nullSafeAppend( artifactId, charSegment );
- break;
- default:
- break;
+ tagName = event.name;
+ hasVersion |= "version".equals( tagName );
+ hasRelativePath |= "relativePath".equals( tagName );
}
- }
-
- super.characters( ch, start, length );
- }
-
- @Override
- public void endElement( String uri, final String localName, String qName )
- throws SAXException
- {
- if ( parsingParent )
- {
- switch ( localName )
+ else if ( event.event == TEXT )
{
- case "parent":
- if ( !hasVersion && ( !hasRelativePath || relativePath != null ) )
- {
- resolvedParent =
- resolveRelativePath( Paths.get( Objects.toString( relativePath, "../pom.xml" ) ) );
- }
- else
+ if ( event.text.matches( "\\s+" ) )
+ {
+ if ( whitespaceAfterParentStart.isEmpty() )
{
- resolvedParent = Optional.empty();
+ whitespaceAfterParentStart = event.text;
}
-
- if ( !hasVersion && resolvedParent.isPresent() )
- {
- try ( Includer i = super.include() )
- {
- super.characters( parentWhitespace.toCharArray(), 0,
- parentWhitespace.length() );
-
- String versionQName = SAXEventUtils.renameQName( qName, "version" );
-
- super.startElement( uri, "version", versionQName, null );
-
- String resolvedParentVersion = resolvedParent.get().getVersion();
-
- super.characters( resolvedParentVersion.toCharArray(), 0,
- resolvedParentVersion.length() );
-
- super.endElement( uri, "version", versionQName );
- }
- }
- super.executeEvents();
-
- parsingParent = false;
- break;
- default:
- // marker?
- break;
+ }
+ else if ( "groupId".equals( tagName ) )
+ {
+ groupId = nullSafeAppend( groupId, event.text );
+ }
+ else if ( "artifactId".equals( tagName ) )
+ {
+ artifactId = nullSafeAppend( artifactId, event.text );
+ }
+ else if ( "relativePath".equals( tagName ) )
+ {
+ relativePath = nullSafeAppend( relativePath, event.text );
+ }
+ else if ( "version".equals( tagName ) )
+ {
+ version = nullSafeAppend( version, event.text );
+ }
+ }
+ else if ( event.event == END_TAG && "parent".equals( event.name ) )
+ {
+ Optional<RelativeProject> resolvedParent;
+ if ( !hasVersion && ( !hasRelativePath || relativePath != null ) )
+ {
+ Path relPath = Paths.get( Objects.toString( relativePath, "../pom.xml" ) );
+ resolvedParent = resolveRelativePath( relPath, groupId, artifactId );
+ }
+ else
+ {
+ resolvedParent = Optional.empty();
+ }
+ if ( !hasVersion && resolvedParent.isPresent() )
+ {
+ int pos = buffer.get( i - 1 ).event == TEXT ? i - 1 : i;
+ Event e = new Event();
+ e.event = TEXT;
+ e.text = whitespaceAfterParentStart;
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = START_TAG;
+ e.namespace = buffer.get( 0 ).namespace;
+ e.prefix = buffer.get( 0 ).prefix;
+ e.name = "version";
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = TEXT;
+ e.text = resolvedParent.get().getVersion();
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = END_TAG;
+ e.name = "version";
+ e.namespace = buffer.get( 0 ).namespace;
+ e.prefix = buffer.get( 0 ).prefix;
+ buffer.add( pos++, e );
+ }
+ break;
}
}
+ buffer.forEach( this::pushEvent );
+ }
- super.endElement( uri, localName, qName );
- state = "";
- }
- protected Optional<RelativeProject> resolveRelativePath( Path relativePath )
+ protected Optional<RelativeProject> resolveRelativePath( Path relativePath, String groupId, String artifactId )
{
Path pomPath = projectPath.resolve( relativePath );
if ( Files.isDirectory( pomPath ) )
@@ -222,4 +171,5 @@ class ParentXMLFilter
}
return Optional.empty();
}
+
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilter.java
deleted file mode 100644
index 767cb0b..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilter.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package org.apache.maven.model.transform;
-
-/*
- * 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.
- */
-
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.LexicalHandler;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-
-/**
- * XML Filter to transform pom.xml to consumer pom.
- * This often means stripping of build-specific information.
- * When extra information is required during filtering it is probably a member of the BuildPomXMLFilter
- *
- * This filter is used at one location:
- * - org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory when publishing POM files.
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class RawToConsumerPomXMLFilter extends AbstractSAXFilter
-{
- RawToConsumerPomXMLFilter( AbstractSAXFilter filter )
- {
- super( filter );
- }
-
- /**
- * Don't allow overwriting parent
- */
- @Override
- public final void setParent( XMLReader parent )
- {
- if ( getParent() == null )
- {
- super.setParent( parent );
- }
- }
-
- @Override
- public LexicalHandler getLexicalHandler()
- {
- return ( (AbstractSAXFilter) getParent() ).getLexicalHandler();
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilterFactory.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilterFactory.java
index d03b9e8..e36342b 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilterFactory.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/RawToConsumerPomXMLFilterFactory.java
@@ -21,14 +21,10 @@ package org.apache.maven.model.transform;
import java.nio.file.Path;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.xml.sax.SAXException;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
- *
+ * @author Guillaume Nodet
* @author Robert Scholte
* @since 4.0.0
*/
@@ -41,20 +37,20 @@ public class RawToConsumerPomXMLFilterFactory
this.buildPomXMLFilterFactory = buildPomXMLFilterFactory;
}
- public final RawToConsumerPomXMLFilter get( Path projectPath )
- throws SAXException, ParserConfigurationException, TransformerConfigurationException
+ public final XmlPullParser get( XmlPullParser orgParser, Path projectPath )
{
- BuildToRawPomXMLFilter parent = buildPomXMLFilterFactory.get( projectPath );
+ XmlPullParser parser = orgParser;
+ parser = buildPomXMLFilterFactory.get( parser, projectPath );
// Ensure that xs:any elements aren't touched by next filters
- AbstractSAXFilter filter = new FastForwardFilter( parent );
+ parser = new FastForwardFilter( parser );
// Strip modules
- filter = new ModulesXMLFilter( filter );
+ parser = new ModulesXMLFilter( parser );
// Adjust relativePath
- filter = new RelativePathXMLFilter( filter );
+ parser = new RelativePathXMLFilter( parser );
- return new RawToConsumerPomXMLFilter( filter );
+ return parser;
}
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ReactorDependencyXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ReactorDependencyXMLFilter.java
index b2d3ca4..7f9dd3b 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/ReactorDependencyXMLFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/ReactorDependencyXMLFilter.java
@@ -19,153 +19,95 @@ package org.apache.maven.model.transform;
* under the License.
*/
+import java.util.List;
import java.util.function.BiFunction;
-import org.apache.maven.model.transform.sax.SAXEventUtils;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import org.apache.maven.model.transform.pull.NodeBufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* Will apply the version if the dependency is part of the reactor
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
-public class ReactorDependencyXMLFilter extends AbstractEventXMLFilter
+public class ReactorDependencyXMLFilter extends NodeBufferingParser
{
- private boolean parsingDependency;
-
- // states
- private String state;
-
- // whiteSpace after <dependency>, to be used to position <version>
- private String dependencyWhitespace;
-
- private boolean hasVersion;
-
- private String groupId;
-
- private String artifactId;
-
private final BiFunction<String, String, String> reactorVersionMapper;
- public ReactorDependencyXMLFilter( BiFunction<String, String, String> reactorVersionMapper )
+ public ReactorDependencyXMLFilter( XmlPullParser xmlPullParser,
+ BiFunction<String, String, String> reactorVersionMapper )
{
+ super( xmlPullParser, "dependency" );
this.reactorVersionMapper = reactorVersionMapper;
}
- @Override
- public void startElement( String uri, String localName, String qName, Attributes atts )
- throws SAXException
- {
- if ( !parsingDependency && "dependency".equals( localName ) )
- {
- parsingDependency = true;
- }
-
- if ( parsingDependency )
- {
- state = localName;
-
- hasVersion |= "version".equals( localName );
- }
- super.startElement( uri, localName, qName, atts );
- }
-
- @Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
+ protected void process( List<Event> buffer )
{
- if ( parsingDependency )
+ // whiteSpace after <dependency>, to be used to position <version>
+ String dependencyWhitespace = "";
+ boolean hasVersion = false;
+ String groupId = null;
+ String artifactId = null;
+ String tagName = null;
+ for ( int i = 0; i < buffer.size(); i++ )
{
- final String eventState = state;
- String value = new String( ch, start, length );
- switch ( eventState )
+ Event event = buffer.get( i );
+ if ( event.event == START_TAG )
{
- case "dependency":
- dependencyWhitespace = nullSafeAppend( dependencyWhitespace, value );
- break;
- case "groupId":
- groupId = nullSafeAppend( groupId, value );
- break;
- case "artifactId":
- artifactId = nullSafeAppend( artifactId, value );
- break;
- default:
- break;
+ tagName = event.name;
+ hasVersion |= "version".equals( tagName );
}
- }
- super.characters( ch, start, length );
- }
-
- @Override
- public void endElement( String uri, final String localName, String qName )
- throws SAXException
- {
- if ( parsingDependency )
- {
- switch ( localName )
+ else if ( event.event == TEXT )
{
- case "dependency":
- if ( !hasVersion )
+ if ( event.text.matches( "\\s+" ) )
+ {
+ if ( dependencyWhitespace.isEmpty() )
{
- String version = getVersion();
-
- // dependency is not part of reactor, probably it is managed
- if ( version != null )
- {
- try ( Includer i = super.include() )
- {
- if ( dependencyWhitespace != null )
- {
- super.characters( dependencyWhitespace.toCharArray(), 0,
- dependencyWhitespace.length() );
-
- }
- String versionQName = SAXEventUtils.renameQName( qName, "version" );
-
- super.startElement( uri, "version", versionQName, null );
- super.characters( version.toCharArray(), 0, version.length() );
- super.endElement( uri, "version", versionQName );
- }
- }
+ dependencyWhitespace = event.text;
}
- super.executeEvents();
-
- parsingDependency = false;
-
- // reset
- hasVersion = false;
- dependencyWhitespace = null;
- groupId = null;
- artifactId = null;
-
- break;
- default:
- break;
+ }
+ else if ( "groupId".equals( tagName ) )
+ {
+ groupId = nullSafeAppend( groupId, event.text );
+ }
+ else if ( "artifactId".equals( tagName ) )
+ {
+ artifactId = nullSafeAppend( artifactId, event.text );
+ }
+ }
+ else if ( event.event == END_TAG && "dependency".equals( event.name ) )
+ {
+ String version = reactorVersionMapper.apply( groupId, artifactId );
+ if ( !hasVersion && version != null )
+ {
+ int pos = buffer.get( i - 1 ).event == TEXT ? i - 1 : i;
+ Event e = new Event();
+ e.event = TEXT;
+ e.text = dependencyWhitespace;
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = START_TAG;
+ e.namespace = buffer.get( 0 ).namespace;
+ e.prefix = buffer.get( 0 ).prefix;
+ e.name = "version";
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = TEXT;
+ e.text = version;
+ buffer.add( pos++, e );
+ e = new Event();
+ e.event = END_TAG;
+ e.name = "version";
+ e.namespace = buffer.get( 0 ).namespace;
+ e.prefix = buffer.get( 0 ).prefix;
+ buffer.add( pos++, e );
+ }
+ break;
}
}
-
- super.endElement( uri, localName, qName );
-
- state = "";
- }
-
- private String getVersion()
- {
- return reactorVersionMapper.apply( groupId, artifactId );
- }
-
- @Override
- protected boolean isParsing()
- {
- return parsingDependency;
- }
-
- @Override
- protected String getState()
- {
- return state;
+ buffer.forEach( this::pushEvent );
}
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RelativePathXMLFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/RelativePathXMLFilter.java
index 2ca09ac..3064a29 100644
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/RelativePathXMLFilter.java
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/RelativePathXMLFilter.java
@@ -19,90 +19,57 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
+import java.util.List;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
+import org.apache.maven.model.transform.pull.NodeBufferingParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
/**
* Remove relativePath element, has no value for consumer pom
*
* @author Robert Scholte
+ * @author Guillaume Nodet
* @since 4.0.0
*/
-class RelativePathXMLFilter
- extends AbstractEventXMLFilter
+public class RelativePathXMLFilter extends NodeBufferingParser
{
- private boolean parsingParent;
- private String state;
-
- RelativePathXMLFilter()
- {
- super();
- }
-
- RelativePathXMLFilter( AbstractSAXFilter parent )
+ public RelativePathXMLFilter( XmlPullParser xmlPullParser )
{
- super( parent );
+ super( xmlPullParser, "parent" );
}
- @Override
- public void startElement( String uri, final String localName, String qName, Attributes atts )
- throws SAXException
+ protected void process( List<Event> buffer )
{
- if ( !parsingParent && "parent".equals( localName ) )
+ boolean skip = false;
+ Event prev = null;
+ for ( Event event : buffer )
{
- parsingParent = true;
- }
-
- if ( parsingParent )
- {
- state = localName;
- }
-
- super.startElement( uri, localName, qName, atts );
- }
-
- @Override
- public void endElement( String uri, String localName, String qName )
- throws SAXException
- {
- if ( parsingParent )
- {
- switch ( localName )
+ if ( event.event == START_TAG && "relativePath".equals( event.name ) )
{
- case "parent":
- executeEvents();
-
- parsingParent = false;
- break;
- default:
- break;
+ skip = true;
+ if ( prev != null && prev.event == TEXT && prev.text.matches( "\\s+" ) )
+ {
+ prev = null;
+ }
+ event = null;
+ }
+ else if ( event.event == END_TAG && "relativePath".equals( event.name ) )
+ {
+ skip = false;
+ event = null;
+ }
+ else if ( skip )
+ {
+ event = null;
+ }
+ if ( prev != null )
+ {
+ pushEvent( prev );
}
+ prev = event;
}
-
- super.endElement( uri, localName, qName );
-
- // for this simple structure resetting to parent it sufficient
- state = "parent";
+ pushEvent( prev );
}
- @Override
- protected boolean isParsing()
- {
- return parsingParent;
- }
-
- @Override
- protected String getState()
- {
- return state;
- }
-
- @Override
- protected boolean acceptEvent( String state )
- {
- return !"relativePath".equals( state );
- }
}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java
new file mode 100644
index 0000000..f8235d8
--- /dev/null
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java
@@ -0,0 +1,563 @@
+package org.apache.maven.model.transform.pull;
+
+/*
+ * 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.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Objects;
+
+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
+{
+
+ protected XmlPullParser xmlPullParser;
+ protected Deque<Event> events;
+ protected Event current;
+ protected boolean disabled;
+
+ @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;
+ }
+
+ @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 )
+ {
+ throw new IllegalStateException( "Not supported during events replay" );
+ }
+ return xmlPullParser.getPositionDescription();
+ }
+
+ @Override
+ public int getLineNumber()
+ {
+ if ( current != null )
+ {
+ throw new IllegalStateException( "Not supported during events replay" );
+ }
+ return xmlPullParser.getLineNumber();
+ }
+
+ @Override
+ public int getColumnNumber()
+ {
+ if ( current != null )
+ {
+ throw new IllegalStateException( "Not supported during events replay" );
+ }
+ return xmlPullParser.getColumnNumber();
+ }
+
+ @Override
+ public boolean isWhitespace() throws XmlPullParserException
+ {
+ if ( current != null )
+ {
+ if ( current.event == TEXT || current.event == CDSECT )
+ {
+ return current.text.matches( "[ \r\t\n]+" );
+ }
+ 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 ( disabled || 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 ( 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();
+ 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();
+ 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:
+ 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;
+ }
+
+ protected void enable()
+ {
+ disabled = false;
+ }
+
+ protected void disable()
+ {
+ if ( events != null && !events.isEmpty() )
+ {
+ throw new IllegalStateException( "Can not disable filter while processing" );
+ }
+ disabled = true;
+ if ( xmlPullParser instanceof BufferingParser )
+ {
+ ( ( BufferingParser ) xmlPullParser ).disable();
+ }
+ }
+
+ protected static String nullSafeAppend( String originalValue, String charSegment )
+ {
+ if ( originalValue == null )
+ {
+ return charSegment;
+ }
+ else
+ {
+ return originalValue + charSegment;
+ }
+ }
+}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/XmlUtils.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/XmlUtils.java
new file mode 100644
index 0000000..f2243c8
--- /dev/null
+++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/XmlUtils.java
@@ -0,0 +1,132 @@
+package org.apache.maven.model.transform.pull;
+
+/*
+ * 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.
+ */
+
+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;
+ }
+}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/AbstractSAXFilter.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/AbstractSAXFilter.java
deleted file mode 100644
index 7189910..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/AbstractSAXFilter.java
+++ /dev/null
@@ -1,143 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-import org.xml.sax.helpers.XMLFilterImpl;
-
-/**
- * XMLFilter with LexicalHandler.
- * Since some filters collect events before processing them, the LexicalHandler events must be collected too.
- * Otherwise the LexicalHandler events might end up before all collected XMLReader events.
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class AbstractSAXFilter extends XMLFilterImpl implements LexicalHandler
-{
- private LexicalHandler lexicalHandler;
-
- public AbstractSAXFilter()
- {
- super();
- }
-
- public AbstractSAXFilter( AbstractSAXFilter parent )
- {
- super( parent );
- parent.setLexicalHandler( this );
- }
-
- public LexicalHandler getLexicalHandler()
- {
- return lexicalHandler;
- }
-
- public void setLexicalHandler( LexicalHandler lexicalHandler )
- {
- this.lexicalHandler = lexicalHandler;
- }
-
- @Override
- public void startDTD( String name, String publicId, String systemId )
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.startDTD( name, publicId, systemId );
- }
- }
-
- @Override
- public void endDTD()
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.endDTD();
- }
- }
-
- @Override
- public void startEntity( String name )
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.startEntity( name );
- }
- }
-
- @Override
- public void endEntity( String name )
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.endEntity( name );
- }
- }
-
- @Override
- public void startCDATA()
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.startCDATA();
- }
- }
-
- @Override
- public void endCDATA()
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.endCDATA();
- }
- }
-
- @Override
- public void comment( char[] ch, int start, int length )
- throws SAXException
- {
- if ( lexicalHandler != null )
- {
- lexicalHandler.comment( ch, start, length );
- }
- }
-
-
- protected static String nullSafeAppend( String originalValue, String charSegment )
- {
- if ( originalValue == null )
- {
- return charSegment;
- }
- else
- {
- return originalValue + charSegment;
- }
- }
-
-
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/CommentRenormalizer.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/CommentRenormalizer.java
deleted file mode 100644
index 6483731..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/CommentRenormalizer.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
-
-/**
- * During parsing the line separators are transformed to \n
- * Unlike characters(), comments don't use the systems line separator for serialization.
- * Hence use this class in the LexicalHandler chain to do so
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class CommentRenormalizer implements LexicalHandler
-{
- private final LexicalHandler lexicalHandler;
-
- private final String lineSeparator;
-
- public CommentRenormalizer( LexicalHandler lexicalHandler )
- {
- this( lexicalHandler, System.lineSeparator() );
- }
-
- // for testing purpose
- CommentRenormalizer( LexicalHandler lexicalHandler, String lineSeparator )
- {
- this.lexicalHandler = lexicalHandler;
- this.lineSeparator = lineSeparator;
- }
-
- @Override
- public void comment( char[] ch, int start, int length )
- throws SAXException
- {
- if ( "\n".equals( lineSeparator ) )
- {
- lexicalHandler.comment( ch, start, length );
- }
- else
- {
- char[] ca = new String( ch, start, length ).replaceAll( "\n", lineSeparator ).toCharArray();
-
- lexicalHandler.comment( ca, 0, ca.length );
- }
- }
-
- @Override
- public void startDTD( String name, String publicId, String systemId )
- throws SAXException
- {
- lexicalHandler.startDTD( name, publicId, systemId );
- }
-
- @Override
- public void endDTD()
- throws SAXException
- {
- lexicalHandler.endDTD();
- }
-
- @Override
- public void startEntity( String name )
- throws SAXException
- {
- lexicalHandler.startEntity( name );
- }
-
- @Override
- public void endEntity( String name )
- throws SAXException
- {
- lexicalHandler.endEntity( name );
- }
-
- @Override
- public void startCDATA()
- throws SAXException
- {
- lexicalHandler.startCDATA();
- }
-
- @Override
- public void endCDATA()
- throws SAXException
- {
- lexicalHandler.endCDATA();
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/Factories.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/Factories.java
deleted file mode 100644
index 835ab0d..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/Factories.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import javax.xml.XMLConstants;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerFactory;
-
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXNotRecognizedException;
-import org.xml.sax.SAXNotSupportedException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.helpers.XMLReaderFactory;
-
-/**
- * Creates XML related factories with OWASP advices applied
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public final class Factories
-{
- private Factories()
- {
- }
-
- /**
- * See
- * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory
- */
- public static TransformerFactory newTransformerFactory()
- {
- TransformerFactory tf = TransformerFactory.newInstance();
- tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_DTD, "" );
- tf.setAttribute( XMLConstants.ACCESS_EXTERNAL_STYLESHEET, "" );
-
- return tf;
- }
-
- public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException
- {
- XMLReader reader = XMLReaderFactory.createXMLReader();
-
- try
- {
- // Xerces 1 - http://xerces.apache.org/xerces-j/features.html#external-general-entities
- // Xerces 2 - http://xerces.apache.org/xerces2-j/features.html#external-general-entities
-
- // Using the XMLReader's setFeature
- reader.setFeature( "http://xml.org/sax/features/external-general-entities", false );
- }
- catch ( SAXNotRecognizedException e )
- {
- // Tried an unknown feature.
- }
- catch ( SAXNotSupportedException e )
- {
- // Tried a feature known to the parser but unsupported.
- }
- return reader;
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEvent.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEvent.java
deleted file mode 100644
index fae783b..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEvent.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import org.xml.sax.SAXException;
-
-/**
- * Command pattern to gather events which can be executed later on.
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-@FunctionalInterface
-public interface SAXEvent
-{
- void execute() throws SAXException;
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventFactory.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventFactory.java
deleted file mode 100644
index c9ae486..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventFactory.java
+++ /dev/null
@@ -1,144 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.Locator;
-import org.xml.sax.ext.LexicalHandler;
-
-/**
- * Factory for SAXEvents
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public final class SAXEventFactory
-{
- private final ContentHandler contentHandler;
-
- private final LexicalHandler lexicalHandler;
-
- protected SAXEventFactory( ContentHandler contentHandler, LexicalHandler lexicalHandler )
- {
- this.contentHandler = contentHandler;
- this.lexicalHandler = lexicalHandler;
- }
-
- public SAXEvent characters( final char[] ch, final int start, final int length )
- {
- final char[] txt = new char[length];
- System.arraycopy( ch, start, txt, 0, length );
- return () -> contentHandler.characters( txt, 0, length );
- }
-
- public SAXEvent endDocument()
- {
- return contentHandler::endDocument;
- }
-
- public SAXEvent endElement( final String uri, final String localName, final String qName )
- {
- return () -> contentHandler.endElement( uri, localName, qName );
- }
-
- public SAXEvent endPrefixMapping( final String prefix )
- {
- return () -> contentHandler.endPrefixMapping( prefix );
- }
-
- public SAXEvent ignorableWhitespace( final char[] ch, final int start, final int length )
- {
- return () -> contentHandler.ignorableWhitespace( ch, start, length );
- }
-
- public SAXEvent processingInstruction( final String target, final String data )
- {
- return () -> contentHandler.processingInstruction( target, data );
- }
-
- public SAXEvent setDocumentLocator( final Locator locator )
- {
- return () -> contentHandler.setDocumentLocator( locator );
- }
-
- public SAXEvent skippedEntity( final String name )
- {
- return () -> contentHandler.skippedEntity( name );
- }
-
- public SAXEvent startDocument()
- {
- return contentHandler::startDocument;
- }
-
- public SAXEvent startElement( final String uri, final String localName, final String qName, final Attributes atts )
- {
- return () -> contentHandler.startElement( uri, localName, qName, atts );
- }
-
- public SAXEvent startPrefixMapping( final String prefix, final String uri )
- {
- return () -> contentHandler.startPrefixMapping( prefix, uri );
- }
-
- public static SAXEventFactory newInstance( ContentHandler contentHandler, LexicalHandler lexicalHandler )
- {
- return new SAXEventFactory( contentHandler, lexicalHandler );
- }
-
- public SAXEvent startDTD( String name, String publicId, String systemId )
- {
- return () -> lexicalHandler.startDTD( name, publicId, systemId );
- }
-
- public SAXEvent endDTD()
- {
- return lexicalHandler::endDTD;
- }
-
- public SAXEvent startEntity( String name )
- {
- return () -> lexicalHandler.startEntity( name );
- }
-
- public SAXEvent endEntity( String name )
- {
- return () -> lexicalHandler.endEntity( name );
-
- }
-
- public SAXEvent startCDATA()
- {
- return lexicalHandler::startCDATA;
- }
-
- public SAXEvent endCDATA()
- {
- return lexicalHandler::endCDATA;
- }
-
- public SAXEvent comment( char[] ch, int start, int length )
- {
- final char[] txt = new char[length];
- System.arraycopy( ch, start, txt, 0, length );
- return () -> lexicalHandler.comment( txt, 0, length );
- }
-}
diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventUtils.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventUtils.java
deleted file mode 100644
index b718d97..0000000
--- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/sax/SAXEventUtils.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import java.util.regex.Pattern;
-
-/**
- * Utility class for SAXEvents
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public final class SAXEventUtils
-{
- private static final Pattern PATTERN = Pattern.compile( "[^:]+$" );
-
- private SAXEventUtils()
- {
- }
-
- /**
- * Returns the newLocalName prefixed with the namespace of the oldQName if present
- *
- * @param oldQName the QName, used for its namespace
- * @param newLocalName the preferred localName
- * @return the new QName
- */
- public static String renameQName( String oldQName, String newLocalName )
- {
- return PATTERN.matcher( oldQName ).replaceFirst( newLocalName );
- }
-}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/AbstractXMLFilterTests.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/AbstractXMLFilterTests.java
index 300d6a1..a18f81a 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/AbstractXMLFilterTests.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/AbstractXMLFilterTests.java
@@ -19,191 +19,41 @@ package org.apache.maven.model.transform;
* under the License.
*/
+import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
-import java.io.Writer;
-import java.net.ContentHandler;
-import java.util.function.Consumer;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.OutputKeys;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.apache.maven.model.transform.sax.Factories;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ext.LexicalHandler;
+import org.apache.maven.model.transform.pull.XmlUtils;
+import org.codehaus.plexus.util.xml.pull.MXParser;
+import org.codehaus.plexus.util.xml.pull.MXSerializer;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
public abstract class AbstractXMLFilterTests
{
- protected AbstractSAXFilter getFilter() throws TransformerException, SAXException, ParserConfigurationException
+ protected XmlPullParser getFilter(XmlPullParser parser)
{
throw new UnsupportedOperationException( "Override one of the getFilter() methods" );
}
- protected AbstractSAXFilter getFilter( Consumer<LexicalHandler> result ) throws TransformerException, SAXException, ParserConfigurationException
- {
- return getFilter();
- }
-
- protected String omitXmlDeclaration()
- {
- return "yes";
- }
-
- protected String indentAmount()
- {
- return null;
- }
-
protected String transform( String input )
- throws TransformerException, SAXException, ParserConfigurationException
+ throws XmlPullParserException, IOException
{
return transform( new StringReader( input ) );
}
- /**
- * Use this method only for testing a single filter.
- *
- * @param input
- * @param filter
- * @return
- * @throws TransformerException
- * @throws SAXException
- * @throws ParserConfigurationException
- */
- protected String transform( String input, AbstractSAXFilter filter )
- throws TransformerException, SAXException, ParserConfigurationException
- {
- setParent( filter );
-
- SAXTransformerFactory transformerFactory = (SAXTransformerFactory) Factories.newTransformerFactory();
- TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
-
- transformerHandler.getTransformer().setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, omitXmlDeclaration() );
- if ( indentAmount() != null )
- {
- transformerHandler.getTransformer().setOutputProperty( OutputKeys.INDENT, "yes" );
- transformerHandler.getTransformer().setOutputProperty( "{http://xml.apache.org/xslt}indent-amount",
- indentAmount() );
- }
-
- Transformer transformer = transformerFactory.newTransformer();
-
- Writer writer = new StringWriter();
- StreamResult result = new StreamResult( writer );
- transformerHandler.setResult( result );
-
- SAXResult transformResult = new SAXResult( transformerHandler );
- SAXSource transformSource = new SAXSource( filter, new InputSource( new StringReader( input ) ) );
-
- transformResult.setLexicalHandler( filter );
- transformer.transform( transformSource, transformResult );
-
- return writer.toString();
-
- }
-
protected String transform( Reader input )
- throws TransformerException, SAXException, ParserConfigurationException
- {
- SAXTransformerFactory transformerFactory = (SAXTransformerFactory) Factories.newTransformerFactory();
- TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
-
- transformerHandler.getTransformer().setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, omitXmlDeclaration() );
- if ( indentAmount() != null )
- {
- transformerHandler.getTransformer().setOutputProperty( OutputKeys.INDENT, "yes" );
- transformerHandler.getTransformer().setOutputProperty( "{http://xml.apache.org/xslt}indent-amount",
- indentAmount() );
- }
-
- Transformer transformer = transformerFactory.newTransformer();
-
- Writer writer = new StringWriter();
- StreamResult result = new StreamResult( writer );
- transformerHandler.setResult( result );
-
- SAXResult transformResult = new SAXResult( transformerHandler );
-
- AbstractSAXFilter filter = getFilter( l -> transformResult.setLexicalHandler( l ) );
- setParent( filter );
-
- filter = new PerCharXMLFilter( filter );
-
- filter.setLexicalHandler( transformerHandler );
-
- SAXSource transformSource = new SAXSource( filter, new InputSource( input ) );
+ throws XmlPullParserException, IOException {
- transformer.transform( transformSource, transformResult );
+ MXParser parser = new MXParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
+ parser.setInput(input);
+ XmlPullParser filter = getFilter( parser );
+ StringWriter writer = new StringWriter();
+ XmlUtils.writeDocument( filter, writer );
return writer.toString();
}
- private void setParent( AbstractSAXFilter filter )
- throws SAXException, ParserConfigurationException
- {
- if ( filter.getParent() == null )
- {
- XMLReader r = Factories.newXMLReader();
-
- AbstractSAXFilter perChar = new PerCharXMLFilter();
- perChar.setParent( r );
-
- filter.setParent( perChar );
- filter.setFeature( "http://xml.org/sax/features/namespaces", true );
- }
- }
-
- /**
- * From {@link ContentHandler}
- * <q>Your code should not assume that algorithms using char-at-a-time idioms will be working in characterunits;
- * in some cases they will split characters. This is relevant wherever XML permits arbitrary characters, such as
- * attribute values,processing instruction data, and comments as well as in data reported from this method. It's
- * also generally relevant whenever Java code manipulates internationalized text; the issue isn't unique to XML.</q>
- *
- * @author Robert Scholte
- */
- class PerCharXMLFilter
- extends AbstractSAXFilter
- {
- public PerCharXMLFilter()
- {
- super();
- }
-
- public PerCharXMLFilter( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- @Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
- {
- for ( int i = 0; i < length; i++ )
- {
- super.characters( ch, start + i, 1 );
- }
- }
-
- @Override
- public void ignorableWhitespace( char[] ch, int start, int length )
- throws SAXException
- {
- for ( int i = 0; i < length; i++ )
- {
- super.ignorableWhitespace( ch, start + i, 1 );
- }
- }
- }
}
\ No newline at end of file
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/CiFriendlyXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/CiFriendlyXMLFilterTest.java
index 80cf84d..bfbbc11 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/CiFriendlyXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/CiFriendlyXMLFilterTest.java
@@ -19,32 +19,18 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
-
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.Test;
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
-import org.junit.jupiter.api.BeforeEach;
-import org.xml.sax.SAXException;
+import static org.junit.jupiter.api.Assertions.assertEquals;
public class CiFriendlyXMLFilterTest extends AbstractXMLFilterTests
{
- private CiFriendlyXMLFilter filter;
+ @Override
+ protected CiFriendlyXMLFilter getFilter(XmlPullParser parser) {
- @BeforeEach
- public void setUp()
- {
- filter = new CiFriendlyXMLFilter( true );
+ CiFriendlyXMLFilter filter = new CiFriendlyXMLFilter( parser, true );
filter.setChangelist( "CHANGELIST" );
- }
-
- @Override
- protected AbstractSAXFilter getFilter()
- throws TransformerException, SAXException, ParserConfigurationException
- {
return filter;
}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ConsumerPomXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ConsumerPomXMLFilterTest.java
index 4fe2c19..ee77d12 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ConsumerPomXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ConsumerPomXMLFilterTest.java
@@ -25,30 +25,17 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.function.BiFunction;
-import java.util.function.Consumer;
import java.util.function.Function;
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerConfigurationException;
-
-import org.apache.maven.model.transform.sax.AbstractSAXFilter;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.Test;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
{
@Override
- protected String omitXmlDeclaration()
- {
- return "no";
- }
-
- @Override
- protected AbstractSAXFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws SAXException, ParserConfigurationException, TransformerConfigurationException
+ protected XmlPullParser getFilter( XmlPullParser orgParser )
{
- final BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new BuildToRawPomXMLFilterFactory( lexicalHandlerConsumer, true )
+ final BuildToRawPomXMLFilterFactory buildPomXMLFilterFactory = new BuildToRawPomXMLFilterFactory( true )
{
@Override
protected Function<Path, Optional<RelativeProject>> getRelativePathMapper()
@@ -82,10 +69,9 @@ public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
};
- RawToConsumerPomXMLFilter filter =
- new RawToConsumerPomXMLFilterFactory( buildPomXMLFilterFactory ).get( Paths.get( "pom.xml" ) );
- filter.setFeature( "http://xml.org/sax/features/namespaces", true );
- return filter;
+ XmlPullParser parser = new RawToConsumerPomXMLFilterFactory( buildPomXMLFilterFactory )
+ .get( orgParser, Paths.get( "pom.xml" ) );
+ return parser;
}
@Test
@@ -254,8 +240,7 @@ public class ConsumerPomXMLFilterTest extends AbstractXMLFilterTests
+ "<!--post-in-->"
+ "</modules>"
+ "<!--after--></project>";
- String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
- "<project><!--before--><!--after--></project>";
+ String expected = "<project><!--before--><!--after--></project>";
String actual = transform( input );
assertThat( actual ).and( expected ).areIdentical();
}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ModulesXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ModulesXMLFilterTest.java
index ce4c8b2..0080788 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ModulesXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ModulesXMLFilterTest.java
@@ -19,23 +19,19 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import static org.xmlunit.assertj.XmlAssert.assertThat;
-
-import java.util.function.Consumer;
-
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.Test;
-import org.xml.sax.ext.LexicalHandler;
+
+import static org.xmlunit.assertj.XmlAssert.assertThat;
public class ModulesXMLFilterTest
extends AbstractXMLFilterTests
{
@Override
- protected ModulesXMLFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
+ protected ModulesXMLFilter getFilter( XmlPullParser parser )
{
- ModulesXMLFilter filter = new ModulesXMLFilter();
- lexicalHandlerConsumer.accept( filter );
- return filter;
+ return new ModulesXMLFilter( parser );
}
@Test
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ParentXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ParentXMLFilterTest.java
index ac499fe..5c66e2f 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ParentXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ParentXMLFilterTest.java
@@ -19,32 +19,43 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
+import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
-import java.util.function.Consumer;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
+import java.util.function.Function;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
public class ParentXMLFilterTest
extends AbstractXMLFilterTests
{
+ private Function<XmlPullParser, ParentXMLFilter> filterCreator;
+
+ @BeforeEach
+ void reset() {
+ filterCreator = null;
+ }
+
@Override
- protected ParentXMLFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerException, SAXException, ParserConfigurationException
+ protected ParentXMLFilter getFilter( XmlPullParser parser )
{
- ParentXMLFilter filter = new ParentXMLFilter( x -> Optional.of( new RelativeProject( "GROUPID",
- "ARTIFACTID",
- "1.0.0" ) ) );
- filter.setProjectPath( Paths.get( "pom.xml").toAbsolutePath() );
- lexicalHandlerConsumer.accept( filter );
+ Function<XmlPullParser, ParentXMLFilter> filterCreator =
+ (this.filterCreator != null ? this.filterCreator : this::createFilter);
+ return filterCreator.apply(parser);
+ }
+
+ protected ParentXMLFilter createFilter( XmlPullParser parser ) {
+ return createFilter( parser,
+ x -> Optional.of(new RelativeProject("GROUPID", "ARTIFACTID", "1.0.0")),
+ Paths.get( "pom.xml").toAbsolutePath() );
+ }
+ protected ParentXMLFilter createFilter( XmlPullParser parser, Function<Path, Optional<RelativeProject>> pathMapper, Path projectPath ) {
+ ParentXMLFilter filter = new ParentXMLFilter( parser, pathMapper, projectPath );
return filter;
}
@@ -52,7 +63,7 @@ public class ParentXMLFilterTest
public void testMinimum()
throws Exception
{
- String input = "<parent/>";
+ String input = "<project><parent /></project>";
String expected = input;
String actual = transform( input );
assertEquals( expected, actual );
@@ -62,11 +73,11 @@ public class ParentXMLFilterTest
public void testNoRelativePath()
throws Exception
{
- String input = "<parent>"
+ String input = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<version>VERSION</version>"
- + "</parent>";
+ + "</parent></project>";
String expected = input;
String actual = transform( input );
@@ -78,15 +89,19 @@ public class ParentXMLFilterTest
public void testDefaultRelativePath()
throws Exception
{
- String input = "<parent>"
- + "<groupId>GROUPID</groupId>"
- + "<artifactId>ARTIFACTID</artifactId>"
- + "</parent>";
- String expected = "<parent>"
- + "<groupId>GROUPID</groupId>"
- + "<artifactId>ARTIFACTID</artifactId>"
- + "<version>1.0.0</version>"
- + "</parent>";
+ String input = "<project>\n"
+ + " <parent>\n"
+ + " <groupId>GROUPID</groupId>\n"
+ + " <artifactId>ARTIFACTID</artifactId>\n"
+ + " </parent>\n"
+ + "</project>";
+ String expected = "<project>" + System.lineSeparator()
+ + " <parent>" + System.lineSeparator()
+ + " <groupId>GROUPID</groupId>" + System.lineSeparator()
+ + " <artifactId>ARTIFACTID</artifactId>" + System.lineSeparator()
+ + " <version>1.0.0</version>" + System.lineSeparator()
+ + " </parent>" + System.lineSeparator()
+ + "</project>";
String actual = transform( input );
@@ -103,16 +118,16 @@ public class ParentXMLFilterTest
public void testEmptyRelativePathNoVersion()
throws Exception
{
- String input = "<parent>"
+ String input = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath></relativePath>"
- + "</parent>";
- String expected = "<parent>"
+ + "</parent></project>";
+ String expected = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
- + "<relativePath/>" // SAX optimization, however "" != null ...
- + "</parent>";
+ + "<relativePath />" // SAX optimization, however "" != null ...
+ + "</parent></project>";
String actual = transform( input );
@@ -123,17 +138,17 @@ public class ParentXMLFilterTest
public void testNoVersion()
throws Exception
{
- String input = "<parent>"
+ String input = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath>RELATIVEPATH</relativePath>"
- + "</parent>";
- String expected = "<parent>"
+ + "</parent></project>";
+ String expected = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath>RELATIVEPATH</relativePath>"
+ "<version>1.0.0</version>"
- + "</parent>";
+ + "</parent></project>";
String actual = transform( input );
@@ -144,17 +159,16 @@ public class ParentXMLFilterTest
public void testInvalidRelativePath()
throws Exception
{
- ParentXMLFilter filter = new ParentXMLFilter( x -> Optional.ofNullable( null ) );
- filter.setProjectPath( Paths.get( "pom.xml").toAbsolutePath() );
+ filterCreator = parser -> createFilter(parser, x -> Optional.ofNullable( null ), Paths.get( "pom.xml").toAbsolutePath() );
- String input = "<parent>"
+ String input = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath>RELATIVEPATH</relativePath>"
- + "</parent>";
+ + "</parent></project>";
String expected = input;
- String actual = transform( input, filter );
+ String actual = transform( input );
assertEquals( expected, actual );
}
@@ -163,18 +177,18 @@ public class ParentXMLFilterTest
public void testRelativePathAndVersion()
throws Exception
{
- String input = "<parent>"
+ String input = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath>RELATIVEPATH</relativePath>"
+ "<version>1.0.0</version>"
- + "</parent>";
- String expected = "<parent>"
+ + "</parent></project>";
+ String expected = "<project><parent>"
+ "<groupId>GROUPID</groupId>"
+ "<artifactId>ARTIFACTID</artifactId>"
+ "<relativePath>RELATIVEPATH</relativePath>"
+ "<version>1.0.0</version>"
- + "</parent>";
+ + "</parent></project>";
String actual = transform( input );
@@ -185,17 +199,20 @@ public class ParentXMLFilterTest
public void testWithWeirdNamespace()
throws Exception
{
- String input = "<relativePath:parent xmlns:relativePath=\"relativePath\">"
+ String input = "<relativePath:project xmlns:relativePath=\"relativePath\">"
+ + "<relativePath:parent>"
+ "<relativePath:groupId>GROUPID</relativePath:groupId>"
+ "<relativePath:artifactId>ARTIFACTID</relativePath:artifactId>"
+ "<relativePath:relativePath>RELATIVEPATH</relativePath:relativePath>"
- + "</relativePath:parent>";
- String expected = "<relativePath:parent xmlns:relativePath=\"relativePath\">"
+ + "</relativePath:parent></relativePath:project>";
+ String expected = "<relativePath:project xmlns:relativePath=\"relativePath\">"
+ + "<relativePath:parent>"
+ "<relativePath:groupId>GROUPID</relativePath:groupId>"
+ "<relativePath:artifactId>ARTIFACTID</relativePath:artifactId>"
+ "<relativePath:relativePath>RELATIVEPATH</relativePath:relativePath>"
+ "<relativePath:version>1.0.0</relativePath:version>"
- + "</relativePath:parent>";
+ + "</relativePath:parent>"
+ + "</relativePath:project>";
String actual = transform( input );
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ReactorDependencyXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ReactorDependencyXMLFilterTest.java
index 69b4783..0304ea6 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/ReactorDependencyXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/ReactorDependencyXMLFilterTest.java
@@ -19,27 +19,29 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import static org.xmlunit.assertj.XmlAssert.assertThat;
-
-import java.util.function.Consumer;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.transform.TransformerException;
+import java.util.function.BiFunction;
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.xml.sax.SAXException;
-import org.xml.sax.ext.LexicalHandler;
+
+import static org.xmlunit.assertj.XmlAssert.assertThat;
public class ReactorDependencyXMLFilterTest
extends AbstractXMLFilterTests
{
+ private BiFunction<String, String, String> reactorVersionMapper;
+
+ @BeforeEach
+ protected void reset() {
+ reactorVersionMapper = null;
+ }
+
@Override
- protected ReactorDependencyXMLFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
- throws TransformerException, SAXException, ParserConfigurationException
+ protected ReactorDependencyXMLFilter getFilter(XmlPullParser parser)
{
- ReactorDependencyXMLFilter filter = new ReactorDependencyXMLFilter( (g, a) -> "1.0.0" );
- lexicalHandlerConsumer.accept( filter );
- return filter;
+ return new ReactorDependencyXMLFilter( parser,
+ reactorVersionMapper != null ? reactorVersionMapper : (g, a) -> "1.0.0" );
}
@Test
@@ -62,7 +64,7 @@ public class ReactorDependencyXMLFilterTest
public void testManagedDependency()
throws Exception
{
- ReactorDependencyXMLFilter filter = new ReactorDependencyXMLFilter( (g, a) -> null );
+ reactorVersionMapper = (g, a) -> null;
String input = "<dependency>"
+ "<groupId>GROUPID</groupId>"
@@ -70,7 +72,7 @@ public class ReactorDependencyXMLFilterTest
+ "</dependency>";
String expected = input;
- String actual = transform( input, filter );
+ String actual = transform( input );
assertThat( actual ).isEqualTo( expected );
}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/RelativePathXMLFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/RelativePathXMLFilterTest.java
index bc1c345..bfe3582 100644
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/RelativePathXMLFilterTest.java
+++ b/maven-model-transform/src/test/java/org/apache/maven/model/transform/RelativePathXMLFilterTest.java
@@ -19,17 +19,18 @@ package org.apache.maven.model.transform;
* under the License.
*/
-import static org.xmlunit.assertj.XmlAssert.assertThat;
-
+import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.junit.jupiter.api.Test;
+import static org.xmlunit.assertj.XmlAssert.assertThat;
+
public class RelativePathXMLFilterTest
extends AbstractXMLFilterTests
{
@Override
- protected RelativePathXMLFilter getFilter()
+ protected RelativePathXMLFilter getFilter(XmlPullParser parser)
{
- return new RelativePathXMLFilter();
+ return new RelativePathXMLFilter(parser);
}
@Test
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/ChainedFilterTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/ChainedFilterTest.java
deleted file mode 100644
index 028b9e5..0000000
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/ChainedFilterTest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import static org.xmlunit.assertj.XmlAssert.assertThat;
-
-import java.io.StringReader;
-import java.io.StringWriter;
-import java.io.Writer;
-
-import javax.xml.transform.Transformer;
-import javax.xml.transform.sax.SAXResult;
-import javax.xml.transform.sax.SAXSource;
-import javax.xml.transform.sax.SAXTransformerFactory;
-import javax.xml.transform.sax.TransformerHandler;
-import javax.xml.transform.stream.StreamResult;
-
-import org.junit.jupiter.api.Test;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-/**
- * A small example of a pipeline of 2 XML Filters, to understand how to get the expected result
- *
- * @author Robert Scholte
- * @since 4.0.0
- */
-public class ChainedFilterTest
-{
-
- @Test
- public void test()
- throws Exception
- {
- String input = "<project><!-- aBc --><name>dEf</name></project>";
-
- SAXTransformerFactory transformerFactory = (SAXTransformerFactory) Factories.newTransformerFactory();
- TransformerHandler transformerHandler = transformerFactory.newTransformerHandler();
-
- Writer writer = new StringWriter();
- StreamResult result = new StreamResult( writer );
- transformerHandler.setResult( result );
-
- SAXResult transformResult = new SAXResult( transformerHandler );
-
- // Watch the order of filters! In reverse order the values would be 'AweSome'
- AbstractSAXFilter filter = new Awesome();
-
- // AbstractSAXFilter doesn't have a constructor with XMLReader, otherwise the LexicalHandler pipeline will be broken
- filter.setParent( Factories.newXMLReader() );
-
- // LexicalHandler of transformerResult must be the first filter
- transformResult.setLexicalHandler( filter );
-
- filter = new ChangeCase( filter );
- // LexicalHandler on last filter must be the transformerHandler
- filter.setLexicalHandler( transformerHandler );
-
- SAXSource transformSource = new SAXSource( filter, new InputSource( new StringReader( input ) ) );
-
- Transformer transformer = transformerFactory.newTransformer();
- transformer.transform( transformSource, transformResult );
-
- String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- + "<project><!--AWESOME--><name>awesome</name></project>";
- assertThat( writer.toString() ).and( expected ).areIdentical();
- }
-
- static class ChangeCase
- extends AbstractSAXFilter
- {
-
- public ChangeCase()
- {
- super();
- }
-
- public ChangeCase( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- @Override
- public void comment( char[] ch, int start, int length )
- throws SAXException
- {
- String s = new String( ch, start, length ).toUpperCase();
- super.comment( s.toCharArray(), 0, s.length() );
- }
-
- @Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
- {
- String s = new String( ch, start, length ).toLowerCase();
- super.characters( s.toCharArray(), 0, s.length() );
- }
- }
-
- static class Awesome
- extends AbstractSAXFilter
- {
-
- public Awesome()
- {
- super();
- }
-
- public Awesome( AbstractSAXFilter parent )
- {
- super( parent );
- }
-
- @Override
- public void comment( char[] ch, int start, int length )
- throws SAXException
- {
- String s = "AweSome";
- super.comment( s.toCharArray(), 0, s.length() );
- }
-
- @Override
- public void characters( char[] ch, int start, int length )
- throws SAXException
- {
- String s = "AweSome";
- super.characters( s.toCharArray(), 0, s.length() );
- }
- }
-
-}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/CommentRenormalizerTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/CommentRenormalizerTest.java
deleted file mode 100644
index c663741..0000000
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/CommentRenormalizerTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.ValueSource;
-
-import org.xml.sax.ext.LexicalHandler;
-
-public class CommentRenormalizerTest
-{
- private LexicalHandler lexicalHandler = mock( LexicalHandler.class );
-
- @ParameterizedTest
- @ValueSource( strings = { "\n", "\r\n", "\r" } )
- public void singleLine( String lineSeparator )
- throws Exception
- {
- CommentRenormalizer commentRenormalizer = new CommentRenormalizer( lexicalHandler, lineSeparator );
-
- char[] ch = "single line".toCharArray();
-
- commentRenormalizer.comment( ch, 0, ch.length );
-
- verify( lexicalHandler ).comment( ch, 0, ch.length );
- }
-
- @ParameterizedTest
- @ValueSource( strings = { "\n", "\r\n", "\r" } )
- public void multiLine( String lineSeparator )
- throws Exception
- {
- CommentRenormalizer commentRenormalizer = new CommentRenormalizer( lexicalHandler, lineSeparator );
-
- String text = "I%sam%sthe%sbest%s";
-
- char[] chIn = String.format( text, "\n", "\n", "\n", "\n" ).toCharArray();
- char[] chOut = String.format( text, lineSeparator, lineSeparator, lineSeparator, lineSeparator ).toCharArray();
-
- commentRenormalizer.comment( chIn, 0, chIn.length );
-
- verify( lexicalHandler ).comment( chOut, 0, chOut.length );
- }
-}
diff --git a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/SAXEventUtilsTest.java b/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/SAXEventUtilsTest.java
deleted file mode 100644
index 8ec4bec..0000000
--- a/maven-model-transform/src/test/java/org/apache/maven/model/transform/sax/SAXEventUtilsTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package org.apache.maven.model.transform.sax;
-
-/*
- * 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.
- */
-
-import static org.hamcrest.MatcherAssert.assertThat;
-
-import static org.hamcrest.CoreMatchers.is;
-
-import org.junit.jupiter.api.Test;
-
-public class SAXEventUtilsTest
-{
- @Test
- public void replaceWithNamespace()
- {
- assertThat( SAXEventUtils.renameQName( "org:bar", "com" ), is( "org:com" ) );
- }
-
- @Test
- public void replaceWithoutNamespace()
- {
- assertThat( SAXEventUtils.renameQName( "bar", "com" ), is( "com" ) );
- }
-}