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.
In order to fully exploit the benefits of mutual stream exclussion when issue 40738 is implemented there is a need for another small improvement. The issue 40738 solves problems with reading improper content of a file when it is being written, but there is often a chance that one could read a file before it is being written to. Right now one can create new data file: FileObject fo = FileUtil.createData (...); and only then can lock the file and obtain the output stream: fo.getOutputStream (fo.getLock ()); during this time another object can grab the stream and try to read from this, not yet initialize file. In order to solve this an API extension is proposed: final class FileUtil.OpenedHandle { public final FileObject file; public final FileLock lock; public final OutputStream os; } OpenedHandle FileUtil.createOpenedData (...); that would create a data file, locked it and returned an output stream to write to it. The file created event should probably be fired only after the stream is closed. If clients used this method, they could safely assume that no other part of infrastructure is reading their files prior they are fully finished.
BTW suggest that FileUtil be reserved for convenience methods and that the proposed class be put elsewhere. Seems like this and issue #40738 are just special cases of the need for a proper threading model (and lock system) for Filesystems. IMHO we could probably just synchronize all Filesystems methods on a single lock and get reasonable performance and a much simpler API and impl, for example.
-> future, not for D of course
Reassigning to new module owner jskrivanek.
If this shall be implemented then I suggest: FileUtil.createAndOpen(..., AtomicReference<FileObject> file, AtomicReference<FileLock> lock, AtomicReference<OutputStream> os); but unless really needed, there is no big reason to implement this method nobody is going to use in near future.
A simpler signature would be something like public final OutputStream [FileObject.]createAndOpen(String child); e.g. Document doc = ...; FileObject folder = ...; OutputStream os = folder.createAndOpen("newfile.xml"); try { XMLUtil.write(doc, os, "UTF-8"); } finally { os.close(); } This would be used quite widely, I think. Currently you have to not only create the new FileObject as a separate step, but also wrap the whole block in an AtomicAction, which is rather clumsy. This pattern (sometimes forgetting the AtomicAction) is repeated many times throughout project system code.
Sounds much better.
Is there an easy way to ensure that the FileCreatedEvent is fired only after OutputStream.close() is called? Wrapping the body of createAndOpen in an AtomicAction of course will not suffice, since the stream is closed after this method returns. And just suppressing the FileCreatedEvent (permitting the FileModifiedEvent to be fired upon stream close) is not good since some listeners may be checking only for FCE. I suppose you could suppress the FCE during the body of the method, and then also set some internal flag so that stream close fires FCE rather than FME?
As soon as the getOutputStream is opened, nobody else is allowed to read file's content. So even if I do not manage to delay the FileCreated event, nobody shall have a chance get access to unfinished data. I'll do this for next release.
Created attachment 101855 [details] FileObject.createAndOpen and impl and test
I'll integrate tomorrow.
core-main#c04673028299
Integrated into 'main-golden', will be available in build *201009110000* on http://bits.netbeans.org/dev/nightly/ (upload may still be in progress) Changeset: http://hg.netbeans.org/main/rev/c04673028299 User: Jaroslav Tulach <jtulach@netbeans.org> Log: #40739: FileObject.createAndOpen