# This patch file was generated by NetBeans IDE
# Following Index: paths are relative to: /data/work/src/netbeans-cdev
# This patch can be applied using context Tools: Patch action on respective folder.
# It uses platform neutral UTF-8 encoding and \n newlines.
# Above lines and this line are ignored by the patching process.
Index: masterfs/apichanges.xml
--- masterfs/apichanges.xml Base (BASE)
+++ masterfs/apichanges.xml Locally Modified (Based On LOCAL)
@@ -49,6 +49,19 @@
MasterFileSystem API
+
+
+ Delegate FileObject.copy() to ProvidedExtensions
+
+
+
+
+
+ ProvidedExtensions.getCopyHandler() allows to delegate a copy operation.
+
+
+
+
Guaranteed event order when deleting and creating files and new calls in ProvidedExtensions
Index: masterfs/manifest.mf
--- masterfs/manifest.mf Base (BASE)
+++ masterfs/manifest.mf Locally Modified (Based On LOCAL)
@@ -1,7 +1,7 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.modules.masterfs/2
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/masterfs/resources/Bundle.properties
-OpenIDE-Module-Specification-Version: 2.27
+OpenIDE-Module-Specification-Version: 2.28
AutoUpdate-Show-In-Client: false
AutoUpdate-Essential-Module: true
Index: masterfs/src/org/netbeans/modules/masterfs/ProvidedExtensionsProxy.java
--- masterfs/src/org/netbeans/modules/masterfs/ProvidedExtensionsProxy.java Base (BASE)
+++ masterfs/src/org/netbeans/modules/masterfs/ProvidedExtensionsProxy.java Locally Modified (Based On LOCAL)
@@ -72,6 +72,20 @@
this.annotationProviders = annotationProviders;
}
+ @Override
+ public IOHandler getCopyHandler(File from, File to) {
+ IOHandler retValue = null;
+ for (Iterator it = annotationProviders.iterator(); it.hasNext() && retValue == null;) {
+ AnnotationProvider provider = (AnnotationProvider) it.next();
+ final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null;
+ if (iListener instanceof ProvidedExtensions) {
+ ProvidedExtensions.IOHandler delgate = ((ProvidedExtensions)iListener).getCopyHandler(from, to);
+ retValue = delgate != null ? new DelegatingIOHandler(delgate) : null;
+ }
+ }
+ return retValue;
+ }
+
public ProvidedExtensions.DeleteHandler getDeleteHandler(final File f) {
ProvidedExtensions.DeleteHandler retValue = null;
for (Iterator it = annotationProviders.iterator(); it.hasNext() && retValue == null;) {
@@ -386,6 +400,51 @@
}
}
+ @Override
+ public void beforeCopy(final FileObject from, final File to) {
+ for (Iterator it = annotationProviders.iterator(); it.hasNext();) {
+ AnnotationProvider provider = (AnnotationProvider) it.next();
+ final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null;
+ if (iListener instanceof ProvidedExtensions) {
+ runCheckCode(new Runnable() {
+ public void run() {
+ ((ProvidedExtensions)iListener).beforeCopy(from, to);
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void copySuccess(final FileObject from, final File to) {
+ for (Iterator it = annotationProviders.iterator(); it.hasNext();) {
+ AnnotationProvider provider = (AnnotationProvider) it.next();
+ final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null;
+ if (iListener instanceof ProvidedExtensions) {
+ runCheckCode(new Runnable() {
+ public void run() {
+ ((ProvidedExtensions)iListener).copySuccess(from, to);
+ }
+ });
+ }
+ }
+ }
+
+ @Override
+ public void copyFailure(final FileObject from, final File to) {
+ for (Iterator it = annotationProviders.iterator(); it.hasNext();) {
+ AnnotationProvider provider = (AnnotationProvider) it.next();
+ final InterceptionListener iListener = (provider != null) ? provider.getInterceptionListener() : null;
+ if (iListener instanceof ProvidedExtensions) {
+ runCheckCode(new Runnable() {
+ public void run() {
+ ((ProvidedExtensions)iListener).copyFailure(from, to);
+ }
+ });
+ }
+ }
+ }
+
public static void checkReentrancy() {
if (reentrantCheck.get() != null) {
Logger.getLogger("org.netbeans.modules.masterfs.ProvidedExtensionsProxy").log(Level.INFO,"Unexpected reentrant call", new Throwable());//NOI18N
Index: masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/BaseFileObj.java
--- masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/BaseFileObj.java Base (BASE)
+++ masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/BaseFileObj.java Locally Modified (Based On LOCAL)
@@ -214,10 +214,43 @@
}
@Override
+ public FileObject copy(FileObject target, String name, String ext) throws IOException {
+ ProvidedExtensions extensions = getProvidedExtensions();
+
+ File to = getToFile(target, name, ext);
+
+ extensions.beforeCopy(target, to);
+ FileObject result = null;
+ try {
+ final IOHandler copyHandler = extensions.getCopyHandler(getFileName().getFile(), to);
+ if (copyHandler != null) {
+ if (target instanceof FolderObj) {
+ result = handleMoveCopy((FolderObj)target, name, ext, copyHandler);
+ } else {
+ copyHandler.handle();
+ refresh(true);
+ //perfromance bottleneck to call refresh on folder
+ //(especially for many files to be copied)
+ target.refresh(true); // XXX ?
+ result = target.getFileObject(name, ext); // XXX ?
+ assert result != null : "Cannot find " + target + " with " + name + "." + ext;
+ }
+ FileUtil.copyAttributes(this, result);
+ } else {
+ result = super.copy(target, name, ext);
+ }
+ } catch (IOException ioe) {
+ extensions.copyFailure(this, to);
+ throw ioe;
+ }
+ extensions.copySuccess(this, to);
+ return result;
+ }
+
+ @Override
public final FileObject move(FileLock lock, FileObject target, String name, String ext) throws IOException {
ProvidedExtensions extensions = getProvidedExtensions();
- File to = (target instanceof FolderObj) ? new File(((BaseFileObj) target).getFileName().getFile(), FileInfo.composeName(name, ext)) :
- new File(FileUtil.toFile(target), FileInfo.composeName(name, ext));
+ File to = getToFile(target, name, ext);
extensions.beforeMove(this, to);
FileObject result = null;
@@ -253,8 +286,17 @@
}
public BaseFileObj move(FileLock lock, FolderObj target, String name, String ext, ProvidedExtensions.IOHandler moveHandler) throws IOException {
- moveHandler.handle();
- String nameExt = FileInfo.composeName(name,ext);
+ return handleMoveCopy(target, name, ext, moveHandler);
+ }
+
+ private File getToFile(FileObject target, String name, String ext) {
+ File to = (target instanceof FolderObj) ? new File(((BaseFileObj) target).getFileName().getFile(), FileInfo.composeName(name, ext)) : new File(FileUtil.toFile(target), FileInfo.composeName(name, ext));
+ return to;
+ }
+
+ private BaseFileObj handleMoveCopy(FolderObj target, String name, String ext, IOHandler handler) throws IOException {
+ handler.handle();
+ String nameExt = FileInfo.composeName(name, ext);
target.getChildrenCache().getChild(nameExt, true);
//TODO: review
BaseFileObj result = null;
@@ -268,9 +310,7 @@
result.fireFileFolderCreatedEvent(false);
}
break;
- }
- // #179109 - result is sometimes null, probably when moved file
- // is not yet ready. We wait max. 1000 ms.
+ } // is not yet ready. We wait max. 1000 ms.
try {
Thread.sleep(100);
} catch (InterruptedException ex) {
@@ -288,7 +328,6 @@
return result;
}
-
void rename(final FileLock lock, final String name, final String ext, final ProvidedExtensions.IOHandler handler) throws IOException {
if (!checkLock(lock)) {
FSException.io("EXC_InvalidLock", lock, getPath()); // NOI18N
Index: masterfs/src/org/netbeans/modules/masterfs/providers/ProvidedExtensions.java
--- masterfs/src/org/netbeans/modules/masterfs/providers/ProvidedExtensions.java Base (BASE)
+++ masterfs/src/org/netbeans/modules/masterfs/providers/ProvidedExtensions.java Locally Modified (Based On LOCAL)
@@ -67,8 +67,26 @@
* @author Radek Matous
*/
public class ProvidedExtensions implements InterceptionListener {
+
/**
* Return instance of {@link ProvidedExtensions.IOHandler}
+ * that is responsible for copying the file or null.
+ *
+ * Just the first non null instance of IOHandler
is used by
+ * MasterFileSystem
+ *
+ * @param from file to be copied
+ * @param to target to copy this file to
+ * @return instance of {@link ProvidedExtensions.IOHandler}
+ * that is responsible for copying the file or null
+ */
+ public ProvidedExtensions.IOHandler getCopyHandler(
+ File from, File to) {
+ return null;
+ }
+
+ /**
+ * Return instance of {@link ProvidedExtensions.IOHandler}
* that is responsible for moving the file or null.
*
* Just the first non null instance of IOHandler
is used by
@@ -170,6 +188,33 @@
/**
* Called by MasterFileSystem
before FileObject
+ * is copied
+ * @param from FileObject to be moved
+ * @param to File target to move this file to
+ * @since 2.28
+ */
+ public void beforeCopy(FileObject from, File to) {}
+
+ /**
+ * Called by MasterFileSystem
after FileObject
+ * was successfully copied
+ * @param from FileObject to be moved
+ * @param to File target to move this file to
+ * @since 2.28
+ */
+ public void copySuccess(FileObject from, File to) {}
+
+ /**
+ * Called by MasterFileSystem
after a FileObject
+ * copy failed
+ * @param from FileObject to be moved
+ * @param to File target to move this file to
+ * @since 2.28
+ */
+ public void copyFailure(FileObject from, File to) {}
+
+ /**
+ * Called by MasterFileSystem
before FileObject
* is moved
* @param from FileObject to be moved
* @param to File target to move this file to
Index: masterfs/test/unit/src/org/netbeans/modules/masterfs/providers/ProvidedExtensionsTest.java
--- masterfs/test/unit/src/org/netbeans/modules/masterfs/providers/ProvidedExtensionsTest.java Base (BASE)
+++ masterfs/test/unit/src/org/netbeans/modules/masterfs/providers/ProvidedExtensionsTest.java Locally Modified (Based On LOCAL)
@@ -336,6 +336,42 @@
}
}
+ public void testCopy_BeforeSuccessFailure() throws IOException {
+ FileObject fromFolder = FileUtil.toFileObject(getWorkDir()).createFolder("copyFrom");
+ FileObject toFolder = FileUtil.toFileObject(getWorkDir()).createFolder("copyTo");
+ assertNotNull(fromFolder);
+ assertNotNull(toFolder);
+ FileObject fromCopy = fromFolder.createData("aa");
+ assertNotNull(fromCopy);
+ iListener.clear();
+
+ assertNotNull(iListener);
+ assertEquals(0,iListener.beforeCopyCalls);
+ assertEquals(0,iListener.copySuccessCalls);
+ assertEquals(0,iListener.copyFailureCalls);
+
+ // copy
+ fromCopy.copy(toFolder, fromCopy.getName(), fromCopy.getExt());
+ assertTrue(fromCopy.isValid());
+ assertEquals(1,iListener.beforeCopyCalls);
+ assertEquals(1,iListener.copySuccessCalls);
+
+ iListener.clear();
+ try {
+ // success
+ assertEquals(0,iListener.copySuccessCalls);
+ assertEquals(0,iListener.copyFailureCalls);
+
+ // move to itself => failure
+ fromCopy.copy(toFolder, fromCopy.getName(), fromCopy.getExt());
+ fail();
+ } catch (IOException ex) {
+ // failure
+ assertEquals(0,iListener.copySuccessCalls);
+ assertEquals(1,iListener.copyFailureCalls);
+ }
+ }
+
public void testImplsRename2() throws IOException {
final List events = new ArrayList();
FileObject fo = FileUtil.toFileObject(getWorkDir());
@@ -559,6 +595,9 @@
private int beforeMoveCalls;
private int moveSuccessCalls;
private int moveFailureCalls;
+ private int beforeCopyCalls;
+ private int copySuccessCalls;
+ private int copyFailureCalls;
private static boolean implsMoveRetVal = true;
private static boolean implsRenameRetVal = true;
@@ -600,6 +639,9 @@
beforeMoveCalls = 0;
moveSuccessCalls = 0;
moveFailureCalls = 0;
+ beforeCopyCalls = 0;
+ copySuccessCalls = 0;
+ copyFailureCalls = 0;
implsFileLockCalls = 0;
implsCanWriteCalls = 0;
}
@@ -659,6 +701,18 @@
moveFailureCalls++;
}
+ public void beforeCopy(FileObject fo, File to) {
+ beforeCopyCalls++;
+ }
+
+ public void copySuccess(FileObject fo, File to) {
+ copySuccessCalls++;
+ }
+
+ public void copyFailure(FileObject fo, File to) {
+ copyFailureCalls++;
+ }
+
public static void nextRefreshCall(File forDir, long retValue, File... toAdd) {
refreshCallForDir = forDir;
refreshCallRetValue = retValue;