|
@@ -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 |
+ |
} |