/* XBN Java: Generically useful, non-GUI Java code. http://sourceforge.net/projects/xbnjava Copyright (C) 1997-2003, Jeff Epstein All rights reserved. Modifications: No Redistribution in binary form, with or without modifications, are permitted provided that the following conditions are met: * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * If modifications are made to source code then this license should indicate that fact in the "Modifications" section above. * Neither the author, nor the contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [NOTE: This license contains NO advertising clause.] */ package xbn.util; import xbn.XBNObject; import xbn.array.VWString; import xbn.named.Named; import xbn.named.VWNamed; import java.io.File; import java.util.Vector; /**

Retrive the paths to all files/dirs contained in a directory. The configuration for DirScan is held by DSConfig

Source code:  DirScan.java.  Example code  XmplDirScan.java.

@since 0.8.2b @version 0.9b @author Jeff Epstein, http://sourceforge.net/projects/xbnjava **/ public class DirScan extends XBNObject { private VWString vws = new VWString(); //State private String sDirBase = null; private DSConfig dsc = null; /**

Create a DirScan.

Equal to DirScan(s_baseDir, (new DSConfig()))

**/ public DirScan(String s_baseDir) { this(s_baseDir, (new DSConfig())); } /**

Create a DirScan.

Notes

@param s_baseDir The base directory to be scanned. May not be null, must point to a directory, and that directory must exist. @param ds_config Configuration for this scan. May not be null. **/ public DirScan(String s_baseDir, DSConfig ds_config) { //Validate parameters...START throwAXIfBadStr(s_baseDir, "s_baseDir", sCNSTR); throwAXIfNull(ds_config, "ds_config", sCNSTR); //This is the public constructor, so this must be the base *directory* File fBase = new File(s_baseDir); if(!fBase.exists() || !fBase.isDirectory()) { throwAX("constructor: s_baseDir (" + s_baseDir + ") must point to a directory, and that directory must exist."); } //Validate parameters...END sDirBase = s_baseDir; dsc = ds_config; //DEBUGGING // dbgnl(s_baseDir + "\n"); //REAL dbgnl(s_baseDir); analyzeDir(fBase, 0, " "); dbg(""); } /**

Get the paths of all the files and directories analyzed for.

It is not efficient to call this repeatedly.

@return A Vector containing zero or more string elements (the base directory is not included), each representing a directory or file contained in the base directory. **/ public final Vector getVector() { return vws.getVector(); } /**

Get the base directory.

@return s_baseDir exactly as provided to the constructor. **/ public final String getBaseDir() { return sDirBase; } /**

Get the DSConfig for direct manipulation.

@return ds_config exactly as provided to the constructor. **/ public final DSConfig getDSConfig() { return dsc; } private void analyzeDir(File f_dir, int i_level, String s_dbgIndent) { if(getDSConfig().getLvlsMaxDepth() != -1 && i_level > getDSConfig().getLvlsMaxDepth()) { //This level is deeper than the maximum. return; } File[] aSubFiles = null; if(getDSConfig().getLvlsMaxDepth() == -1 || (i_level + 1) <= getDSConfig().getLvlsMaxDepth()) { if(getDSConfig().getFileFilter() != null) { //Only retrieve those files conforming to the java.io.FileFilter aSubFiles = f_dir.listFiles(getDSConfig().getFileFilter()); } else { //Retrieve all files. aSubFiles = f_dir.listFiles(); } } if(aSubFiles == null || aSubFiles.length == 0) { //There are no objects in this directory. //(See File#listFiles() for reasons why aSubFiles may // return null.) return; } //The files are listed in alphabetical order, regardless //if they're files or directories... if(getDSConfig().areFilesFirst()) { //...but we want to list files separately and first, // Each should be in alphabetical order. nlzFilesFirst(aSubFiles, i_level, s_dbgIndent); } else { // if(true) { // throwAX("HEY!"); // } //...and that's okay. Desired, even. for(int i = 0; i < aSubFiles.length; i++) { //Add this path to the vector. if(aSubFiles[i].isFile()) { vws.add(aSubFiles[i].getPath()); //DEBUGGING // sopl(i_level + "/" + getDSConfig().getLvlsMaxDepth() + s_dbgIndent + aSubFiles[i].getName()); } else { if(!getDSConfig().doIgnoreDirs()) { //Do add directories to the result. vws.add(aSubFiles[i].getPath()); } //Directory //DEBUGGING // sopl(i_level + "/" + getDSConfig().getLvlsMaxDepth() + s_dbgIndent + "[" + aSubFiles[i].getName() + "]\n"); analyzeDir(aSubFiles[i], (i_level + 1), null); } } } } /**

Get some information about this DirScan.

**/ public final String toString() { return this.getClass().getName() + ": getBaseDir()='" + getBaseDir() + "', getDSConfig()=[" + getDSConfig().toString() + "]"; } private void nlzFilesFirst(File[] af_sub, int i_level, String s_dbgIndent) { //This extra work should only be done when explicitely //asked for, or for when debugging output would make no //sense without it. VWNamed vwnFiles = new VWNamed(true); VWNamed vwnDirs = new VWNamed(true); for(int i = 0; i < af_sub.length; i++) { if(af_sub[i].isFile()) { vwnFiles.add(new FileNamed(af_sub[i])); } else { vwnDirs.add(new FileNamed(af_sub[i])); } } //Now we can list the files first (in alpha order), and //then dirs (in alpha order). while(vwnFiles.size() > 0) { File f = ((FileNamed)vwnFiles.getNamed(0)).getFile(); vwnFiles.getVector().removeElementAt(0); //Add this path to the vector. vws.add(f.getPath()); //1 DEBUGGING // dbg(i_level + "/" + getDSConfig().getLvlsMaxDepth() + s_dbgIndent + f.getName()); //1 REAL dbgnl("."); } while(vwnDirs.size() > 0) { File f = ((FileNamed)vwnDirs.getNamed(0)).getFile(); vwnDirs.getVector().removeElementAt(0); //Add this path to the vector. vws.add(f.getPath()); //Directory if(getDSConfig().getOptrDbg().isOn()) { //2 DEBUGGING // dbgnl(i_level + "/" + getDSConfig().getLvlsMaxDepth() + s_dbgIndent + "[" + f.getName() + "]\n"); //2 REAL dbgnl("\n" + s_dbgIndent + " [" + f.getName() + "]"); } analyzeDir(f, (i_level + 1), (s_dbgIndent + " ")); } } private void dbg(String s_msg) { getDSConfig().getOptrDbg().write(s_msg); } private void dbgnl(String s_msg) { getDSConfig().getOptrDbg().writeNoln(s_msg); } } class FileNamed implements Named { File f = null; public FileNamed(File f_ile) { f = f_ile; } public final String getName() { return f.getPath(); } public final File getFile() { return f; } }