This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 40739
Collapse All | Expand All

(-)a/openide.filesystems/apichanges.xml (+17 lines)
Lines 49-54 Link Here
49
        <apidef name="filesystems">Filesystems API</apidef>
49
        <apidef name="filesystems">Filesystems API</apidef>
50
    </apidefs>
50
    </apidefs>
51
    <changes>
51
    <changes>
52
        <change id="createAndOpen">
53
            <api name="filesystems"/>
54
            <summary>FileObject.createAndOpen</summary>
55
            <version major="7" minor="40"/>
56
            <date day="10" month="9" year="2010"/>
57
            <author login="jtulach"/>
58
            <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
59
            <description>
60
                <p>
61
                Create a file and write its content (almost) atomically using the new
62
                <a href="@TOP@/org/openide/filesystems/FileObject.html#createAndOpen(java.lang.String)">FileObject.createAndOpen</a>
63
                method.
64
                </p>
65
            </description>
66
            <class package="org.openide.filesystems" name="FileObject"/>
67
            <issue number="40739"/>
68
        </change>
52
        <change id="addRecursiveListenerStop">
69
        <change id="addRecursiveListenerStop">
53
            <api name="filesystems"/>
70
            <api name="filesystems"/>
54
            <summary>Interruptable addRecursiveListener</summary>
71
            <summary>Interruptable addRecursiveListener</summary>
(-)a/openide.filesystems/manifest.mf (-1 / +1 lines)
Lines 2-6 Link Here
2
OpenIDE-Module: org.openide.filesystems
2
OpenIDE-Module: org.openide.filesystems
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
5
OpenIDE-Module-Specification-Version: 7.39
5
OpenIDE-Module-Specification-Version: 7.40
6
6
(-)a/openide.filesystems/src/org/openide/filesystems/FileEvent.java (+5 lines)
Lines 226-231 Link Here
226
            if (atomicAction != null && atomicAction.getClass().getName().indexOf("AsyncRefreshAtomicAction") != -1) {
226
            if (atomicAction != null && atomicAction.getClass().getName().indexOf("AsyncRefreshAtomicAction") != -1) {
227
                return true;
227
                return true;
228
            }
228
            }
229
            if (atomicAction instanceof FileSystem.AsyncAtomicAction) {
230
                if (((FileSystem.AsyncAtomicAction)atomicAction).isAsynchronous()) {
231
                    return true;
232
                }
233
            }
229
            currentPropID = currentPropID.getPreviousLink();
234
            currentPropID = currentPropID.getPreviousLink();
230
        }
235
        }
231
236
(-)a/openide.filesystems/src/org/openide/filesystems/FileObject.java (+47 lines)
Lines 883-888 Link Here
883
    public FileObject createData(String name) throws IOException {
883
    public FileObject createData(String name) throws IOException {
884
        return createData(name, ""); // NOI18N        
884
        return createData(name, ""); // NOI18N        
885
    }
885
    }
886
    
887
    /** 
888
     * Creates new file in this folder and immediately opens it for writing.
889
     * This method prevents possible race condition which can happen
890
     * when using the {@link #createData(java.lang.String)} method.  
891
     * Using {@link #createData(java.lang.String) that method} makes it
892
     * possible for someone to read the content of the newly created
893
     * file before its content is written. This method does its best to eliminate
894
     * such race condition.
895
     * 
896
     * <p class="nonnormative">
897
     * This method usually delivers both, {@link FileChangeListener#fileDataCreated(org.openide.filesystems.FileEvent) data created}
898
     * and {@link FileChangeListener#fileChanged(org.openide.filesystems.FileEvent) changed} 
899
     * events. Preferably it delivers them asynchronously. The assumption
900
     * is that the file will be (at least partially) written before
901
     * the listeners start to process the first event. The safety is additionally
902
     * ensured by <q>mutual exclusion</q> between output and input streams 
903
     * for the same file (any call to {@link #getInputStream()} will be blocked
904
     * for at least two seconds if there is existing open output stream). 
905
     * If you finish writing the content of your file in those two seconds,
906
     * you can be sure, nobody will have read its content yet.
907
     * </p>
908
     * 
909
     * @param name name of file to create with its extension
910
     * @return output stream to use to write content of the file
911
     * @throws IOException if the file cannot be created (e.g. already exists), or if <code>this</code> is not a folder
912
     * @since 7.40
913
     */
914
    public OutputStream createAndOpen(final String name) throws IOException {
915
        class R implements FileSystem.AsyncAtomicAction {
916
            OutputStream os;
917
            
918
            @Override
919
            public void run() throws IOException {
920
                FileObject fo = createData(name);
921
                os = fo.getOutputStream();
922
            }
923
924
            @Override
925
            public boolean isAsynchronous() {
926
                return true;
927
            }
928
        }
929
        R r = new R();
930
        getFileSystem().runAtomicAction(r);
931
        return r.os;
932
    }
886
933
887
    /** Test whether this file can be written to or not.
934
    /** Test whether this file can be written to or not.
888
     * <P>
935
     * <P>
(-)a/openide.filesystems/src/org/openide/filesystems/FileSystem.java (+4 lines)
Lines 841-846 Link Here
841
        */
841
        */
842
        public void run() throws IOException;
842
        public void run() throws IOException;
843
    }
843
    }
844
    
845
    static interface AsyncAtomicAction extends AtomicAction {
846
        boolean isAsynchronous();
847
    }
844
848
845
    /** Allows a filesystem to annotate a group of files (typically comprising a data object) with additional markers.
849
    /** Allows a filesystem to annotate a group of files (typically comprising a data object) with additional markers.
846
     * <p>This could be useful, for
850
     * <p>This could be useful, for
(-)a/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java (+70 lines)
Lines 324-329 Link Here
324
        value.equals((String)fo3.getAttribute(attrName)) );
324
        value.equals((String)fo3.getAttribute(attrName)) );
325
        fileDataCreatedAssert("parent should fire fileDataCreated",1);
325
        fileDataCreatedAssert("parent should fire fileDataCreated",1);
326
    }
326
    }
327
328
    public void  testCreateAndOpen() throws Exception {
329
        checkSetUp();
330
        FileObject f;
331
        try {
332
            f = getTestFolder1(root).createFolder("createAndOpen");
333
        } catch (IOException iex) {
334
            fsAssert("If read only FS, then OK to fail",
335
            fs.isReadOnly());
336
            return;
337
        }
338
        final FileObject fold = f;
339
        
340
        class L extends FileChangeAdapter {
341
            String dataCreated;
342
            String changed;
343
344
            @Override
345
            public synchronized void fileDataCreated(FileEvent fe) {
346
                try {
347
                    FileObject ch = fold.getFileObject("child.txt");
348
                    assertNotNull("Child found", ch);
349
                    
350
                    dataCreated = ch.asText();
351
                    notifyAll();
352
                } catch (IOException ex) {
353
                    throw new IllegalStateException(ex);
354
                }
355
            }
356
357
            @Override
358
            public synchronized void fileChanged(FileEvent fe) {
359
                try {
360
                    FileObject ch = fold.getFileObject("child.txt");
361
                    assertNotNull("Child found", ch);
362
363
                    changed = ch.asText();
364
                    notifyAll();
365
                } catch (IOException ex) {
366
                    throw new IllegalStateException(ex);
367
                }
368
            }
369
            
370
371
            public synchronized void waitEvents() throws InterruptedException {
372
                for (int i = 0; i < 100; i++) {
373
                    if (changed != null && dataCreated != null) {
374
                        break;
375
                    }
376
                    wait(100);
377
                }
378
            }
379
        }
380
381
        L l = new L();
382
        fold.addFileChangeListener(l);
383
        assertEquals("No children", 0, fold.getChildren().length);
384
        
385
        OutputStream os = fold.createAndOpen("child.txt");
386
        os.write("Ahoj".getBytes());
387
        os.close();
388
        
389
        FileObject ch = fold.getFileObject("child.txt");
390
        assertNotNull("Child found", ch);
391
        assertEquals("Right content now", "Ahoj", ch.asText());
392
        
393
        l.waitEvents();
394
        assertEquals("Right content when changed", "Ahoj", l.changed);
395
        assertEquals("Right content when created", "Ahoj", l.dataCreated);
396
    }
327
    
397
    
328
    /** Test of copy method, of class org.openide.filesystems.FileObject. */
398
    /** Test of copy method, of class org.openide.filesystems.FileObject. */
329
    public void  testCopy1_FS() throws IOException {
399
    public void  testCopy1_FS() throws IOException {

Return to bug 40739