? openide/fs/test/unit/src/org/openide/filesystems/RepositoryTest.java Index: openide/arch/arch-openide-filesystems.xml =================================================================== RCS file: /shared/data/ccvs/repository/openide/arch/arch-openide-filesystems.xml,v retrieving revision 1.25 diff -u -r1.25 arch-openide-filesystems.xml --- openide/arch/arch-openide-filesystems.xml 15 Aug 2006 15:21:26 -0000 1.25 +++ openide/arch/arch-openide-filesystems.xml 7 Mar 2007 16:33:10 -0000 @@ -22,7 +22,7 @@ ]> @@ -718,5 +718,354 @@ No. + + + + + + +

+ NetBeans internally uses the concept of a virtual filesystem. This module + provide APIs for accessing such virtual files as well as some support classes + to make writing of custom vitual filesystems easier. +

+
+ + + + + +

+ XXX no answer for arch-quality +

+
+ + + + + +

+ XXX no answer for arch-time +

+
+ + + + + +

+ Many of the usecases are described at the + overall documentation, + in a way how to + register a mime type. + Some of the additional usecases are covered here. +

+ + +

+ Since version 7.1 there is a way to change the content of system file + system in a dynamic way. As system file systems contains various + definitions (in NetBeans Platform menus, toolbars, layout of windows, etc.) + it de-facto allows global change to these settings for example when + user logs into some system. +

+ +

+ First thing to do is to create an implementation of filesystem. + It can be created either from scratch, or by subclassing + AbstractFileSystem, + or + MultiFileSystem. + In this example we will subclass the + MultiFileSystem: +

+ +
+public class LoginFileSystem extends MultiFileSystem {
+  public LoginFileSystem() {
+    // let's create the filesystem empty, because the user
+    // is not yet logged in
+    super(new FileSystem[0]);
+  }
+  
+  public static void assignURL(URL u) {
+    LoginFileSystem lfs = Lookup.getDefault().lookup(LoginFileSystem.class);
+    XMLFileSystem xmlFS = new XMLFileSystem(u);
+    lfs.setDelegates(new FileSystem[] { xmlFS });
+  }
+}
+      
+ +

+ It is necessary to register this instance in lookup by creating two files: +

+
    +
  • META-INF/services/org.openide.filesystems.FileSystem
  • +
  • META-INF/services/your.module.LoginFileSystem
  • +
+

+ and filling these files with a single line containing the full + name of your filesystem - e.g. your.module.LoginFileSystem. + When done, the system will find out your registration of the filesystem + on startup and will merge the content of the filesystem into the + default system file system. You can show a dialog letting the user + to log in to some system anytime later, and when the user is successfully + in, just call LoginFileSystem.assignURL(url) where the + URL is an XML file in the same format + as used for regular layer files inside of many NetBeans modules. + The system will notice the change in the content and notify all the + config file listeners accordingly. +

+ +

+ Of course, instead of + XMLFileSystem + you can use for example + memory file system, + or any other you write yourself. +

+
+
+ + + + + + + + + + + + +

+ XXX no answer for compat-deprecation +

+
+ + + + + +

+ XXX no answer for deploy-dependencies +

+
+ + + + + +

+ XXX no answer for exec-ant-tasks +

+
+ + + + + +

+ XXX no answer for exec-threading +

+
+ + + + + +

+ XXX no answer for perf-spi +

+
+ + + + + +

+ XXX no answer for resources-preferences +

+
+ + + + + +

+ XXX no answer for security-grant +

+
+ + + + + +

+ XXX no answer for security-policy +

+
Index: openide/fs/apichanges.xml =================================================================== RCS file: /shared/data/ccvs/repository/openide/fs/apichanges.xml,v retrieving revision 1.11 diff -u -r1.11 apichanges.xml --- openide/fs/apichanges.xml 7 Sep 2006 08:43:36 -0000 1.11 +++ openide/fs/apichanges.xml 7 Mar 2007 16:33:11 -0000 @@ -23,6 +23,28 @@ Filesystems API + + + Allow modules to dynamically add/remove layer content + + + + + +

+ Repository.getDefaultFileSystem's content can now be + influenced by adding own + FileSystems + into global + Lookup.getDefault(). + This is supposed to work in a standalone mode as well + as inside NetBeans Platform. The tutorial is available + in the usecases section of achitecture description. +

+
+ + +
Added additional methods FileUtil.createData Index: openide/fs/manifest.mf =================================================================== RCS file: /shared/data/ccvs/repository/openide/fs/manifest.mf,v retrieving revision 1.8 diff -u -r1.8 manifest.mf --- openide/fs/manifest.mf 31 May 2006 15:42:10 -0000 1.8 +++ openide/fs/manifest.mf 7 Mar 2007 16:33:11 -0000 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.filesystems -OpenIDE-Module-Specification-Version: 7.0 +OpenIDE-Module-Specification-Version: 7.1 OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties Index: openide/fs/src/org/openide/filesystems/ExternalUtil.java =================================================================== RCS file: /shared/data/ccvs/repository/openide/fs/src/org/openide/filesystems/ExternalUtil.java,v retrieving revision 1.7 diff -u -r1.7 ExternalUtil.java --- openide/fs/src/org/openide/filesystems/ExternalUtil.java 28 Oct 2006 21:57:38 -0000 1.7 +++ openide/fs/src/org/openide/filesystems/ExternalUtil.java 7 Mar 2007 16:33:11 -0000 @@ -18,10 +18,14 @@ */ package org.openide.filesystems; +import java.util.ArrayList; +import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import org.openide.util.Exceptions; import org.openide.util.Lookup; +import org.openide.util.LookupEvent; +import org.openide.util.LookupListener; /** Contains utility methods to deal with repository and error manager, @@ -120,7 +124,30 @@ if (repository == null) { // if not provided use default one - repository = new Repository(FileUtil.createMemoryFileSystem()); + repository = new Repository(new MainFS()); } } + + private static final class MainFS extends MultiFileSystem implements LookupListener { + private static final Lookup.Result ALL = Lookup.getDefault().lookupResult(FileSystem.class); + private static final FileSystem MEMORY = FileUtil.createMemoryFileSystem(); + + public MainFS() { + super(computeDelegates()); + ALL.addLookupListener(this); + resultChanged(null); + } + + private static FileSystem[] computeDelegates() { + List arr = new ArrayList(); + arr.add(MEMORY); + arr.addAll(ALL.allInstances()); + return arr.toArray(new FileSystem[0]); + } + + + public void resultChanged(LookupEvent ev) { + setDelegates(computeDelegates()); + } + } // end of MainFS } Index: core/startup/src/org/netbeans/core/startup/layers/SystemFileSystem.java =================================================================== RCS file: /shared/data/ccvs/repository/core/startup/src/org/netbeans/core/startup/layers/SystemFileSystem.java,v retrieving revision 1.8 diff -u -r1.8 SystemFileSystem.java --- core/startup/src/org/netbeans/core/startup/layers/SystemFileSystem.java 3 Aug 2006 09:57:27 -0000 1.8 +++ core/startup/src/org/netbeans/core/startup/layers/SystemFileSystem.java 7 Mar 2007 16:33:12 -0000 @@ -29,6 +29,8 @@ import java.io.ObjectStreamException; import java.io.Serializable; import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.MissingResourceException; @@ -42,13 +44,15 @@ import org.openide.filesystems.LocalFileSystem; import org.openide.filesystems.MultiFileSystem; import org.openide.filesystems.Repository; +import org.openide.util.Lookup; import org.openide.util.NbBundle; /** The system FileSystem - represents system files under $NETBEANS_HOME/system. * * @author Jan Jancura, Ian Formanek, Petr Hamernik */ -public final class SystemFileSystem extends MultiFileSystem implements FileSystem.Status { +public final class SystemFileSystem extends MultiFileSystem +implements FileSystem.Status, org.openide.util.LookupListener { // Must be public for BeanInfo to work: #11186. /** generated Serialized Version UID */ @@ -65,6 +69,11 @@ /** name of file attribute with URL to 32x32 color icon */ private static final String ATTR_ICON_32 = "SystemFileSystem.icon32"; // NOI18N + /** lookup result we listen on */ + private static Lookup.Result result = Lookup.getDefault().lookupResult(FileSystem.class); + /** the set of layers provided by the system */ + private static FileSystem[] layers; + /** user fs */ private ModuleLayeredFileSystem user; /** home fs */ @@ -73,13 +82,16 @@ /** @param fss list of file systems to delegate to */ @SuppressWarnings("deprecation") - private SystemFileSystem (FileSystem[] fss) throws PropertyVetoException { - super (fss); - user = (ModuleLayeredFileSystem) fss[0]; - home = fss.length > 2 ? (ModuleLayeredFileSystem) fss[1] : null; - - setSystemName (SYSTEM_NAME); - setHidden (true); + private SystemFileSystem() throws PropertyVetoException { + super(computeLayers()); + user = (ModuleLayeredFileSystem) layers[0]; + home = layers.length > 2 ? (ModuleLayeredFileSystem) layers[1] : null; + + setSystemName(SYSTEM_NAME); + setHidden(true); + + result.addLookupListener(this); + resultChanged(null); } @@ -113,8 +125,9 @@ else s.add (arr[i]); + layers = (FileSystem[])arr.clone(); // create own internal copy of passed filesystems - setDelegates(arr.clone()); + setDelegates(computeLayers()); firePropertyChange ("layers", null, null); // NOI18N } @@ -127,6 +140,19 @@ // don't return reference to internal buffer return getDelegates().clone(); } + + private synchronized static FileSystem[] computeLayers () { + FileSystem[] fromLookup = (FileSystem[])result.allInstances ().toArray (new FileSystem[0]); + + if (fromLookup.length > 0) { + ArrayList arr = new ArrayList(layers.length + fromLookup.length); + arr.addAll (Arrays.asList (layers)); + arr.addAll (Arrays.asList (fromLookup)); + return (FileSystem[])arr.toArray (new FileSystem[0]); + } + + return layers; + } protected FileSystem createWritableOnForRename (String oldName, String newName) throws IOException { return createWritableOn (oldName); @@ -280,7 +306,8 @@ ("org.netbeans.core.projects.FixedFileSystem", "Automatic Manifest Installation"); // NOI18N arr[home == null ? 1 : 2] = FixedFileSystem.deflt; - return new SystemFileSystem (arr); + layers = arr; + return new SystemFileSystem (); } /** Notification that a file has migrated from one file system @@ -297,9 +324,14 @@ } // --- SAFETY --- - private Object writeReplace () throws ObjectStreamException { - new NotSerializableException ("WARNING - SystemFileSystem is not designed to be serialized").printStackTrace (); // NOI18N - return new SingletonSerializer (); + private Object writeReplace() throws ObjectStreamException { + new NotSerializableException("WARNING - SystemFileSystem is not designed to be serialized").printStackTrace(); // NOI18N + return new SingletonSerializer(); + } + + /** Refresh layers */ + public synchronized void resultChanged(org.openide.util.LookupEvent ev) { + setDelegates(computeLayers()); } private static final class SingletonSerializer extends Object implements Serializable {