mirror of https://github.com/apache/maven.git
[MNG-7182] Use the MX xpp parser instead of a STAX transformation (#486)
This commit is contained in:
parent
98a6c4f14c
commit
ae8aebea19
|
@ -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;
|
||||
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 extends AbstractModelSourceTransformer
|
||||
class ConsumerModelSourceTransformer
|
||||
{
|
||||
@Override
|
||||
protected AbstractSAXFilter getSAXFilter( Path pomFile,
|
||||
TransformerContext context,
|
||||
Consumer<LexicalHandler> lexicalHandlerConsumer )
|
||||
throws TransformerConfigurationException, SAXException, ParserConfigurationException
|
||||
public InputStream transform( Path pomFile, TransformerContext context )
|
||||
throws IOException, XmlPullParserException
|
||||
{
|
||||
return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context,
|
||||
lexicalHandlerConsumer, true ) ).get( pomFile );
|
||||
}
|
||||
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 );
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
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" );
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
new DefaultBuildPomXMLFilterFactory( context, false );
|
||||
|
||||
return buildPomXMLFilterFactory.get( pomFile );
|
||||
}
|
||||
|
||||
@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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 )
|
||||
try ( XmlStreamReader in = ReaderFactory.newXmlReader( input ) )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ under the License.
|
|||
<name>Maven Model XML Transform</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.plexus</groupId>
|
||||
<artifactId>plexus-utils</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 );
|
||||
}
|
|
@ -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( "${" ) )
|
||||
if ( event.event == TEXT && replace && event.text.contains( "${" ) )
|
||||
{
|
||||
char[] ch = replaceChain.apply( characters ).toCharArray();
|
||||
super.characters( ch, 0, ch.length );
|
||||
event.text = replaceChain.apply( event.text );
|
||||
}
|
||||
else
|
||||
{
|
||||
char[] ch = characters.toCharArray();
|
||||
super.characters( ch, 0, ch.length );
|
||||
}
|
||||
characters = null;
|
||||
parseVersion = false;
|
||||
pushEvent( event );
|
||||
}
|
||||
|
||||
super.endElement( uri, localName, qName );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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++;
|
||||
}
|
||||
state.push( localName );
|
||||
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.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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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()
|
||||
ModulesXMLFilter( XmlPullParser xmlPullParser )
|
||||
{
|
||||
super();
|
||||
super( xmlPullParser, "modules" );
|
||||
}
|
||||
|
||||
ModulesXMLFilter( AbstractSAXFilter parent )
|
||||
protected void process( List<Event> buffer )
|
||||
{
|
||||
super( parent );
|
||||
// Do nothing, as we want to delete those nodes completely
|
||||
}
|
||||
|
||||
@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()
|
||||
{
|
||||
return parsingModules;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getState()
|
||||
{
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean acceptEvent( String state )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
protected void process( List<Event> buffer )
|
||||
{
|
||||
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 ) )
|
||||
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++ )
|
||||
{
|
||||
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
|
||||
{
|
||||
if ( parsingParent )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
else if ( event.event == TEXT )
|
||||
{
|
||||
if ( event.text.matches( "\\s+" ) )
|
||||
{
|
||||
if ( whitespaceAfterParentStart.isEmpty() )
|
||||
{
|
||||
whitespaceAfterParentStart = event.text;
|
||||
}
|
||||
}
|
||||
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.characters( ch, start, length );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endElement( String uri, final String localName, String qName )
|
||||
throws SAXException
|
||||
{
|
||||
if ( parsingParent )
|
||||
{
|
||||
switch ( localName )
|
||||
{
|
||||
case "parent":
|
||||
if ( !hasVersion && ( !hasRelativePath || relativePath != null ) )
|
||||
{
|
||||
resolvedParent =
|
||||
resolveRelativePath( Paths.get( Objects.toString( relativePath, "../pom.xml" ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedParent = Optional.empty();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
protected void process( List<Event> buffer )
|
||||
{
|
||||
if ( !parsingDependency && "dependency".equals( localName ) )
|
||||
// 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++ )
|
||||
{
|
||||
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
|
||||
{
|
||||
if ( parsingDependency )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
public RelativePathXMLFilter( XmlPullParser xmlPullParser )
|
||||
{
|
||||
super();
|
||||
super( xmlPullParser, "parent" );
|
||||
}
|
||||
|
||||
RelativePathXMLFilter( AbstractSAXFilter parent )
|
||||
protected void process( List<Event> buffer )
|
||||
{
|
||||
super( parent );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startElement( String uri, final String localName, String qName, Attributes atts )
|
||||
throws SAXException
|
||||
{
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
|
||||
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* Buffer events while parsing a given element to allow some post-processing.
|
||||
*
|
||||
* @author Guillaume Nodet
|
||||
* @since 4.0.0
|
||||
*/
|
||||
public abstract class NodeBufferingParser extends BufferingParser
|
||||
{
|
||||
|
||||
private final List<Event> buffer = new ArrayList<>();
|
||||
|
||||
private final String nodeName;
|
||||
|
||||
private boolean buffering;
|
||||
|
||||
public NodeBufferingParser( XmlPullParser xmlPullParser, String nodeName )
|
||||
{
|
||||
super( xmlPullParser );
|
||||
this.nodeName = Objects.requireNonNull( nodeName );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean accept() throws XmlPullParserException, IOException
|
||||
{
|
||||
if ( nodeName.equals( xmlPullParser.getName() ) )
|
||||
{
|
||||
if ( xmlPullParser.getEventType() == START_TAG && !buffering )
|
||||
{
|
||||
buffer.add( bufferEvent() );
|
||||
buffering = true;
|
||||
return false;
|
||||
}
|
||||
if ( xmlPullParser.getEventType() == END_TAG && buffering )
|
||||
{
|
||||
buffer.add( bufferEvent() );
|
||||
process( buffer );
|
||||
buffering = false;
|
||||
buffer.clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if ( buffering )
|
||||
{
|
||||
buffer.add( bufferEvent() );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected abstract void process( List<Event> buffer );
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
throws XmlPullParserException, IOException {
|
||||
|
||||
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 ) );
|
||||
|
||||
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 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
@BeforeEach
|
||||
public void setUp()
|
||||
{
|
||||
filter = new CiFriendlyXMLFilter( true );
|
||||
filter.setChangelist( "CHANGELIST" );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSAXFilter getFilter()
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
protected CiFriendlyXMLFilter getFilter(XmlPullParser parser) {
|
||||
|
||||
CiFriendlyXMLFilter filter = new CiFriendlyXMLFilter( parser, true );
|
||||
filter.setChangelist( "CHANGELIST" );
|
||||
return filter;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
protected XmlPullParser getFilter( XmlPullParser orgParser )
|
||||
{
|
||||
return "no";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AbstractSAXFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
|
||||
throws SAXException, ParserConfigurationException, TransformerConfigurationException
|
||||
{
|
||||
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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
@Override
|
||||
protected ParentXMLFilter getFilter( Consumer<LexicalHandler> lexicalHandlerConsumer )
|
||||
throws TransformerException, SAXException, ParserConfigurationException
|
||||
{
|
||||
ParentXMLFilter filter = new ParentXMLFilter( x -> Optional.of( new RelativeProject( "GROUPID",
|
||||
"ARTIFACTID",
|
||||
"1.0.0" ) ) );
|
||||
filter.setProjectPath( Paths.get( "pom.xml").toAbsolutePath() );
|
||||
lexicalHandlerConsumer.accept( filter );
|
||||
private Function<XmlPullParser, ParentXMLFilter> filterCreator;
|
||||
|
||||
@BeforeEach
|
||||
void reset() {
|
||||
filterCreator = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParentXMLFilter getFilter( XmlPullParser parser )
|
||||
{
|
||||
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 );
|
||||
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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 );
|
||||
}
|
||||
}
|
|
@ -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" ) );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue