Subversion Repository Public Repository

litesoft

Diff Revisions 948 vs 950 for /trunk/Java/core/Server/src/org/litesoft/util/Directories.java

Diff revisions: vs.
  @@ -1,416 +1,416 @@
1 - // This Source Code is in the Public Domain per: http://unlicense.org
2 - package org.litesoft.util;
3 -
4 - import org.litesoft.commonfoundation.exceptions.*;
5 - import org.litesoft.commonfoundation.typeutils.Objects;
6 - import org.litesoft.commonfoundation.typeutils.*;
7 -
8 - import java.io.*;
9 - import java.util.*;
10 -
11 - @SuppressWarnings("UnusedDeclaration")
12 - public class Directories {
13 - public static String currentWorking() {
14 - return System.getProperty( "user.dir" );
15 - }
16 -
17 - public static String temp() {
18 - return System.getProperty( "java.io.tmpdir" );
19 - }
20 -
21 - public static File findFromCurrent( String pSubPath ) {
22 - return find( currentWorking(), pSubPath );
23 - }
24 -
25 - public static File find( String pStartingPath, String pSubPath ) {
26 - Objects.assertNotNull( "StartingPath", pStartingPath );
27 - pSubPath = Strings.assertNotNullNotEmpty( "SubPath", pSubPath );
28 -
29 - File target = locate( pStartingPath, pSubPath, Paths.justTheLastName( pSubPath ) + ".path" );
30 - if ( target != null ) {
31 - return target;
32 - }
33 - throw new IllegalStateException( "Unable to locate Directory: " + pSubPath );
34 - }
35 -
36 - private static File locate( String pStartingPath, String pSubPath, String pRedirectorName ) {
37 - File base = new File( pStartingPath );
38 - do {
39 - File target = new File( base, pSubPath );
40 - if ( target.exists() ) {
41 - return target;
42 - }
43 - if ( pRedirectorName != null ) {
44 - target = new File( base, pRedirectorName );
45 - if ( target.isFile() ) {
46 - for ( String line : FileUtils.loadTextFile( target ) ) {
47 - if ( Strings.isNotNullOrEmpty( line ) ) {
48 - if ( null != (target = locate( line, pSubPath, null )) ) {
49 - return target;
50 - }
51 - }
52 - }
53 - }
54 - }
55 - base = base.getParentFile();
56 - }
57 - while ( base != null );
58 - return null;
59 - }
60 -
61 - public static File assertDirectory( File pExpectedDir )
62 - throws FileSystemException {
63 - Objects.assertNotNull( "ExpectedDir", pExpectedDir );
64 - if ( !pExpectedDir.isDirectory() ) {
65 - throw new FileSystemException( "Not a Directory: " + pExpectedDir.getAbsolutePath() );
66 - }
67 - return pExpectedDir;
68 - }
69 -
70 - public static void checkDirectoryable( File pExpectedDir )
71 - throws FileSystemException {
72 - Objects.assertNotNull( "ExpectedDir", pExpectedDir );
73 - if ( !pExpectedDir.isDirectory() && pExpectedDir.exists() ) {
74 - throw new FileSystemException( "Exists, but is Not a Directory: " + pExpectedDir.getAbsolutePath() );
75 - }
76 - }
77 -
78 - public static File insureParent( File pExpectedFile )
79 - throws FileSystemException {
80 - Objects.assertNotNull( "ExpectedFile", pExpectedFile );
81 - File zParentFile = pExpectedFile.getParentFile();
82 - if ( zParentFile != null ) {
83 - insure( zParentFile );
84 - }
85 - return pExpectedFile;
86 - }
87 -
88 - public static File insure( File pExpectedDir )
89 - throws FileSystemException {
90 - Objects.assertNotNull( "ExpectedDir", pExpectedDir );
91 - if ( !pExpectedDir.isDirectory() ) {
92 - if ( pExpectedDir.exists() ) {
93 - throw new FileSystemException( "Exists, but is Not a Directory: " + pExpectedDir.getAbsolutePath() );
94 - }
95 - if ( !pExpectedDir.mkdirs() || !pExpectedDir.isDirectory() ) {
96 - throw new FileSystemException( "Unable to create Directory: " + pExpectedDir.getAbsolutePath() );
97 - }
98 - }
99 - return pExpectedDir;
100 - }
101 -
102 - public static void moveAllFiles( String pFromPath, String pToPath ) {
103 - File zFrom = assertDirectory( new File( pFromPath ) );
104 - File zTo = insure( new File( pToPath ) );
105 - File[] zFiles = zFrom.listFiles();
106 - if ( zFiles != null ) {
107 - for ( File zFile : zFiles ) {
108 - String zName = zFile.getName();
109 - moveFile( zFile, new File( zTo, zName ) );
110 - }
111 - }
112 - }
113 -
114 - public static void moveFile( File pSourceFile, File pTargetFile )
115 - throws FileSystemException {
116 - Objects.assertNotNull( "SourceFile", pSourceFile );
117 - Objects.assertNotNull( "TargetFile", pTargetFile );
118 - Throwable zProblem = null;
119 - try {
120 - if ( pSourceFile.exists() ) {
121 - insureParent( pTargetFile );
122 - }
123 - if ( pSourceFile.renameTo( pTargetFile ) ) {
124 - if ( pTargetFile.exists() ) {
125 - return;
126 - }
127 - }
128 - }
129 - catch ( RuntimeException e ) {
130 - zProblem = e;
131 - }
132 - throw new FileSystemException( "Failed to Move (rename): " + pSourceFile + " to " + pTargetFile, zProblem );
133 - }
134 -
135 - public static void deleteIfExists( File pDirectory )
136 - throws FileSystemException {
137 - Objects.assertNotNull( "Directory", pDirectory );
138 - if ( pDirectory.isDirectory() ) {
139 - LowLevelDeleteAllEntries( pDirectory );
140 - if ( !pDirectory.delete() || pDirectory.exists() ) {
141 - throw new FileSystemException( "Unable to delete: " + pDirectory.getAbsolutePath() );
142 - }
143 - }
144 - }
145 -
146 - @SuppressWarnings({"UnusedDeclaration"})
147 - public static void deleteAllEntries( File pDirectory )
148 - throws FileSystemException {
149 - Objects.assertNotNull( "Directory", pDirectory );
150 - if ( pDirectory.isDirectory() ) {
151 - LowLevelDeleteAllEntries( pDirectory );
152 - }
153 - }
154 -
155 - private static void LowLevelDeleteAllEntries( File pDirectory )
156 - throws FileSystemException {
157 - String[] files = pDirectory.list();
158 - for ( String file : files ) {
159 - File entry = new File( pDirectory, file );
160 - if ( entry.isDirectory() ) {
161 - deleteIfExists( entry );
162 - } else {
163 - FileUtils.deleteIfExists( entry );
164 - }
165 - }
166 - }
167 -
168 - /**
169 - * @param pExpectedDirectory e.g. C:\work\OBEDS\test\odlfExpected
170 - * @param pActualDirectory e.g. C:\work\OBEDS\test\odlf
171 - *
172 - * @return error if not null or empty
173 - */
174 - @SuppressWarnings({"UnusedDeclaration"})
175 - public static String compare( String pExpectedDirectory, String pActualDirectory, String... pSkipEntries ) {
176 - File expected = new File( pExpectedDirectory );
177 - File actual = new File( pActualDirectory );
178 - if ( !expected.isDirectory() ) {
179 - return "'" + expected.getAbsolutePath() + "' Not a Directory";
180 - }
181 - if ( !actual.isDirectory() ) {
182 - return "'" + actual.getAbsolutePath() + "' Not a Directory";
183 - }
184 -
185 - AllButFilter filter = new AllButFilter( pSkipEntries );
186 - String[] entriesExpected = expected.list( filter );
187 - String[] entriesActual = actual.list( filter );
188 - Arrays.sort( entriesExpected );
189 - Arrays.sort( entriesActual );
190 - if ( entriesActual.length == 0 ) {
191 - return (entriesExpected.length == 0) ? null : // No Error
192 - "Missing: " + addEntries( entriesExpected, 0 ).substring( 1 );
193 - }
194 - if ( entriesExpected.length == 0 ) {
195 - return "Unexpected: " + addEntries( entriesActual, 0 ).substring( 1 );
196 - }
197 - List<FileMatcher> matchers = new ArrayList<FileMatcher>();
198 - StringBuilder unexpected = new StringBuilder();
199 - StringBuilder missing = new StringBuilder();
200 - int atActual = 0;
201 - int atExpected = 0;
202 - while ( (atActual < entriesActual.length) && (atExpected < entriesExpected.length) ) {
203 - int cmp = entriesActual[atActual].compareTo( entriesExpected[atExpected] );
204 - if ( cmp == 0 ) {
205 - // Equal
206 - matchers.add( new FileMatcher( pExpectedDirectory, pActualDirectory, entriesExpected[atExpected++] ) );
207 - atActual++;
208 - } else if ( cmp > 0 ) {
209 - // Actual > Expected
210 - add( missing, entriesExpected[atExpected++] );
211 - } else {
212 - // Actual < Expected
213 - add( unexpected, entriesActual[atActual++] );
214 - }
215 - }
216 - while ( atActual < entriesActual.length ) {
217 - add( unexpected, entriesActual[atActual++] );
218 - }
219 - while ( atExpected < entriesExpected.length ) {
220 - add( missing, entriesExpected[atExpected++] );
221 - }
222 - StringBuilder issues = new StringBuilder();
223 - if ( unexpected.length() != 0 ) {
224 - issues.append( "<br>" ).append( "Unexpected: " ).append( unexpected.toString().substring( 1 ) );
225 - }
226 - if ( missing.length() != 0 ) {
227 - issues.append( "<br>" ).append( "Missing: " ).append( missing.toString().substring( 1 ) );
228 - }
229 - if ( issues.length() != 0 ) {
230 - return issues.toString();
231 - }
232 - for ( FileMatcher matcher : matchers ) {
233 - matcher.checkLengths( issues );
234 - }
235 - if ( issues.length() != 0 ) {
236 - return issues.toString();
237 - }
238 - for ( FileMatcher matcher : matchers ) {
239 - matcher.checkContents( issues );
240 - }
241 - if ( issues.length() != 0 ) {
242 - return issues.toString();
243 - }
244 - return null; // No error
245 - }
246 -
247 - private static String addEntries( String[] pEntries, int pAt ) {
248 - StringBuilder sb = new StringBuilder();
249 - while ( pAt < pEntries.length ) {
250 - add( sb, pEntries[pAt++] );
251 - }
252 - return sb.toString();
253 - }
254 -
255 - private static void add( StringBuilder pSb, String pEntry ) {
256 - pSb.append( ", " ).append( pEntry );
257 - }
258 -
259 - public static class DirsOnlyFilter implements FilenameFilter {
260 - public static final FilenameFilter INSTANCE = new DirsOnlyFilter();
261 -
262 - @Override
263 - public boolean accept( File dir, String name ) {
264 - return new File( dir, name ).isDirectory();
265 - }
266 - }
267 -
268 - public static class DirsOnlyFileFilter implements FileFilter {
269 - public static final FileFilter INSTANCE = new DirsOnlyFileFilter();
270 -
271 - @Override
272 - public boolean accept( File pathname ) {
273 - return pathname.isDirectory();
274 - }
275 - }
276 -
277 - public static class AllButFilter implements FilenameFilter {
278 - private String[] mButs;
279 -
280 - public AllButFilter( String... pButs ) {
281 - mButs = pButs;
282 - }
283 -
284 - @Override
285 - public boolean accept( File dir, String name ) {
286 - for ( String but : mButs ) {
287 - if ( name.equals( but ) ) {
288 - return false;
289 - }
290 - }
291 - return true;
292 - }
293 - }
294 -
295 - public static class FileMatcher {
296 - private File mExpected, mActual;
297 - private String mName;
298 -
299 - public FileMatcher( String pExpectedDirectory, String pActualDirectory, String pName ) {
300 - mName = pName;
301 - mExpected = new File( pExpectedDirectory, pName );
302 - mActual = new File( pActualDirectory, pName );
303 - }
304 -
305 - public void checkLengths( StringBuilder pIssues ) {
306 - long expected = mExpected.length();
307 - long actual = mActual.length();
308 -
309 - if ( actual != expected ) {
310 - pIssues.append( "<br>Files '" ).append( mName ).append( "' Lengths MisMatch " ).append( "Actual(" ).append( actual ).append( ") != Expected(" )
311 - .append( expected ).append( ")" );
312 - }
313 - }
314 -
315 - public void checkContents( StringBuilder pIssues ) {
316 - StreamBlockReader eSBR = new StreamBlockReader();
317 - StreamBlockReader aSBR = new StreamBlockReader();
318 - try {
319 - eSBR.initialize( new FileInputStream( mExpected ) );
320 - aSBR.initialize( new FileInputStream( mActual ) );
321 - eSBR.readNextBlock();
322 - aSBR.readNextBlock();
323 - do {
324 - if ( !eSBR.blocksEqual( aSBR ) ) {
325 - pIssues.append( "<br>Files '" ).append( mName ).append( "' Contents Mismatch" );
326 - return;
327 - }
328 - }
329 - while ( 0 != (eSBR.readNextBlock() + aSBR.readNextBlock()) );
330 - }
331 - catch ( IOException e ) {
332 - pIssues.append( "<br>Files '" ).append( mName ).append( "' IOException: " ).append( e.getMessage() );
333 - }
334 - finally {
335 - eSBR.dispose();
336 - aSBR.dispose();
337 - }
338 - }
339 - }
340 -
341 - public static class StreamBlockReader {
342 - private InputStream mInputStream = null;
343 - private byte[] mBuf = new byte[16 * 1024];
344 - private int mCount = 0;
345 -
346 - public void initialize( InputStream pInputStream ) {
347 - mInputStream = pInputStream;
348 - mCount = 0;
349 - }
350 -
351 - public int readNextBlock()
352 - throws IOException {
353 - mCount = 0;
354 - int bytes;
355 - while ( 0 < (bytes = mInputStream.read( mBuf, mCount, mBuf.length - mCount )) ) {
356 - mCount += bytes;
357 - if ( mCount == mBuf.length ) {
358 - break;
359 - }
360 - }
361 - return mCount;
362 - }
363 -
364 - public boolean blocksEqual( StreamBlockReader pThem ) {
365 - if ( this.mCount != pThem.mCount ) {
366 - return false;
367 - }
368 - for ( int i = 0; i < mCount; i++ ) {
369 - if ( this.mBuf[i] != pThem.mBuf[i] ) {
370 - return false;
371 - }
372 - }
373 - return true;
374 - }
375 -
376 - public void dispose() {
377 - if ( mInputStream != null ) {
378 - Utils.dispose( mInputStream );
379 - mInputStream = null;
380 - }
381 - }
382 - }
383 -
384 - public static void main( String[] args )
385 - throws Exception {
386 - DirectoriesDepthFirst.Visitor zVisitor = new MyVisitor( FileUtils.createFileNameFilter( Strings.parseChar( args[0], '*' ) ) );
387 -
388 - new DirectoriesDepthFirst( zVisitor ).process( new File( currentWorking() ) );
389 - }
390 -
391 - private static class MyVisitor implements DirectoriesDepthFirst.Visitor {
392 - private FilenameFilter mFilter;
393 -
394 - public MyVisitor( FilenameFilter pFilter ) {
395 - mFilter = pFilter;
396 - }
397 -
398 - @Override
399 - public void process( File pDirectory )
400 - throws IOException {
401 - File[] zFiles = pDirectory.listFiles( mFilter );
402 - if ( Objects.isNotNullOrEmpty( zFiles ) ) {
403 - System.out.println( pDirectory );
404 - for ( File zFile : zFiles ) {
405 - boolean zDeleted = zFile.delete();
406 - System.out.println( " " + (zDeleted ? " " : "!") + " " + zFile.getName() );
407 - }
408 - String[] zFileNames = pDirectory.list();
409 - if ( Objects.isNullOrEmpty( zFileNames ) ) {
410 - boolean zDeleted = pDirectory.delete();
411 - System.out.println( " " + (zDeleted ? "x!" : "!x") );
412 - }
413 - }
414 - }
415 - }
416 - }
1 + // This Source Code is in the Public Domain per: http://unlicense.org
2 + package org.litesoft.util;
3 +
4 + import org.litesoft.commonfoundation.base.*;
5 + import org.litesoft.commonfoundation.exceptions.*;
6 + import org.litesoft.commonfoundation.typeutils.*;
7 +
8 + import java.io.*;
9 + import java.util.*;
10 +
11 + @SuppressWarnings("UnusedDeclaration")
12 + public class Directories {
13 + public static String currentWorking() {
14 + return System.getProperty( "user.dir" );
15 + }
16 +
17 + public static String temp() {
18 + return System.getProperty( "java.io.tmpdir" );
19 + }
20 +
21 + public static File findFromCurrent( String pSubPath ) {
22 + return find( currentWorking(), pSubPath );
23 + }
24 +
25 + public static File find( String pStartingPath, String pSubPath ) {
26 + Confirm.isNotNull( "StartingPath", pStartingPath );
27 + pSubPath = Confirm.significant( "SubPath", pSubPath );
28 +
29 + File target = locate( pStartingPath, pSubPath, Paths.justTheLastName( pSubPath ) + ".path" );
30 + if ( target != null ) {
31 + return target;
32 + }
33 + throw new IllegalStateException( "Unable to locate Directory: " + pSubPath );
34 + }
35 +
36 + private static File locate( String pStartingPath, String pSubPath, String pRedirectorName ) {
37 + File base = new File( pStartingPath );
38 + do {
39 + File target = new File( base, pSubPath );
40 + if ( target.exists() ) {
41 + return target;
42 + }
43 + if ( pRedirectorName != null ) {
44 + target = new File( base, pRedirectorName );
45 + if ( target.isFile() ) {
46 + for ( String line : FileUtils.loadTextFile( target ) ) {
47 + if ( Currently.isNotNullOrEmpty( line ) ) {
48 + if ( null != (target = locate( line, pSubPath, null )) ) {
49 + return target;
50 + }
51 + }
52 + }
53 + }
54 + }
55 + base = base.getParentFile();
56 + }
57 + while ( base != null );
58 + return null;
59 + }
60 +
61 + public static File assertDirectory( File pExpectedDir )
62 + throws FileSystemException {
63 + Confirm.isNotNull( "ExpectedDir", pExpectedDir );
64 + if ( !pExpectedDir.isDirectory() ) {
65 + throw new FileSystemException( "Not a Directory: " + pExpectedDir.getAbsolutePath() );
66 + }
67 + return pExpectedDir;
68 + }
69 +
70 + public static void checkDirectoryable( File pExpectedDir )
71 + throws FileSystemException {
72 + Confirm.isNotNull( "ExpectedDir", pExpectedDir );
73 + if ( !pExpectedDir.isDirectory() && pExpectedDir.exists() ) {
74 + throw new FileSystemException( "Exists, but is Not a Directory: " + pExpectedDir.getAbsolutePath() );
75 + }
76 + }
77 +
78 + public static File insureParent( File pExpectedFile )
79 + throws FileSystemException {
80 + Confirm.isNotNull( "ExpectedFile", pExpectedFile );
81 + File zParentFile = pExpectedFile.getParentFile();
82 + if ( zParentFile != null ) {
83 + insure( zParentFile );
84 + }
85 + return pExpectedFile;
86 + }
87 +
88 + public static File insure( File pExpectedDir )
89 + throws FileSystemException {
90 + Confirm.isNotNull( "ExpectedDir", pExpectedDir );
91 + if ( !pExpectedDir.isDirectory() ) {
92 + if ( pExpectedDir.exists() ) {
93 + throw new FileSystemException( "Exists, but is Not a Directory: " + pExpectedDir.getAbsolutePath() );
94 + }
95 + if ( !pExpectedDir.mkdirs() || !pExpectedDir.isDirectory() ) {
96 + throw new FileSystemException( "Unable to create Directory: " + pExpectedDir.getAbsolutePath() );
97 + }
98 + }
99 + return pExpectedDir;
100 + }
101 +
102 + public static void moveAllFiles( String pFromPath, String pToPath ) {
103 + File zFrom = assertDirectory( new File( pFromPath ) );
104 + File zTo = insure( new File( pToPath ) );
105 + File[] zFiles = zFrom.listFiles();
106 + if ( zFiles != null ) {
107 + for ( File zFile : zFiles ) {
108 + String zName = zFile.getName();
109 + moveFile( zFile, new File( zTo, zName ) );
110 + }
111 + }
112 + }
113 +
114 + public static void moveFile( File pSourceFile, File pTargetFile )
115 + throws FileSystemException {
116 + Confirm.isNotNull( "SourceFile", pSourceFile );
117 + Confirm.isNotNull( "TargetFile", pTargetFile );
118 + Throwable zProblem = null;
119 + try {
120 + if ( pSourceFile.exists() ) {
121 + insureParent( pTargetFile );
122 + }
123 + if ( pSourceFile.renameTo( pTargetFile ) ) {
124 + if ( pTargetFile.exists() ) {
125 + return;
126 + }
127 + }
128 + }
129 + catch ( RuntimeException e ) {
130 + zProblem = e;
131 + }
132 + throw new FileSystemException( "Failed to Move (rename): " + pSourceFile + " to " + pTargetFile, zProblem );
133 + }
134 +
135 + public static void deleteIfExists( File pDirectory )
136 + throws FileSystemException {
137 + Confirm.isNotNull( "Directory", pDirectory );
138 + if ( pDirectory.isDirectory() ) {
139 + LowLevelDeleteAllEntries( pDirectory );
140 + if ( !pDirectory.delete() || pDirectory.exists() ) {
141 + throw new FileSystemException( "Unable to delete: " + pDirectory.getAbsolutePath() );
142 + }
143 + }
144 + }
145 +
146 + @SuppressWarnings({"UnusedDeclaration"})
147 + public static void deleteAllEntries( File pDirectory )
148 + throws FileSystemException {
149 + Confirm.isNotNull( "Directory", pDirectory );
150 + if ( pDirectory.isDirectory() ) {
151 + LowLevelDeleteAllEntries( pDirectory );
152 + }
153 + }
154 +
155 + private static void LowLevelDeleteAllEntries( File pDirectory )
156 + throws FileSystemException {
157 + String[] files = pDirectory.list();
158 + for ( String file : files ) {
159 + File entry = new File( pDirectory, file );
160 + if ( entry.isDirectory() ) {
161 + deleteIfExists( entry );
162 + } else {
163 + FileUtils.deleteIfExists( entry );
164 + }
165 + }
166 + }
167 +
168 + /**
169 + * @param pExpectedDirectory e.g. C:\work\OBEDS\test\odlfExpected
170 + * @param pActualDirectory e.g. C:\work\OBEDS\test\odlf
171 + *
172 + * @return error if not null or empty
173 + */
174 + @SuppressWarnings({"UnusedDeclaration"})
175 + public static String compare( String pExpectedDirectory, String pActualDirectory, String... pSkipEntries ) {
176 + File expected = new File( pExpectedDirectory );
177 + File actual = new File( pActualDirectory );
178 + if ( !expected.isDirectory() ) {
179 + return "'" + expected.getAbsolutePath() + "' Not a Directory";
180 + }
181 + if ( !actual.isDirectory() ) {
182 + return "'" + actual.getAbsolutePath() + "' Not a Directory";
183 + }
184 +
185 + AllButFilter filter = new AllButFilter( pSkipEntries );
186 + String[] entriesExpected = expected.list( filter );
187 + String[] entriesActual = actual.list( filter );
188 + Arrays.sort( entriesExpected );
189 + Arrays.sort( entriesActual );
190 + if ( entriesActual.length == 0 ) {
191 + return (entriesExpected.length == 0) ? null : // No Error
192 + "Missing: " + addEntries( entriesExpected, 0 ).substring( 1 );
193 + }
194 + if ( entriesExpected.length == 0 ) {
195 + return "Unexpected: " + addEntries( entriesActual, 0 ).substring( 1 );
196 + }
197 + List<FileMatcher> matchers = new ArrayList<FileMatcher>();
198 + StringBuilder unexpected = new StringBuilder();
199 + StringBuilder missing = new StringBuilder();
200 + int atActual = 0;
201 + int atExpected = 0;
202 + while ( (atActual < entriesActual.length) && (atExpected < entriesExpected.length) ) {
203 + int cmp = entriesActual[atActual].compareTo( entriesExpected[atExpected] );
204 + if ( cmp == 0 ) {
205 + // Equal
206 + matchers.add( new FileMatcher( pExpectedDirectory, pActualDirectory, entriesExpected[atExpected++] ) );
207 + atActual++;
208 + } else if ( cmp > 0 ) {
209 + // Actual > Expected
210 + add( missing, entriesExpected[atExpected++] );
211 + } else {
212 + // Actual < Expected
213 + add( unexpected, entriesActual[atActual++] );
214 + }
215 + }
216 + while ( atActual < entriesActual.length ) {
217 + add( unexpected, entriesActual[atActual++] );
218 + }
219 + while ( atExpected < entriesExpected.length ) {
220 + add( missing, entriesExpected[atExpected++] );
221 + }
222 + StringBuilder issues = new StringBuilder();
223 + if ( unexpected.length() != 0 ) {
224 + issues.append( "<br>" ).append( "Unexpected: " ).append( unexpected.toString().substring( 1 ) );
225 + }
226 + if ( missing.length() != 0 ) {
227 + issues.append( "<br>" ).append( "Missing: " ).append( missing.toString().substring( 1 ) );
228 + }
229 + if ( issues.length() != 0 ) {
230 + return issues.toString();
231 + }
232 + for ( FileMatcher matcher : matchers ) {
233 + matcher.checkLengths( issues );
234 + }
235 + if ( issues.length() != 0 ) {
236 + return issues.toString();
237 + }
238 + for ( FileMatcher matcher : matchers ) {
239 + matcher.checkContents( issues );
240 + }
241 + if ( issues.length() != 0 ) {
242 + return issues.toString();
243 + }
244 + return null; // No error
245 + }
246 +
247 + private static String addEntries( String[] pEntries, int pAt ) {
248 + StringBuilder sb = new StringBuilder();
249 + while ( pAt < pEntries.length ) {
250 + add( sb, pEntries[pAt++] );
251 + }
252 + return sb.toString();
253 + }
254 +
255 + private static void add( StringBuilder pSb, String pEntry ) {
256 + pSb.append( ", " ).append( pEntry );
257 + }
258 +
259 + public static class DirsOnlyFilter implements FilenameFilter {
260 + public static final FilenameFilter INSTANCE = new DirsOnlyFilter();
261 +
262 + @Override
263 + public boolean accept( File dir, String name ) {
264 + return new File( dir, name ).isDirectory();
265 + }
266 + }
267 +
268 + public static class DirsOnlyFileFilter implements FileFilter {
269 + public static final FileFilter INSTANCE = new DirsOnlyFileFilter();
270 +
271 + @Override
272 + public boolean accept( File pathname ) {
273 + return pathname.isDirectory();
274 + }
275 + }
276 +
277 + public static class AllButFilter implements FilenameFilter {
278 + private String[] mButs;
279 +
280 + public AllButFilter( String... pButs ) {
281 + mButs = pButs;
282 + }
283 +
284 + @Override
285 + public boolean accept( File dir, String name ) {
286 + for ( String but : mButs ) {
287 + if ( name.equals( but ) ) {
288 + return false;
289 + }
290 + }
291 + return true;
292 + }
293 + }
294 +
295 + public static class FileMatcher {
296 + private File mExpected, mActual;
297 + private String mName;
298 +
299 + public FileMatcher( String pExpectedDirectory, String pActualDirectory, String pName ) {
300 + mName = pName;
301 + mExpected = new File( pExpectedDirectory, pName );
302 + mActual = new File( pActualDirectory, pName );
303 + }
304 +
305 + public void checkLengths( StringBuilder pIssues ) {
306 + long expected = mExpected.length();
307 + long actual = mActual.length();
308 +
309 + if ( actual != expected ) {
310 + pIssues.append( "<br>Files '" ).append( mName ).append( "' Lengths MisMatch " ).append( "Actual(" ).append( actual ).append( ") != Expected(" )
311 + .append( expected ).append( ")" );
312 + }
313 + }
314 +
315 + public void checkContents( StringBuilder pIssues ) {
316 + StreamBlockReader eSBR = new StreamBlockReader();
317 + StreamBlockReader aSBR = new StreamBlockReader();
318 + try {
319 + eSBR.initialize( new FileInputStream( mExpected ) );
320 + aSBR.initialize( new FileInputStream( mActual ) );
321 + eSBR.readNextBlock();
322 + aSBR.readNextBlock();
323 + do {
324 + if ( !eSBR.blocksEqual( aSBR ) ) {
325 + pIssues.append( "<br>Files '" ).append( mName ).append( "' Contents Mismatch" );
326 + return;
327 + }
328 + }
329 + while ( 0 != (eSBR.readNextBlock() + aSBR.readNextBlock()) );
330 + }
331 + catch ( IOException e ) {
332 + pIssues.append( "<br>Files '" ).append( mName ).append( "' IOException: " ).append( e.getMessage() );
333 + }
334 + finally {
335 + eSBR.dispose();
336 + aSBR.dispose();
337 + }
338 + }
339 + }
340 +
341 + public static class StreamBlockReader {
342 + private InputStream mInputStream = null;
343 + private byte[] mBuf = new byte[16 * 1024];
344 + private int mCount = 0;
345 +
346 + public void initialize( InputStream pInputStream ) {
347 + mInputStream = pInputStream;
348 + mCount = 0;
349 + }
350 +
351 + public int readNextBlock()
352 + throws IOException {
353 + mCount = 0;
354 + int bytes;
355 + while ( 0 < (bytes = mInputStream.read( mBuf, mCount, mBuf.length - mCount )) ) {
356 + mCount += bytes;
357 + if ( mCount == mBuf.length ) {
358 + break;
359 + }
360 + }
361 + return mCount;
362 + }
363 +
364 + public boolean blocksEqual( StreamBlockReader pThem ) {
365 + if ( this.mCount != pThem.mCount ) {
366 + return false;
367 + }
368 + for ( int i = 0; i < mCount; i++ ) {
369 + if ( this.mBuf[i] != pThem.mBuf[i] ) {
370 + return false;
371 + }
372 + }
373 + return true;
374 + }
375 +
376 + public void dispose() {
377 + if ( mInputStream != null ) {
378 + Utils.dispose( mInputStream );
379 + mInputStream = null;
380 + }
381 + }
382 + }
383 +
384 + public static void main( String[] args )
385 + throws Exception {
386 + DirectoriesDepthFirst.Visitor zVisitor = new MyVisitor( FileUtils.createFileNameFilter( Strings.parseChar( args[0], '*' ) ) );
387 +
388 + new DirectoriesDepthFirst( zVisitor ).process( new File( currentWorking() ) );
389 + }
390 +
391 + private static class MyVisitor implements DirectoriesDepthFirst.Visitor {
392 + private FilenameFilter mFilter;
393 +
394 + public MyVisitor( FilenameFilter pFilter ) {
395 + mFilter = pFilter;
396 + }
397 +
398 + @Override
399 + public void process( File pDirectory )
400 + throws IOException {
401 + File[] zFiles = pDirectory.listFiles( mFilter );
402 + if ( Currently.isNotNullOrEmpty( zFiles ) ) {
403 + System.out.println( pDirectory );
404 + for ( File zFile : zFiles ) {
405 + boolean zDeleted = zFile.delete();
406 + System.out.println( " " + (zDeleted ? " " : "!") + " " + zFile.getName() );
407 + }
408 + String[] zFileNames = pDirectory.list();
409 + if ( Currently.isNullOrEmpty( zFileNames ) ) {
410 + boolean zDeleted = pDirectory.delete();
411 + System.out.println( " " + (zDeleted ? "x!" : "!x") );
412 + }
413 + }
414 + }
415 + }
416 + }