From fa1578d2d90175ca3db1757007c7bd70b8b42b45 Mon Sep 17 00:00:00 2001 From: LAMAA Liwae Date: Wed, 10 Oct 2018 10:57:15 +0300 Subject: [PATCH] [MSHARED-763] - Include a dependency change detection. --- .../incremental/IncrementalBuildHelper.java | 158 +++++++++++++++++- .../IncrementalBuildHelperRequest.java | 28 ++++ 2 files changed, 185 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelper.java b/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelper.java index cebe33f..26ec85d 100644 --- a/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelper.java +++ b/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelper.java @@ -28,8 +28,18 @@ import org.apache.maven.shared.utils.io.FileUtils; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; import java.io.IOException; +import java.io.FileNotFoundException; import java.util.Set; +import java.util.HashSet; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; +import java.util.HashMap; /** * Various helper methods to support incremental builds @@ -42,7 +52,7 @@ public class IncrementalBuildHelper private static final String MAVEN_STATUS_ROOT = "maven-status"; public static final String CREATED_FILES_LST_FILENAME = "createdFiles.lst"; private static final String INPUT_FILES_LST_FILENAME = "inputFiles.lst"; - + private static final String DEPENDENCY_INFO_FILENAME = "dependencies.info"; private static final String[] EMPTY_ARRAY = new String[0]; /** @@ -67,6 +77,15 @@ public class IncrementalBuildHelper */ private String[] filesBeforeAction = new String[0]; + /** + * Used to keep dependencies info. + * @see #dependencyTreeChanged(IncrementalBuildHelperRequest) + * @see #keepDependencyInfo() + */ + private final List classpathElements = new ArrayList(); + private final Map dependencyInfo = new HashMap(); + + public IncrementalBuildHelper( MojoExecution mojoExecution, MavenSession mavenSession ) { this( mojoExecution, getMavenProject( mavenSession ) ); @@ -359,6 +378,143 @@ public void afterRebuildExecution( IncrementalBuildHelperRequest incrementalBuil } } + /** + * Detect whether the dependencies has changed since the last build. + * + * @param incrementalBuildHelperRequest + * @return true if the set of dependencies got changed since the last build. + * @throws MojoExecutionException + */ + public boolean dependencyTreeChanged( IncrementalBuildHelperRequest incrementalBuildHelperRequest ) + throws MojoExecutionException + { + File mojoConfigBase = getMojoStatusDirectory(); + File mojoConfigFile = new File ( mojoConfigBase, DEPENDENCY_INFO_FILENAME ); + + classpathElements.clear(); + dependencyInfo.clear(); + + final List classpathElementsNew = incrementalBuildHelperRequest.getClasspathElements(); + + for ( String classPathElement : classpathElementsNew ) + { + File artifactPath = new File ( classPathElement ); + if ( artifactPath.isFile() ) + { + dependencyInfo.put( artifactPath, artifactPath.lastModified() ); + classpathElements.add( artifactPath ); + } + } + if ( dependencyInfo == null ) + { + return false; + } + if ( !mojoConfigFile.exists() ) + { + //no file, assume rebuild + return true; + } + + Map origDependencyInfo; + List origClasspathElements; + try + { + ObjectInputStream ois = new ObjectInputStream ( new FileInputStream( mojoConfigFile ) ); + origClasspathElements = ( List ) ois.readObject(); + origDependencyInfo = ( Map ) ois.readObject(); + ois.close(); + } + catch ( FileNotFoundException e ) + { + //no file, assume rebuild + return true; + } + catch ( IOException e ) + { + //assume rebuild + return true; + } + catch ( ClassNotFoundException e ) + { + //unexpected exception, assume rebuild + return true; + } + // Check newly added dependencies + + Set newDependencies = new HashSet( dependencyInfo.keySet() ); + newDependencies.removeAll( origDependencyInfo.keySet() ); + if ( !newDependencies.isEmpty() ) + { + // new dependencies are detected + return true; + } + + + // Check removed dependencies + + Set removedDependencies = new HashSet( origDependencyInfo.keySet() ); + removedDependencies.removeAll( dependencyInfo.keySet() ); + if ( !removedDependencies.isEmpty() ) + { + //removed dependencies are detected + return true; + } + + + // Here keys of both dependencyInfo and origDependencyInfo are equal. + // Let's check the values. + for ( Map.Entry di : dependencyInfo.entrySet() ) + { + final Long originalTimestamp = origDependencyInfo.get( di.getKey() ); + final Long timestamp = di.getValue(); + if ( !originalTimestamp.equals( timestamp ) ) + { + //modified AR is detected + return true; + } + } + + if ( !origClasspathElements.equals( classpathElements ) ) + { + //order of JARs in classpath is changed + return true; + } + + // obviously there was no new file detected. + return false; + + } + + public void keepDependencyInfo() throws MojoExecutionException + { + File mojoConfigBase = getMojoStatusDirectory(); + File mojoConfigFile = new File( mojoConfigBase, DEPENDENCY_INFO_FILENAME ); + + if ( dependencyInfo == null ) + { + mojoConfigFile.delete(); + return; + } + + try + { + ObjectOutputStream oos = new ObjectOutputStream( new FileOutputStream( mojoConfigFile ) ); + oos.writeObject( classpathElements ); + oos.writeObject( dependencyInfo ); + oos.close(); + } + catch ( FileNotFoundException ex ) + { + //unexpected exception. it will rebuild + } + catch ( IOException ex ) + { + //can't write to file, it will rebuild + mojoConfigFile.delete(); + } + } + + private String[] toArrayOfPath( Set files ) { diff --git a/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelperRequest.java b/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelperRequest.java index 8423172..ef6bbd2 100644 --- a/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelperRequest.java +++ b/src/main/java/org/apache/maven/shared/incremental/IncrementalBuildHelperRequest.java @@ -22,6 +22,9 @@ import java.io.File; import java.util.HashSet; import java.util.Set; +import java.util.List; +import java.util.ArrayList; +import java.util.Map; /** * @author Olivier Lamy @@ -33,6 +36,10 @@ public class IncrementalBuildHelperRequest private File outputDirectory; + private List classpathElements; + + private Map dependencyInfo; + public IncrementalBuildHelperRequest() { // no op @@ -73,4 +80,25 @@ public IncrementalBuildHelperRequest outputDirectory( File outputDirectory ) this.outputDirectory = outputDirectory; return this; } + + public List getClasspathElements() + { + if ( classpathElements == null ) + { + this.classpathElements = new ArrayList(); + } + return classpathElements; + } + + public void setClasspathElements( List classpathElements ) + { + this.classpathElements = classpathElements; + } + + public IncrementalBuildHelperRequest classpathElements( List classpathElements ) + { + this.classpathElements = classpathElements; + return this; + } + }