You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2014/12/18 22:36:41 UTC

svn commit: r1646543 - in /maven/plugins/trunk/maven-remote-resources-plugin: pom.xml src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java

Author: krosenvold
Date: Thu Dec 18 21:36:41 2014
New Revision: 1646543

URL: http://svn.apache.org/r1646543
Log:
[MRRESOURCES-91] Avoid overwrite of the destination file if the produced contents is the same

maven-remote-resource-plugin is used in Apache pom to add DEPENDENCIES, and the resulting file is overwritten on each build.
It leads to jar being rebuild, etc leading to longer compilation times.

Patch by Vladimir Sitnikov <si...@gmail.com>

This closes #40

Modified:
    maven/plugins/trunk/maven-remote-resources-plugin/pom.xml
    maven/plugins/trunk/maven-remote-resources-plugin/src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java

Modified: maven/plugins/trunk/maven-remote-resources-plugin/pom.xml
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-remote-resources-plugin/pom.xml?rev=1646543&r1=1646542&r2=1646543&view=diff
==============================================================================
--- maven/plugins/trunk/maven-remote-resources-plugin/pom.xml (original)
+++ maven/plugins/trunk/maven-remote-resources-plugin/pom.xml Thu Dec 18 21:36:41 2014
@@ -146,6 +146,11 @@ under the License.
 
     <!-- other -->
     <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.2</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.velocity</groupId>
       <artifactId>velocity</artifactId>
       <version>1.7</version>

Modified: maven/plugins/trunk/maven-remote-resources-plugin/src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java
URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-remote-resources-plugin/src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java?rev=1646543&r1=1646542&r2=1646543&view=diff
==============================================================================
--- maven/plugins/trunk/maven-remote-resources-plugin/src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java (original)
+++ maven/plugins/trunk/maven-remote-resources-plugin/src/main/java/org/apache/maven/plugin/resources/remote/ProcessRemoteResourcesMojo.java Thu Dec 18 21:36:41 2014
@@ -19,6 +19,7 @@ package org.apache.maven.plugin.resource
  * under the License.
  */
 
+import java.io.ByteArrayInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -50,6 +51,7 @@ import java.util.Properties;
 import java.util.Set;
 import java.util.TreeMap;
 
+import org.apache.commons.io.output.DeferredFileOutputStream;
 import org.apache.maven.ProjectDependenciesResolver;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.factory.ArtifactFactory;
@@ -305,6 +307,16 @@ public class ProcessRemoteResourcesMojo
     protected boolean includeProjectProperties = false;
 
     /**
+     * When the result of velocity transformation fits in memory, it is compared with the actual contents on disk
+     * to eliminate unnecessary destination file overwrite. This improves build times since further build steps
+     * typically rely on the modification date.
+     *
+     * @since 1.6
+     */
+    @Parameter( defaultValue = "5242880" )
+    protected int velocityFilterInMemoryThreshold = 5 * 1024 * 1024;
+
+    /**
      * The list of resources defined for the project.
      */
     @Parameter( defaultValue = "${project.resources}", readonly = true, required = true )
@@ -808,39 +820,41 @@ public class ProcessRemoteResourcesMojo
                 {
                     Reader reader = null;
                     Writer writer = null;
+                    DeferredFileOutputStream os = new DeferredFileOutputStream( velocityFilterInMemoryThreshold, file );
                     try
                     {
+
                         if ( encoding != null )
                         {
                             reader = new InputStreamReader( new FileInputStream( source ), encoding );
-                            writer = new OutputStreamWriter( new FileOutputStream( file ), encoding );
+                            writer = new OutputStreamWriter( os, encoding );
                         }
                         else
                         {
                             reader = ReaderFactory.newPlatformReader( source );
-                            writer = WriterFactory.newPlatformWriter( file );
+                            writer = WriterFactory.newPlatformWriter( os );
                         }
 
                         velocity.evaluate( context, writer, "", reader );
-                        velocity.evaluate( context, writer, "", reader );
                     }
                     catch ( ParseErrorException e )
                     {
-                        throw new MojoExecutionException( "Error rendering velocity resource.", e );
+                        throw new MojoExecutionException( "Error rendering velocity resource: " + source, e );
                     }
                     catch ( MethodInvocationException e )
                     {
-                        throw new MojoExecutionException( "Error rendering velocity resource.", e );
+                        throw new MojoExecutionException( "Error rendering velocity resource: " + source, e );
                     }
                     catch ( ResourceNotFoundException e )
                     {
-                        throw new MojoExecutionException( "Error rendering velocity resource.", e );
+                        throw new MojoExecutionException( "Error rendering velocity resource: " + source, e );
                     }
                     finally
                     {
                         IOUtil.close( writer );
                         IOUtil.close( reader );
                     }
+                    fileWriteIfDiffers( os );
                 }
                 else if ( resource.isFiltering() )
                 {
@@ -871,6 +885,64 @@ public class ProcessRemoteResourcesMojo
         return false;
     }
 
+    /**
+     * If the transformation result fits in memory and the destination file already exists
+     * then both are compared.
+     * <p>If destination file is byte-by-byte equal, then it is not overwritten.
+     * This improves subsequent compilation times since upstream plugins property see that
+     * the resource was not modified.
+     * <p>Note: the method should be called after {@link org.apache.commons.io.output.DeferredFileOutputStream#close}
+     *
+     * @param outStream Deferred stream
+     * @throws IOException
+     */
+    private void fileWriteIfDiffers( DeferredFileOutputStream outStream ) throws IOException
+    {
+        File file = outStream.getFile();
+        if ( outStream.isThresholdExceeded() )
+        {
+            getLog().info( "File " + file + " was overwritten due to content limit threshold "
+                    + outStream.getThreshold() + " reached" );
+            return;
+        }
+        boolean needOverwrite = true;
+
+        if ( file.exists() )
+        {
+            InputStream is = new FileInputStream( file );
+            InputStream newContents = new ByteArrayInputStream( outStream.getData() );
+            try
+            {
+                needOverwrite = !IOUtil.contentEquals( is, newContents );
+                if ( getLog().isDebugEnabled() )
+                {
+                    getLog().debug( "File " + file + " contents "
+                            + ( needOverwrite ? "differs" : "does not differ" ) );
+                }
+            }
+            finally
+            {
+                IOUtil.close( is );
+            }
+        }
+
+        if ( !needOverwrite )
+        {
+            getLog().info( "File " + file + " is up to date" );
+            return;
+        }
+        getLog().info( "Writing " + file );
+        OutputStream os = new FileOutputStream( file );
+        try
+        {
+            outStream.writeTo( os );
+        }
+        finally
+        {
+            IOUtil.close( os );
+        }
+    }
+
     private MavenFileFilterRequest setupRequest( Resource resource, File source, File file )
     {
         MavenFileFilterRequest req = new MavenFileFilterRequest();
@@ -1107,17 +1179,18 @@ public class ProcessRemoteResourcesMojo
                         {
                             if ( doVelocity )
                             {
-                                PrintWriter writer;
+                                DeferredFileOutputStream os =
+                                        new DeferredFileOutputStream( velocityFilterInMemoryThreshold, f );
+                                Writer writer;
                                 if ( bundle.getSourceEncoding() == null )
                                 {
-                                    writer = new PrintWriter( new FileWriter( f ) );
+                                    writer = new OutputStreamWriter( os );
                                 }
                                 else
                                 {
                                     writer =
-                                        new PrintWriter( new OutputStreamWriter( new FileOutputStream( f ),
-                                                                                 bundle.getSourceEncoding() ) );
-
+                                        new OutputStreamWriter( os,
+                                                                bundle.getSourceEncoding() );
                                 }
 
                                 try
@@ -1139,6 +1212,7 @@ public class ProcessRemoteResourcesMojo
                                 {
                                     IOUtil.close( writer );
                                 }
+                                fileWriteIfDiffers( os );
                             }
                             else
                             {