Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,91 +23,30 @@
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Consumer;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.sax.SAXTransformerFactory;
import javax.xml.transform.sax.TransformerHandler;

import org.apache.maven.model.building.AbstractModelSourceTransformer;
import org.apache.maven.model.building.DefaultBuildPomXMLFilterFactory;
import org.apache.maven.model.building.TransformerContext;
import org.apache.maven.model.transform.sax.AbstractSAXFilter;
import org.apache.maven.xml.internal.DefaultConsumerPomXMLFilterFactory;
import org.xml.sax.SAXException;
import org.xml.sax.ext.LexicalHandler;

class ConsumerModelSourceTransformer extends AbstractModelSourceTransformer
import org.apache.maven.model.transform.RawToConsumerPomXMLFilterFactory;
import org.apache.maven.model.transform.pull.XmlUtils;
import org.codehaus.plexus.util.ReaderFactory;
import org.codehaus.plexus.util.xml.XmlStreamReader;
import org.codehaus.plexus.util.xml.pull.EntityReplacementMap;
import org.codehaus.plexus.util.xml.pull.MXParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParser;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;

class ConsumerModelSourceTransformer
{
@Override
protected AbstractSAXFilter getSAXFilter( Path pomFile,
TransformerContext context,
Consumer<LexicalHandler> lexicalHandlerConsumer )
throws TransformerConfigurationException, SAXException, ParserConfigurationException
{
return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context,
lexicalHandlerConsumer, true ) ).get( pomFile );
}

/**
* This transformer will ensure that encoding and version are kept.
* However, it cannot prevent:
* <ul>
* <li>attributes will be on one line</li>
* <li>Unnecessary whitespace before the rootelement will be removed</li>
* </ul>
*/
@Override
protected TransformerHandler getTransformerHandler( Path pomFile )
throws IOException, org.apache.maven.model.building.TransformerException
public InputStream transform( Path pomFile, TransformerContext context )
throws IOException, XmlPullParserException
{
final TransformerHandler transformerHandler;

final SAXTransformerFactory transformerFactory = getTransformerFactory();

// Keep same encoding+version
try ( InputStream input = Files.newInputStream( pomFile ) )
{
XMLStreamReader streamReader =
XMLInputFactory.newFactory().createXMLStreamReader( input );

transformerHandler = transformerFactory.newTransformerHandler();

final String encoding = streamReader.getCharacterEncodingScheme();
final String version = streamReader.getVersion();

Transformer transformer = transformerHandler.getTransformer();
transformer.setOutputProperty( OutputKeys.METHOD, "xml" );
if ( encoding == null && version == null )
{
transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "yes" );
}
else
{
transformer.setOutputProperty( OutputKeys.OMIT_XML_DECLARATION, "no" );
XmlStreamReader reader = ReaderFactory.newXmlReader( Files.newInputStream( pomFile ) );
XmlPullParser parser = new MXParser( EntityReplacementMap.defaultEntityReplacementMap );
parser.setInput( reader );
parser = new RawToConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context, true ) )
Comment thread
gnodet marked this conversation as resolved.
.get( parser, pomFile );

if ( encoding != null )
{
transformer.setOutputProperty( OutputKeys.ENCODING, encoding );
}
if ( version != null )
{
transformer.setOutputProperty( OutputKeys.VERSION, version );
}
}
}
catch ( XMLStreamException | TransformerConfigurationException e )
{
throw new org.apache.maven.model.building.TransformerException(
"Failed to detect XML encoding and version", e );
}
return transformerHandler;
return XmlUtils.writeDocument( reader, parser );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,26 @@
* 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;
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;
Expand All @@ -37,6 +49,7 @@
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;
Expand All @@ -59,19 +72,6 @@
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
*/
Expand Down Expand Up @@ -310,7 +310,7 @@ public InputStream transformData( File pomFile )
{
return new ConsumerModelSourceTransformer().transform( pomFile.toPath(), context );
}
catch ( TransformerException e )
catch ( XmlPullParserException e )
{
throw new TransformException( e );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,35 +19,6 @@
* 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.
Expand All @@ -58,181 +29,5 @@
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();
}
}
}
}
Loading