1 package org.apache.maven.shared.utils.io;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Stack;
26
27
28
29
30
31
32 class DirectoryWalker
33 {
34
35
36
37 static class DirStackEntry
38 {
39
40
41
42 private final int count;
43
44
45
46
47 private final File dir;
48
49
50
51
52 private int index;
53
54
55
56
57 private double percentageOffset;
58
59
60
61
62 private double percentageSize;
63
64
65
66
67
68
69
70 public DirStackEntry( File d, int length )
71 {
72 dir = d;
73 count = length;
74 }
75
76
77
78
79
80
81 public double getNextPercentageOffset()
82 {
83 return percentageOffset + ( index * ( percentageSize / count ) );
84 }
85
86
87
88
89
90
91 public double getNextPercentageSize()
92 {
93 return ( percentageSize / count );
94 }
95
96
97
98
99
100
101 public int getPercentage()
102 {
103 double percentageWithinDir = (double) index / (double) count;
104 return (int) Math.floor( percentageOffset + ( percentageWithinDir * percentageSize ) );
105 }
106
107 public String toString()
108 {
109 return "DirStackEntry[" + "dir=" + dir.getAbsolutePath() + ",count=" + count + ",index=" + index
110 + ",percentageOffset=" + percentageOffset + ",percentageSize=" + percentageSize + ",percentage()="
111 + getPercentage() + ",getNextPercentageOffset()=" + getNextPercentageOffset()
112 + ",getNextPercentageSize()=" + getNextPercentageSize() + "]";
113 }
114 }
115
116 private File baseDir;
117
118 private int baseDirOffset;
119
120 private Stack<DirStackEntry> dirStack;
121
122 private final List<String> excludes;
123
124 private final List<String> includes;
125
126 private final List<DirectoryWalkListener> listeners;
127
128 public DirectoryWalker()
129 {
130 this.includes = new ArrayList<String>();
131 this.excludes = new ArrayList<String>();
132 this.listeners = new ArrayList<DirectoryWalkListener>();
133 }
134
135 public void addDirectoryWalkListener( DirectoryWalkListener listener )
136 {
137 this.listeners.add( listener );
138 }
139
140 void addExclude( String exclude )
141 {
142 this.excludes.add( fixPattern( exclude ) );
143 }
144
145 void addInclude( String include )
146 {
147 this.includes.add( fixPattern( include ) );
148 }
149
150
151
152
153 public void addSCMExcludes()
154 {
155 String scmexcludes[] = DirectoryScanner.DEFAULTEXCLUDES;
156 for ( String scmexclude : scmexcludes )
157 {
158 addExclude( scmexclude );
159 }
160 }
161
162 private void fireStep( File file )
163 {
164 DirStackEntry dsEntry = dirStack.peek();
165 int percentage = dsEntry.getPercentage();
166 for ( DirectoryWalkListener listener : this.listeners )
167 {
168 listener.directoryWalkStep( percentage, file );
169 }
170 }
171
172 private void fireWalkFinished()
173 {
174 for ( Object listener1 : this.listeners )
175 {
176 DirectoryWalkListener listener = (DirectoryWalkListener) listener1;
177 listener.directoryWalkFinished();
178 }
179 }
180
181 private void fireWalkStarting()
182 {
183 for ( Object listener1 : this.listeners )
184 {
185 DirectoryWalkListener listener = (DirectoryWalkListener) listener1;
186 listener.directoryWalkStarting( this.baseDir );
187 }
188 }
189
190 private void fireDebugMessage( String message )
191 {
192 for ( Object listener1 : this.listeners )
193 {
194 DirectoryWalkListener listener = (DirectoryWalkListener) listener1;
195 listener.debug( message );
196 }
197 }
198
199 private String fixPattern( String pattern )
200 {
201 String cleanPattern = pattern;
202
203 if ( File.separatorChar != '/' )
204 {
205 cleanPattern = cleanPattern.replace( '/', File.separatorChar );
206 }
207
208 if ( File.separatorChar != '\\' )
209 {
210 cleanPattern = cleanPattern.replace( '\\', File.separatorChar );
211 }
212
213 return cleanPattern;
214 }
215
216 private boolean isExcluded( String name )
217 {
218 return isMatch( this.excludes, name );
219 }
220
221 private boolean isIncluded( String name )
222 {
223 return isMatch( this.includes, name );
224 }
225
226 private boolean isMatch( List<String> patterns, String name )
227 {
228 for ( String pattern : patterns )
229 {
230 boolean caseSensitive = true;
231 if ( SelectorUtils.matchPath( pattern, name, caseSensitive ) )
232 {
233 return true;
234 }
235 }
236
237 return false;
238 }
239
240 private String relativeToBaseDir( File file )
241 {
242 return file.getAbsolutePath().substring( baseDirOffset + 1 );
243 }
244
245
246
247
248 public void scan()
249 {
250 if ( baseDir == null )
251 {
252 throw new IllegalStateException( "Scan Failure. BaseDir not specified." );
253 }
254
255 if ( !baseDir.exists() )
256 {
257 throw new IllegalStateException( "Scan Failure. BaseDir does not exist." );
258 }
259
260 if ( !baseDir.isDirectory() )
261 {
262 throw new IllegalStateException( "Scan Failure. BaseDir is not a directory." );
263 }
264
265 if ( this.includes.isEmpty() )
266 {
267
268 addInclude( "**" );
269 }
270
271 fireWalkStarting();
272 dirStack = new Stack<DirStackEntry>();
273 scanDir( this.baseDir );
274 fireWalkFinished();
275 }
276
277 private void scanDir( File dir )
278 {
279 File files[] = dir.listFiles();
280
281 if ( files == null )
282 {
283 return;
284 }
285
286 DirStackEntry curStackEntry = new DirStackEntry( dir, files.length );
287 if ( dirStack.isEmpty() )
288 {
289 curStackEntry.percentageOffset = 0;
290 curStackEntry.percentageSize = 100;
291 }
292 else
293 {
294 DirStackEntry previousStackEntry = dirStack.peek();
295 curStackEntry.percentageOffset = previousStackEntry.getNextPercentageOffset();
296 curStackEntry.percentageSize = previousStackEntry.getNextPercentageSize();
297 }
298
299 dirStack.push( curStackEntry );
300
301 for ( int idx = 0; idx < files.length; idx++ )
302 {
303 curStackEntry.index = idx;
304 String name = relativeToBaseDir( files[idx] );
305
306 if ( isExcluded( name ) )
307 {
308 fireDebugMessage( name + " is excluded." );
309 continue;
310 }
311
312 if ( files[idx].isDirectory() )
313 {
314 scanDir( files[idx] );
315 }
316 else
317 {
318 if ( isIncluded( name ) )
319 {
320 fireStep( files[idx] );
321 }
322 }
323 }
324
325 dirStack.pop();
326 }
327
328
329
330
331 public void setBaseDir( File baseDir )
332 {
333 this.baseDir = baseDir;
334 this.baseDirOffset = baseDir.getAbsolutePath().length();
335 }
336
337 }