Subversion Repository Public Repository

litesoft

Diff Revisions 949 vs 950 for /trunk/Java/ScarPlus/src/com/esotericsoftware/filesystem/Paths.java

Diff revisions: vs.
  @@ -1,510 +1,510 @@
1 - package com.esotericsoftware.filesystem;
2 -
3 - import com.esotericsoftware.utils.*;
4 - import com.esotericsoftware.wildcard.*;
5 -
6 - import java.io.*;
7 - import java.util.*;
8 - import java.util.zip.*;
9 -
10 - /**
11 - * Collects filesystem paths using wildcards, preserving the directory structure. Copies, deletes, and zips paths.
12 - */
13 - public class Paths
14 - {
15 - static private List<String> sDefaultGlobExcludes = new ArrayList<String>();
16 -
17 - /**
18 - * Only the Files will be stored!
19 - */
20 - private final RootedPathsCollection mPaths = new RootedPathsCollection();
21 -
22 - /**
23 - * Creates an empty Paths object.
24 - */
25 - public Paths()
26 - {
27 - }
28 -
29 - /**
30 - * Creates a Paths object and calls {@link #glob(String, String[])} with the specified arguments.
31 - */
32 - public Paths( String dir, String... patterns )
33 - {
34 - glob( dir, patterns );
35 - }
36 -
37 - public Long getGreatestLastModified()
38 - {
39 - return isEmpty() ? null : mPaths.getGreatestLastModified();
40 - }
41 -
42 - public boolean isEmpty()
43 - {
44 - return mPaths.isEmpty();
45 - }
46 -
47 - public int count()
48 - {
49 - return mPaths.count();
50 - }
51 -
52 - public List<FilePath> getPaths()
53 - {
54 - return mPaths.collectPaths( new ArrayList<FilePath>() );
55 - }
56 -
57 - public RootedPaths[] getRootedPaths()
58 - {
59 - return mPaths.getRootedPaths();
60 - }
61 -
62 - public void add( FilePath pFilePath )
63 - {
64 - mPaths.add( pFilePath );
65 - }
66 -
67 - @SuppressWarnings({"UnusedDeclaration"})
68 - public void add( RootedPaths pRootedPaths )
69 - {
70 - mPaths.add( pRootedPaths );
71 - }
72 -
73 - public void add( RootedPathsCollection pRootedPathsCollection )
74 - {
75 - mPaths.mergeIn( pRootedPathsCollection );
76 - }
77 -
78 - /**
79 - * Adds all paths from the specified Paths object to this Paths object.
80 - */
81 - public void add( Paths paths )
82 - {
83 - add( paths.mPaths );
84 - }
85 -
86 - /**
87 - * Calls {@link #glob(String, String...)}.
88 - */
89 - @SuppressWarnings({"UnusedDeclaration"})
90 - public void glob( String dir, List<String> patterns )
91 - {
92 - glob( dir, (patterns == null) ? Util.EMPTY_STRING_ARRAY : patterns.toArray( new String[patterns.size()] ) );
93 - }
94 -
95 - /**
96 - * Collects all files and directories in the specified directory matching the wildcard patterns.
97 - *
98 - * @param dir The directory containing the paths to collect. If it does not exist, no paths are collected. If null, "." is
99 - * assumed.
100 - * @param patterns The wildcard patterns of the paths to collect or exclude. Patterns may optionally contain wildcards
101 - * represented by asterisks and question marks. If empty or omitted then the dir parameter is split on the "|"
102 - * character, the first element is used as the directory and remaining are used as the patterns. If null, ** is
103 - * assumed (collects all paths).<br>
104 - * <br>
105 - * A single question mark (?) matches any single character. Eg, something? collects any path that is named
106 - * "something" plus any character.<br>
107 - * <br>
108 - * A single asterisk (*) matches any characters up to the next slash (/). Eg, *\*\something* collects any path that
109 - * has two directories of any name, then a file or directory that starts with the name "something".<br>
110 - * <br>
111 - * A double asterisk (**) matches any characters. Eg, **\something\** collects any path that contains a directory
112 - * named "something".<br>
113 - * <br>
114 - * A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
115 - * patterns would select the paths.
116 - */
117 - public void glob( String dir, String... patterns )
118 - {
119 - new PathPatterns( dir, patterns ).addTo( mPaths );
120 - }
121 -
122 - // ^^^^^^^^^^^^^^^^^^^^^^^ Should These be supported as they can introduce potentially conflicting FileSubPaths ^^^^^^^^^^^^^^^^^^^^^^^
123 -
124 - /**
125 - * Copies the files and directories to the specified directory.
126 - *
127 - * @return A paths object containing the paths of the new files.
128 - */
129 - @SuppressWarnings({"ResultOfMethodCallIgnored"})
130 - public Paths copyTo( String destDir )
131 - {
132 - File zDest = new File( destDir );
133 - zDest.mkdirs();
134 -
135 - Paths newPaths = new Paths();
136 - for ( FilePath path : getPaths() )
137 - {
138 - String zSubPath = path.getFileSubPath();
139 - FileUtil.copyFile( path.file(), new File( destDir, zSubPath ) );
140 - newPaths.mPaths.add( new FilePath( zDest, zSubPath ) );
141 - }
142 - return newPaths;
143 - }
144 -
145 - /**
146 - * Compresses the files and directories specified by the paths into a new zip file at the specified location. If there are no
147 - * paths or all the paths are directories, no zip file will be created.
148 - *
149 - * @return Files Zipped, 0 means Zip File not even created!
150 - */
151 - public int zip( String destFile )
152 - {
153 - return zip( destFile, ZipFactory.FOR_ZIPS );
154 - }
155 -
156 - public int zip( String destFile, ZipFactory pFactory )
157 - {
158 - List<FilePath> zPaths = getPaths();
159 - if ( !zPaths.isEmpty() )
160 - {
161 - ZipOutputStream out = pFactory.createZOS( destFile, zPaths );
162 - try
163 - {
164 - for ( FilePath path : zPaths )
165 - {
166 - try
167 - {
168 - out.putNextEntry( pFactory.createZE( path.getFileSubPath().replace( '\\', '/' ) ) );
169 - }
170 - catch ( IOException e )
171 - {
172 - throw new WrappedIOException( e );
173 - }
174 - FileInputStream in = FileUtil.createFileInputStream( path.file() );
175 - try
176 - {
177 - FileUtil.append( in, out );
178 - out.closeEntry();
179 - }
180 - catch ( IOException e )
181 - {
182 - throw new WrappedIOException( e );
183 - }
184 - finally
185 - {
186 - FileUtil.close( in );
187 - }
188 - }
189 - }
190 - finally
191 - {
192 - FileUtil.close( out );
193 - }
194 - }
195 - return zPaths.size();
196 - }
197 -
198 - /**
199 - * Returns the absolute paths delimited by the specified character.
200 - */
201 - public String toString( String delimiter )
202 - {
203 - StringBuilder sb = new StringBuilder( 256 );
204 - for ( String path : getFullPaths() )
205 - {
206 - if ( sb.length() > 0 )
207 - {
208 - sb.append( delimiter );
209 - }
210 - sb.append( path );
211 - }
212 - return sb.toString();
213 - }
214 -
215 - /**
216 - * Returns the absolute paths delimited by commas.
217 - */
218 - public String toString()
219 - {
220 - return toString( ", " );
221 - }
222 -
223 - /**
224 - * Returns a Paths object containing the paths that are files, as if each file were selected from its parent directory.
225 - */
226 - public Paths flatten()
227 - {
228 - Paths newPaths = new Paths();
229 - for ( File zFile : getFiles() )
230 - {
231 - newPaths.add( new FilePath( zFile.getParentFile(), zFile.getName() ) );
232 - }
233 - return newPaths;
234 - }
235 -
236 - /**
237 - * Returns the paths as File objects.
238 - */
239 - public List<File> getFiles()
240 - {
241 - List<FilePath> zPaths = getPaths();
242 - List<File> files = new ArrayList<File>( zPaths.size() );
243 - for ( FilePath path : zPaths )
244 - {
245 - files.add( path.file() );
246 - }
247 - return files;
248 - }
249 -
250 - /**
251 - * Returns the portion of the path after the root directory where the path was collected.
252 - */
253 - public List<String> getRelativePaths( String pCanonicalJarPath )
254 - {
255 - File zCanonicalJarDir = new File(pCanonicalJarPath).getParentFile();
256 - List<FilePath> zPaths = getPaths();
257 - List<String> rv = new ArrayList<String>( zPaths.size() );
258 - for ( FilePath path : zPaths )
259 - {
260 - rv.add(path.relativeFromDir(zCanonicalJarDir));
261 - }
262 - return rv;
263 - }
264 -
265 - /**
266 - * Returns the full paths.
267 - */
268 - public List<String> getFullPaths()
269 - {
270 - List<File> zFiles = getFiles();
271 - List<String> rv = new ArrayList<String>( zFiles.size() );
272 - for ( File file : zFiles )
273 - {
274 - rv.add( file.getPath() );
275 - }
276 - return rv;
277 - }
278 -
279 - /**
280 - * Returns the paths' filenames.
281 - */
282 - public List<String> getNames()
283 - {
284 - List<File> zFiles = getFiles();
285 - List<String> rv = new ArrayList<String>( zFiles.size() );
286 - for ( File file : zFiles )
287 - {
288 - rv.add( file.getName() );
289 - }
290 - return rv;
291 - }
292 -
293 - /**
294 - * Clears the exclude patterns that will be used in addition to the excludes specified for all glob searches.
295 - */
296 - @SuppressWarnings({"UnusedDeclaration"})
297 - static public void clearDefaultGlobExcludes()
298 - {
299 - sDefaultGlobExcludes.clear();
300 - }
301 -
302 - /**
303 - * Adds exclude patterns that will be used in addition to the excludes specified for all glob searches.
304 - */
305 - static public void addDefaultGlobExcludes( String... pDefaultGlobExcludes )
306 - {
307 - if ( pDefaultGlobExcludes != null )
308 - {
309 - sDefaultGlobExcludes.addAll( Arrays.asList( pDefaultGlobExcludes ) );
310 - }
311 - }
312 -
313 - private static class PathPatterns
314 - {
315 - private final File mPath;
316 - private final boolean mIsFile;
317 - private final List<Pattern> mIncludes = new ArrayList<Pattern>();
318 - private final List<Pattern> mExcludes = new ArrayList<Pattern>();
319 -
320 - public PathPatterns( String pPath, String[] pPatterns )
321 - {
322 - pPath = Util.deNull( pPath, "." ).trim();
323 - if ( pPatterns == null || pPatterns.length == 0 )
324 - {
325 - String[] split = pPath.split( "\\|" ); // split on a '|'
326 - pPath = split[0].trim();
327 - pPatterns = new String[split.length - 1];
328 - for ( int i = 1, n = split.length; i < n; i++ )
329 - {
330 - pPatterns[i - 1] = split[i].trim();
331 - }
332 - }
333 - File zPath = new File( pPath );
334 - if ( zPath.isFile() )
335 - {
336 - if ( pPatterns.length != 0 )
337 - {
338 - throw new IllegalArgumentException( "Files (e.g. " + zPath + ") may NOT have patterns: " + Arrays.asList( pPatterns ) );
339 - }
340 - mIsFile = true;
341 - mPath = FileUtil.getCanonicalFile( zPath );
342 - return;
343 - }
344 - if ( !zPath.isDirectory() )
345 - {
346 - throw new IllegalArgumentException( "Path Reference not a File or Directory: " + zPath );
347 - }
348 - mIsFile = false;
349 - mPath = FileUtil.getCanonicalFile( zPath );
350 - List<String> zIncludes = new ArrayList<String>();
351 - List<String> zExcludes = new ArrayList<String>();
352 - for ( String zPattern : pPatterns )
353 - {
354 - if ( null != (zPattern = Util.noEmpty( zPattern )) )
355 - {
356 - List<String> zList = zIncludes;
357 - if ( zPattern.charAt( 0 ) == '!' )
358 - {
359 - if ( null == (zPattern = Util.noEmpty( zPattern.substring( 1 ) )) )
360 - {
361 - continue;
362 - }
363 - zList = zExcludes;
364 - }
365 - zList.add( zPattern );
366 - }
367 - }
368 - if ( zIncludes.isEmpty() )
369 - {
370 - zIncludes.add( "**" );
371 - }
372 - if ( sDefaultGlobExcludes != null )
373 - {
374 - zExcludes.addAll( sDefaultGlobExcludes );
375 - }
376 - addPatterns( mIncludes, zIncludes );
377 - addPatterns( mExcludes, zExcludes );
378 - }
379 -
380 - private void addPatterns( List<Pattern> pTargetPatterns, List<String> pSourcePatterns )
381 - {
382 - for ( String zPattern : pSourcePatterns )
383 - {
384 - pTargetPatterns.add( new Pattern( zPattern ) );
385 - }
386 - }
387 -
388 - public void addTo( RootedPathsCollection pPaths )
389 - {
390 - if ( mIsFile )
391 - {
392 - pPaths.add( new FilePath( mPath.getParentFile(), mPath.getName() ) );
393 - return;
394 - }
395 - // Must be a Directory! (See Above)
396 - RootedPaths zPaths = new RootedPaths( mPath );
397 - String[] zFileNames = mPath.list();
398 - for ( String zFileName : zFileNames )
399 - {
400 - File zFile = new File( mPath, zFileName );
401 - if ( zFile.isDirectory() )
402 - {
403 - if ( !excludedDir( zFileName ) && acceptableDir( zFileName ) )
404 - {
405 - addTo( zPaths, zFileName + "/", zFile );
406 - }
407 - }
408 - else
409 - {
410 - if ( !excludedFile( zFileName ) && acceptableFile( zFileName ) )
411 - {
412 - zPaths.addCanonicalRelativePath( zFileName );
413 - }
414 - }
415 - }
416 - pPaths.add( zPaths );
417 - }
418 -
419 - private void addTo( RootedPaths pPaths, String pAdditionalDirPath, File pDirectory )
420 - {
421 - String[] zFileNames = pDirectory.list();
422 - for ( String zFileName : zFileNames )
423 - {
424 - String zPath = pAdditionalDirPath + "/" + zFileName;
425 - File zFile = new File( pDirectory, zFileName );
426 - if ( zFile.isDirectory() )
427 - {
428 - if ( !excludedDir( zPath ) && acceptableDir( zPath ) )
429 - {
430 - addTo( pPaths, zPath + "/", zFile );
431 - }
432 - }
433 - else
434 - {
435 - if ( !excludedFile( zPath ) && acceptableFile( zPath ) )
436 - {
437 -
438 - String zFullCanonicalPath = FileUtil.getCanonicalPath( zFile );
439 - String zRelativeCanonicalPath = zFullCanonicalPath.substring( mPath.getPath().length() + 1 );
440 - pPaths.addCanonicalRelativePath( zRelativeCanonicalPath );
441 - }
442 - }
443 - }
444 - }
445 -
446 - private boolean acceptableDir( String pPath )
447 - {
448 - for ( Pattern zInclude : mIncludes )
449 - {
450 - if ( zInclude.acceptableDirPath( pPath ) )
451 - {
452 - return true;
453 - }
454 - }
455 - return false;
456 - }
457 -
458 - private boolean acceptableFile( String pPath )
459 - {
460 - for ( Pattern zInclude : mIncludes )
461 - {
462 - if ( zInclude.matchesFilePath( pPath ) )
463 - {
464 - return true;
465 - }
466 - }
467 - return false;
468 - }
469 -
470 - private boolean excludedDir( String pPath )
471 - {
472 - for ( Pattern zExclude : mExcludes )
473 - {
474 - if ( zExclude.matchesDirPathAndChildren( pPath ) )
475 - {
476 - return true;
477 - }
478 - }
479 - return false;
480 - }
481 -
482 - private boolean excludedFile( String pPath )
483 - {
484 - for ( Pattern zExclude : mExcludes )
485 - {
486 - if ( zExclude.matchesFilePath( pPath ) )
487 - {
488 - return true;
489 - }
490 - }
491 - return false;
492 - }
493 - }
494 -
495 - public static void main( String[] args )
496 - throws Exception
497 - {
498 - if ( args.length == 0 )
499 - {
500 - System.out.println( "Usage: dir [pattern] [, pattern ...]" );
501 - System.exit( 0 );
502 - }
503 - List<String> patterns = Arrays.asList( args );
504 - patterns = patterns.subList( 1, patterns.size() );
505 - for ( String path : new Paths( args[0], patterns.toArray( new String[patterns.size()] ) ).getFullPaths() )
506 - {
507 - System.out.println( path );
508 - }
509 - }
510 - }
1 + package com.esotericsoftware.filesystem;
2 +
3 + import com.esotericsoftware.utils.*;
4 + import com.esotericsoftware.wildcard.*;
5 +
6 + import java.io.*;
7 + import java.util.*;
8 + import java.util.zip.*;
9 +
10 + /**
11 + * Collects filesystem paths using wildcards, preserving the directory structure. Copies, deletes, and zips paths.
12 + */
13 + public class Paths
14 + {
15 + static private List<String> sDefaultGlobExcludes = new ArrayList<String>();
16 +
17 + /**
18 + * Only the Files will be stored!
19 + */
20 + private final RootedPathsCollection mPaths = new RootedPathsCollection();
21 +
22 + /**
23 + * Creates an empty Paths object.
24 + */
25 + public Paths()
26 + {
27 + }
28 +
29 + /**
30 + * Creates a Paths object and calls {@link #glob(String, String[])} with the specified arguments.
31 + */
32 + public Paths( String dir, String... patterns )
33 + {
34 + glob( dir, patterns );
35 + }
36 +
37 + public Long getGreatestLastModified()
38 + {
39 + return isEmpty() ? null : mPaths.getGreatestLastModified();
40 + }
41 +
42 + public boolean isEmpty()
43 + {
44 + return mPaths.isEmpty();
45 + }
46 +
47 + public int count()
48 + {
49 + return mPaths.count();
50 + }
51 +
52 + public List<FilePath> getPaths()
53 + {
54 + return mPaths.collectPaths( new ArrayList<FilePath>() );
55 + }
56 +
57 + public RootedPaths[] getRootedPaths()
58 + {
59 + return mPaths.getRootedPaths();
60 + }
61 +
62 + public void add( FilePath pFilePath )
63 + {
64 + mPaths.add( pFilePath );
65 + }
66 +
67 + @SuppressWarnings({"UnusedDeclaration"})
68 + public void add( RootedPaths pRootedPaths )
69 + {
70 + mPaths.add( pRootedPaths );
71 + }
72 +
73 + public void add( RootedPathsCollection pRootedPathsCollection )
74 + {
75 + mPaths.mergeIn( pRootedPathsCollection );
76 + }
77 +
78 + /**
79 + * Adds all paths from the specified Paths object to this Paths object.
80 + */
81 + public void add( Paths paths )
82 + {
83 + add( paths.mPaths );
84 + }
85 +
86 + /**
87 + * Calls {@link #glob(String, String...)}.
88 + */
89 + @SuppressWarnings({"UnusedDeclaration"})
90 + public void glob( String dir, List<String> patterns )
91 + {
92 + glob( dir, (patterns == null) ? Util.EMPTY_STRING_ARRAY : patterns.toArray( new String[patterns.size()] ) );
93 + }
94 +
95 + /**
96 + * Collects all files and directories in the specified directory matching the wildcard patterns.
97 + *
98 + * @param dir The directory containing the paths to collect. If it does not exist, no paths are collected. If null, "." is
99 + * assumed.
100 + * @param patterns The wildcard patterns of the paths to collect or exclude. Patterns may optionally contain wildcards
101 + * represented by asterisks and question marks. If empty or omitted then the dir parameter is split on the "|"
102 + * character, the first element is used as the directory and remaining are used as the patterns. If null, ** is
103 + * assumed (collects all paths).<br>
104 + * <br>
105 + * A single question mark (?) matches any single character. Eg, something? collects any path that is named
106 + * "something" plus any character.<br>
107 + * <br>
108 + * A single asterisk (*) matches any characters up to the next slash (/). Eg, *\*\something* collects any path that
109 + * has two directories of any name, then a file or directory that starts with the name "something".<br>
110 + * <br>
111 + * A double asterisk (**) matches any characters. Eg, **\something\** collects any path that contains a directory
112 + * named "something".<br>
113 + * <br>
114 + * A pattern starting with an exclamation point (!) causes paths matched by the pattern to be excluded, even if other
115 + * patterns would select the paths.
116 + */
117 + public void glob( String dir, String... patterns )
118 + {
119 + new PathPatterns( dir, patterns ).addTo( mPaths );
120 + }
121 +
122 + // ^^^^^^^^^^^^^^^^^^^^^^^ Should These be supported as they can introduce potentially conflicting FileSubPaths ^^^^^^^^^^^^^^^^^^^^^^^
123 +
124 + /**
125 + * Copies the files and directories to the specified directory.
126 + *
127 + * @return A paths object containing the paths of the new files.
128 + */
129 + @SuppressWarnings({"ResultOfMethodCallIgnored"})
130 + public Paths copyTo( String destDir )
131 + {
132 + File zDest = new File( destDir );
133 + zDest.mkdirs();
134 +
135 + Paths newPaths = new Paths();
136 + for ( FilePath path : getPaths() )
137 + {
138 + String zSubPath = path.getFileSubPath();
139 + FileUtil.copyFile( path.file(), new File( destDir, zSubPath ) );
140 + newPaths.mPaths.add( new FilePath( zDest, zSubPath ) );
141 + }
142 + return newPaths;
143 + }
144 +
145 + /**
146 + * Compresses the files and directories specified by the paths into a new zip file at the specified location. If there are no
147 + * paths or all the paths are directories, no zip file will be created.
148 + *
149 + * @return Files Zipped, 0 means Zip File not even created!
150 + */
151 + public int zip( String destFile )
152 + {
153 + return zip( destFile, ZipFactory.FOR_ZIPS );
154 + }
155 +
156 + public int zip( String destFile, ZipFactory pFactory )
157 + {
158 + List<FilePath> zPaths = getPaths();
159 + if ( !zPaths.isEmpty() )
160 + {
161 + ZipOutputStream out = pFactory.createZOS( destFile, zPaths );
162 + try
163 + {
164 + for ( FilePath path : zPaths )
165 + {
166 + try
167 + {
168 + out.putNextEntry( pFactory.createZE( path.getFileSubPath().replace( '\\', '/' ) ) );
169 + }
170 + catch ( IOException e )
171 + {
172 + throw new WrappedIOException( e );
173 + }
174 + FileInputStream in = FileUtil.createFileInputStream( path.file() );
175 + try
176 + {
177 + FileUtil.append( in, out );
178 + out.closeEntry();
179 + }
180 + catch ( IOException e )
181 + {
182 + throw new WrappedIOException( e );
183 + }
184 + finally
185 + {
186 + FileUtil.close( in );
187 + }
188 + }
189 + }
190 + finally
191 + {
192 + FileUtil.close( out );
193 + }
194 + }
195 + return zPaths.size();
196 + }
197 +
198 + /**
199 + * Returns the absolute paths delimited by the specified character.
200 + */
201 + public String toString( String delimiter )
202 + {
203 + StringBuilder sb = new StringBuilder( 256 );
204 + for ( String path : getFullPaths() )
205 + {
206 + if ( sb.length() > 0 )
207 + {
208 + sb.append( delimiter );
209 + }
210 + sb.append( path );
211 + }
212 + return sb.toString();
213 + }
214 +
215 + /**
216 + * Returns the absolute paths delimited by commas.
217 + */
218 + public String toString()
219 + {
220 + return toString( ", " );
221 + }
222 +
223 + /**
224 + * Returns a Paths object containing the paths that are files, as if each file were selected from its parent directory.
225 + */
226 + public Paths flatten()
227 + {
228 + Paths newPaths = new Paths();
229 + for ( File zFile : getFiles() )
230 + {
231 + newPaths.add( new FilePath( zFile.getParentFile(), zFile.getName() ) );
232 + }
233 + return newPaths;
234 + }
235 +
236 + /**
237 + * Returns the paths as File objects.
238 + */
239 + public List<File> getFiles()
240 + {
241 + List<FilePath> zPaths = getPaths();
242 + List<File> files = new ArrayList<File>( zPaths.size() );
243 + for ( FilePath path : zPaths )
244 + {
245 + files.add( path.file() );
246 + }
247 + return files;
248 + }
249 +
250 + /**
251 + * Returns the portion of the path after the root directory where the path was collected.
252 + */
253 + public List<String> getRelativePaths( String pCanonicalJarPath )
254 + {
255 + File zCanonicalJarDir = new File(pCanonicalJarPath).getParentFile();
256 + List<FilePath> zPaths = getPaths();
257 + List<String> rv = new ArrayList<String>( zPaths.size() );
258 + for ( FilePath path : zPaths )
259 + {
260 + rv.add(path.relativeFromDir(zCanonicalJarDir));
261 + }
262 + return rv;
263 + }
264 +
265 + /**
266 + * Returns the full paths.
267 + */
268 + public List<String> getFullPaths()
269 + {
270 + List<File> zFiles = getFiles();
271 + List<String> rv = new ArrayList<String>( zFiles.size() );
272 + for ( File file : zFiles )
273 + {
274 + rv.add( file.getPath() );
275 + }
276 + return rv;
277 + }
278 +
279 + /**
280 + * Returns the paths' filenames.
281 + */
282 + public List<String> getNames()
283 + {
284 + List<File> zFiles = getFiles();
285 + List<String> rv = new ArrayList<String>( zFiles.size() );
286 + for ( File file : zFiles )
287 + {
288 + rv.add( file.getName() );
289 + }
290 + return rv;
291 + }
292 +
293 + /**
294 + * Clears the exclude patterns that will be used in addition to the excludes specified for all glob searches.
295 + */
296 + @SuppressWarnings({"UnusedDeclaration"})
297 + static public void clearDefaultGlobExcludes()
298 + {
299 + sDefaultGlobExcludes.clear();
300 + }
301 +
302 + /**
303 + * Adds exclude patterns that will be used in addition to the excludes specified for all glob searches.
304 + */
305 + static public void addDefaultGlobExcludes( String... pDefaultGlobExcludes )
306 + {
307 + if ( pDefaultGlobExcludes != null )
308 + {
309 + sDefaultGlobExcludes.addAll( Arrays.asList( pDefaultGlobExcludes ) );
310 + }
311 + }
312 +
313 + private static class PathPatterns
314 + {
315 + private final File mPath;
316 + private final boolean mIsFile;
317 + private final List<Pattern> mIncludes = new ArrayList<Pattern>();
318 + private final List<Pattern> mExcludes = new ArrayList<Pattern>();
319 +
320 + public PathPatterns( String pPath, String[] pPatterns )
321 + {
322 + pPath = Util.deNull( pPath, "." ).trim();
323 + if ( pPatterns == null || pPatterns.length == 0 )
324 + {
325 + String[] split = pPath.split( "\\|" ); // split on a '|'
326 + pPath = split[0].trim();
327 + pPatterns = new String[split.length - 1];
328 + for ( int i = 1, n = split.length; i < n; i++ )
329 + {
330 + pPatterns[i - 1] = split[i].trim();
331 + }
332 + }
333 + File zPath = new File( pPath );
334 + if ( zPath.isFile() )
335 + {
336 + if ( pPatterns.length != 0 )
337 + {
338 + throw new IllegalArgumentException( "Files (e.g. " + zPath + ") may NOT have patterns: " + Arrays.asList( pPatterns ) );
339 + }
340 + mIsFile = true;
341 + mPath = FileUtil.getCanonicalFile( zPath );
342 + return;
343 + }
344 + if ( !zPath.isDirectory() )
345 + {
346 + throw new IllegalArgumentException( "Path Reference not a File or Directory: " + zPath );
347 + }
348 + mIsFile = false;
349 + mPath = FileUtil.getCanonicalFile( zPath );
350 + List<String> zIncludes = new ArrayList<String>();
351 + List<String> zExcludes = new ArrayList<String>();
352 + for ( String zPattern : pPatterns )
353 + {
354 + if ( null != (zPattern = Util.noEmpty( zPattern )) )
355 + {
356 + List<String> zList = zIncludes;
357 + if ( zPattern.charAt( 0 ) == '!' )
358 + {
359 + if ( null == (zPattern = Util.noEmpty( zPattern.substring( 1 ) )) )
360 + {
361 + continue;
362 + }
363 + zList = zExcludes;
364 + }
365 + zList.add( zPattern );
366 + }
367 + }
368 + if ( zIncludes.isEmpty() )
369 + {
370 + zIncludes.add( "**" );
371 + }
372 + if ( sDefaultGlobExcludes != null )
373 + {
374 + zExcludes.addAll( sDefaultGlobExcludes );
375 + }
376 + addPatterns( mIncludes, zIncludes );
377 + addPatterns( mExcludes, zExcludes );
378 + }
379 +
380 + private void addPatterns( List<Pattern> pTargetPatterns, List<String> pSourcePatterns )
381 + {
382 + for ( String zPattern : pSourcePatterns )
383 + {
384 + pTargetPatterns.add( new Pattern( zPattern ) );
385 + }
386 + }
387 +
388 + public void addTo( RootedPathsCollection pPaths )
389 + {
390 + if ( mIsFile )
391 + {
392 + pPaths.add( new FilePath( mPath.getParentFile(), mPath.getName() ) );
393 + return;
394 + }
395 + // Must be a Directory! (See Above)
396 + RootedPaths zPaths = new RootedPaths( mPath );
397 + String[] zFileNames = mPath.list();
398 + for ( String zFileName : zFileNames )
399 + {
400 + File zFile = new File( mPath, zFileName );
401 + if ( zFile.isDirectory() )
402 + {
403 + if ( !excludedDir( zFileName ) && acceptableDir( zFileName ) )
404 + {
405 + addTo( zPaths, zFileName + "/", zFile );
406 + }
407 + }
408 + else
409 + {
410 + if ( !excludedFile( zFileName ) && acceptableFile( zFileName ) )
411 + {
412 + zPaths.addCanonicalRelativePath( zFileName );
413 + }
414 + }
415 + }
416 + pPaths.add( zPaths );
417 + }
418 +
419 + private void addTo( RootedPaths pPaths, String pAdditionalDirPath, File pDirectory )
420 + {
421 + String[] zFileNames = pDirectory.list();
422 + for ( String zFileName : zFileNames )
423 + {
424 + String zPath = pAdditionalDirPath + "/" + zFileName;
425 + File zFile = new File( pDirectory, zFileName );
426 + if ( zFile.isDirectory() )
427 + {
428 + if ( !excludedDir( zPath ) && acceptableDir( zPath ) )
429 + {
430 + addTo( pPaths, zPath + "/", zFile );
431 + }
432 + }
433 + else
434 + {
435 + if ( !excludedFile( zPath ) && acceptableFile( zPath ) )
436 + {
437 +
438 + String zFullCanonicalPath = FileUtil.getCanonicalPath( zFile );
439 + String zRelativeCanonicalPath = zFullCanonicalPath.substring( mPath.getPath().length() + 1 );
440 + pPaths.addCanonicalRelativePath( zRelativeCanonicalPath );
441 + }
442 + }
443 + }
444 + }
445 +
446 + private boolean acceptableDir( String pPath )
447 + {
448 + for ( Pattern zInclude : mIncludes )
449 + {
450 + if ( zInclude.acceptableDirPath( pPath ) )
451 + {
452 + return true;
453 + }
454 + }
455 + return false;
456 + }
457 +
458 + private boolean acceptableFile( String pPath )
459 + {
460 + for ( Pattern zInclude : mIncludes )
461 + {
462 + if ( zInclude.matchesFilePath( pPath ) )
463 + {
464 + return true;
465 + }
466 + }
467 + return false;
468 + }
469 +
470 + private boolean excludedDir( String pPath )
471 + {
472 + for ( Pattern zExclude : mExcludes )
473 + {
474 + if ( zExclude.matchesDirPathAndChildren( pPath ) )
475 + {
476 + return true;
477 + }
478 + }
479 + return false;
480 + }
481 +
482 + private boolean excludedFile( String pPath )
483 + {
484 + for ( Pattern zExclude : mExcludes )
485 + {
486 + if ( zExclude.matchesFilePath( pPath ) )
487 + {
488 + return true;
489 + }
490 + }
491 + return false;
492 + }
493 + }
494 +
495 + public static void main( String[] args )
496 + throws Exception
497 + {
498 + if ( args.length == 0 )
499 + {
500 + System.out.println( "Usage: dir [pattern] [, pattern ...]" );
501 + System.exit( 0 );
502 + }
503 + List<String> patterns = Arrays.asList( args );
504 + patterns = patterns.subList( 1, patterns.size() );
505 + for ( String path : new Paths( args[0], patterns.toArray( new String[patterns.size()] ) ).getFullPaths() )
506 + {
507 + System.out.println( path );
508 + }
509 + }
510 + }