From 67830a13fb47619e1cec3dbee9561d3a0d8d0d8b Mon Sep 17 00:00:00 2001 From: John Dennis Casey Date: Tue, 29 Mar 2005 05:28:08 +0000 Subject: [PATCH] o Adding source-scanner support, for selectively including source files to be compiled, or processed in some way. This is going to be a core-plugin facility, so it's in maven-plugin. o Added support to maven-compiler-plugin for a source scanner to determine the files that actually need recompiling...currently based on lastModification date. o All of this stuff needs a good integration test, but it shouldn't mess any existing functionality up for now. Unit tests for the scanner stuff are included. git-svn-id: https://svn.apache.org/repos/asf/maven/components/trunk@163698 13f79535-47bb-0310-9956-ffa450edef68 --- .../scan/AbstractSourceInclusionScanner.java | 42 ++ .../util/scan/InclusionScanException.java | 36 ++ .../util/scan/SourceInclusionScanner.java | 32 ++ .../plugin/util/scan/StaleSourceScanner.java | 133 ++++++ .../util/scan/mapping/SourceMapping.java | 32 ++ .../util/scan/mapping/SuffixMapping.java | 70 +++ .../util/scan/StaleSourceScannerTest.java | 440 ++++++++++++++++++ .../org/apache/maven/plugin/CompilerMojo.java | 136 ++++-- 8 files changed, 879 insertions(+), 42 deletions(-) create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/AbstractSourceInclusionScanner.java create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/InclusionScanException.java create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/SourceInclusionScanner.java create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/StaleSourceScanner.java create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SourceMapping.java create mode 100644 maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SuffixMapping.java create mode 100644 maven-plugin/src/test/java/org/apache/maven/plugin/util/scan/StaleSourceScannerTest.java diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/AbstractSourceInclusionScanner.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/AbstractSourceInclusionScanner.java new file mode 100644 index 0000000000..7fa7738497 --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/AbstractSourceInclusionScanner.java @@ -0,0 +1,42 @@ +package org.apache.maven.plugin.util.scan; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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 org.apache.maven.plugin.util.scan.mapping.SourceMapping; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * @author jdcasey + */ +public abstract class AbstractSourceInclusionScanner + implements SourceInclusionScanner +{ + + private final List sourceMappings = new ArrayList(); + + public final void addSourceMapping( SourceMapping sourceMapping ) + { + sourceMappings.add( sourceMapping ); + } + + protected final List getSourceMappings() + { + return Collections.unmodifiableList( sourceMappings ); + } + +} \ No newline at end of file diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/InclusionScanException.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/InclusionScanException.java new file mode 100644 index 0000000000..d69bf44dc2 --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/InclusionScanException.java @@ -0,0 +1,36 @@ +package org.apache.maven.plugin.util.scan; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +/** + * @author jdcasey + */ +public class InclusionScanException + extends Exception +{ + + public InclusionScanException( String message ) + { + super( message ); + } + + public InclusionScanException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/SourceInclusionScanner.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/SourceInclusionScanner.java new file mode 100644 index 0000000000..f1bea56942 --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/SourceInclusionScanner.java @@ -0,0 +1,32 @@ +package org.apache.maven.plugin.util.scan; + +import org.apache.maven.plugin.util.scan.mapping.SourceMapping; + +import java.io.File; +import java.util.Set; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +/** + * @author jdcasey + */ +public interface SourceInclusionScanner +{ + + void addSourceMapping( SourceMapping sourceMapping ); + + Set getIncludedSources( File sourceDir, File targetDir ) throws InclusionScanException; + +} \ No newline at end of file diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/StaleSourceScanner.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/StaleSourceScanner.java new file mode 100644 index 0000000000..309f5d5d9b --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/StaleSourceScanner.java @@ -0,0 +1,133 @@ +package org.apache.maven.plugin.util.scan; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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 org.apache.maven.plugin.util.scan.mapping.SourceMapping; +import org.codehaus.plexus.util.DirectoryScanner; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +/** + * @author jdcasey + */ +public class StaleSourceScanner + extends AbstractSourceInclusionScanner +{ + + private final long lastUpdatedWithinMsecs; + + private final Set sourceIncludes; + + private final Set sourceExcludes; + + public StaleSourceScanner( long lastUpdatedWithinMsecs ) + { + this( lastUpdatedWithinMsecs, Collections.singleton("**/*"), Collections.EMPTY_SET ); + } + + public StaleSourceScanner() + { + this( 0, Collections.singleton("**/*"), Collections.EMPTY_SET ); + } + + public StaleSourceScanner( long lastUpdatedWithinMsecs, Set sourceIncludes, Set sourceExcludes ) + { + this.lastUpdatedWithinMsecs = lastUpdatedWithinMsecs; + + this.sourceIncludes = sourceIncludes; + this.sourceExcludes = sourceExcludes; + } + + public Set getIncludedSources( File sourceDir, File targetDir ) + throws InclusionScanException + { + Set matchingSources = new HashSet(); + + List srcMappings = getSourceMappings(); + + String[] potentialIncludes = scanForSources( sourceDir ); + for ( int i = 0; i < potentialIncludes.length; i++ ) + { + String path = potentialIncludes[i]; + + File sourceFile = new File( sourceDir, path ); + + staleSourceFileTesting: for ( Iterator patternIt = srcMappings.iterator(); patternIt.hasNext(); ) + { + SourceMapping mapping = (SourceMapping) patternIt.next(); + + Set targetFiles = mapping.getTargetFiles( targetDir, path ); + + // never include files that don't have corresponding target mappings. + // the targets don't have to exist on the filesystem, but the + // mappers must tell us to look for them. + for ( Iterator targetIt = targetFiles.iterator(); targetIt.hasNext(); ) + { + File targetFile = (File) targetIt.next(); + + if ( !targetFile.exists() + || ( targetFile.lastModified() + lastUpdatedWithinMsecs < sourceFile.lastModified() ) ) + { + matchingSources.add( sourceFile ); + break staleSourceFileTesting; + } + } + } + } + + return matchingSources; + } + + private String[] scanForSources( File sourceDir ) + { + DirectoryScanner ds = new DirectoryScanner(); + ds.setFollowSymlinks(true); + ds.setBasedir( sourceDir ); + + String[] includes = null; + if ( sourceIncludes.isEmpty() ) + { + includes = new String[0]; + } + else + { + includes = (String[]) sourceIncludes.toArray( new String[sourceIncludes.size()] ); + } + + ds.setIncludes( includes ); + + String[] excludes = null; + if ( sourceExcludes.isEmpty() ) + { + excludes = new String[0]; + } + else + { + excludes = (String[]) sourceExcludes.toArray( new String[sourceExcludes.size()] ); + } + + ds.setExcludes( excludes ); + + ds.scan(); + + return ds.getIncludedFiles(); + } + +} \ No newline at end of file diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SourceMapping.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SourceMapping.java new file mode 100644 index 0000000000..675e3690dc --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SourceMapping.java @@ -0,0 +1,32 @@ +package org.apache.maven.plugin.util.scan.mapping; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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 org.apache.maven.plugin.util.scan.InclusionScanException; + +import java.io.File; +import java.util.Set; + +/** + * @author jdcasey + */ +public interface SourceMapping +{ + + Set getTargetFiles(File targetDir, String source) throws InclusionScanException; + +} diff --git a/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SuffixMapping.java b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SuffixMapping.java new file mode 100644 index 0000000000..9609285ea7 --- /dev/null +++ b/maven-plugin/src/main/java/org/apache/maven/plugin/util/scan/mapping/SuffixMapping.java @@ -0,0 +1,70 @@ +package org.apache.maven.plugin.util.scan.mapping; + +import org.apache.maven.plugin.util.scan.InclusionScanException; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +/** + * @author jdcasey + */ +public final class SuffixMapping + implements SourceMapping +{ + + private final String sourceSuffix; + + private final Set targetSuffixes; + + public SuffixMapping( String sourceSuffix, String targetSuffix ) + { + this.sourceSuffix = sourceSuffix; + + this.targetSuffixes = Collections.singleton( targetSuffix ); + } + + public SuffixMapping( String sourceSuffix, Set targetSuffixes ) + { + this.sourceSuffix = sourceSuffix; + + this.targetSuffixes = Collections.unmodifiableSet( targetSuffixes ); + } + + public Set getTargetFiles( File targetDir, String source ) + throws InclusionScanException + { + Set targetFiles = new HashSet(); + + if(source.endsWith(sourceSuffix)) + { + String base = source.substring( 0, source.length() - sourceSuffix.length() ); + + for ( Iterator it = targetSuffixes.iterator(); it.hasNext(); ) + { + String suffix = (String) it.next(); + + targetFiles.add( new File( targetDir, base + suffix ) ); + } + } + + return targetFiles; + } + +} \ No newline at end of file diff --git a/maven-plugin/src/test/java/org/apache/maven/plugin/util/scan/StaleSourceScannerTest.java b/maven-plugin/src/test/java/org/apache/maven/plugin/util/scan/StaleSourceScannerTest.java new file mode 100644 index 0000000000..8976c9416a --- /dev/null +++ b/maven-plugin/src/test/java/org/apache/maven/plugin/util/scan/StaleSourceScannerTest.java @@ -0,0 +1,440 @@ +package org.apache.maven.plugin.util.scan; + +import org.apache.maven.plugin.util.scan.StaleSourceScanner; +import org.apache.maven.plugin.util.scan.mapping.SuffixMapping; +import org.codehaus.plexus.util.IOUtil; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.net.URL; +import java.util.Collections; +import java.util.Set; + +import junit.framework.TestCase; + +/* + * Copyright 2001-2005 The Apache Software Foundation. + * + * Licensed 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. + */ + +/** + * @author jdcasey + */ +public class StaleSourceScannerTest + extends TestCase +{ + private static final String TESTFILE_DEST_MARKER_FILE = StaleSourceScanner.class.getName().replace('.', '/') + "-testMarker.txt"; + + // test 1. + public void testWithDefaultConstructorShouldFindOneStaleSource() throws Exception + { + File base = new File(getTestBaseDir(), "test1"); + + long now = System.currentTimeMillis(); + + File targetFile = new File(base, "file.xml"); + + writeFile(targetFile); + + targetFile.setLastModified(now - 60000); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + sourceFile.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 1, result.size()); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile)); + } + + // test 2. + public void testWithDefaultConstructorShouldNotFindStaleSources() throws Exception + { + File base = new File(getTestBaseDir(), "test2"); + + long now = System.currentTimeMillis(); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + sourceFile.setLastModified(now - 60000); + + File targetFile = new File(base, "file.xml"); + + writeFile(targetFile); + + targetFile.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 0, result.size()); + + assertFalse("expected stale source file not found in result", result.contains(sourceFile)); + } + + // test 3. + public void testWithDefaultConstructorShouldFindStaleSourcesBecauseOfMissingTargetFile() throws Exception + { + File base = new File(getTestBaseDir(), "test3"); + + long now = System.currentTimeMillis(); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 1, result.size()); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile)); + } + + // test 4. + public void testWithDefaultConstructorShouldFindStaleSourcesOneBecauseOfMissingTargetAndOneBecauseOfStaleTarget() throws Exception + { + File base = new File(getTestBaseDir(), "test4"); + + long now = System.currentTimeMillis(); + + File targetFile = new File(base, "file2.xml"); + + writeFile(targetFile); + + targetFile.setLastModified(now - 60000); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + File sourceFile2 = new File(base, "file2.java"); + + writeFile(sourceFile2); + + sourceFile2.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 2, result.size()); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile)); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile2)); + } + + // test 5. + public void testWithDefaultConstructorShouldFindOneStaleSourcesWithStaleTargetAndOmitUpToDateSource() throws Exception + { + File base = new File(getTestBaseDir(), "test5"); + + long now = System.currentTimeMillis(); + + // target/source (1) should result in source being included. + + // write the target file first, and set the lastmod to some time in the + // past to ensure this. + File targetFile = new File(base, "file.xml"); + + writeFile(targetFile); + + targetFile.setLastModified(now - 60000); + + // now write the source file, and set the lastmod to now. + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + sourceFile.setLastModified(now); + + // target/source (2) should result in source being omitted. + + // write the source file first, and set the lastmod to some time in the + // past to ensure this. + File sourceFile2 = new File(base, "file2.java"); + + writeFile(sourceFile2); + + sourceFile2.setLastModified(now - 60000); + + // now write the target file, with lastmod of now. + File targetFile2 = new File(base, "file2.xml"); + + writeFile(targetFile2); + + targetFile2.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 1, result.size()); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile)); + } + + // test 6. + public void testConstructedWithMsecsShouldReturnOneSourceFileOfTwoDueToLastMod() throws Exception + { + File base = new File(getTestBaseDir(), "test6"); + + long now = System.currentTimeMillis(); + + File targetFile = new File(base, "file.xml"); + + writeFile(targetFile); + + // should be within the threshold of lastMod for stale sources. + targetFile.setLastModified(now - 8000); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + // modified 'now' for comparison with the above target file. + sourceFile.setLastModified(now); + + File targetFile2 = new File(base, "file2.xml"); + + writeFile(targetFile2); + + targetFile2.setLastModified(now - 12000); + + File sourceFile2 = new File(base, "file2.java"); + + writeFile(sourceFile2); + + // modified 'now' for comparison to above target file. + sourceFile2.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(10000); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 1, result.size()); + + assertTrue("expected stale source file not found in result", result.contains(sourceFile2)); + + assertFalse("expected stale source file not found in result", result.contains(sourceFile)); + } + + // test 7. + public void testConstructedWithMsecsIncludesAndExcludesShouldReturnOneSourceFileOfThreeDueToIncludePattern() throws Exception + { + File base = new File(getTestBaseDir(), "test7"); + + long now = System.currentTimeMillis(); + + File targetFile = new File(base, "file.xml"); + + writeFile(targetFile); + + // should be within the threshold of lastMod for stale sources. + targetFile.setLastModified(now - 12000); + + File sourceFile = new File(base, "file.java"); + + writeFile(sourceFile); + + // modified 'now' for comparison with the above target file. + sourceFile.setLastModified(now); + + File targetFile2 = new File(base, "file2.xml"); + + writeFile(targetFile2); + + targetFile2.setLastModified(now - 12000); + + File sourceFile2 = new File(base, "file2.java"); + + writeFile(sourceFile2); + + // modified 'now' for comparison to above target file. + sourceFile2.setLastModified(now); + + File targetFile3 = new File(base, "file3.xml"); + + writeFile(targetFile3); + + targetFile3.setLastModified(now - 12000); + + File sourceFile3 = new File(base, "file3.java"); + + writeFile(sourceFile3); + + // modified 'now' for comparison to above target file. + sourceFile3.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(0, Collections.singleton("*3.java"), Collections.EMPTY_SET); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 1, result.size()); + + assertFalse("expected stale source file not found in result", result.contains(sourceFile)); + + assertFalse("unexpected stale source file found in result", result.contains(sourceFile2)); + + assertTrue("unexpected stale source file found in result", result.contains(sourceFile3)); + } + + // test 8. + public void testConstructedWithMsecsIncludesAndExcludesShouldReturnTwoSourceFilesOfThreeDueToExcludePattern() throws Exception + { + File base = new File(getTestBaseDir(), "test8"); + + long now = System.currentTimeMillis(); + + File targetFile = new File(base, "fileX.xml"); + + writeFile(targetFile); + + // should be within the threshold of lastMod for stale sources. + targetFile.setLastModified(now - 12000); + + File sourceFile = new File(base, "fileX.java"); + + writeFile(sourceFile); + + // modified 'now' for comparison with the above target file. + sourceFile.setLastModified(now); + + File targetFile2 = new File(base, "file2.xml"); + + writeFile(targetFile2); + + targetFile2.setLastModified(now - 12000); + + File sourceFile2 = new File(base, "file2.java"); + + writeFile(sourceFile2); + + // modified 'now' for comparison to above target file. + sourceFile2.setLastModified(now); + + File targetFile3 = new File(base, "file3.xml"); + + writeFile(targetFile3); + + targetFile3.setLastModified(now - 12000); + + File sourceFile3 = new File(base, "file3.java"); + + writeFile(sourceFile3); + + // modified 'now' for comparison to above target file. + sourceFile3.setLastModified(now); + + SuffixMapping mapping = new SuffixMapping(".java", ".xml"); + + StaleSourceScanner scanner = new StaleSourceScanner(0, Collections.singleton("**/*"), Collections.singleton("*X.*")); + + scanner.addSourceMapping(mapping); + + Set result = scanner.getIncludedSources(base, base); + + assertEquals("wrong number of stale sources returned.", 2, result.size()); + + assertFalse("unexpected stale source file found in result", result.contains(sourceFile)); + + assertTrue("expected stale source not file found in result", result.contains(sourceFile2)); + + assertTrue("expected stale source not file found in result", result.contains(sourceFile3)); + } + + private File getTestBaseDir() + { + ClassLoader cl = Thread.currentThread().getContextClassLoader(); + URL markerResource = cl.getResource(TESTFILE_DEST_MARKER_FILE); + + File basedir = null; + if(markerResource != null) + { + File marker = new File(markerResource.getPath()); + basedir = marker.getParentFile().getAbsoluteFile(); + } + else + { + // punt. + System.out.println("Cannot find marker file: \'" + TESTFILE_DEST_MARKER_FILE + "\' in classpath. Using '.' for basedir."); + basedir = new File(".").getAbsoluteFile(); + } + + return basedir; + } + + private void writeFile(File file) throws IOException + { + FileWriter fWriter = null; + try + { + File parent = file.getParentFile(); + if(!parent.exists()) + { + parent.mkdirs(); + } + + file.deleteOnExit(); + + fWriter = new FileWriter(file); + fWriter.write("This is just a test file."); + } + finally + { + IOUtil.close(fWriter); + } + } + +} diff --git a/maven-plugins/maven-compiler-plugin/src/main/java/org/apache/maven/plugin/CompilerMojo.java b/maven-plugins/maven-compiler-plugin/src/main/java/org/apache/maven/plugin/CompilerMojo.java index 6ee5a5cbd1..394168539b 100644 --- a/maven-plugins/maven-compiler-plugin/src/main/java/org/apache/maven/plugin/CompilerMojo.java +++ b/maven-plugins/maven-compiler-plugin/src/main/java/org/apache/maven/plugin/CompilerMojo.java @@ -2,20 +2,22 @@ /* * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed 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. + * + * Licensed 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 org.apache.maven.plugin.util.scan.InclusionScanException; +import org.apache.maven.plugin.util.scan.SourceInclusionScanner; +import org.apache.maven.plugin.util.scan.StaleSourceScanner; +import org.apache.maven.plugin.util.scan.mapping.SuffixMapping; import org.codehaus.plexus.compiler.Compiler; import org.codehaus.plexus.compiler.CompilerConfiguration; import org.codehaus.plexus.compiler.CompilerError; @@ -23,42 +25,35 @@ import java.io.File; import java.util.ArrayList; +import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Set; /** - * @author Jason van Zyl + * @author Jason van Zyl * @version $Id$ * @goal compile * @requiresDependencyResolution * @description Compiles application sources - * @parameter name="compileSourceRoots" - * type="java.util.List" - * required="true" - * validator="" - * expression="#project.compileSourceRoots" - * description="" - * @parameter name="outputDirectory" - * type="String" - * required="true" - * validator="" - * expression="#project.build.outputDirectory" - * description="" - * @parameter name="classpathElements" - * type="List" - * required="true" - * validator="" - * expression="#project.compileClasspathElements" - * description="" - * @parameter name="debug" - * type="boolean" - * required="false" - * validator="" - * expression="#maven.compiler.debug" - * description="Whether to include debugging information in the compiled class files; the default value is false" + * @parameter name="compileSourceRoots" type="java.util.List" required="true" validator="" + * expression="#project.compileSourceRoots" description="" + * @parameter name="outputDirectory" type="String" required="true" validator="" + * expression="#project.build.outputDirectory" description="" + * @parameter name="classpathElements" type="List" required="true" validator="" + * expression="#project.compileClasspathElements" description="" + * @parameter name="debug" type="boolean" required="false" validator="" + * expression="#maven.compiler.debug" description="Whether to include debugging + * information in the compiled class files; the default value is false" * @todo change debug parameter type to Boolean - * @parameter name="source" type="String" required="false" expression="#source" validator="" description="The -source argument for the Java compiler" - * @parameter name="target" type="String" required="false" expression="#target" validator="" description="The -target argument for the Java compiler" + * @parameter name="source" type="String" required="false" expression="#source" validator="" + * description="The -source argument for the Java compiler" + * @parameter name="target" type="String" required="false" expression="#target" validator="" + * description="The -target argument for the Java compiler" + * @parameter name="staleMillis" type="long" required="false" expression="#lastModGranularityMs" + * validator="" description="The granularity in milliseconds of the last modification + * date for testing whether a source needs recompilation" + * @todo change staleMillis parameter type to Long */ public class CompilerMojo @@ -79,6 +74,9 @@ public class CompilerMojo private String target; + // TODO: Use long when supported + private String staleMillis = "0"; + public void execute() throws PluginExecutionException { @@ -99,11 +97,18 @@ public void execute() compilerConfiguration.setClasspathEntries( classpathElements ); compilerConfiguration.setSourceLocations( compileSourceRoots ); + Set staleSources = computeStaleSources(); + + if ( staleSources != null && !staleSources.isEmpty() ) + { + compilerConfiguration.setSourceFiles( staleSources ); + } + if ( source != null ) { compilerConfiguration.addCompilerOption( "-source", source ); } - + if ( target != null ) { compilerConfiguration.addCompilerOption( "-target", target ); @@ -143,8 +148,55 @@ public void execute() } } + private Set computeStaleSources() + throws PluginExecutionException + { + long staleTime = 0; + + if ( staleMillis != null && staleMillis.length() > 0 ) + { + try + { + staleTime = Long.parseLong( staleMillis ); + } + catch ( NumberFormatException e ) + { + throw new PluginExecutionException( "Invalid staleMillis plugin parameter value: \'" + staleMillis + + "\'", e ); + } + + } + SuffixMapping mapping = new SuffixMapping( ".java", ".class" ); + + SourceInclusionScanner scanner = new StaleSourceScanner( staleTime ); + + File outDir = new File( outputDirectory ); + + Set staleSources = new HashSet(); + + for ( Iterator it = compileSourceRoots.iterator(); it.hasNext(); ) + { + String sourceRoot = (String) it.next(); + + File rootFile = new File( sourceRoot ); + + try + { + staleSources.addAll( scanner.getIncludedSources( rootFile, outDir ) ); + } + catch ( InclusionScanException e ) + { + throw new PluginExecutionException( "Error scanning source root: \'" + sourceRoot + + "\' for stale files to recompile.", e ); + } + } + + return staleSources; + } + /** - * @todo also in ant plugin. This should be resolved at some point so that it does not need to be calculated continuously - or should the plugins accept empty source roots as is? + * @todo also in ant plugin. This should be resolved at some point so that it does not need to + * be calculated continuously - or should the plugins accept empty source roots as is? */ private static List removeEmptyCompileSourceRoots( List compileSourceRootsList ) { @@ -163,4 +215,4 @@ private static List removeEmptyCompileSourceRoots( List compileSourceRootsList ) } return newCompileSourceRootsList; } -} +} \ No newline at end of file