diff --git a/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java b/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java
index 5d03525e..582336fa 100644
--- a/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java
@@ -19,11 +19,19 @@
* under the License.
*/
+import org.apache.maven.shared.utils.io.conductor.EnforceExcludesOverIncludes;
+
import java.io.File;
import java.io.IOException;
+import java.nio.file.FileVisitOption;
+import java.nio.file.FileVisitResult;
import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -31,6 +39,8 @@
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import static java.nio.file.FileVisitOption.FOLLOW_LINKS;
+
/**
* Class for scanning a directory for files/directories which match certain criteria.
*
@@ -108,9 +118,7 @@
* @author Magesh Umasankar
* @author Bruce Atherton
* @author Antoine Levy-Lambert
- * @deprecated use {@code java.nio.file.DirectoryStream} and related classes
*/
-@Deprecated
public class DirectoryScanner
{
/**
@@ -158,7 +166,7 @@ public class DirectoryScanner
/**
* The base directory to be scanned.
*/
- private File basedir;
+ private Path basedir;
/**
* The patterns for the files to be included.
@@ -217,8 +225,6 @@ public class DirectoryScanner
/**
* Whether or not symbolic links should be followed.
- *
- *
*/
private boolean followSymlinks = true;
@@ -228,11 +234,6 @@ public class DirectoryScanner
*/
private ScanConductor scanConductor = null;
- /**
- * The last ScanAction. We need to store this in the instance as the scan() method doesn't return
- */
- private ScanConductor.ScanAction scanAction = null;
-
/**
* Sole constructor.
*/
@@ -258,6 +259,16 @@ public void setBasedir( final String basedir )
* @param basedir The base directory for scanning. Should not be null.
*/
public void setBasedir( @Nonnull final File basedir )
+ {
+ setBasedir( basedir.toPath() );
+ }
+
+ /**
+ * Sets the base directory to be scanned. This is the directory which is scanned recursively.
+ *
+ * @param basedir The base directory for scanning. Should not be null.
+ */
+ public void setBasedir( @Nonnull final Path basedir )
{
this.basedir = basedir;
}
@@ -269,7 +280,7 @@ public void setBasedir( @Nonnull final File basedir )
*/
public File getBasedir()
{
- return basedir;
+ return basedir.toFile();
}
/**
@@ -362,6 +373,15 @@ public void setScanConductor( final ScanConductor scanConductor )
this.scanConductor = scanConductor;
}
+ /**
+ * Set {@link EnforceExcludesOverIncludes} scan conductor for a faster scanning
+ * and generally no functional side effect.
+ */
+ public void setEnforceExcludesOverIncludes()
+ {
+ setScanConductor( new EnforceExcludesOverIncludes() );
+ }
+
/**
* Scans the base directory for files which match at least one include pattern and don't match any exclude patterns.
* If there are selectors then the files must pass muster there, as well.
@@ -376,11 +396,11 @@ public void scan()
{
throw new IllegalStateException( "No basedir set" );
}
- if ( !basedir.exists() )
+ if ( !Files.exists( basedir ) )
{
throw new IllegalStateException( "basedir " + basedir + " does not exist" );
}
- if ( !basedir.isDirectory() )
+ if ( !Files.isDirectory( basedir ) )
{
throw new IllegalStateException( "basedir " + basedir + " is not a directory" );
}
@@ -388,42 +408,164 @@ public void scan()
setupDefaultFilters();
setupMatchPatterns();
- filesIncluded = new ArrayList();
- filesNotIncluded = new ArrayList();
- filesExcluded = new ArrayList();
- dirsIncluded = new ArrayList();
- dirsNotIncluded = new ArrayList();
- dirsExcluded = new ArrayList();
- scanAction = ScanConductor.ScanAction.CONTINUE;
+ if ( scanConductor instanceof ScannerAware ) // after the init
+ {
+ ( ( ScannerAware ) scanConductor ).setDirectoryScanner( this );
+ }
+
+ filesIncluded = new ArrayList<>();
+ filesNotIncluded = new ArrayList<>();
+ filesExcluded = new ArrayList<>();
+ dirsIncluded = new ArrayList<>();
+ dirsNotIncluded = new ArrayList<>();
+ dirsExcluded = new ArrayList<>();
+
+ doScan( basedir, followSymlinks ? EnumSet.of( FOLLOW_LINKS ) : EnumSet.noneOf( FileVisitOption.class ), true );
+ }
- if ( isIncluded( "" ) )
+ private void doScan( final Path root, final Set options, final boolean fast )
+ {
+ try
{
- if ( !isExcluded( "" ) )
+ Files.walkFileTree( root, options, Integer.MAX_VALUE, new SimpleFileVisitor()
{
- if ( scanConductor != null )
+ @Override
+ public FileVisitResult preVisitDirectory( final Path dir, final BasicFileAttributes attrs )
+ throws IOException
+ {
+ final String name = root.relativize( dir ).toString();
+ if ( isIncluded( name ) )
+ {
+ if ( !isExcluded( name ) )
+ {
+ if ( scanConductor != null )
+ {
+ final ScanConductor.ScanAction scanAction = scanConductor.visitDirectory(
+ name, dir.toFile() );
+ if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
+ || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
+ {
+ return FileVisitResult.SKIP_SIBLINGS;
+ }
+ if ( ScanConductor.ScanAction.NO_RECURSE.equals( scanAction ) )
+ {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+ dirsIncluded.add( name );
+ }
+ else
+ {
+ dirsExcluded.add( name );
+ if ( fast && !couldHoldIncluded( name ) )
+ {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ if ( scanConductor != null )
+ {
+ final FileVisitResult result = toVisitResult( dir, name );
+ if ( result != null )
+ {
+ return result;
+ }
+ }
+ // else continue to visit
+ }
+ }
+ else
+ {
+ if ( fast && couldHoldIncluded( name ) )
+ {
+ if ( scanConductor != null )
+ {
+ final FileVisitResult result = toVisitResult( dir, name );
+ if ( result != null )
+ {
+ return result;
+ }
+ }
+ dirsNotIncluded.add( name );
+ }
+ else if ( !fast )
+ {
+ final FileVisitResult result = toVisitResult( dir, name );
+ if ( result != null )
+ {
+ return result;
+ }
+ }
+ }
+ return super.preVisitDirectory( dir, attrs );
+ }
+
+ @Override
+ public FileVisitResult visitFile( final Path file, final BasicFileAttributes attrs ) throws IOException
{
- scanAction = scanConductor.visitDirectory( "", basedir );
+ final String name = root.relativize( file ).toString();
+ if ( !followSymlinks && Files.isSymbolicLink( file ) )
+ {
+ final Path resolved = file.toRealPath( );
+ if ( Files.isDirectory( resolved ) )
+ {
+ dirsIncluded.add( name );
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+ if ( isIncluded( name ) )
+ {
+ if ( !isExcluded( name ) )
+ {
+ final ScanConductor.ScanAction scanAction;
+ if ( scanConductor != null )
+ {
+ scanAction = scanConductor.visitFile( name, file.toFile() );
+ }
+ else
+ {
+ scanAction = null;
+ }
+
+ if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
+ || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
+ {
+ return FileVisitResult.SKIP_SIBLINGS;
+ }
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
- || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction )
- || ScanConductor.ScanAction.NO_RECURSE.equals( scanAction ) )
+ filesIncluded.add( name );
+ }
+ else
+ {
+ filesExcluded.add( name );
+ }
+ }
+ else
{
- return;
+ filesNotIncluded.add( name );
}
+ return super.visitFile( file, attrs );
}
+ } );
+ }
+ catch ( final IOException e )
+ {
+ throw new IllegalStateException( e );
+ }
+ }
- dirsIncluded.add( "" );
- }
- else
- {
- dirsExcluded.add( "" );
- }
+ private FileVisitResult toVisitResult( final Path dir, final String name )
+ {
+ final ScanConductor.ScanAction scanAction = scanConductor.visitDirectory(
+ name, dir.toFile() );
+ if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
+ || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
+ {
+ return FileVisitResult.SKIP_SIBLINGS;
}
- else
+ if ( ScanConductor.ScanAction.NO_RECURSE.equals( scanAction ) )
{
- dirsNotIncluded.add( "" );
+ return FileVisitResult.SKIP_SUBTREE;
}
- scandir( basedir, "", true );
+ return null;
}
/**
@@ -523,15 +665,18 @@ void slowScan()
return;
}
- final String[] excl = dirsExcluded.toArray( new String[dirsExcluded.size()] );
+ final String[] excl = dirsExcluded.toArray( new String[ 0 ] );
+
+ final String[] notIncl = dirsNotIncluded.toArray( new String[ 0 ] );
- final String[] notIncl = dirsNotIncluded.toArray( new String[dirsNotIncluded.size()] );
+ final EnumSet opts = followSymlinks
+ ? EnumSet.of( FOLLOW_LINKS ) : EnumSet.noneOf( FileVisitOption.class );
for ( String anExcl : excl )
{
if ( !couldHoldIncluded( anExcl ) )
{
- scandir( new File( basedir, anExcl ), anExcl + File.separator, false );
+ doScan( basedir.resolve( anExcl ), opts, false );
}
}
@@ -539,214 +684,13 @@ void slowScan()
{
if ( !couldHoldIncluded( aNotIncl ) )
{
- scandir( new File( basedir, aNotIncl ), aNotIncl + File.separator, false );
+ doScan( basedir.resolve( aNotIncl ), opts, false );
}
}
haveSlowResults = true;
}
- /**
- * Scans the given directory for files and directories. Found files and directories are placed in their respective
- * collections, based on the matching of includes, excludes, and the selectors. When a directory is found, it is
- * scanned recursively.
- *
- * @param dir The directory to scan. Must not be null.
- * @param vpath The path relative to the base directory (needed to prevent problems with an absolute path when using
- * dir). Must not be null.
- * @param fast Whether or not this call is part of a fast scan.
- * @see #filesIncluded
- * @see #filesNotIncluded
- * @see #filesExcluded
- * @see #dirsIncluded
- * @see #dirsNotIncluded
- * @see #dirsExcluded
- * @see #slowScan
- */
- void scandir( @Nonnull final File dir, @Nonnull final String vpath, final boolean fast )
- {
- String[] newfiles = dir.list();
-
- if ( newfiles == null )
- {
- /*
- * two reasons are mentioned in the API docs for File.list (1) dir is not a directory. This is impossible as
- * we wouldn't get here in this case. (2) an IO error occurred (why doesn't it throw an exception then???)
- */
-
- /*
- * [jdcasey] (2) is apparently happening to me, as this is killing one of my tests... this is affecting the
- * assembly plugin, fwiw. I will initialize the newfiles array as zero-length for now. NOTE: I can't find
- * the problematic code, as it appears to come from a native method in UnixFileSystem...
- */
- newfiles = new String[0];
-
- // throw new IOException( "IO error scanning directory " + dir.getAbsolutePath() );
- }
-
- if ( !followSymlinks )
- {
- newfiles = doNotFollowSymbolicLinks( dir, vpath, newfiles );
- }
-
- for ( final String newfile : newfiles )
- {
- final String name = vpath + newfile;
- final File file = new File( dir, newfile );
- if ( file.isDirectory() )
- {
- if ( isIncluded( name ) )
- {
- if ( !isExcluded( name ) )
- {
- if ( scanConductor != null )
- {
- scanAction = scanConductor.visitDirectory( name, file );
-
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
- || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
- {
- return;
- }
- }
-
- if ( !ScanConductor.ScanAction.NO_RECURSE.equals( scanAction ) )
- {
- dirsIncluded.add( name );
- if ( fast )
- {
- scandir( file, name + File.separator, fast );
-
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction ) )
- {
- return;
- }
- }
- }
- scanAction = null;
-
- }
- else
- {
- dirsExcluded.add( name );
- if ( fast && couldHoldIncluded( name ) )
- {
- scandir( file, name + File.separator, fast );
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction ) )
- {
- return;
- }
- scanAction = null;
- }
- }
- }
- else
- {
- if ( fast && couldHoldIncluded( name ) )
- {
- if ( scanConductor != null )
- {
- scanAction = scanConductor.visitDirectory( name, file );
-
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
- || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
- {
- return;
- }
- }
- if ( !ScanConductor.ScanAction.NO_RECURSE.equals( scanAction ) )
- {
- dirsNotIncluded.add( name );
-
- scandir( file, name + File.separator, fast );
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction ) )
- {
- return;
- }
- }
- scanAction = null;
- }
- }
- if ( !fast )
- {
- scandir( file, name + File.separator, fast );
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction ) )
- {
- return;
- }
- scanAction = null;
- }
- }
- else if ( file.isFile() )
- {
- if ( isIncluded( name ) )
- {
- if ( !isExcluded( name ) )
- {
- if ( scanConductor != null )
- {
- scanAction = scanConductor.visitFile( name, file );
- }
-
- if ( ScanConductor.ScanAction.ABORT.equals( scanAction )
- || ScanConductor.ScanAction.ABORT_DIRECTORY.equals( scanAction ) )
- {
- return;
- }
-
- filesIncluded.add( name );
- }
- else
- {
- filesExcluded.add( name );
- }
- }
- else
- {
- filesNotIncluded.add( name );
- }
- }
- }
- }
-
- private String[] doNotFollowSymbolicLinks( final File dir, final String vpath, String[] newfiles )
- {
- final List noLinks = new ArrayList();
- for ( final String newfile : newfiles )
- {
- try
- {
- if ( isSymbolicLink( dir, newfile ) )
- {
- final String name = vpath + newfile;
- final File file = new File( dir, newfile );
- if ( file.isDirectory() )
- {
- dirsExcluded.add( name );
- }
- else
- {
- filesExcluded.add( name );
- }
- }
- else
- {
- noLinks.add( newfile );
- }
- }
- catch ( final IOException ioe )
- {
- final String msg =
- "IOException caught while checking " + "for links, couldn't get cannonical path!";
- // will be caught and redirected to Ant's logging system
- System.err.println( msg );
- noLinks.add( newfile );
- }
- }
- newfiles = noLinks.toArray( new String[noLinks.size()] );
- return newfiles;
- }
-
/**
* Tests whether or not a name matches against at least one include pattern.
*
@@ -787,18 +731,16 @@ boolean isExcluded( @Nonnull final String name )
* Returns the names of the files which matched at least one of the include patterns and none of the exclude
* patterns. The names are relative to the base directory.
*
- * @deprecated this method does not work correctly on Windows.
* @return the names of the files which matched at least one of the include patterns and none of the exclude
* patterns. May also contain symbolic links to files.
*/
- @Deprecated
public String[] getIncludedFiles()
{
if ( filesIncluded == null )
{
return new String[0];
}
- return filesIncluded.toArray( new String[filesIncluded.size()] );
+ return filesIncluded.toArray( new String[0] );
}
/**
@@ -891,21 +833,16 @@ public void addDefaultExcludes()
excludes = newExcludes;
}
- /**
- * Checks whether a given file is a symbolic link.
- *
- * It doesn't really test for symbolic links but whether the canonical and absolute paths of the file are identical
- * - this may lead to false positives on some platforms.
- *
- *
- * @param parent the parent directory of the file to test
- * @param name the name of the file to test.
- *
- */
- boolean isSymbolicLink( final File parent, final String name )
- throws IOException
+ public MatchPatterns getExcludesPatterns()
+ {
+ setupDefaultFilters();
+ return excludesPatterns;
+ }
+
+ public MatchPatterns getIncludesPatterns()
{
- return Files.isSymbolicLink( parent.toPath() );
+ setupDefaultFilters();
+ return includesPatterns;
}
private void setupDefaultFilters()
diff --git a/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java b/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java
index 8abff427..25b35a7b 100644
--- a/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java
@@ -33,9 +33,7 @@
* Significantly more efficient than using strings, since re-evaluation and re-tokenizing is avoided.
*
* @author Kristian Rosenvold
- * @deprecated use {@code java.nio.filejava.nio.file.DirectoryStream.Filter} and related classes
*/
-@Deprecated
public class MatchPattern
{
private final String source;
diff --git a/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java b/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java
index 693acb1c..8e59f48f 100644
--- a/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java
@@ -27,9 +27,7 @@
* A list of patterns to be matched
*
* @author Kristian Rosenvold
- * @deprecated use {@code java.nio.filejava.nio.file.DirectoryStream.Filter} and related classes
*/
-@Deprecated
public class MatchPatterns
{
private final MatchPattern[] patterns;
diff --git a/src/main/java/org/apache/maven/shared/utils/io/ScanConductor.java b/src/main/java/org/apache/maven/shared/utils/io/ScanConductor.java
index 08d7a1cd..20c9a10e 100644
--- a/src/main/java/org/apache/maven/shared/utils/io/ScanConductor.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/ScanConductor.java
@@ -34,9 +34,7 @@
*
* @author Mark Struberg
*
- * @deprecated use {@code java.nio.file.Files.walkFileTree()} and related classes
*/
-@Deprecated
public interface ScanConductor
{
/**
diff --git a/src/main/java/org/apache/maven/shared/utils/io/ScannerAware.java b/src/main/java/org/apache/maven/shared/utils/io/ScannerAware.java
new file mode 100644
index 00000000..82542039
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/io/ScannerAware.java
@@ -0,0 +1,29 @@
+package org.apache.maven.shared.utils.io;
+
+/*
+ * 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.
+ */
+
+/**
+ * Enables a {@link ScanConductor} to access the {@link DirectoryScanner} configuration.
+ * It is set once the scanner is initialized.
+ */
+public interface ScannerAware
+{
+ void setDirectoryScanner( DirectoryScanner scanner );
+}
diff --git a/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java b/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java
index b716e7c8..8f920da2 100644
--- a/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java
+++ b/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java
@@ -38,10 +38,7 @@
* ajkuiper@wxs.nl
* @author Magesh Umasankar
* @author Bruce Atherton
- *
- * @deprecated use {@code java.nio.file.Files.walkFileTree()} and related classes
*/
-@Deprecated
public final class SelectorUtils
{
diff --git a/src/main/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludes.java b/src/main/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludes.java
new file mode 100644
index 00000000..98e44a00
--- /dev/null
+++ b/src/main/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludes.java
@@ -0,0 +1,58 @@
+package org.apache.maven.shared.utils.io.conductor;
+
+/*
+ * 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 org.apache.maven.shared.utils.io.DirectoryScanner;
+import org.apache.maven.shared.utils.io.MatchPatterns;
+import org.apache.maven.shared.utils.io.ScanConductor;
+import org.apache.maven.shared.utils.io.ScannerAware;
+
+import java.io.File;
+
+/**
+ * If an exclude is defined on a folder it does not visit of the children
+ * even if some include can match children.
+ */
+public class EnforceExcludesOverIncludes implements ScanConductor, ScannerAware
+{
+ private MatchPatterns excludes;
+
+ @Override
+ public ScanAction visitDirectory( final String name, final File directory )
+ {
+ if ( excludes.matches( name, true ) )
+ {
+ return ScanAction.NO_RECURSE;
+ }
+ return ScanAction.CONTINUE;
+ }
+
+ @Override
+ public ScanAction visitFile( final String name, final File file )
+ {
+ return ScanAction.CONTINUE;
+ }
+
+ @Override
+ public void setDirectoryScanner( final DirectoryScanner scanner )
+ {
+ excludes = scanner.getExcludesPatterns();
+ }
+}
diff --git a/src/test/java/org/apache/maven/shared/utils/io/DirectoryScannerTest.java b/src/test/java/org/apache/maven/shared/utils/io/DirectoryScannerTest.java
index 01110069..48956394 100644
--- a/src/test/java/org/apache/maven/shared/utils/io/DirectoryScannerTest.java
+++ b/src/test/java/org/apache/maven/shared/utils/io/DirectoryScannerTest.java
@@ -162,7 +162,7 @@ public void followSymlinksFalse()
ds.scan();
List included = Arrays.asList( ds.getIncludedFiles() );
assertAlwaysIncluded( included );
- assertEquals( 9, included.size() );
+ assertEquals( included.toString(), 9, included.size() );
List includedDirs = Arrays.asList( ds.getIncludedDirectories() );
assertTrue( includedDirs.contains( "" ) );
assertTrue( includedDirs.contains( "aRegularDir" ) );
@@ -243,14 +243,6 @@ public void testSimpleExcludes()
/* expExclDirs */ NONE );
}
- public void testIsSymbolicLink()
- throws IOException
- {
- File file = new File( "." );
- DirectoryScanner ds = new DirectoryScanner();
- ds.isSymbolicLink( file, "abc" );
- }
-
/**
* Performs a scan and test for the given parameters if not null.
*/
diff --git a/src/test/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludesTest.java b/src/test/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludesTest.java
new file mode 100644
index 00000000..9fe0d379
--- /dev/null
+++ b/src/test/java/org/apache/maven/shared/utils/io/conductor/EnforceExcludesOverIncludesTest.java
@@ -0,0 +1,92 @@
+package org.apache.maven.shared.utils.io.conductor;
+
+/*
+ * 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 org.apache.maven.shared.utils.io.DirectoryScanner;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.junit.Assert.assertEquals;
+
+public class EnforceExcludesOverIncludesTest
+{
+ @Rule
+ public final TemporaryFolder folder = new TemporaryFolder();
+
+ @Test
+ public void dontVisitChildren() throws IOException
+ {
+ createFakeFiles();
+
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setScanConductor(new EnforceExcludesOverIncludes());
+ scanner.setExcludes( "**/target/**" );
+ scanner.setIncludes( "**" ); // files in target will match include but our conductor will bypass them anyway
+ scanner.setBasedir( folder.getRoot() );
+ scanner.scan();
+ assertResultEquals( asList( "bar", "sub/other" ), scanner.getIncludedFiles() );
+ assertResultEquals( singletonList( "target" ), scanner.getExcludedDirectories() );
+ }
+
+ @Test // we don't set the conductor to ensure we have a "control" test to compare to the other
+ public void controlTest() throws IOException
+ {
+ createFakeFiles();
+
+ DirectoryScanner scanner = new DirectoryScanner();
+ scanner.setExcludes( "**/target/**" );
+ scanner.setIncludes( "**" ); // files in target will match include but our conductor will bypass them anyway
+ scanner.setBasedir( folder.getRoot() );
+ scanner.scan();
+ assertResultEquals( asList( "bar", "sub/other" ), scanner.getIncludedFiles() );
+ assertResultEquals( asList( "target", "target/nested" ), scanner.getExcludedDirectories() );
+ }
+
+ private void createFakeFiles() throws IOException
+ {
+ touch(new File(folder.getRoot(), "bar"));
+ touch(new File(folder.getRoot(), "sub/other"));
+ touch(new File(folder.getRoot(), "target/foo"));
+ touch(new File(folder.getRoot(), "target/nested/dummy"));
+ }
+
+ private void assertResultEquals( final List expected, final String[] actual )
+ {
+ final List actualList = new ArrayList<>( asList( actual ) );
+ Collections.sort( actualList );
+ assertEquals( expected, actualList );
+ }
+
+ private void touch( final File file ) throws IOException
+ {
+ file.getParentFile().mkdirs();
+ file.createNewFile();
+ }
+}