34
34
import java .nio .file .NoSuchFileException ;
35
35
import java .nio .file .StandardCopyOption ;
36
36
import java .nio .file .StandardOpenOption ;
37
+ import java .util .Locale ;
37
38
import org .eclipse .core .filesystem .EFS ;
38
39
import org .eclipse .core .filesystem .IFileInfo ;
39
40
import org .eclipse .core .filesystem .IFileStore ;
50
51
import org .eclipse .core .runtime .IStatus ;
51
52
import org .eclipse .core .runtime .MultiStatus ;
52
53
import org .eclipse .core .runtime .NullProgressMonitor ;
53
- import org .eclipse .core .runtime .OperationCanceledException ;
54
54
import org .eclipse .core .runtime .Status ;
55
55
import org .eclipse .core .runtime .SubMonitor ;
56
56
import org .eclipse .osgi .util .NLS ;
@@ -131,19 +131,17 @@ public String[] childNames(int options, IProgressMonitor monitor) {
131
131
132
132
@ Override
133
133
public void copy (IFileStore destFile , int options , IProgressMonitor monitor ) throws CoreException {
134
- if (destFile instanceof LocalFile ) {
135
- File source = file ;
136
- File destination = ((LocalFile ) destFile ).file ;
134
+ if (destFile instanceof LocalFile destination ) {
137
135
//handle case variants on a case-insensitive OS, or copying between
138
136
//two equivalent files in an environment that supports symbolic links.
139
137
//in these nothing needs to be copied (and doing so would likely lose data)
140
138
try {
141
- if (isSameFile (source , destination )) {
139
+ if (isSameFile (this . file , destination . file )) {
142
140
//nothing to do
143
141
return ;
144
142
}
145
143
} catch (IOException e ) {
146
- String message = NLS .bind (Messages .couldNotRead , source .getAbsolutePath ());
144
+ String message = NLS .bind (Messages .couldNotRead , this . file .getAbsolutePath ());
147
145
Policy .error (EFS .ERROR_READ , message , e );
148
146
}
149
147
}
@@ -179,8 +177,7 @@ public void delete(int options, IProgressMonitor monitor) throws CoreException {
179
177
else
180
178
monitor = new InfiniteProgress (monitor );
181
179
try {
182
- monitor .beginTask (NLS .bind (Messages .deleting , this ), 200 );
183
- IStatus result = internalDelete (file , filePath , monitor );
180
+ IStatus result = internalDelete (file , monitor );
184
181
if (!result .isOK ())
185
182
throw new CoreException (result );
186
183
} finally {
@@ -190,13 +187,17 @@ public void delete(int options, IProgressMonitor monitor) throws CoreException {
190
187
191
188
@ Override
192
189
public boolean equals (Object obj ) {
193
- if (!(obj instanceof LocalFile ))
190
+ if (this == obj ) {
191
+ return true ;
192
+ }
193
+ if (!(obj instanceof LocalFile otherFile )) {
194
194
return false ;
195
+ }
195
196
//Mac oddity: file.equals returns false when case is different even when
196
197
//file system is not case sensitive (Radar bug 3190672)
197
- LocalFile otherFile = (LocalFile ) obj ;
198
- if (LocalFileSystem .MACOSX )
198
+ if (LocalFileSystem .MACOSX ) {
199
199
return filePath .equalsIgnoreCase (otherFile .filePath );
200
+ }
200
201
return file .equals (otherFile .file );
201
202
}
202
203
@@ -247,7 +248,7 @@ public IFileStore getParent() {
247
248
@ Override
248
249
public int hashCode () {
249
250
if (LocalFileSystem .MACOSX )
250
- return filePath .toLowerCase ().hashCode ();
251
+ return filePath .toLowerCase (Locale . ENGLISH ).hashCode ();
251
252
return file .hashCode ();
252
253
}
253
254
@@ -256,10 +257,9 @@ public int hashCode() {
256
257
* the provided status object. The filePath is passed as a parameter
257
258
* to optimize java.io.File object creation.
258
259
*/
259
- private IStatus internalDelete (File target , String pathToDelete , IProgressMonitor monitor ) {
260
- if (monitor .isCanceled ()) {
261
- throw new OperationCanceledException ();
262
- }
260
+ private IStatus internalDelete (File target , IProgressMonitor monitor ) {
261
+ SubMonitor subMonitor = SubMonitor .convert (monitor , NLS .bind (Messages .deleting , target ), IProgressMonitor .UNKNOWN );
262
+ subMonitor .checkCanceled ();
263
263
try {
264
264
try {
265
265
// First try to delete - this should succeed for files and symbolic links to directories.
@@ -275,29 +275,15 @@ private IStatus internalDelete(File target, String pathToDelete, IProgressMonito
275
275
}
276
276
} catch (DirectoryNotEmptyException e ) {
277
277
// The target is a directory and it's not empty
278
- monitor .subTask (NLS .bind (Messages .deleting , target ));
279
- String [] directoryElements = target .list ();
278
+ File [] directoryElements = target .listFiles ();
280
279
if (directoryElements == null ) {
281
- directoryElements = EMPTY_STRING_ARRAY ;
280
+ directoryElements = new File [ 0 ]; // Unlikely to happen if the directory is not empty
282
281
}
283
- int parentLength = pathToDelete .length ();
284
-
282
+ subMonitor .setWorkRemaining (directoryElements .length );
285
283
// Try to delete all children.
286
284
MultiStatus deleteChildrenStatus = new MultiStatus (Policy .PI_FILE_SYSTEM , EFS .ERROR_DELETE , Messages .deleteProblem , null );
287
- for (String element : directoryElements ) {
288
- if (monitor .isCanceled ()) {
289
- throw new OperationCanceledException ();
290
- }
291
- // Optimized creation of child path object
292
- StringBuilder childBuffer = new StringBuilder (parentLength + element .length () + 1 );
293
- childBuffer .append (pathToDelete );
294
- childBuffer .append (File .separatorChar );
295
- childBuffer .append (element );
296
- String childName = childBuffer .toString ();
297
-
298
- deleteChildrenStatus .add (internalDelete (new File (childName ), childName , monitor ));
299
-
300
- monitor .worked (1 );
285
+ for (File element : directoryElements ) {
286
+ deleteChildrenStatus .add (internalDelete (element , subMonitor .split (1 )));
301
287
}
302
288
303
289
// Abort if one of the children couldn't be deleted.
@@ -319,7 +305,7 @@ private IStatus internalDelete(File target, String pathToDelete, IProgressMonito
319
305
String message = fetchInfo ().getAttribute (EFS .ATTRIBUTE_READ_ONLY ) //
320
306
? Messages .couldnotDeleteReadOnly
321
307
322
- // This is the worst-case scenario: something failed but we don't know what. The children were
308
+ // This is the worst-case scenario: something failed but we don't know what. The children were
323
309
// deleted successfully and the directory is NOT read-only... there's nothing else to report.
324
310
: Messages .couldnotDelete ;
325
311
@@ -337,21 +323,25 @@ private IStatus createErrorStatus(File target, String msg, Exception e) {
337
323
338
324
@ Override
339
325
public boolean isParentOf (IFileStore other ) {
340
- if (!(other instanceof LocalFile ))
326
+ if (!(other instanceof LocalFile otherFile )) {
341
327
return false ;
328
+ }
342
329
String thisPath = filePath ;
343
- String thatPath = (( LocalFile ) other ) .filePath ;
330
+ String thatPath = otherFile .filePath ;
344
331
int thisLength = thisPath .length ();
345
332
int thatLength = thatPath .length ();
346
333
//if equal then not a parent
347
- if (thisLength >= thatLength )
334
+ if (thisLength >= thatLength ) {
348
335
return false ;
336
+ }
349
337
if (getFileSystem ().isCaseSensitive ()) {
350
- if (thatPath .indexOf (thisPath ) != 0 )
338
+ if (! thatPath .startsWith (thisPath )) {
351
339
return false ;
340
+ }
352
341
} else {
353
- if (thatPath .toLowerCase (). indexOf (thisPath .toLowerCase ()) != 0 )
342
+ if (! thatPath .toLowerCase (Locale . ENGLISH ). startsWith (thisPath .toLowerCase (Locale . ENGLISH ))) {
354
343
return false ;
344
+ }
355
345
}
356
346
//The common portion must end with a separator character for this to be a parent of that
357
347
return thisPath .charAt (thisLength - 1 ) == File .separatorChar || thatPath .charAt (thisLength ) == File .separatorChar ;
@@ -397,12 +387,12 @@ public IFileStore mkdir(int options, IProgressMonitor monitor) throws CoreExcept
397
387
398
388
@ Override
399
389
public void move (IFileStore destFile , int options , IProgressMonitor monitor ) throws CoreException {
400
- if (!(destFile instanceof LocalFile )) {
390
+ if (!(destFile instanceof LocalFile destinationFile )) {
401
391
super .move (destFile , options , monitor );
402
392
return ;
403
393
}
404
394
File source = file ;
405
- File destination = (( LocalFile ) destFile ) .file ;
395
+ File destination = destinationFile .file ;
406
396
boolean overwrite = (options & EFS .OVERWRITE ) != 0 ;
407
397
SubMonitor subMonitor = SubMonitor .convert (monitor , NLS .bind (Messages .moving , source .getAbsolutePath ()), 1 );
408
398
try {
@@ -462,8 +452,8 @@ private boolean isSameFile(File source, File destination) throws IOException {
462
452
// avoid NoSuchFileException for performance reasons
463
453
return false ;
464
454
}
465
- // isSameFile is faster then using getCanonicalPath
466
- return java . nio . file . Files .isSameFile (source .toPath (), destination .toPath ());
455
+ // isSameFile is faster then using getCanonicalPath
456
+ return Files .isSameFile (source .toPath (), destination .toPath ());
467
457
} catch (NoSuchFileException e ) {
468
458
// ignore - it is the normal case that the destination does not exist.
469
459
// slowest path though
@@ -477,17 +467,7 @@ public InputStream openInputStream(int options, IProgressMonitor monitor) throws
477
467
try {
478
468
return new FileInputStream (file );
479
469
} catch (FileNotFoundException e ) {
480
- String message ;
481
- if (!file .exists ()) {
482
- message = NLS .bind (Messages .fileNotFound , filePath );
483
- Policy .error (EFS .ERROR_NOT_EXISTS , message , e );
484
- } else if (file .isDirectory ()) {
485
- message = NLS .bind (Messages .notAFile , filePath );
486
- Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
487
- } else {
488
- message = NLS .bind (Messages .couldNotRead , filePath );
489
- Policy .error (EFS .ERROR_READ , message , e );
490
- }
470
+ handleReadIOException (e );
491
471
return null ;
492
472
}
493
473
}
@@ -498,37 +478,31 @@ public byte[] readAllBytes(int options, IProgressMonitor monitor) throws CoreExc
498
478
try {
499
479
return Files .readAllBytes (file .toPath ());
500
480
} catch (IOException e ) {
501
- String message ;
502
- if (!file .exists ()) {
503
- message = NLS .bind (Messages .fileNotFound , filePath );
504
- Policy .error (EFS .ERROR_NOT_EXISTS , message , e );
505
- } else if (file .isDirectory ()) {
506
- message = NLS .bind (Messages .notAFile , filePath );
507
- Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
508
- } else {
509
- message = NLS .bind (Messages .couldNotRead , filePath );
510
- Policy .error (EFS .ERROR_READ , message , e );
511
- }
481
+ handleReadIOException (e );
512
482
return null ;
513
483
}
514
484
}
515
485
486
+ private void handleReadIOException (IOException e ) throws CoreException {
487
+ if (!file .exists ()) {
488
+ String message = NLS .bind (Messages .fileNotFound , filePath );
489
+ Policy .error (EFS .ERROR_NOT_EXISTS , message , e );
490
+ } else if (file .isDirectory ()) {
491
+ String message = NLS .bind (Messages .notAFile , filePath );
492
+ Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
493
+ } else {
494
+ String message = NLS .bind (Messages .couldNotRead , filePath );
495
+ Policy .error (EFS .ERROR_READ , message , e );
496
+ }
497
+ }
498
+
516
499
/** @see #write(byte[], int, IProgressMonitor) */
517
500
@ Override
518
501
public OutputStream openOutputStream (int options , IProgressMonitor monitor ) throws CoreException {
519
502
try {
520
503
return new FileOutputStream (file , (options & EFS .APPEND ) != 0 );
521
504
} catch (FileNotFoundException e ) {
522
- checkReadOnlyParent (file , e );
523
- String message ;
524
- String path = filePath ;
525
- if (file .isDirectory ()) {
526
- message = NLS .bind (Messages .notAFile , path );
527
- Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
528
- } else {
529
- message = NLS .bind (Messages .couldNotWrite , path );
530
- Policy .error (EFS .ERROR_WRITE , message , e );
531
- }
505
+ handleWriteIOException (e );
532
506
return null ;
533
507
}
534
508
}
@@ -544,16 +518,18 @@ public void write(byte[] content, int options, IProgressMonitor monitor) throws
544
518
Files .write (file .toPath (), content ); // default uses StandardOpenOption.TRUNCATE_EXISTING
545
519
}
546
520
} catch (IOException e ) {
547
- checkReadOnlyParent (file , e );
548
- String message ;
549
- String path = filePath ;
550
- if (file .isDirectory ()) {
551
- message = NLS .bind (Messages .notAFile , path );
552
- Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
553
- } else {
554
- message = NLS .bind (Messages .couldNotWrite , path );
555
- Policy .error (EFS .ERROR_WRITE , message , e );
556
- }
521
+ handleWriteIOException (e );
522
+ }
523
+ }
524
+
525
+ private void handleWriteIOException (IOException e ) throws CoreException {
526
+ checkReadOnlyParent (file , e );
527
+ if (file .isDirectory ()) {
528
+ String message = NLS .bind (Messages .notAFile , filePath );
529
+ Policy .error (EFS .ERROR_WRONG_TYPE , message , e );
530
+ } else {
531
+ String message = NLS .bind (Messages .couldNotWrite , filePath );
532
+ Policy .error (EFS .ERROR_WRITE , message , e );
557
533
}
558
534
}
559
535
@@ -592,11 +568,11 @@ public URI toURI() {
592
568
593
569
@ Override
594
570
public int compareTo (IFileStore other ) {
595
- if (other instanceof LocalFile ) {
571
+ if (other instanceof LocalFile otherFile ) {
596
572
// We can compare paths in the local file implementation, because LocalFile don't have a query string, port, or authority
597
573
// We use `toURI` here because it performs file normalisation e.g. /a/b/../c -> /a/c
598
574
// The URI is cached by the LocalFile after normalisation so this effectively results in a straight lookup
599
- return FileStoreUtil .comparePathSegments (this .toURI ().getPath (), (( LocalFile ) other ) .toURI ().getPath ());
575
+ return FileStoreUtil .comparePathSegments (this .toURI ().getPath (), otherFile .toURI ().getPath ());
600
576
}
601
577
return super .compareTo (other );
602
578
}
0 commit comments