View Javadoc

1   /*
2    * Copyright (c) 1998, 2005 Gargoyle Software Inc. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, are permitted provided that the following conditions are met:
6    *
7    * 1. Redistributions of source code must retain the above copyright notice,
8    *    this list of conditions and the following disclaimer.
9    * 2. Redistributions in binary form must reproduce the above copyright notice,
10   *    this list of conditions and the following disclaimer in the documentation
11   *    and/or other materials provided with the distribution.
12   * 3. The end-user documentation included with the redistribution, if any, must
13   *    include the following acknowledgment:
14   *
15   *       "This product includes software developed by Gargoyle Software Inc.
16   *        (http://www.GargoyleSoftware.com/)."
17   *
18   *    Alternately, this acknowledgment may appear in the software itself, if
19   *    and wherever such third-party acknowledgments normally appear.
20   * 4. The name "Gargoyle Software" must not be used to endorse or promote
21   *    products derived from this software without prior written permission.
22   *    For written permission, please contact info@GargoyleSoftware.com.
23   * 5. Products derived from this software may not be called "GSBase", nor may
24   *    "GSBase" appear in their name, without prior written permission of
25   *    Gargoyle Software Inc.
26   *
27   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
28   * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
29   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARGOYLE
30   * SOFTWARE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
32   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
33   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
36   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37   */
38  package com.gargoylesoftware.base.util;
39  
40  import java.io.File;
41  import java.io.FileFilter;
42  import java.util.ArrayList;
43  import java.util.Collection;
44  import java.util.LinkedList;
45  import java.util.List;
46  
47  /***
48   *  A class to walk through the directory structure from a given starting point
49   *  and return either files or directories or both.<p>
50   *
51   * The following sample gets all java files.
52   * <pre>
53   * final FileFilter filter = new FileFilter() {
54   *     public boolean accept( final File file ) {
55   *         return file.getName().endsWith(".java");
56   *     }
57   * };
58   *
59   * final DirectoryWalker directoryWalker = new DirectoryWalker(".");
60   * final Collection files = directoryWalker.getFiles(filter);
61   * </pre>
62   *
63   * @version  $Revision: 1.6 $
64   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
65   */
66  public class DirectoryWalker {
67      private final File startingDirectory_;
68  
69  
70      /***
71       *  Create an instance
72       *
73       * @param  startingDirectory the directory to start in
74       */
75      public DirectoryWalker( final String startingDirectory ) {
76          if( startingDirectory == null ) {
77              throw new NullPointerException();
78          }
79          if( startingDirectory.length() == 0 ) {
80              throw new DetailedIllegalArgumentException( "startingDirectory", startingDirectory, "May not be empty" );
81          }
82          startingDirectory_ = new File( startingDirectory );
83          if( startingDirectory_.exists() == false ) {
84              throw new DetailedIllegalArgumentException( "startingDirectory", startingDirectory, "Doesn't exist" );
85          }
86          if( startingDirectory_.isDirectory() == false ) {
87              throw new DetailedIllegalArgumentException( "startingDirectory", startingDirectory, "Not a directory" );
88          }
89      }
90  
91  
92      /***
93       *  Walk through the directory structure and return a collection containing
94       *  all those files for which the filter returns true
95       *
96       * @param  filter An object to determine whether or not to include this file
97       *      in the returned collection
98       * @return  A collection of File objects
99       */
100     public Collection getFiles( final FileFilter filter ) {
101 
102         return walk( filter, true, false );
103     }
104 
105 
106     /***
107      *  Walk through the directory structure and return a collection containing
108      *  all those directories for which the filter returns true
109      *
110      * @param  filter An object to determine whether or not to include this
111      *      directory in the returned collection
112      * @return  A collection of File objects
113      */
114     public Collection getDirectories( final FileFilter filter ) {
115         return walk( filter, false, true );
116     }
117 
118 
119     /***
120      *  Walk through the directory structure and return a collection containing
121      *  all those files and directories for which the filter returns true
122      *
123      * @param  filter An object to determine whether or not to include this
124      *      file/directory in the returned collection
125      * @return  A collection of File objects
126      */
127     public Collection getFilesAndDirectories( final FileFilter filter ) {
128         return walk( filter, true, true );
129     }
130 
131 
132     private Collection walk(
133             final FileFilter filter,
134             final boolean includeFiles,
135             final boolean includeDirectories ) {
136 
137         int i;
138         final Collection results = new ArrayList();
139         final List pendingDirectories = new LinkedList();
140         pendingDirectories.add( startingDirectory_ );
141 
142         File dir;
143 
144         if( includeDirectories && filter.accept( startingDirectory_ ) ) {
145             results.add( startingDirectory_ );
146         }
147 
148         while( pendingDirectories.isEmpty() == false ) {
149             dir = (File)pendingDirectories.get( 0 );
150             pendingDirectories.remove( 0 );
151 
152             final File[] files = dir.listFiles();
153             for( i = 0; i < files.length; i++ ) {
154                 final File currentFile = files[i];
155                 if( includeFiles && currentFile.isFile() && filter.accept( currentFile ) ) {
156                     results.add( currentFile );
157                 }
158                 else if( currentFile.isDirectory() ) {
159                     if( includeDirectories && filter.accept( currentFile ) ) {
160                         results.add( currentFile );
161                     }
162 
163                     pendingDirectories.add( currentFile );
164                 }
165             }
166         }
167 
168         return results;
169     }
170 }
171