Subversion Repository Public Repository

litesoft

Diff Revisions 958 vs 959 for /trunk/Java/ScarPlus/src/com/esotericsoftware/filesystem/Paths.java

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