DevFaqDynamicSystemFilesystem

(Difference between revisions)
m
(Using Dynamically Added Layers)
Line 11: Line 11:
At runtime, when you want to add contents to the system filesystem, simply add additional filesystems to your <code>MultiFileSystem</code>.  To remove the contents, simply remove those filesystems.
At runtime, when you want to add contents to the system filesystem, simply add additional filesystems to your <code>MultiFileSystem</code>.  To remove the contents, simply remove those filesystems.
-
A convenient way to do this is to use XMLFileSystem - this is a filesystem created with exactly the same syntax as [[DevFaqModulesLayerFile| normal module XML layer files]]. The following code loads an XML filesystem, which is in an XML file in the same package as the class, called <code>dynamicContent.xml</code>:
+
A convenient way to do this is to use XMLFileSystem - this is a filesystem created with exactly the same syntax as normal module XML layer files (see [[DevFaqModulesLayerFile]]). The following code loads an XML filesystem, which is in an XML file in the same package as the class, called <code>dynamicContent.xml</code>:
<pre>
<pre>
-
@ServiceProvider (service=FileSystem.class)
+
@ServiceProvider(service=FileSystem.class)
public class DynamicLayerContent extends MultiFileSystem {
public class DynamicLayerContent extends MultiFileSystem {
     private static DynamicLayerContent INSTANCE;
     private static DynamicLayerContent INSTANCE;
     public DynamicLayerContent() {
     public DynamicLayerContent() {
-
         //will be created on startup, exactly once
+
         // will be created on startup, exactly once
         INSTANCE = this;
         INSTANCE = this;
 +
        setPropagateMasks(true); // permit *_hidden masks to be used
     }
     }
-
 
     static boolean hasContent() {
     static boolean hasContent() {
         return INSTANCE.getDelegates().length &gt; 0;
         return INSTANCE.getDelegates().length &gt; 0;
     }
     }
-
 
     static void enable() {
     static void enable() {
         if (!hasContent()) {
         if (!hasContent()) {
Line 31: Line 30:
                 INSTANCE.setDelegates(new XMLFileSystem(
                 INSTANCE.setDelegates(new XMLFileSystem(
                         DynamicLayerContent.class.getResource(
                         DynamicLayerContent.class.getResource(
-
                         &quot;dynamicContent.xml&quot;)));
+
                         "dynamicContent.xml")));
             } catch (SAXException ex) {
             } catch (SAXException ex) {
                 Exceptions.printStackTrace(ex);
                 Exceptions.printStackTrace(ex);
Line 37: Line 36:
         }
         }
     }
     }
-
 
     static void disable() {
     static void disable() {
-
         INSTANCE.setDelegates (new FileSystem[0]);
+
         INSTANCE.setDelegates();
     }
     }
}
}
Line 47: Line 45:
* If the new layer contents are fixed and known, but perhaps correspond to user roles which may be overlaid together, split up the functionality for each role into a separate XML file (hint: define an enum of roles, where each role can point to an XML file URL, use <code>[http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumSet.html#of%28E,%20E...%29 EnumSet.of()]</code> and process that to decide what to enable)
* If the new layer contents are fixed and known, but perhaps correspond to user roles which may be overlaid together, split up the functionality for each role into a separate XML file (hint: define an enum of roles, where each role can point to an XML file URL, use <code>[http://java.sun.com/j2se/1.5.0/docs/api/java/util/EnumSet.html#of%28E,%20E...%29 EnumSet.of()]</code> and process that to decide what to enable)
* Write contents programmatically, but write folders/files to an in-memory filesystem created using <code>[http://bits.netbeans.org/dev/javadoc/org-openide-filesystems/org/openide/filesystems/FileUtil.html#createMemoryFileSystem() FileUtil.createMemoryFileSystem()]</code> so the contents disappear on VM exit
* Write contents programmatically, but write folders/files to an in-memory filesystem created using <code>[http://bits.netbeans.org/dev/javadoc/org-openide-filesystems/org/openide/filesystems/FileUtil.html#createMemoryFileSystem() FileUtil.createMemoryFileSystem()]</code> so the contents disappear on VM exit
-
 
-
''Note that as of NetBeans 6.8, you can use this technique to '''add''' contents to the system filesystem, but not to '''remove''' or mask files or folders (using <code>_hidden</code> in dynamic filesystem content will not work)''
 

Revision as of 22:07, 14 June 2010

Can I dynamically change the contents of the System Filesystem at runtime?

Yes. This technique is commonly used in platform applications which require the user to log in, to keep menu contents/toolbar actions/keyboard shortcuts/window definitions hidden until the user is authenticated.

There are two ways to do it. The most obvious way is to programmatically write files to disk at runtime (call FileUtil.getConfigRoot().createFolder(), etc.). This technique is appropriate if you are creating files which should be preserved across restarts (for example, adding folders to the Favorites window). It is completely inappropriate in the case of authentication, or any other case where you do not want the added files to be present after restart. You cannot depend on the application always being shut down normally and having a chance to clean such files up - since they are actually written to disk.

Using Dynamically Added Layers

The alternative is quite simple: Write a subclass of MultiFileSystem. Put it in the default lookup.

At runtime, when you want to add contents to the system filesystem, simply add additional filesystems to your MultiFileSystem. To remove the contents, simply remove those filesystems.

A convenient way to do this is to use XMLFileSystem - this is a filesystem created with exactly the same syntax as normal module XML layer files (see DevFaqModulesLayerFile). The following code loads an XML filesystem, which is in an XML file in the same package as the class, called dynamicContent.xml:

@ServiceProvider(service=FileSystem.class)
public class DynamicLayerContent extends MultiFileSystem {
    private static DynamicLayerContent INSTANCE;
    public DynamicLayerContent() {
        // will be created on startup, exactly once
        INSTANCE = this;
        setPropagateMasks(true); // permit *_hidden masks to be used
    }
    static boolean hasContent() {
        return INSTANCE.getDelegates().length > 0;
    }
    static void enable() {
        if (!hasContent()) {
            try {
                INSTANCE.setDelegates(new XMLFileSystem(
                        DynamicLayerContent.class.getResource(
                        "dynamicContent.xml")));
            } catch (SAXException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }
    static void disable() {
        INSTANCE.setDelegates();
    }
}

If finer grained control of what is added is needed at runtime, there are two possibilities, using this general approach:

  • If the new layer contents are fixed and known, but perhaps correspond to user roles which may be overlaid together, split up the functionality for each role into a separate XML file (hint: define an enum of roles, where each role can point to an XML file URL, use EnumSet.of() and process that to decide what to enable)
  • Write contents programmatically, but write folders/files to an in-memory filesystem created using FileUtil.createMemoryFileSystem() so the contents disappear on VM exit
Not logged in. Log in, Register

By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo