KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > core > registry > ContextBindings


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.core.registry;
21
22 import org.netbeans.api.registry.BindingEvent;
23 import org.netbeans.api.registry.Context;
24 import org.netbeans.api.registry.ContextException;
25 import org.netbeans.spi.registry.BasicContext;
26 import org.netbeans.spi.registry.SpiUtils;
27 import org.openide.ErrorManager;
28 import org.openide.filesystems.FileObject;
29 import org.openide.filesystems.FileSystem;
30
31 import java.io.IOException JavaDoc;
32 import java.util.*;
33
34 /**
35  * This class manages bindings in the context. All non-primitive and non-simple
36  * datas are wrapped into ObjectBinding class.
37  */

38 class ContextBindings {
39
40     // folder of the context
41
private FileObject folder;
42     
43     // context of this ContextBindings
44
private BasicContext ctx;
45     
46     // folders and their FSs.
47
// this impl supports resettability if both FSs are provided.
48
private FileObject defFO;
49     private FileObject custFO;
50     private FileSystem defFS;
51     private FileSystem custFS;
52
53     // used to distinguish _binding_ changes done in this class and outside of the core/registry
54
static FileSystem.AtomicAction referenceAction = new RegistryAtomicAction () {
55         public void run() throws IOException JavaDoc {
56         }
57     };
58     
59     public static final String JavaDoc PRIMITIVE_BINDING_PREFIX = "BINDING:";
60
61     // map of ObjectBinding instances
62
private Map bindings = new HashMap();
63
64     private ContextBindings(FileObject folder, BasicContext ctx, FileSystem defFS, FileSystem custFS) {
65         this.folder = folder;
66         this.ctx = ctx;
67         this.defFS = defFS;
68         this.custFS= custFS;
69         
70         FileObject[] children = this.folder.getChildren();
71         for (int i=0; i<children.length; i++) {
72             ObjectBinding ob = ObjectBinding.get(this.ctx, children[i]);
73             if (ob != null) {
74                 bindings.put(ob.getBindingName(),ob);
75             }
76         }
77     }
78     
79     public static ContextBindings createContextBindings(FileObject folder, BasicContext ctx) {
80         return new ContextBindings(folder, ctx, null, null);
81     }
82     
83     public static ContextBindings createResettableContextBindings(FileObject folder, BasicContext ctx, FileSystem defaults, FileSystem customizations) {
84         return new ContextBindings(folder, ctx, defaults, customizations);
85     }
86
87     private synchronized FileObject getDefFolder() {
88         if (defFO != null && defFO.isValid()) {
89             return defFO;
90         }
91         defFO = (defFS != null) ? defFS.findResource(folder.getPath()) : null;
92         return defFO;
93     }
94     
95     private synchronized FileObject getCustFolder() {
96         if (custFO != null && custFO.isValid()) {
97             return custFO;
98         }
99         custFO = custFS.findResource(folder.getPath());
100         return custFO;
101     }
102
103     // go through all bindings and do their refresh according to added/removed convertors
104
void modulesChanged(Collection added, Collection removed) {
105         assert added != null;
106         assert removed != null;
107         Iterator it = added.iterator();
108         while (it.hasNext()) {
109             processBindingChange(BindingEvent.BINDING_ADDED, it.next());
110         }
111         it = removed.iterator();
112         while (it.hasNext()) {
113             processBindingChange(BindingEvent.BINDING_REMOVED, it.next());
114         }
115     }
116     
117     private void processBindingChange(int eventType, Object JavaDoc moduleDescriptor) {
118         Iterator it = bindings.values().iterator();
119         while (it.hasNext()) {
120             ObjectBinding ob = (ObjectBinding)it.next();
121             if (ob.getModuleDescriptor().equals(moduleDescriptor)) {
122                 fireBindingEvent(ob.getBindingName(), eventType);
123             }
124         }
125     }
126
127     
128     private void fireBindingEvent(String JavaDoc bindingName, int eventType) {
129         BindingEvent be = SpiUtils.createBindingEvent(ctx, bindingName, eventType);
130         // fires this change on all relevant contexts
131
FileSystemListener.fireContextEvent(((ContextImpl)ctx).getRootContextImpl(), folder, be);
132     }
133     
134     
135     /** Helper method for FileSystemListener to check whether the file
136      * which was added/modified or removed in core/external operation
137      * is relevant to this context and must be fired as binding change.
138      *
139      * This method must not only properly answer, but also updates its
140      * internal binding cache.
141      */

142     boolean isRelevantChange(FileObject fo, boolean removed) {
143         if (!removed) {
144             ObjectBinding ob = findObjectBinding(fo.getName());
145             if (ob != null) {
146                 return true;
147             } else {
148                 ob = ObjectBinding.get(ctx, fo);
149                 if (ob != null) {
150                     bindings.put(ob.getBindingName(), ob);
151                     return true;
152                 } else {
153                     return false;
154                 }
155             }
156         } else {
157             ObjectBinding ob = findObjectBinding(fo.getName());
158             if (ob != null) {
159                 bindings.remove(fo.getName());
160                 return true;
161             } else {
162                 return false;
163             }
164         }
165     }
166
167     
168     // couple of methods for managing of primitive and simple data types:
169

170
171 /*
172     The process of binding removal might include also removal of its attributes
173     and so it must be done in atomic action to group all events. Otherwise removal
174     of binding's attribute can notify client's listener which in turn can execute its code
175     in the middle of binding removal.
176         
177     also lastAtomicAction variable is set to this atomic action so that
178     FS listener can distinguish _binding_ changes done in core/registry and outside
179 */

180     public void bindObject(final String JavaDoc bindingName, final Object JavaDoc object) throws ContextException {
181         try {
182             folder.getFileSystem().runAtomicAction(new RegistryAtomicAction () {
183                 public void run() throws IOException JavaDoc {
184                     doBindObject(bindingName, object);
185                 }
186             });
187         } catch (IOException JavaDoc ex) {
188             ContextException ce = SpiUtils.createContextException(ctx, "Error on underlaying filesystem occured.");
189             ErrorManager.getDefault().annotate(ce, ex);
190             throw ce;
191         }
192     }
193
194     private void doBindObject(String JavaDoc bindingName, Object JavaDoc object) throws IOException JavaDoc {
195         if (object == null) {
196             ObjectBinding[] ob = new ObjectBinding[] {findObjectBinding(bindingName), PrimitiveBinding.get(folder, bindingName)};
197             for (int i = 0; i < ob.length; i++) {
198                 ObjectBinding objectBinding = ob[i];
199                 if (objectBinding != null ) {
200                     objectBinding.delete();
201                 }
202             }
203             bindings.remove(bindingName);
204         } else {
205             boolean isPrimitive = PrimitiveBinding.isPrimitive(object);
206             ObjectBinding toDelete = isPrimitive ? findObjectBinding(bindingName) : PrimitiveBinding.get(folder, bindingName);
207             if (toDelete != null) toDelete.delete();
208             bindings.remove(bindingName);
209             
210             ObjectBinding toCreate = PrimitiveBinding.create(folder, bindingName, object);
211             if (toCreate == null) {
212                 toCreate = ObjectBinding.write (ctx, folder, bindingName, object);
213                 bindings.put(bindingName, toCreate);
214             }
215         }
216     }
217     
218     public Object JavaDoc lookupObject(String JavaDoc bindingName) throws ContextException {
219         Object JavaDoc o = getBindingFromCache(bindingName);
220         if (o != null) return o;
221         
222         try {
223             ObjectBinding[] ob = new ObjectBinding[] {findObjectBinding(bindingName), PrimitiveBinding.get(folder, bindingName)};
224             for (int i = 0; i < ob.length; i++) {
225                 ObjectBinding objectBinding = ob[i];
226                 if (objectBinding != null && objectBinding.isEnabled() ) {
227                     o = objectBinding.getObject();
228                 }
229             }
230             
231             return o;
232         } catch (IOException JavaDoc e) {
233             ContextException ce = SpiUtils.createContextException(ctx, e.getLocalizedMessage());
234             ObjectBinding.getErrorManager().annotate(ce,e);
235             throw ce;
236         }
237     }
238
239     private Object JavaDoc getBindingFromCache(String JavaDoc bindingName) throws ContextException {
240         Object JavaDoc o = null;
241         ObjectBinding ob1 = (ObjectBinding)bindings.get(bindingName);
242         if (ob1 != null && ob1.isEnabled()) {
243             try {
244                 o = ob1.getObject();
245             } catch (IOException JavaDoc e) {
246                 ContextException ce = SpiUtils.createContextException(ctx,e.getLocalizedMessage());
247                 ObjectBinding.getErrorManager().annotate(ce, e);
248                 throw ce;
249             }
250         }
251         return o;
252     }
253     
254     private ObjectBinding findObjectBinding(String JavaDoc bindingName) {
255         Iterator it = bindings.values().iterator();
256         while (it.hasNext()) {
257             ObjectBinding ob = (ObjectBinding)it.next();
258             if (ob.getBindingName().equals(bindingName)) {
259                 return ob;
260             }
261         }
262         return null;
263     }
264
265     public Collection getNames() {
266         Set retVal = new HashSet();
267         
268         Set obMerged = new HashSet ();
269         obMerged.addAll(bindings.values());
270         obMerged.addAll (PrimitiveBinding.getAll(folder));
271         
272         for (Iterator iterator = obMerged.iterator(); iterator.hasNext();) {
273             ObjectBinding ob = (ObjectBinding) iterator.next();
274             if (ob != null && ob.isEnabled()) retVal.add(ob.getBindingName());
275         }
276         
277         return retVal;
278     }
279     
280     public boolean hasDefault(String JavaDoc bindingName) {
281         assert bindingName != null;
282         boolean retVal = false;
283         
284         FileObject defF = getDefFolder();
285         if (defF != null) {
286             retVal = (findBindingFile(defF, bindingName) != null || PrimitiveBinding.get(defF, bindingName) != null);
287         }
288         
289         return retVal;
290     }
291
292     private static FileObject findBindingFile(FileObject folder, String JavaDoc bindingName) {
293         FileObject fo = null;
294         Collection exts = ObjectBinding.getFileExtensions();
295         for (Iterator iterator = exts.iterator(); iterator.hasNext();) {
296             String JavaDoc ext = (String JavaDoc) iterator.next();
297             fo = folder.getFileObject(bindingName, ext);
298             if (fo != null) break;
299         }
300         return fo;
301     }
302   
303     
304     public boolean isModified(String JavaDoc bindingName) {
305         assert bindingName != null;
306         if (custFS == null) {
307             return false;
308         }
309         FileObject custF = getCustFolder();
310         if (custF == null) {
311             // MultiFilesystem stores attributes of folders which do not exist
312
// on writable layer yet on root file object of the writable filesystem
313
// in the format of "folder\folder\attribute". Check that here:
314
return PrimitiveBinding.isCustomizedAndAttachedToRoot(custFS, folder, bindingName) ? true : false;
315         }
316         
317         return (findBindingFile(custF, bindingName) != null || PrimitiveBinding.get(custF, bindingName) != null);
318     }
319     
320     public void revert(final String JavaDoc bindingName) throws ContextException {
321         // execute revert in atomic action to group all events.
322
try {
323             folder.getFileSystem().runAtomicAction(new RegistryAtomicAction () {
324                 public void run() throws IOException JavaDoc {
325                     doRevert(bindingName);
326                 }
327             });
328         } catch (IOException JavaDoc ex) {
329             ContextException ce = SpiUtils.createContextException(ctx, "Error on underlaying filesystem occured.");
330             ErrorManager.getDefault().annotate(ce, ex);
331             throw ce;
332         }
333     }
334     
335     private void doRevert(String JavaDoc bindingName) throws IOException JavaDoc {
336         assert bindingName != null;
337         if (isModified(bindingName)) {
338             FileObject custF = getCustFolder();
339             if (custF != null) {
340                 ObjectBinding ob = PrimitiveBinding.get(custF, bindingName);
341                 if (ob == null) ob = ObjectBinding.get(ctx, findBindingFile(custF, bindingName));
342                 if (ob != null) ob.delete();
343                 bindings.remove(bindingName);
344                 removeMaskFile(custF, bindingName);
345                 
346                 // Binding from customization layer was removed. Check
347
// binding on the default layer. If it is binding file create ObjectBinding info
348
ob = ObjectBinding.get(ctx, findBindingFile(folder, bindingName));
349                 if (ob != null) bindings.put(ob.getBindingName(), ob);
350             } else {
351                 //special case
352
// MultiFilesystem stores attributes of folders which do not exist
353
// on writable layer yet on root file object of the writable filesystem
354
// in the format of "folder\folder\attribute". Check that here:
355
PrimitiveBinding.deleteIfCustomizedAndAttachedToRoot(custFS, folder, bindingName);
356             }
357         }
358     }
359
360     private static void removeMaskFile(FileObject folder, String JavaDoc name) throws IOException JavaDoc {
361         Enumeration en = folder.getChildren(false);
362         while (en.hasMoreElements()) {
363             FileObject fo = (FileObject)en.nextElement();
364             if (fo.getName().equals(name) && fo.getExt().endsWith("_hidden")) {
365                 fo.delete();
366                 break;
367             }
368         }
369     }
370     
371     public boolean existBinding(String JavaDoc bindingName) {
372         return (findObjectBinding(bindingName) != null || PrimitiveBinding.get(folder, bindingName) != null);
373     }
374
375     
376     public FileObject getBindingFile(String JavaDoc bindingName) {
377         ObjectBinding ob = findObjectBinding(bindingName);
378         if (ob == null) {
379             return null;
380         }
381         if (!ob.isEnabled()) {
382             return null;
383         }
384         return ob.getFile();
385     }
386     
387     public boolean isBindingFile(FileObject fo) {
388         Iterator it = bindings.values().iterator();
389         while (it.hasNext()) {
390             ObjectBinding ob = (ObjectBinding)it.next();
391             if (fo.equals(ob.getFile())) {
392                 return true;
393             }
394         }
395         return false;
396     }
397     private static abstract class RegistryAtomicAction implements FileSystem.AtomicAction {
398         public boolean equals(Object JavaDoc obj) {
399             return (obj instanceof RegistryAtomicAction);
400         }
401
402         public int hashCode() {
403             return RegistryAtomicAction.class.hashCode();
404         }
405     }
406 }
407
Popular Tags