Lines 49-55
Link Here
|
49 |
import java.io.IOException; |
49 |
import java.io.IOException; |
50 |
import java.io.InputStream; |
50 |
import java.io.InputStream; |
51 |
import java.io.OutputStream; |
51 |
import java.io.OutputStream; |
52 |
import java.lang.ref.SoftReference; |
|
|
53 |
import java.net.ConnectException; |
52 |
import java.net.ConnectException; |
54 |
import java.util.Set; |
53 |
import java.util.Set; |
55 |
import java.util.StringTokenizer; |
54 |
import java.util.StringTokenizer; |
Lines 58-63
Link Here
|
58 |
import java.util.concurrent.Future; |
57 |
import java.util.concurrent.Future; |
59 |
import java.util.concurrent.TimeUnit; |
58 |
import java.util.concurrent.TimeUnit; |
60 |
import java.util.concurrent.locks.Condition; |
59 |
import java.util.concurrent.locks.Condition; |
|
|
60 |
import java.util.concurrent.locks.Lock; |
61 |
import java.util.concurrent.locks.ReentrantLock; |
61 |
import java.util.concurrent.locks.ReentrantLock; |
62 |
import java.util.logging.Level; |
62 |
import java.util.logging.Level; |
63 |
import org.netbeans.modules.dlight.libs.common.DLightLibsCommonLogger; |
63 |
import org.netbeans.modules.dlight.libs.common.DLightLibsCommonLogger; |
Lines 72-77
Link Here
|
72 |
import org.openide.filesystems.FileEvent; |
72 |
import org.openide.filesystems.FileEvent; |
73 |
import org.openide.filesystems.FileLock; |
73 |
import org.openide.filesystems.FileLock; |
74 |
import org.openide.filesystems.FileObject; |
74 |
import org.openide.filesystems.FileObject; |
|
|
75 |
import org.openide.util.Exceptions; |
75 |
|
76 |
|
76 |
/** |
77 |
/** |
77 |
* |
78 |
* |
Lines 79-94
Link Here
|
79 |
*/ |
80 |
*/ |
80 |
public final class RemotePlainFile extends RemoteFileObjectBase { |
81 |
public final class RemotePlainFile extends RemoteFileObjectBase { |
81 |
|
82 |
|
|
|
83 |
public static enum UploadState { |
84 |
OK, |
85 |
UPLOADING, |
86 |
FAILED |
87 |
} |
88 |
|
82 |
private static final int LOCK_TIMEOUT = Integer.getInteger("remote.rwlock.timeout", 4); // NOI18N |
89 |
private static final int LOCK_TIMEOUT = Integer.getInteger("remote.rwlock.timeout", 4); // NOI18N |
83 |
|
90 |
|
84 |
private final char fileTypeChar; |
91 |
private final char fileTypeChar; |
85 |
// private SoftReference<CachedRemoteInputStream> fileContentCache = new SoftReference<CachedRemoteInputStream>(null); |
92 |
// private SoftReference<CachedRemoteInputStream> fileContentCache = new SoftReference<CachedRemoteInputStream>(null); |
86 |
private SimpleRWLock rwl = new SimpleRWLock(); |
93 |
private SimpleRWLock rwl = new SimpleRWLock(); |
|
|
94 |
|
95 |
private final Object uploadStateLock = new Object(); |
96 |
|
97 |
/** guarded by uploadStateLock */ |
98 |
private UploadState uploadState; |
99 |
|
100 |
/** guarded by RemoteFileSystem.getLock(getCache()) */ |
101 |
private long lastUploadTimestamp = -1; |
87 |
|
102 |
|
88 |
/*package*/ RemotePlainFile(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv, |
103 |
/*package*/ RemotePlainFile(RemoteFileObject wrapper, RemoteFileSystem fileSystem, ExecutionEnvironment execEnv, |
89 |
RemoteDirectory parent, String remotePath, File cache, FileType fileType) { |
104 |
RemoteDirectory parent, String remotePath, File cache, FileType fileType) { |
90 |
super(wrapper, fileSystem, execEnv, parent, remotePath, cache); |
105 |
super(wrapper, fileSystem, execEnv, parent, remotePath, cache); |
91 |
fileTypeChar = fileType.toChar(); // TODO: pass when created |
106 |
fileTypeChar = fileType.toChar(); // TODO: pass when created |
|
|
107 |
changeUploadState( |
108 |
fileSystem.getPendingUploadsManager().isPendingOrFailedUpload(remotePath) ? |
109 |
UploadState.FAILED : UploadState.OK); |
92 |
} |
110 |
} |
93 |
|
111 |
|
94 |
@Override |
112 |
@Override |
Lines 444-449
Link Here
|
444 |
// Fixing #206726 - If a remote file is saved frequently, "File modified externally" message appears, user changes are lost |
462 |
// Fixing #206726 - If a remote file is saved frequently, "File modified externally" message appears, user changes are lost |
445 |
@Override |
463 |
@Override |
446 |
protected void refreshImpl(boolean recursive, Set<String> antiLoop, boolean expected) throws ConnectException, IOException, InterruptedException, CancellationException, ExecutionException { |
464 |
protected void refreshImpl(boolean recursive, Set<String> antiLoop, boolean expected) throws ConnectException, IOException, InterruptedException, CancellationException, ExecutionException { |
|
|
465 |
if (fixUpload()) { |
466 |
return; |
467 |
} |
447 |
if (Boolean.getBoolean("cnd.remote.refresh.plain.file")) { //NOI18N |
468 |
if (Boolean.getBoolean("cnd.remote.refresh.plain.file")) { //NOI18N |
448 |
long time = System.currentTimeMillis(); |
469 |
long time = System.currentTimeMillis(); |
449 |
getParent().refreshImpl(false, antiLoop, expected); |
470 |
getParent().refreshImpl(false, antiLoop, expected); |
Lines 451-461
Link Here
|
451 |
} |
472 |
} |
452 |
} |
473 |
} |
453 |
|
474 |
|
|
|
475 |
/*package*/ boolean fixUpload() { |
476 |
boolean fixUpload = false; |
477 |
if (ConnectionManager.getInstance().isConnectedTo(getExecutionEnvironment())) { |
478 |
synchronized (uploadStateLock) { |
479 |
fixUpload = (uploadState == UploadState.FAILED); |
480 |
} |
481 |
if (fixUpload) { |
482 |
try { |
483 |
upload(); |
484 |
} catch (IOException ex) { |
485 |
ex.printStackTrace(); |
486 |
} |
487 |
} |
488 |
} |
489 |
return fixUpload; |
490 |
} |
491 |
|
454 |
@Override |
492 |
@Override |
455 |
public FileType getType() { |
493 |
public FileType getType() { |
456 |
return FileType.fromChar(fileTypeChar); |
494 |
return FileType.fromChar(fileTypeChar); |
457 |
} |
495 |
} |
458 |
|
496 |
|
|
|
497 |
public UploadState getUploadState() { |
498 |
synchronized (uploadStateLock) { |
499 |
return uploadState; |
500 |
} |
501 |
} |
502 |
|
503 |
private UploadState changeUploadState(UploadState newState) { |
504 |
return changeUploadState(null, newState); |
505 |
} |
506 |
|
507 |
private UploadState changeUploadState(UploadState from, UploadState to) { |
508 |
synchronized (uploadStateLock) { |
509 |
if (from != null && from != uploadState) { |
510 |
return null; |
511 |
} |
512 |
UploadState prevState = uploadState; |
513 |
uploadState = to; |
514 |
switch (to) { |
515 |
case OK: |
516 |
getFileSystem().getPendingUploadsManager().removePendingOrFailedUpload(this); |
517 |
break; |
518 |
case UPLOADING: |
519 |
getFileSystem().getPendingUploadsManager().addPendingUpload(this); |
520 |
break; |
521 |
case FAILED: |
522 |
getFileSystem().getPendingUploadsManager().addFailedUpload(this); |
523 |
break; |
524 |
default: |
525 |
Exceptions.printStackTrace(new IllegalStateException( |
526 |
"Unexpected " + UploadState.class.getSimpleName() + ": " + to)); //NOI18N |
527 |
} |
528 |
return prevState; |
529 |
} |
530 |
} |
531 |
|
532 |
@Override |
533 |
/*package*/ boolean isPendingRemoteDelivery() { |
534 |
synchronized (uploadStateLock) { |
535 |
return uploadState == UploadState.UPLOADING || uploadState == UploadState.FAILED; |
536 |
} |
537 |
} |
538 |
|
459 |
private static class DelegateOutputStream extends OutputStream { |
539 |
private static class DelegateOutputStream extends OutputStream { |
460 |
|
540 |
|
461 |
private final FileOutputStream delegate; |
541 |
private final FileOutputStream delegate; |
Lines 487-539
Link Here
|
487 |
} |
567 |
} |
488 |
try { |
568 |
try { |
489 |
delegate.close(); |
569 |
delegate.close(); |
490 |
file.setPendingRemoteDelivery(true); |
570 |
file.upload(); |
491 |
CommonTasksSupport.UploadParameters params = new CommonTasksSupport.UploadParameters( |
|
|
492 |
file.getCache(), file.getExecutionEnvironment(), file.getPath(), -1, false, null); |
493 |
Future<UploadStatus> task = CommonTasksSupport.uploadFile(params); |
494 |
try { |
495 |
UploadStatus uploadStatus = task.get(); |
496 |
if (uploadStatus.isOK()) { |
497 |
RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} succeeded", this); |
498 |
file.getParent().updateStat(file, uploadStatus.getStatInfo()); |
499 |
FileEvent ev = new FileEvent(file.getOwnerFileObject(), file.getOwnerFileObject(), true, uploadStatus.getStatInfo().getLastModified().getTime()); |
500 |
file.getOwnerFileObject().fireFileChangedEvent(file.getListenersWithParent(), ev); |
501 |
} else { |
502 |
RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} failed", this); |
503 |
file.setPendingRemoteDelivery(false); |
504 |
throw new IOException(uploadStatus.getError() + " " + uploadStatus.getExitCode()); //NOI18N |
505 |
} |
506 |
} catch (InterruptedException ex) { |
507 |
throw newIOException(ex); |
508 |
} catch (ExecutionException ex) { |
509 |
//Exceptions.printStackTrace(ex); // should never be the case - the task is done |
510 |
if (!ConnectionManager.getInstance().isConnectedTo(file.getExecutionEnvironment())) { |
511 |
file.getFileSystem().addPendingFile(file); |
512 |
throw new ConnectException(ex.getMessage()); |
513 |
} else { |
514 |
if (RemoteFileSystemUtils.isFileNotFoundException(ex)) { |
515 |
throw new FileNotFoundException(file.getPath()); |
516 |
} else if (ex.getCause() instanceof IOException) { |
517 |
throw (IOException) ex.getCause(); |
518 |
} else { |
519 |
throw newIOException(ex); |
520 |
} |
521 |
} |
522 |
} |
523 |
closed = true; |
571 |
closed = true; |
524 |
} finally { |
572 |
} finally { |
525 |
file.rwl.writeUnlock(); |
573 |
file.rwl.writeUnlock(); |
526 |
} |
574 |
} |
527 |
} |
575 |
} |
528 |
|
576 |
|
529 |
private IOException newIOException(Exception cause) { |
|
|
530 |
return new IOException("Error uploading " + file.getPath() + " to " + file.getExecutionEnvironment() + ':' + //NOI18N |
531 |
cause.getMessage(), cause); |
532 |
} |
533 |
|
534 |
@Override |
577 |
@Override |
535 |
public void flush() throws IOException { |
578 |
public void flush() throws IOException { |
536 |
delegate.flush(); |
579 |
delegate.flush(); |
537 |
} |
580 |
} |
538 |
} |
581 |
} |
|
|
582 |
|
583 |
private void upload() throws IOException { |
584 |
|
585 |
Lock writeLock = RemoteFileSystem.getLock(getCache()).writeLock(); |
586 |
writeLock.lock(); |
587 |
try { |
588 |
long cacheTimestamp = getCache().lastModified(); |
589 |
UploadState us = getUploadState(); |
590 |
if (us == UploadState.OK && cacheTimestamp == lastUploadTimestamp) { |
591 |
return; |
592 |
} |
593 |
lastUploadTimestamp = -1; |
594 |
changeUploadState(UploadState.UPLOADING); |
595 |
CommonTasksSupport.UploadParameters params = new CommonTasksSupport.UploadParameters( |
596 |
getCache(), getExecutionEnvironment(), getPath(), -1, false, null); |
597 |
Future<UploadStatus> task = CommonTasksSupport.uploadFile(params); |
598 |
try { |
599 |
UploadStatus uploadStatus = task.get(); |
600 |
if (uploadStatus.isOK()) { |
601 |
RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} succeeded", this); |
602 |
getParent().updateStat(this, uploadStatus.getStatInfo()); |
603 |
changeUploadState(UploadState.OK); |
604 |
lastUploadTimestamp = cacheTimestamp; |
605 |
FileEvent ev = new FileEvent(getOwnerFileObject(), getOwnerFileObject(), true, uploadStatus.getStatInfo().getLastModified().getTime()); |
606 |
getOwnerFileObject().fireFileChangedEvent(getListenersWithParent(), ev); |
607 |
} else { |
608 |
RemoteLogger.getInstance().log(Level.FINEST, "WritingQueue: uploading {0} failed", this); |
609 |
throw new IOException(uploadStatus.getError() + " " + uploadStatus.getExitCode()); //NOI18N |
610 |
} |
611 |
} catch (InterruptedException ex) { |
612 |
throw newIOException(this, ex); |
613 |
} catch (ExecutionException ex) { |
614 |
//Exceptions.printStackTrace(ex); // should never be the case - the task is done |
615 |
if (!ConnectionManager.getInstance().isConnectedTo(getExecutionEnvironment())) { |
616 |
getFileSystem().addPendingFile(this); |
617 |
throw new ConnectException(ex.getMessage()); |
618 |
} else { |
619 |
if (RemoteFileSystemUtils.isFileNotFoundException(ex)) { |
620 |
throw new FileNotFoundException(getPath()); |
621 |
} else if (ex.getCause() instanceof IOException) { |
622 |
throw (IOException) ex.getCause(); |
623 |
} else { |
624 |
throw newIOException(this, ex); |
625 |
} |
626 |
} |
627 |
} finally { |
628 |
changeUploadState(UploadState.UPLOADING, UploadState.FAILED); |
629 |
} |
630 |
} finally { |
631 |
writeLock.unlock(); |
632 |
} |
633 |
} |
634 |
|
635 |
private IOException newIOException(RemotePlainFile file, Exception cause) { |
636 |
return new IOException("Error uploading " + file.getPath() + " to " + file.getExecutionEnvironment() + ':' + //NOI18N |
637 |
cause.getMessage(), cause); |
638 |
} |
539 |
} |
639 |
} |