View Javadoc

1   /*
2    * Copyright (c) 2003, Henri Yandell
3    * All rights reserved.
4    * 
5    * Redistribution and use in source and binary forms, with or 
6    * without modification, are permitted provided that the 
7    * following conditions are met:
8    * 
9    * + Redistributions of source code must retain the above copyright notice, 
10   *   this list of conditions and the following disclaimer.
11   * 
12   * + Redistributions in binary form must reproduce the above copyright notice, 
13   *   this list of conditions and the following disclaimer in the documentation 
14   *   and/or other materials provided with the distribution.
15   * 
16   * + Neither the name of Genjava-Core nor the names of its contributors 
17   *   may be used to endorse or promote products derived from this software 
18   *   without specific prior written permission.
19   * 
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
23   * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
30   * POSSIBILITY OF SUCH DAMAGE.
31   */
32  package com.generationjava.io.find;
33  
34  import java.io.File;
35  import java.util.List;
36  import java.util.LinkedList;
37  import java.util.Iterator;
38  import java.util.Map;
39  
40  /***
41   * Finds Files in a file system.
42   *
43   * Informs FindListeners whenever a Find is made, and returns the 
44   * finds to the user.
45   */
46  public class FileFinder implements Finder {
47  
48      // helper methods to handle options in String->whatever
49      private static int toInt(Object obj) {
50          if(obj == null) {
51              return 0;
52          } else
53          if(obj instanceof Number) {
54              return ((Number)obj).intValue();
55          } else {
56              String str = obj.toString();
57              try {
58                  return Integer.parseInt(str.toString());
59              } catch(NumberFormatException nfe) {
60                  throw new IllegalArgumentException("String argument "+str+" must be parseable as an integer.  ");
61              }
62          }
63      }
64      private static boolean toBoolean(Object obj) {
65          if(obj == null) {
66              return false;
67          } else
68          if(obj instanceof Boolean) {
69              return ((Boolean)obj).booleanValue();
70          } else
71          if(obj instanceof Number) {
72              return ((Number)obj).intValue() != 0;
73          } else {
74              String str = obj.toString();
75              return new Boolean(str).booleanValue();
76          }
77      }
78  
79      private List findListeners;
80  
81      /***
82       * Find all files in the specified directory.
83       */
84      public File[] find(File directory) {
85          return find(directory, new java.util.HashMap());
86      }
87  
88      // add maxdepth and mindepth somehow
89      public File[] find(File directory, Map options) {
90          notifyDirectoryStarted(directory);
91  
92          boolean depthFirst = toBoolean(options.get(Finder.DEPTH));
93  
94          // to implement
95          int maxDepth = toInt(options.get(Finder.MAXDEPTH));
96          int minDepth = toInt(options.get(Finder.MINDEPTH));
97          boolean ignoreHiddenDirs = toBoolean(options.get(Finder.IGNORE_HIDDEN_DIRS));
98  
99          FindingFilter filter = new FindingFilter(options);
100         List list = find(directory, filter, depthFirst);
101         if(filter.accept(directory)) {
102             if(depthFirst) {
103                 list.add( directory );
104             } else {
105                 list.add( 0, directory );
106             }
107         }
108         File[] files = (File[]) list.toArray(new File[0]);
109         notifyDirectoryFinished(directory, files);
110         return files;
111     }
112 
113     private List find(File directory, FindingFilter filter, boolean depthFirst) {
114 
115         // we can't use listFiles(filter) here, directories don't work correctly
116         File[] list = directory.listFiles();
117 
118         if (list == null) {
119             return null;
120         }
121 
122         List retlist = new LinkedList();
123         int sz = list.length;
124 
125         for (int i = 0; i < sz; i++) {
126             File tmp = list[i];
127             if(!depthFirst && filter.accept(tmp)) {
128                 retlist.add(tmp);
129                 notifyFileFound(directory,tmp);
130             }
131             if (tmp.isDirectory()) {
132                 notifyDirectoryStarted(tmp);
133                 List sublist = find(tmp, filter, depthFirst);
134                 int subsz = sublist.size();
135                 for (int j = 0; j < subsz; j++) {
136                     retlist.add(sublist.get(j));
137                 }
138                 notifyDirectoryFinished(tmp, (File[]) sublist.toArray(new File[0]));
139             }
140             if(depthFirst && filter.accept(tmp)) {
141                 retlist.add(tmp);
142                 notifyFileFound(directory,tmp);
143             }
144         }
145 
146         return retlist;
147     }
148     
149     /***
150      * Add a FindListener.
151      */
152     public void addFindListener(FindListener fl) {
153         if(findListeners == null) {
154             findListeners = new LinkedList();
155         }
156         findListeners.add(fl);
157     }
158 
159     /***
160      * Remove a FindListener.
161      */
162     public void removeFindListener(FindListener fl) {
163         if(findListeners != null) {
164             findListeners.remove(fl);
165         }
166     }
167 
168     /***
169      * Notify all FindListeners that a directory is being started.
170      */
171     public void notifyDirectoryStarted(File directory) {
172         if(!directory.isDirectory()) {
173             return;
174         }
175         if(findListeners != null) {
176             FindEvent fe = new FindEvent(this,"directoryStarted",directory);
177             Iterator itr = findListeners.iterator();
178             while(itr.hasNext()) {
179                 FindListener findListener = (FindListener)itr.next();
180                 findListener.directoryStarted( fe );
181             }
182         }
183     }
184 
185     /***
186      * Notify all FindListeners that a directory has been finished.
187      * Supplying the filenames that have been found.
188      */
189     public void notifyDirectoryFinished(File directory, File[] files) {
190         if(!directory.isDirectory()) {
191             return;
192         }
193         if(findListeners != null) {
194             FindEvent fe = new FindEvent(this,"directoryFinished",directory,files);
195             Iterator itr = findListeners.iterator();
196             while(itr.hasNext()) {
197                 FindListener findListener = (FindListener)itr.next();
198                 findListener.directoryFinished( fe );
199             }
200         }
201     }
202 
203     /***
204      * Notify FindListeners that a file has been found.
205      */
206     public void notifyFileFound(File directory, File file) {
207         if(file.isDirectory()) {
208             return;
209         }
210         if(findListeners != null) {
211             FindEvent fe = new FindEvent(this,"fileFound",directory,file);
212             Iterator itr = findListeners.iterator();
213             while(itr.hasNext()) {
214                 FindListener findListener = (FindListener)itr.next();
215                 findListener.fileFound( fe );
216             }
217         }
218     }
219     
220 }