~ubuntu-branches/ubuntu/trusty/netbeans/trusty

« back to all changes in this revision

Viewing changes to core/src/org/netbeans/core/DataSystem.java

  • Committer: Bazaar Package Importer
  • Author(s): Marek Slama
  • Date: 2008-01-29 14:11:22 UTC
  • Revision ID: james.westby@ubuntu.com-20080129141122-fnzjbo11ntghxfu7
Tags: upstream-6.0.1
ImportĀ upstreamĀ versionĀ 6.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 
3
 *
 
4
 * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
 
5
 *
 
6
 * The contents of this file are subject to the terms of either the GNU
 
7
 * General Public License Version 2 only ("GPL") or the Common
 
8
 * Development and Distribution License("CDDL") (collectively, the
 
9
 * "License"). You may not use this file except in compliance with the
 
10
 * License. You can obtain a copy of the License at
 
11
 * http://www.netbeans.org/cddl-gplv2.html
 
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 
13
 * specific language governing permissions and limitations under the
 
14
 * License.  When distributing the software, include this License Header
 
15
 * Notice in each file and include the License file at
 
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
 
17
 * particular file as subject to the "Classpath" exception as provided
 
18
 * by Sun in the GPL Version 2 section of the License file that
 
19
 * accompanied this code. If applicable, add the following below the
 
20
 * License Header, with the fields enclosed by brackets [] replaced by
 
21
 * your own identifying information:
 
22
 * "Portions Copyrighted [year] [name of copyright owner]"
 
23
 *
 
24
 * Contributor(s):
 
25
 *
 
26
 * The Original Software is NetBeans. The Initial Developer of the Original
 
27
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
 
28
 * Microsystems, Inc. All Rights Reserved.
 
29
 *
 
30
 * If you wish your version of this file to be governed by only the CDDL
 
31
 * or only the GPL Version 2, indicate your decision by adding
 
32
 * "[Contributor] elects to include this software in this distribution
 
33
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 
34
 * single choice of license, a recipient has the option to distribute
 
35
 * your version of this file under either the CDDL, the GPL Version 2 or
 
36
 * to extend the choice of license to its licensees as provided above.
 
37
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 
38
 * Version 2 license, then the option applies only if the new code is
 
39
 * made subject to such option by the copyright holder.
 
40
 */
 
41
 
 
42
package org.netbeans.core;
 
43
 
 
44
import java.beans.PropertyChangeEvent;
 
45
import java.beans.PropertyChangeListener;
 
46
import java.io.File;
 
47
import java.net.MalformedURLException;
 
48
import java.net.URL;
 
49
import java.util.ArrayList;
 
50
import java.util.Collection;
 
51
import java.util.Enumeration;
 
52
import java.util.Iterator;
 
53
import java.util.LinkedHashSet;
 
54
import java.util.Set;
 
55
import java.util.logging.Level;
 
56
import java.util.logging.Logger;
 
57
import javax.swing.Action;
 
58
import org.openide.filesystems.FileObject;
 
59
import org.openide.filesystems.FileStateInvalidException;
 
60
import org.openide.filesystems.FileSystem;
 
61
import org.openide.filesystems.Repository;
 
62
import org.openide.filesystems.RepositoryEvent;
 
63
import org.openide.filesystems.RepositoryListener;
 
64
import org.openide.filesystems.RepositoryReorderedEvent;
 
65
import org.openide.filesystems.URLMapper;
 
66
import org.openide.loaders.DataFilter;
 
67
import org.openide.loaders.DataFolder;
 
68
import org.openide.loaders.DataObject;
 
69
import org.openide.loaders.DataObjectNotFoundException;
 
70
import org.openide.loaders.InstanceSupport;
 
71
import org.openide.loaders.RepositoryNodeFactory;
 
72
import org.openide.nodes.AbstractNode;
 
73
import org.openide.nodes.Children;
 
74
import org.openide.nodes.FilterNode;
 
75
import org.openide.nodes.Node;
 
76
import org.openide.util.HelpCtx;
 
77
import org.openide.util.Lookup;
 
78
import org.openide.util.NbBundle;
 
79
import org.openide.util.WeakListeners;
 
80
import org.openide.util.actions.SystemAction;
 
81
 
 
82
/** Data system encapsulates logical structure of more file systems.
 
83
* It also allows filtering of content of DataFolders
 
84
*
 
85
* @author Jaroslav Tulach, Petr Hamernik
 
86
*/
 
87
public final class DataSystem extends AbstractNode 
 
88
implements RepositoryListener {
 
89
    /** default instance */
 
90
    private static DataSystem def;
 
91
 
 
92
    /** the file system pool to work with */
 
93
    private transient Repository fileSystemPool;
 
94
 
 
95
    /** filter for the data system */
 
96
    DataFilter filter;
 
97
 
 
98
    /** Constructor.
 
99
    * @param fsp file system pool
 
100
    * @param filter the filter for filtering files
 
101
    */
 
102
    private DataSystem(Children ch, Repository fsp, DataFilter filter) {
 
103
        super (ch);
 
104
        fileSystemPool = fsp;
 
105
        this.filter = filter;
 
106
        initialize();
 
107
        setIconBaseWithExtension ("org/netbeans/core/resources/repository.gif"); // NOI18N
 
108
        setName (NbBundle.getBundle (DataSystem.class).getString ("dataSystemName"));
 
109
        setShortDescription (NbBundle.getBundle (DataSystem.class).getString ("CTL_Repository_Hint"));
 
110
        getCookieSet ().add (new InstanceSupport.Instance (fsp));
 
111
    }
 
112
 
 
113
    /** Constructor. Uses default file system pool.
 
114
    * @param filter the filter to use
 
115
    */
 
116
    private DataSystem(Children ch, DataFilter filter) {
 
117
        this (ch, Repository.getDefault(), filter);
 
118
    }
 
119
 
 
120
    public HelpCtx getHelpCtx () {
 
121
        return new HelpCtx (DataSystem.class);
 
122
    }
 
123
 
 
124
    /** Factory for DataSystem instances */
 
125
    public static Node getDataSystem(DataFilter filter) {
 
126
        if (filter == null) {
 
127
            if (def != null) {
 
128
                return def;
 
129
            }
 
130
            return def = new DataSystem(new DSMap (), DataFilter.ALL);
 
131
        } else {
 
132
            return new DataSystem(new DSMap (), filter);
 
133
        }
 
134
    }
 
135
 
 
136
    /** Gets a DataSystem */
 
137
    public static Node getDataSystem() {
 
138
        return getDataSystem(null);
 
139
    }
 
140
 
 
141
    void initialize () {
 
142
        fileSystemPool.addRepositoryListener(WeakListeners.create(RepositoryListener.class,
 
143
                                                                  this,
 
144
                                                                  fileSystemPool));
 
145
        Enumeration en = fileSystemPool.getFileSystems ();
 
146
        while (en.hasMoreElements ()) {
 
147
            FileSystem fs = (FileSystem)en.nextElement ();
 
148
            fs.addPropertyChangeListener (org.openide.util.WeakListeners.propertyChange ((DSMap)getChildren (), fs));
 
149
        }
 
150
        refresh ();
 
151
    }
 
152
 
 
153
    /** writes this node to ObjectOutputStream and its display name
 
154
    */
 
155
    public Node.Handle getHandle() {
 
156
        return filter == DataFilter.ALL ? new DSHandle (null) : new DSHandle(filter);
 
157
    }
 
158
 
 
159
 
 
160
    public Action[] getActions(boolean context) {
 
161
        return new Action[] {
 
162
                   SystemAction.get (org.openide.actions.FindAction.class),
 
163
                   //Problem with ToolsAction as last item and separator. When ToolsAction
 
164
                   //is empty separator is displayed as last item.
 
165
                   //null,
 
166
                   SystemAction.get (org.openide.actions.ToolsAction.class),
 
167
                   //SystemAction.get (org.openide.actions.PropertiesAction.class), // #12072
 
168
                   //SystemAction.get (org.openide.actions.CustomizeAction.class),
 
169
               };
 
170
    }
 
171
 
 
172
    /** Called when new file system is added to the pool.
 
173
    * @param ev event describing the action
 
174
    */
 
175
    public void fileSystemAdded (RepositoryEvent ev) {
 
176
        ev.getFileSystem ().addPropertyChangeListener (
 
177
            org.openide.util.WeakListeners.propertyChange ((DSMap)getChildren (), ev.getFileSystem ())
 
178
        );
 
179
        refresh ();
 
180
    }
 
181
 
 
182
    /** Called when a file system is deleted from the pool.
 
183
    * @param ev event describing the action
 
184
    */
 
185
    public void fileSystemRemoved (RepositoryEvent ev) {
 
186
        refresh ();
 
187
    }
 
188
    /** Called when the fsp is reordered */
 
189
    public void fileSystemPoolReordered(RepositoryReorderedEvent ev) {
 
190
        refresh ();
 
191
    }
 
192
 
 
193
    /** Refreshes the pool.
 
194
    */
 
195
    void refresh () {
 
196
        refresh (null);
 
197
    }
 
198
 
 
199
    /** Refreshes the pool.
 
200
    * @param fs file system to remove
 
201
    */
 
202
    void refresh (FileSystem fs) {
 
203
        // XXX hack to show only masterfs and no other filesystems
 
204
        // should later be solved better
 
205
        // XXX should check if fs.root.url.protocol is not 'file' or 'jar', and if so, show it also
 
206
        // (to display network mounts)        
 
207
        URLMapper mapper = getMasterFsURLMapper();
 
208
        if (mapper == null) {
 
209
            //original solution based on Repository
 
210
            ((DSMap)getChildren ()).refresh (fileSystemPool, fs);
 
211
        } else {
 
212
            ((DSMap)getChildren ()).refreshListRoots(mapper);
 
213
        }
 
214
    }
 
215
 
 
216
    private static URLMapper getMasterFsURLMapper() {
 
217
        URLMapper retVal = null;
 
218
        Lookup.Result result = Lookup.getDefault().lookupResult(URLMapper.class);
 
219
        Collection c = result.allInstances();
 
220
        for (Iterator iterator = c.iterator(); iterator.hasNext();) {
 
221
            URLMapper mapper = (URLMapper) iterator.next();
 
222
            if (mapper != null && "org.netbeans.modules.masterfs.MasterURLMapper".equals(mapper.getClass().getName())) {//NOI18N
 
223
                retVal = mapper;
 
224
                break;
 
225
            }
 
226
        }
 
227
        return retVal;
 
228
    }
 
229
    
 
230
    /** We have customizer */
 
231
    public boolean hasCustomizer() {
 
232
        return true;
 
233
    }
 
234
 
 
235
    /** Children that listens to changes in filesystem pool.
 
236
    */
 
237
    static class DSMap extends Children.Keys implements PropertyChangeListener {
 
238
 
 
239
        public void propertyChange (PropertyChangeEvent ev) {
 
240
            //System.out.println ("Property change"); // NOI18N
 
241
            DataSystem ds = getDS ();
 
242
            if (ds == null) return;
 
243
 
 
244
            if ("root".equals(ev.getPropertyName())) {
 
245
                FileSystem fs = (FileSystem)ev.getSource ();
 
246
                ds.refresh (fs);
 
247
                ds.refresh ();
 
248
            }
 
249
        }
 
250
 
 
251
        /** The node */
 
252
        private DataSystem getDS() {
 
253
            return (DataSystem)getNode ();
 
254
        }
 
255
 
 
256
        protected Node[] createNodes (Object key) {
 
257
            DataFolder df = (DataFolder)key;
 
258
            Node n = new FilterNode(df.getNodeDelegate(), df.createNodeChildren (getDS ().filter));
 
259
            return new Node[] {n};
 
260
        }
 
261
 
 
262
        /** Refreshes the pool.
 
263
        * @param fileSystemPool the pool
 
264
        * @param fs file system to remove
 
265
        */
 
266
        public void refresh(Repository fileSystemPool, FileSystem fs) {
 
267
            @SuppressWarnings("unchecked") Enumeration<FileSystem> en = (Enumeration<FileSystem>)fileSystemPool.getFileSystems();
 
268
            ArrayList<DataFolder> list = new ArrayList<DataFolder>();
 
269
            while (en.hasMoreElements()) {
 
270
                FileSystem fsystem = en.nextElement();
 
271
                DataObject root = null;
 
272
                try {
 
273
                    root = DataObject.find(fsystem.getRoot());
 
274
                }
 
275
                catch (DataObjectNotFoundException e) {
 
276
                    Logger.getLogger(DataSystem.class.getName()).log(Level.WARNING, null, e);
 
277
                    // root will remain null and will be accepted
 
278
                    // (as that seems safer than not accepting it)
 
279
                }
 
280
                if ((root instanceof DataFolder) && getDS().filter.acceptDataObject(root))  {
 
281
                    list.add((DataFolder)root);
 
282
                }                
 
283
            }
 
284
            setKeys(list);
 
285
        }
 
286
        
 
287
        private void refreshListRoots(URLMapper mapper) {
 
288
            File[] files = File.listRoots();
 
289
            Set<DataFolder> rootSet = new LinkedHashSet<DataFolder>();
 
290
 
 
291
            for (int i = 0; i < files.length; i++) {
 
292
                File file = files[i];
 
293
                FileObject fo = fetchFileObject(file, mapper);
 
294
 
 
295
                if (fo != null) {
 
296
                    try {
 
297
                        fo = fo.getFileSystem().getRoot();
 
298
                    }
 
299
                    catch (FileStateInvalidException e) {
 
300
                        continue;
 
301
                    }
 
302
                    DataObject root = null;
 
303
 
 
304
                    try {
 
305
                        root = DataObject.find(fo);
 
306
                    }
 
307
                    catch (DataObjectNotFoundException e) {
 
308
                        Logger.getLogger(DataSystem.class.getName()).log(Level.WARNING, null, e);
 
309
                    }
 
310
                    if ((root instanceof DataFolder) &&
 
311
                        getDS().filter.acceptDataObject(root)) {
 
312
                        rootSet.add((DataFolder) root);
 
313
                    }
 
314
                }
 
315
            }
 
316
            setKeys(rootSet);
 
317
        }
 
318
 
 
319
 
 
320
        private FileObject fetchFileObject(File file, URLMapper mapper) {
 
321
            /*intentiionally isn't used FileUtil.toFileObject because here can't be 
 
322
            called method normalizeFile which causes problems with removeable drives 
 
323
            on Windows*/             
 
324
            FileObject retVal = null;
 
325
            try {                
 
326
                FileObject[] all  = mapper.getFileObjects(toUrl(file));//NOI18N
 
327
                if (all != null && all.length > 0) {
 
328
                    retVal = all [0];
 
329
                }
 
330
            } catch (MalformedURLException e) {
 
331
                retVal = null;
 
332
            }
 
333
            return retVal;
 
334
        }
 
335
 
 
336
        private URL toUrl(File file) throws MalformedURLException {
 
337
            return (org.openide.util.Utilities.isWindows()) ? new URL ("file:/"+file.getAbsolutePath ()) : file.toURI().toURL();//NOI18N   
 
338
        }
 
339
 
 
340
    }
 
341
    
 
342
    
 
343
 
 
344
    /** Serialization. */
 
345
    private static class DSHandle implements Node.Handle {
 
346
        DataFilter filter;
 
347
 
 
348
        static final long serialVersionUID =-2266375092419944364L;
 
349
        public DSHandle(DataFilter f) {
 
350
            filter = f;
 
351
        }
 
352
 
 
353
        public Node getNode() {
 
354
            return getDataSystem (filter);
 
355
        }
 
356
    }
 
357
    
 
358
    /** @deprecated No longer useful in the UI. */
 
359
    public static final class NbRepositoryNodeFactory extends RepositoryNodeFactory {
 
360
        
 
361
        public Node repository(DataFilter f) {
 
362
            return DataSystem.getDataSystem(f == DataFilter.ALL ? null : f);
 
363
        }
 
364
        
 
365
    }
 
366
    
 
367
}