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 26338
Collapse All | Expand All

(-)openide/arch/arch-openide-filesystems.xml (-1 / +350 lines)
Lines 22-28 Link Here
22
]>
22
]>
23
23
24
<api-answers
24
<api-answers
25
  question-version="1.12"
25
  question-version="1.29"
26
  author="rmatous@netbeans.org"
26
  author="rmatous@netbeans.org"
27
>
27
>
28
28
Lines 718-722 Link Here
718
<answer id="resources-read">
718
<answer id="resources-read">
719
No.
719
No.
720
</answer>
720
</answer>
721
722
723
724
725
<!--
726
        <question id="arch-overall" when="init">
727
            Describe the overall architecture. 
728
            <hint>
729
            What will be API for 
730
            <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi" shape="rect">
731
                clients and what support API</a>? 
732
            What parts will be pluggable?
733
            How will plug-ins be registered? Please use <code>&lt;api type="export"/&gt;</code>
734
            to describe your general APIs and specify their
735
            <a href="http://openide.netbeans.org/tutorial/api-design.html#category-private" shape="rect">
736
            stability categories</a>.
737
            If possible please provide simple diagrams.
738
            </hint>
739
        </question>
740
-->
741
 <answer id="arch-overall">
742
  <p>
743
   NetBeans internally uses the concept of a virtual filesystem. This module
744
   provide APIs for accessing such virtual files as well as some support classes
745
   to make writing of custom vitual filesystems easier.
746
  </p>
747
 </answer>
748
749
750
751
<!--
752
        <question id="arch-quality" when="init">
753
            How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html" shape="rect">quality</a>
754
            of your code be tested and 
755
            how are future regressions going to be prevented?
756
            <hint>
757
            What kind of testing do
758
            you want to use? How much functionality, in which areas,
759
            should be covered by the tests? How you find out that your
760
            project was successful?
761
            </hint>
762
        </question>
763
-->
764
 <answer id="arch-quality">
765
  <p>
766
   XXX no answer for arch-quality
767
  </p>
768
 </answer>
769
770
771
772
<!--
773
        <question id="arch-time" when="init">
774
            What are the time estimates of the work?
775
            <hint>
776
            Please express your estimates of how long the design, implementation,
777
            stabilization are likely to last. How many people will be needed to
778
            implement this and what is the expected milestone by which the work should be 
779
            ready?
780
            </hint>
781
        </question>
782
-->
783
 <answer id="arch-time">
784
  <p>
785
   XXX no answer for arch-time
786
  </p>
787
 </answer>
788
789
790
791
<!--
792
        <question id="arch-usecases" when="init">
793
            <hint>
794
                Content of this answer will be displayed as part of page at
795
                http://www.netbeans.org/download/dev/javadoc/usecases.html 
796
                You can use tags &lt;usecase name="name&gt; regular html description &lt;/usecase&gt;
797
                and if you want to use an URL you can prefix if with @TOP@ to begin
798
                at the root of your javadoc
799
            </hint>
800
        
801
            Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase" shape="rect">
802
            use cases</a> of the new API. Who will use it under
803
            what circumstances? What kind of code would typically need to be written
804
            to use the module?
805
        </question>
806
-->
807
 <answer id="arch-usecases">
808
  <p>
809
   Many of the usecases are described at the
810
   <a href="@TOP@/org/openide/filesystems/doc-files/api.html">overall documentation</a>,
811
   in a way how to 
812
   <a href="@TOP@/org/openide/filesystems/doc-files/HOWTO-MIME.html">register a mime type</a>.
813
   Some of the additional usecases are covered here.
814
  </p>
815
  
816
  <usecase id="login-changes" name="How to change menus, etc. after login?">
817
      <p>
818
      Since version 7.1 there is a way to change the content of system file
819
      system in a dynamic way. As system file systems contains various 
820
      definitions (in NetBeans Platform menus, toolbars, layout of windows, etc.)
821
      it de-facto allows global change to these settings for example when
822
      user logs into some system.
823
      </p>
824
      
825
      <p>
826
          First thing to do is to create an implementation of filesystem.
827
          It can be created either from scratch, or by subclassing
828
          <a href="@TOP@/org/openide/filesystems/AbstractFileSystem.html">AbstractFileSystem</a>,
829
          or
830
          <a href="@TOP@/org/openide/filesystems/MultiFileSystem.html">MultiFileSystem</a>.
831
          In this example we will subclass the 
832
          <a href="@TOP@/org/openide/filesystems/MultiFileSystem.html">MultiFileSystem</a>:
833
      </p>
834
      
835
      <pre>
836
public class LoginFileSystem extends <a href="@TOP@/org/openide/filesystems/MultiFileSystem.html">MultiFileSystem</a> {
837
  public LoginFileSystem() {
838
    // let's create the filesystem empty, because the user
839
    // is not yet logged in
840
    super(new FileSystem[0]);
841
  }
842
  
843
  public static void assignURL(URL u) {
844
    LoginFileSystem lfs = <a href="@org-openide-util@/org/openide/util/Lookup.html">Lookup</a>.getDefault().lookup(LoginFileSystem.class);
845
    <a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">XMLFileSystem</a> xmlFS = new <a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">XMLFileSystem</a>(u);
846
    lfs.setDelegates(new FileSystem[] { xmlFS });
847
  }
848
}
849
      </pre>
850
      
851
      <p>
852
      It is necessary to register this instance in lookup by creating two files:
853
      </p>
854
      <ul>
855
          <li><code>META-INF/services/org.openide.filesystems.FileSystem</code></li>
856
          <li><code>META-INF/services/your.module.LoginFileSystem</code></li>
857
      </ul>
858
      <p>
859
          and filling these files with a single line containing the full
860
          name of your filesystem - e.g. <code>your.module.LoginFileSystem</code>.
861
          When done, the system will find out your registration of the filesystem
862
          on startup and will merge the content of the filesystem into the 
863
          default system file system. You can show a dialog letting the user
864
          to log in to some system anytime later, and when the user is successfully
865
          in, just call <code>LoginFileSystem.assignURL(url)</code> where the
866
          URL is an XML file in <a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">the same format</a>
867
          as used for regular layer files inside of many NetBeans modules.
868
          The system will notice the change in the content and notify all the
869
          config file listeners accordingly.
870
      </p>
871
      
872
      <p>
873
          Of course, instead of 
874
          <a href="@TOP@/org/openide/filesystems/XMLFileSystem.html">XMLFileSystem</a>
875
          you can use for example
876
          <a href="@TOP@/org/openide/filesystems/FileUtil.html#createMemoryFileSystem()">memory file system</a>,
877
          or any other you write yourself.
878
      </p>
879
  </usecase>
880
 </answer>
881
882
883
884
<!--
885
        <question id="arch-where" when="impl">
886
            Where one can find sources for your module?
887
            <hint>
888
                Please provide link to the CVS web client at
889
                http://www.netbeans.org/download/source_browse.html
890
                or just use tag defaultanswer generate='here'
891
            </hint>
892
        </question>
893
-->
894
 <answer id="arch-where">
895
  <defaultanswer generate='here' />
896
 </answer>
897
898
899
900
<!--
901
        <question id="compat-deprecation" when="init">
902
            How the introduction of your project influences functionality
903
            provided by previous version of the product?
904
            <hint>
905
            If you are planning to deprecate/remove/change any existing APIs,
906
            list them here accompanied with the reason explaining why you
907
            are doing so.
908
            </hint>
909
        </question>
910
-->
911
 <answer id="compat-deprecation">
912
  <p>
913
   XXX no answer for compat-deprecation
914
  </p>
915
 </answer>
916
917
918
919
<!--
920
        <question id="deploy-dependencies" when="final">
921
            What do other modules need to do to declare a dependency on this one,
922
            in addition to or instead of the normal module dependency declaration
923
            (e.g. tokens to require)?
924
            <hint>
925
                Provide a sample of the actual lines you would add to a module manifest
926
                to declare a dependency, for example OpenIDE-Module-Requires: some.token.
927
                If other modules should not depend on this module, or should just use a
928
                simple regular module dependency, you can just answer "nothing". If you
929
                intentionally expose a semistable API to clients using implementation
930
                dependencies, you should mention that here (but there is no need to give
931
                an example of usage).
932
            </hint>
933
        </question>
934
-->
935
 <answer id="deploy-dependencies">
936
  <p>
937
   XXX no answer for deploy-dependencies
938
  </p>
939
 </answer>
940
941
942
943
<!--
944
        <question id="exec-ant-tasks" when="impl">
945
            Do you define or register any ant tasks that other can use?
946
            
947
            <hint>
948
            If you provide an ant task that users can use, you need to be very
949
            careful about its syntax and behaviour, as it most likely forms an
950
	          API for end users and as there is a lot of end users, their reaction
951
            when such API gets broken can be pretty strong.
952
            </hint>
953
        </question>
954
-->
955
 <answer id="exec-ant-tasks">
956
  <p>
957
   XXX no answer for exec-ant-tasks
958
  </p>
959
 </answer>
960
961
962
963
<!--
964
        <question id="exec-threading" when="init">
965
            What threading models, if any, does your module adhere to? How the
966
            project behaves with respect to threading?
967
            <hint>
968
                Is your API threadsafe? Can it be accessed from any threads or
969
                just from some dedicated ones? Any special relation to AWT and
970
                its Event Dispatch thread? Also
971
                if your module calls foreign APIs which have a specific threading model,
972
                indicate how you comply with the requirements for multithreaded access
973
                (synchronization, mutexes, etc.) applicable to those APIs.
974
                If your module defines any APIs, or has complex internal structures
975
                that might be used from multiple threads, declare how you protect
976
                data against concurrent access, race conditions, deadlocks, etc.,
977
                and whether such rules are enforced by runtime warnings, errors, assertions, etc.
978
                Examples: a class might be non-thread-safe (like Java Collections); might
979
                be fully thread-safe (internal locking); might require access through a mutex
980
                (and may or may not automatically acquire that mutex on behalf of a client method);
981
                might be able to run only in the event queue; etc.
982
                Also describe when any events are fired: synchronously, asynchronously, etc.
983
                Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations" shape="rect">Threading Recommendations</a> (in progress)
984
            </hint>
985
        </question>
986
-->
987
 <answer id="exec-threading">
988
  <p>
989
   XXX no answer for exec-threading
990
  </p>
991
 </answer>
992
993
994
995
<!--
996
        <question id="perf-spi" when="init">
997
            How the performance of the plugged in code will be enforced?
998
            <hint>
999
            If you allow foreign code to be plugged into your own module, how
1000
            do you enforce that it will behave correctly and quickly and will not
1001
            negatively influence the performance of your own module?
1002
            </hint>
1003
        </question>
1004
-->
1005
 <answer id="perf-spi">
1006
  <p>
1007
   XXX no answer for perf-spi
1008
  </p>
1009
 </answer>
1010
1011
1012
1013
<!--
1014
        <question id="resources-preferences" when="final">
1015
            Does your module uses preferences via Preferences API? Does your module use NbPreferences or
1016
            or regular JDK Preferences ? Does it read, write or both ? 
1017
            Does it share preferences with other modules ? If so, then why ?
1018
            <hint>
1019
                You may use
1020
                    &lt;api type="export" group="preferences"
1021
                    name="preference node name" category="private"&gt;
1022
                    description of individual keys, where it is used, what it
1023
                    influences, whether the module reads/write it, etc.
1024
                    &lt;/api&gt;
1025
                Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
1026
                Note that if you use NbPreferences this name will then be the same as the code name base of the module.
1027
            </hint>
1028
        </question>
1029
-->
1030
 <answer id="resources-preferences">
1031
  <p>
1032
   XXX no answer for resources-preferences
1033
  </p>
1034
 </answer>
1035
1036
1037
1038
<!--
1039
        <question id="security-grant" when="final">
1040
            Does your code grant additional rights to some other code?
1041
            <hint>Avoid using a class loader that adds extra
1042
            permissions to loaded code unless really necessary.
1043
            Also note that your API implementation
1044
            can also expose unneeded permissions to enemy code by
1045
            calling AccessController.doPrivileged().</hint>
1046
        </question>
1047
-->
1048
 <answer id="security-grant">
1049
  <p>
1050
   XXX no answer for security-grant
1051
  </p>
1052
 </answer>
1053
1054
1055
1056
<!--
1057
        <question id="security-policy" when="final">
1058
            Does your functionality require modifications to the standard policy file?
1059
            <hint>Your code might pass control to third-party code not
1060
            coming from trusted domains. This could be code downloaded over the
1061
            network or code coming from libraries that are not bundled
1062
            with NetBeans. Which permissions need to be granted to which domains?</hint>
1063
        </question>
1064
-->
1065
 <answer id="security-policy">
1066
  <p>
1067
   XXX no answer for security-policy
1068
  </p>
1069
 </answer>
721
1070
722
</api-answers>
1071
</api-answers>
(-)openide/fs/apichanges.xml (+22 lines)
Lines 23-28 Link Here
23
        <apidef name="filesystems">Filesystems API</apidef>
23
        <apidef name="filesystems">Filesystems API</apidef>
24
    </apidefs>
24
    </apidefs>
25
    <changes>
25
    <changes>
26
        <change id="add-content-to-sfs">
27
            <api name="filesystems"/>
28
            <summary>Allow modules to dynamically add/remove layer content</summary>
29
            <version major="7" minor="1"/>
30
            <date day="12" month="3" year="2007"/>
31
            <author login="jtulach"/>
32
            <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
33
            <description>
34
                <p>
35
                    Repository.getDefaultFileSystem's content can now be 
36
                    influenced by adding own 
37
                    <a href="@TOP@/org/openide/filesystems/FileSystem.html">FileSystem</a>s
38
                    into global 
39
                    <a href="@org-openide-util@/org/openide/util/Lookup.html">Lookup.getDefault()</a>.
40
                    This is supposed to work in a standalone mode as well 
41
                    as inside NetBeans Platform. The tutorial is available
42
                    in the <a href="@TOP@/architecture-summary.html#answer-arch-usecases">usecases section</a> of achitecture description.
43
                </p>
44
            </description>
45
            <class package="org.openide.filesystems" name="Repository"/>
46
            <issue number="26338"/>
47
        </change>
26
        <change id="createData-and-createFolder-take-File-as-parameter">
48
        <change id="createData-and-createFolder-take-File-as-parameter">
27
            <api name="filesystems"/>
49
            <api name="filesystems"/>
28
            <summary>Added additional methods <code>FileUtil.createData</code>
50
            <summary>Added additional methods <code>FileUtil.createData</code>
(-)openide/fs/manifest.mf (-1 / +1 lines)
Lines 1-5 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.openide.filesystems
2
OpenIDE-Module: org.openide.filesystems
3
OpenIDE-Module-Specification-Version: 7.0
3
OpenIDE-Module-Specification-Version: 7.1
4
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
4
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
5
5
(-)openide/fs/src/org/openide/filesystems/ExternalUtil.java (-1 / +28 lines)
Lines 18-27 Link Here
18
 */
18
 */
19
package org.openide.filesystems;
19
package org.openide.filesystems;
20
20
21
import java.util.ArrayList;
22
import java.util.List;
21
import java.util.logging.Level;
23
import java.util.logging.Level;
22
import java.util.logging.Logger;
24
import java.util.logging.Logger;
23
import org.openide.util.Exceptions;
25
import org.openide.util.Exceptions;
24
import org.openide.util.Lookup;
26
import org.openide.util.Lookup;
27
import org.openide.util.LookupEvent;
28
import org.openide.util.LookupListener;
25
29
26
30
27
/** Contains utility methods to deal with repository and error manager,
31
/** Contains utility methods to deal with repository and error manager,
Lines 120-126 Link Here
120
124
121
        if (repository == null) {
125
        if (repository == null) {
122
            // if not provided use default one
126
            // if not provided use default one
123
            repository = new Repository(FileUtil.createMemoryFileSystem());
127
            repository = new Repository(new MainFS());
124
        }
128
        }
125
    }
129
    }
130
    
131
    private static final class MainFS extends MultiFileSystem implements LookupListener {
132
        private static final Lookup.Result<FileSystem> ALL = Lookup.getDefault().lookupResult(FileSystem.class);
133
        private static final FileSystem MEMORY = FileUtil.createMemoryFileSystem();
134
        
135
        public MainFS() {
136
            super(computeDelegates());
137
            ALL.addLookupListener(this);
138
            resultChanged(null);
139
        }
140
        
141
        private static FileSystem[] computeDelegates() {
142
            List<FileSystem> arr = new ArrayList<FileSystem>();
143
            arr.add(MEMORY);
144
            arr.addAll(ALL.allInstances());
145
            return arr.toArray(new FileSystem[0]);
146
        }
147
        
148
    
149
        public void resultChanged(LookupEvent ev) {
150
            setDelegates(computeDelegates());
151
        }
152
    } // end of MainFS
126
}
153
}
(-)core/startup/src/org/netbeans/core/startup/layers/SystemFileSystem.java (-13 / +45 lines)
Lines 29-34 Link Here
29
import java.io.ObjectStreamException;
29
import java.io.ObjectStreamException;
30
import java.io.Serializable;
30
import java.io.Serializable;
31
import java.net.URL;
31
import java.net.URL;
32
import java.util.ArrayList;
33
import java.util.Arrays;
32
import java.util.HashSet;
34
import java.util.HashSet;
33
import java.util.Iterator;
35
import java.util.Iterator;
34
import java.util.MissingResourceException;
36
import java.util.MissingResourceException;
Lines 42-54 Link Here
42
import org.openide.filesystems.LocalFileSystem;
44
import org.openide.filesystems.LocalFileSystem;
43
import org.openide.filesystems.MultiFileSystem;
45
import org.openide.filesystems.MultiFileSystem;
44
import org.openide.filesystems.Repository;
46
import org.openide.filesystems.Repository;
47
import org.openide.util.Lookup;
45
import org.openide.util.NbBundle;
48
import org.openide.util.NbBundle;
46
49
47
/** The system FileSystem - represents system files under $NETBEANS_HOME/system.
50
/** The system FileSystem - represents system files under $NETBEANS_HOME/system.
48
*
51
*
49
* @author Jan Jancura, Ian Formanek, Petr Hamernik
52
* @author Jan Jancura, Ian Formanek, Petr Hamernik
50
*/
53
*/
51
public final class SystemFileSystem extends MultiFileSystem implements FileSystem.Status {
54
public final class SystemFileSystem extends MultiFileSystem 
55
implements FileSystem.Status, org.openide.util.LookupListener {
52
    // Must be public for BeanInfo to work: #11186.
56
    // Must be public for BeanInfo to work: #11186.
53
57
54
    /** generated Serialized Version UID */
58
    /** generated Serialized Version UID */
Lines 65-70 Link Here
65
    /** name of file attribute with URL to 32x32 color icon */
69
    /** name of file attribute with URL to 32x32 color icon */
66
    private static final String ATTR_ICON_32 = "SystemFileSystem.icon32"; // NOI18N
70
    private static final String ATTR_ICON_32 = "SystemFileSystem.icon32"; // NOI18N
67
71
72
    /** lookup result we listen on */
73
    private static Lookup.Result<FileSystem> result = Lookup.getDefault().lookupResult(FileSystem.class);
74
    /** the set of layers provided by the system */
75
    private static FileSystem[] layers;
76
68
    /** user fs */
77
    /** user fs */
69
    private ModuleLayeredFileSystem user;
78
    private ModuleLayeredFileSystem user;
70
    /** home fs */
79
    /** home fs */
Lines 73-85 Link Here
73
    /** @param fss list of file systems to delegate to
82
    /** @param fss list of file systems to delegate to
74
    */
83
    */
75
    @SuppressWarnings("deprecation")
84
    @SuppressWarnings("deprecation")
76
    private SystemFileSystem (FileSystem[] fss) throws PropertyVetoException {
85
    private SystemFileSystem() throws PropertyVetoException {
77
        super (fss);
86
        super(computeLayers());
78
        user = (ModuleLayeredFileSystem) fss[0];
87
        user = (ModuleLayeredFileSystem) layers[0];
79
        home = fss.length > 2 ? (ModuleLayeredFileSystem) fss[1] : null;
88
        home = layers.length > 2 ? (ModuleLayeredFileSystem) layers[1] : null;
80
89
        
81
        setSystemName (SYSTEM_NAME);
90
        setSystemName(SYSTEM_NAME);
82
        setHidden (true);
91
        setHidden(true);
92
        
93
        result.addLookupListener(this);
94
        resultChanged(null);
83
    }
95
    }
84
96
85
97
Lines 113-120 Link Here
113
            else
125
            else
114
                s.add (arr[i]);
126
                s.add (arr[i]);
115
127
128
        layers = (FileSystem[])arr.clone();
116
        // create own internal copy of passed filesystems
129
        // create own internal copy of passed filesystems
117
        setDelegates(arr.clone());
130
        setDelegates(computeLayers());
118
        firePropertyChange ("layers", null, null); // NOI18N
131
        firePropertyChange ("layers", null, null); // NOI18N
119
    }
132
    }
120
    
133
    
Lines 127-132 Link Here
127
        // don't return reference to internal buffer
140
        // don't return reference to internal buffer
128
        return getDelegates().clone();
141
        return getDelegates().clone();
129
    }
142
    }
143
    
144
    private synchronized static FileSystem[] computeLayers () {
145
        FileSystem[] fromLookup = (FileSystem[])result.allInstances ().toArray (new FileSystem[0]);
146
        
147
        if (fromLookup.length > 0) {
148
            ArrayList<FileSystem> arr = new ArrayList<FileSystem>(layers.length + fromLookup.length);
149
            arr.addAll (Arrays.asList (layers));
150
            arr.addAll (Arrays.asList (fromLookup));
151
            return (FileSystem[])arr.toArray (new FileSystem[0]);
152
        }
153
        
154
        return layers;
155
    }
130
156
131
    protected FileSystem createWritableOnForRename (String oldName, String newName) throws IOException {        
157
    protected FileSystem createWritableOnForRename (String oldName, String newName) throws IOException {        
132
        return createWritableOn (oldName);
158
        return createWritableOn (oldName);
Lines 280-286 Link Here
280
            ("org.netbeans.core.projects.FixedFileSystem", "Automatic Manifest Installation"); // NOI18N
306
            ("org.netbeans.core.projects.FixedFileSystem", "Automatic Manifest Installation"); // NOI18N
281
        arr[home == null ? 1 : 2] = FixedFileSystem.deflt;
307
        arr[home == null ? 1 : 2] = FixedFileSystem.deflt;
282
308
283
        return new SystemFileSystem (arr);
309
        layers = arr;
310
        return new SystemFileSystem ();
284
    }
311
    }
285
312
286
    /** Notification that a file has migrated from one file system
313
    /** Notification that a file has migrated from one file system
Lines 297-305 Link Here
297
    }
324
    }
298
325
299
    // --- SAFETY ---
326
    // --- SAFETY ---
300
    private Object writeReplace () throws ObjectStreamException {
327
    private Object writeReplace() throws ObjectStreamException {
301
        new NotSerializableException ("WARNING - SystemFileSystem is not designed to be serialized").printStackTrace (); // NOI18N
328
        new NotSerializableException("WARNING - SystemFileSystem is not designed to be serialized").printStackTrace(); // NOI18N
302
        return new SingletonSerializer ();
329
        return new SingletonSerializer();
330
    }
331
    
332
    /** Refresh layers */
333
    public synchronized void resultChanged(org.openide.util.LookupEvent ev) {
334
        setDelegates(computeLayers());
303
    }
335
    }
304
    
336
    
305
    private static final class SingletonSerializer extends Object implements Serializable {
337
    private static final class SingletonSerializer extends Object implements Serializable {

Return to bug 26338