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 <[email protected]>

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
                             {


Reply via email to