org.codehaus.plexus.util.DirectoryWalker Maven / Gradle / Ivy
package org.codehaus.plexus.util;
/*
* Copyright The Codehaus 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 java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Stack;
/**
* DirectoryWalker
*
*
*/
public class DirectoryWalker
{
/**
* DirStackEntry is an Item on the {@link DirectoryWalker#dirStack}
*/
class DirStackEntry
{
/**
* Count of files in the directory.
*/
public int count;
/**
* Current Directory.
*/
public File dir;
/**
* Index (or offset) within the directory count.
*/
public int index;
/**
* Offset for percentage calculations. Based on parent DirStackEntry.
*/
public double percentageOffset;
/**
* Size of percentage space to work with.
*/
public double percentageSize;
/**
* Create a DirStackEntry.
*
* @param d the directory to track
* @param length the length of entries in the directory.
*/
public DirStackEntry( File d, int length )
{
dir = d;
count = length;
}
/**
* Calculate the next percentage offset. Used by the next DirStackEntry.
*
* @return the value for the next percentage offset.
*/
public double getNextPercentageOffset()
{
return percentageOffset + ( index * ( percentageSize / count ) );
}
/**
* Calculate the next percentage size. Used by the next DirStackEntry.
*
* @return the value for the next percentage size.
*/
public double getNextPercentageSize()
{
return ( percentageSize / count );
}
/**
* The percentage of the DirStackEntry right now. Based on count, index, percentageOffset, and percentageSize.
*
* @return the percentage right now.
*/
public int getPercentage()
{
double percentageWithinDir = (double) index / (double) count;
return (int) Math.floor( percentageOffset + ( percentageWithinDir * percentageSize ) );
}
@Override
public String toString()
{
return "DirStackEntry[" + "dir=" + dir.getAbsolutePath() + ",count=" + count + ",index=" + index
+ ",percentageOffset=" + percentageOffset + ",percentageSize=" + percentageSize + ",percentage()="
+ getPercentage() + ",getNextPercentageOffset()=" + getNextPercentageOffset()
+ ",getNextPercentageSize()=" + getNextPercentageSize() + "]";
}
}
private File baseDir;
private int baseDirOffset;
private Stack dirStack;
private List excludes;
private List includes;
private boolean isCaseSensitive = true;
private List listeners;
private boolean debugEnabled = false;
public DirectoryWalker()
{
includes = new ArrayList();
excludes = new ArrayList();
listeners = new ArrayList();
}
public void addDirectoryWalkListener( DirectoryWalkListener listener )
{
listeners.add( listener );
}
public void addExclude( String exclude )
{
excludes.add( fixPattern( exclude ) );
}
public void addInclude( String include )
{
includes.add( fixPattern( include ) );
}
/**
* Add's to the Exclude List the default list of SCM excludes.
*/
public void addSCMExcludes()
{
String scmexcludes[] = AbstractScanner.DEFAULTEXCLUDES;
for ( String scmexclude : scmexcludes )
{
addExclude( scmexclude );
}
}
private void fireStep( File file )
{
DirStackEntry dsEntry = dirStack.peek();
int percentage = dsEntry.getPercentage();
for ( Object listener1 : listeners )
{
DirectoryWalkListener listener = (DirectoryWalkListener) listener1;
listener.directoryWalkStep( percentage, file );
}
}
private void fireWalkFinished()
{
for ( DirectoryWalkListener listener1 : listeners )
{
listener1.directoryWalkFinished();
}
}
private void fireWalkStarting()
{
for ( DirectoryWalkListener listener1 : listeners )
{
listener1.directoryWalkStarting( baseDir );
}
}
private void fireDebugMessage( String message )
{
for ( DirectoryWalkListener listener1 : listeners )
{
listener1.debug( message );
}
}
private String fixPattern( String pattern )
{
String cleanPattern = pattern;
if ( File.separatorChar != '/' )
{
cleanPattern = cleanPattern.replace( '/', File.separatorChar );
}
if ( File.separatorChar != '\\' )
{
cleanPattern = cleanPattern.replace( '\\', File.separatorChar );
}
return cleanPattern;
}
public void setDebugMode( boolean debugEnabled )
{
this.debugEnabled = debugEnabled;
}
/**
* @return Returns the baseDir.
*/
public File getBaseDir()
{
return baseDir;
}
/**
* @return Returns the excludes.
*/
public List getExcludes()
{
return excludes;
}
/**
* @return Returns the includes.
*/
public List getIncludes()
{
return includes;
}
private boolean isExcluded( String name )
{
return isMatch( excludes, name );
}
private boolean isIncluded( String name )
{
return isMatch( includes, name );
}
private boolean isMatch( List patterns, String name )
{
for ( String pattern1 : patterns )
{
if ( SelectorUtils.matchPath( pattern1, name, isCaseSensitive ) )
{
return true;
}
}
return false;
}
private String relativeToBaseDir( File file )
{
return file.getAbsolutePath().substring( baseDirOffset + 1 );
}
/**
* Removes a DirectoryWalkListener.
*
* @param listener the listener to remove.
*/
public void removeDirectoryWalkListener( DirectoryWalkListener listener )
{
listeners.remove( listener );
}
/**
* Performs a Scan against the provided {@link #setBaseDir(File)}
*/
public void scan()
{
if ( baseDir == null )
{
throw new IllegalStateException( "Scan Failure. BaseDir not specified." );
}
if ( !baseDir.exists() )
{
throw new IllegalStateException( "Scan Failure. BaseDir does not exist." );
}
if ( !baseDir.isDirectory() )
{
throw new IllegalStateException( "Scan Failure. BaseDir is not a directory." );
}
if ( includes.isEmpty() )
{
// default to include all.
addInclude( "**" );
}
if ( debugEnabled )
{
Iterator it;
StringBuilder dbg = new StringBuilder();
dbg.append( "DirectoryWalker Scan" );
dbg.append( "\n Base Dir: " ).append( baseDir.getAbsolutePath() );
dbg.append( "\n Includes: " );
it = includes.iterator();
while ( it.hasNext() )
{
String include = it.next();
dbg.append( "\n - \"" ).append( include ).append( "\"" );
}
dbg.append( "\n Excludes: " );
it = excludes.iterator();
while ( it.hasNext() )
{
String exclude = it.next();
dbg.append( "\n - \"" ).append( exclude ).append( "\"" );
}
fireDebugMessage( dbg.toString() );
}
fireWalkStarting();
dirStack = new Stack();
scanDir( baseDir );
fireWalkFinished();
}
private void scanDir( File dir )
{
File[] files = dir.listFiles();
if ( files == null )
{
return;
}
DirectoryWalker.DirStackEntry curStackEntry = new DirectoryWalker.DirStackEntry( dir, files.length );
if ( dirStack.isEmpty() )
{
curStackEntry.percentageOffset = 0;
curStackEntry.percentageSize = 100;
}
else
{
DirectoryWalker.DirStackEntry previousStackEntry = dirStack.peek();
curStackEntry.percentageOffset = previousStackEntry.getNextPercentageOffset();
curStackEntry.percentageSize = previousStackEntry.getNextPercentageSize();
}
dirStack.push( curStackEntry );
for ( int idx = 0; idx < files.length; idx++ )
{
curStackEntry.index = idx;
String name = relativeToBaseDir( files[idx] );
if ( isExcluded( name ) )
{
fireDebugMessage( name + " is excluded." );
continue;
}
if ( files[idx].isDirectory() )
{
scanDir( files[idx] );
}
else
{
if ( isIncluded( name ) )
{
fireStep( files[idx] );
}
}
}
dirStack.pop();
}
/**
* @param baseDir The baseDir to set.
*/
public void setBaseDir( File baseDir )
{
this.baseDir = baseDir;
baseDirOffset = baseDir.getAbsolutePath().length();
}
/**
* @param entries The excludes to set.
*/
public void setExcludes( List entries )
{
excludes.clear();
if ( entries != null )
{
for ( String entry : entries )
{
excludes.add( fixPattern( entry ) );
}
}
}
/**
* @param entries The includes to set.
*/
public void setIncludes( List entries )
{
includes.clear();
if ( entries != null )
{
for ( String entry : entries )
{
includes.add( fixPattern( entry ) );
}
}
}
}