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
Version:$Id$
/** * DirectoryWalker * * @version $Id$ */
public class DirectoryWalker {
DirStackEntry is an Item on the DirectoryWalker.dirStack
/** * DirStackEntry is an Item on the {@link DirectoryWalker#dirStack} */
class DirStackEntry {
Count of files in the directory.
/** * Count of files in the directory. */
public int count;
Current Directory.
/** * Current Directory. */
public File dir;
Index (or offset) within the directory count.
/** * Index (or offset) within the directory count. */
public int index;
Offset for percentage calculations. Based on parent DirStackEntry.
/** * Offset for percentage calculations. Based on parent DirStackEntry. */
public double percentageOffset;
Size of percentage space to work with.
/** * Size of percentage space to work with. */
public double percentageSize;
Create a DirStackEntry.
Params:
  • d – the directory to track
  • length – the length of entries in the directory.
/** * 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.
Returns:the value for the next percentage offset.
/** * 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.
Returns:the value for the next percentage size.
/** * 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.
Returns:the percentage right now.
/** * 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 ) ); } 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<DirectoryWalker.DirStackEntry> dirStack; private List<String> excludes; private List<String> includes; private boolean isCaseSensitive = true; private List<DirectoryWalkListener> listeners; private boolean debugEnabled = false; public DirectoryWalker() { includes = new ArrayList<String>(); excludes = new ArrayList<String>(); listeners = new ArrayList<DirectoryWalkListener>(); } 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.
/** * Add's to the Exclude List the default list of SCM excludes. */
public void addSCMExcludes() { String scmexcludes[] = DirectoryScanner.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; }
Returns:Returns the baseDir.
/** * @return Returns the baseDir. */
public File getBaseDir() { return baseDir; }
Returns:Returns the excludes.
/** * @return Returns the excludes. */
public List<String> getExcludes() { return excludes; }
Returns:Returns the includes.
/** * @return Returns the includes. */
public List<String> 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<String> 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.
Params:
  • listener – the listener to remove.
/** * Removes a DirectoryWalkListener. * * @param listener the listener to remove. */
public void removeDirectoryWalkListener( DirectoryWalkListener listener ) { listeners.remove( listener ); }
Performs a Scan against the provided setBaseDir(File)
/** * 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<String> 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 = (DirectoryWalker.DirStackEntry) 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(); }
Params:
  • baseDir – The baseDir to set.
/** * @param baseDir The baseDir to set. */
public void setBaseDir( File baseDir ) { this.baseDir = baseDir; baseDirOffset = baseDir.getAbsolutePath().length(); }
Params:
  • entries – The excludes to set.
/** * @param entries The excludes to set. */
public void setExcludes( List<String> entries ) { excludes.clear(); if ( entries != null ) { for ( String entry : entries ) { excludes.add( fixPattern( entry ) ); } } }
Params:
  • entries – The includes to set.
/** * @param entries The includes to set. */
public void setIncludes( List<String> entries ) { includes.clear(); if ( entries != null ) { for ( String entry : entries ) { includes.add( fixPattern( entry ) ); } } } }