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