You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by GitBox <gi...@apache.org> on 2020/06/15 09:07:17 UTC

[GitHub] [maven] michael-o commented on a change in pull request #286: [MNG-6656] Introduce base for build/consumer process

michael-o commented on a change in pull request #286:
URL: https://github.com/apache/maven/pull/286#discussion_r440025887



##########
File path: maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java
##########
@@ -406,15 +444,17 @@ private ModelSource createStubModelSource( Artifact artifact )
     @SuppressWarnings( "checkstyle:parameternumber" )
     private boolean build( List<ProjectBuildingResult> results, List<InterimResult> interimResults,
                            Map<String, MavenProject> projectIndex, List<File> pomFiles, Set<File> aggregatorFiles,
-                           boolean isRoot, boolean recursive, InternalConfig config )
+                           boolean isRoot, boolean recursive, InternalConfig config,

Review comment:
       Why is the first boolean prefixed with an `is`, the second is not. It should be consistent, maybe both w/o `is`.

##########
File path: maven-core/src/main/java/org/apache/maven/project/ReactorModelPool.java
##########
@@ -19,53 +19,127 @@
  * under the License.
  */
 
-import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.maven.model.Model;
 
 /**
- * Holds all POM files that are known to the reactor. This allows the project builder to resolve imported POMs from the
+ * Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
  * reactor when building another project's effective model.
  *
  * @author Benjamin Bentmann
+ * @author Robert Scholte
  */
 class ReactorModelPool
 {
+    private final Map<GAKey, Set<Model>> modelsByGa = new HashMap<>();
+
+    private final Map<Path, Model> modelsByPath = new HashMap<>();
+
+    /**
+     * Get the model by its GAV or (since 3.7.0) by its GA if there is only one.

Review comment:
       If this `get` is new, the version should go to `@since`.

##########
File path: maven-core/src/main/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformer.java
##########
@@ -0,0 +1,111 @@
+package org.apache.maven.internal.aether;
+
+/*
+ * 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.nio.file.Files;
+import java.nio.file.Path;
+
+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.xml.Factories;
+import org.apache.maven.xml.internal.DefaultConsumerPomXMLFilterFactory;
+import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
+import org.xml.sax.SAXException;
+
+class ConsumerModelSourceTransformer extends AbstractModelSourceTransformer
+{
+    @Override
+    protected AbstractSAXFilter getSAXFilter( Path pomFile, TransformerContext context )
+        throws TransformerConfigurationException, SAXException, ParserConfigurationException
+    {
+        return new DefaultConsumerPomXMLFilterFactory( new DefaultBuildPomXMLFilterFactory( context ) ).get( pomFile );
+    }
+    
+    /**
+     * This transformer will ensure that encoding and version are kept.
+     * However, it cannot prevent:
+     * <ul>
+     *   <li>line-endings will be unix-style(LF)</li>
+     *   <li>attributes will be on one line</li>
+     *   <li>Unnecessary whitespace before the rootelement will be remove</li> 
+     * </ul>
+     */
+    @Override
+    protected TransformerHandler getTransformerHandler( Path pomFile )
+        throws IOException, org.apache.maven.model.building.TransformerException
+    {
+        final TransformerHandler transformerHandler;
+        
+        final SAXTransformerFactory transformerFactory =
+                        (SAXTransformerFactory) Factories.newTransformerFactory();
+        
+        // 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 );

Review comment:
       I wonder whether we should retain the encoding or use UTF-8 canonically.

##########
File path: maven-core/src/main/java/org/apache/maven/project/ReactorModelPool.java
##########
@@ -19,53 +19,127 @@
  * under the License.
  */
 
-import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+
+import org.apache.maven.model.Model;
 
 /**
- * Holds all POM files that are known to the reactor. This allows the project builder to resolve imported POMs from the
+ * Holds all Models that are known to the reactor. This allows the project builder to resolve imported Models from the
  * reactor when building another project's effective model.
  *
  * @author Benjamin Bentmann
+ * @author Robert Scholte
  */
 class ReactorModelPool
 {
+    private final Map<GAKey, Set<Model>> modelsByGa = new HashMap<>();
+
+    private final Map<Path, Model> modelsByPath = new HashMap<>();
+
+    /**
+     * Get the model by its GAV or (since 3.7.0) by its GA if there is only one.
+     *  
+     * @param groupId, never {@code null}
+     * @param artifactId, never {@code null}
+     * @param version, can be {@code null}
+     * @return the matching model or {@code null}
+     * @throws IllegalStateException if version was null and multiple modules share the same groupId + artifactId
+     * @throws NoSuchElementException if model could not be found
+     */
+    public Model get( String groupId, String artifactId, String version )
+        throws IllegalStateException, NoSuchElementException

Review comment:
       Runtime exceptions go into the Javadoc only. See Effective Java.

##########
File path: maven-model-builder/src/main/java/org/apache/maven/model/building/AbstractModelSourceTransformer.java
##########
@@ -0,0 +1,196 @@
+package org.apache.maven.model.building;
+
+/*
+ * 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.FileInputStream;
+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.Path;
+import java.util.concurrent.atomic.AtomicInteger;
+
+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.TransformerHandler;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.maven.xml.Factories;
+import org.apache.maven.xml.sax.ext.CommentRenormalizer;
+import org.apache.maven.xml.sax.filter.AbstractSAXFilter;
+import org.xml.sax.SAXException;
+
+/**
+ * 
+ * @author Robert Scholte
+ * @since 3.7.0
+ */
+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 )
+        throws TransformerConfigurationException, SAXException, ParserConfigurationException;
+
+    protected OutputStream filterOutputStream( OutputStream outputStream, Path pomFile )
+    {
+        return outputStream;
+    }
+    
+    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 AbstractSAXFilter filter;
+        try
+        {
+            filter = getSAXFilter( pomFile, context );
+            filter.setLexicalHandler( transformerHandler );
+        }
+        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( new FileInputStream( pomFile.toFile() ) ) );
+
+        final PipedOutputStream pout = new PipedOutputStream();
+        final PipedInputStream pipedInputStream = new PipedInputStream( pout );
+        
+        OutputStream out = filterOutputStream( pout, pomFile );
+
+        final javax.xml.transform.Result result; 
+        if ( transformerHandler == null )
+        {
+            result = new StreamResult( out );
+        }
+        else
+        {
+            result = new SAXResult( transformerHandler );
+            ( (SAXResult) result ).setLexicalHandler( new CommentRenormalizer( transformerHandler ) );
+            transformerHandler.setResult( new StreamResult( out ) );
+        }
+
+        IOExceptionHandler eh = new IOExceptionHandler();
+
+        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 )
+                {
+                    throw new AssertionError( "Failed to transform pom", t );

Review comment:
       I don't think it is appropriate to use `Error` for use. I'd wrap into an runtime or illegal state exception.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
users@infra.apache.org