KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > api > registry > Context


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.api.registry;
21
22 import org.netbeans.modules.registry.ApiContextFactory;
23 import org.netbeans.modules.registry.OrderingSupport;
24 import org.netbeans.spi.registry.BasicContext;
25 import org.netbeans.spi.registry.MergedContextProvider;
26 import org.netbeans.spi.registry.ResettableContext;
27 import org.netbeans.spi.registry.SpiUtils;
28 import org.openide.ErrorManager;
29 import org.openide.util.Lookup;
30 import org.openide.util.Mutex;
31 import org.openide.util.NbBundle;
32
33 import java.awt.*;
34 import java.beans.PropertyChangeListener JavaDoc;
35 import java.lang.ref.WeakReference JavaDoc;
36 import java.net.MalformedURLException JavaDoc;
37 import java.net.URL JavaDoc;
38 import java.util.*;
39 import java.util.List JavaDoc;
40
41 /**
42  * This API class is representing a context which consists of a set of
43  * name-to-object bindings. It contains methods for examining and
44  * updating these bindings. The contexts are composed into
45  * hierarchical collection which form configuration system. The
46  * configuration system allows applicatioRootns to store and retrieve
47  * data. How data are stored is not specified by the Registry API.
48  * It is up to provided implementation of Registry SPI to properly
49  * document it and that documentation must be consulted.
50  *
51  * <p>The hierarchical collection of contexts is similar to folders
52  * in a hierarchical file system. There exist a root context containing
53  * all the contexts. The name of this context is <i>"/"</i>
54  * and it is also absolute name of the context. The names
55  * of individual contexts cannot be empty, but does not have to
56  * be unique. However, absolute name of the context must be
57  * unique. Children of the root context have absolute names of
58  * <i>"/" + context name</i>. All other contexts have absolute names of
59  * <i>parent's context absolute name + "/" + context name</i>.
60  *
61  * <p>The context can contain the subcontext and binding with the same name
62  * and they will coexist.
63  *
64  * <p>The context has getters and setters for all primitive data types,
65  * for a few basic object types (eg. Color, URL, etc.) and for Object.
66  * As was said above the storage format is specific per Registry SPI
67  * implementation, but following is valid for all backends:
68  * <ul>
69  * <li><b>primitive data types:</b> the primitive data type is converted into corresponding
70  * object counterpart and the object is stored. Retrieval of the primitive
71  * value does the opposite: the object is retrieved and converted to primitive data
72  * type. Each context implementation must support storage of these data types.</li>
73  * <li><b>supported basic object types:</b> these object types in addition to
74  * basic data types must be persistable by all context implementations.</li>
75  * <li><b>any other Object:</b> it is up to specific Registry SPI implementation
76  * to document what is supported and how in this area.</li>
77  * </ul>
78  *
79  * <p>Getters do not throw exceptions. They accept default value parameter which
80  * is returned if value does not exist or it could not be read. The exceptions are logged.
81  *
82  * <p>Putting null value removes the binding.
83  *
84  *<p>Rename of binding is not supported because no useful usecase was found.
85  *
86  * <p>All methods are properly synchronized and can be accessed from multiple
87  * threads without any synchronization on the client side. During the modification is
88  * whole hierarchy of contexts exclusively locked.
89  *
90  * <p>TBD: Names restrictions: length, valid characters, etc.
91  * The context name nor binding name cannot contain "/" character.
92  *
93  * @author David Konecny
94  */

95 public final class Context {
96     
97     /** SPI context to which this API context delegates most of the calls. */
98     BasicContext delegate;
99     
100     /** Cache of the created API contexts. The key is is SPI context and
101      * value is WeakReference to API context. */

102     private static WeakHashMap contextCache = new WeakHashMap();
103     
104     // This should theoretically be in ApiContextFactoryImpl, but that would
105
// mean that variable ApiContextFactory.DEFAULT would not initialized
106
// before ApiContextFactoryImpl was loaded into VM what can be sometimes
107
// too late. On the other hand Context class is loaded as one of the first classes.
108
// That's why it is here.
109
private static final Mutex.Privileged privilegedMutex = new Mutex.Privileged();
110     private static final Mutex mutex = new Mutex (privilegedMutex);
111     
112     static {
113         ApiContextFactory.DEFAULT = new ApiContextFactoryImpl();
114     }
115     
116     private static BasicContext defaultRootContext;
117     
118     private static final ErrorManager errorManager = ErrorManager.getDefault().getInstance("org.netbeans.api.registry");
119     
120     private Context(BasicContext delegate) {
121         this.delegate = delegate;
122     }
123     
124     ///////////////////////////
125
// Context related methods:
126
///////////////////////////
127

128     /**
129      * Getter for default instance of registry.
130      *
131      * <p>Application specific documentation must be consulted to learn which
132      * exact implementation will be returned by this method. For example for
133      * NetBeans it can be implementation working on top of the root of
134      * SystemFileSystem.
135      *
136      * @return default root context
137      */

138     public static Context getDefault() {
139         return Context.getApiContext(getRC());
140     }
141
142
143    /**
144      * Returns context, that merges all its delegates. See JavaDoc overview for more details.
145      * @param delegates array of contexts that should be merged
146      * @return merged context
147      * @since 1.6
148      */

149     public static Context merge (final Context[] delegates) {
150         BasicContext mergedBasic = SpiUtils.merge(new MergedContextProvider() {
151             public void addPropertyChangeListener(PropertyChangeListener JavaDoc listener) {
152             }
153
154             public void removePropertyChangeListener(PropertyChangeListener JavaDoc listener) {
155             }
156
157             public BasicContext[] getDelegates() {
158                 List JavaDoc basicDelegates = new ArrayList();
159                 for (int i = 0; i < delegates.length; i++) {
160                     Context delegate = delegates[i];
161                     basicDelegates.add(delegate.delegate);
162                 }
163
164                 return (BasicContext[])basicDelegates.toArray(new BasicContext[0]);
165             }
166         });
167         return SpiUtils.createContext(mergedBasic);
168     }
169
170     /**
171      * Name of the context.
172      *
173      * @return name of the context; cannot be null
174      */

175     public String JavaDoc getContextName() {
176         return delegate.getContextName();
177     }
178     
179     /**
180      * Gets root context.
181      *
182      * @return root context
183      */

184     public Context getRootContext() {
185         return getApiContext(delegate.getRootContext());
186     }
187     
188     /**
189      * Getter for the absolute name of the context, eg. "/mymodule/mysettings".
190      * It is full path from the root context.
191      *
192      * @return absolute name of this context; cannot be null
193      */

194     public String JavaDoc getAbsoluteContextName() {
195         BasicContext ctx = delegate;
196         StringBuffer JavaDoc sb = new StringBuffer JavaDoc(ctx.getContextName());
197         while (ctx.getParentContext() != null) {
198             ctx = ctx.getParentContext();
199             if (ctx.getContextName().equals("/")) {
200                 sb.insert(0, ctx.getContextName());
201             } else {
202                 sb.insert(0, "/");
203                 sb.insert(0, ctx.getContextName());
204             }
205         }
206         return sb.toString();
207     }
208
209     /**
210      * Retrieve subcontext of the given name. The multi-level path
211      * is accepted as subcontext name (eg. "sub1/sub2/mysub").
212      *
213      * @param subcontextName multi-level subcontext name to retrieve
214      * @return Context or null if subcontext does not exist
215      */

216     public Context getSubcontext(String JavaDoc subcontextName) {
217         Mutex.Privileged mp = getMutexPrivileged();
218         try {
219             mp.enterReadAccess();
220             StringTokenizer tok = new StringTokenizer(subcontextName, "/"); // NOI18N
221
BasicContext ctx = delegate;
222             while (tok.hasMoreTokens() && ctx != null) {
223                 String JavaDoc name = tok.nextToken();
224                 ctx = ctx.getSubcontext(name);
225             }
226             return getApiContext(ctx);
227         } finally {
228             mp.exitReadAccess();
229         }
230     }
231     
232     /**
233      * Retrieve parent context.
234      *
235      * @return parent context or null in case of root context
236      */

237     public Context getParentContext() {
238         Mutex.Privileged mp = getMutexPrivileged();
239         try {
240             mp.enterReadAccess();
241             return getApiContext(delegate.getParentContext());
242         } finally {
243             mp.exitReadAccess();
244         }
245     }
246     
247     /**
248      * Create subcontext of the given name. The multi-level path
249      * is accepted as subcontext name (eg. "sub1/sub2/mysub"). All
250      * intermediate subcontexts which do not exist will be created. If
251      * subcontext already exist it is just retrieved.
252      *
253      * @param subcontextName multi-level subcontext name to create
254      * @return created or retrieved context
255      * @throws ContextException thrown when subcontext cannot be created
256      */

257     public Context createSubcontext(String JavaDoc subcontextName) throws ContextException {
258         Mutex.Privileged mp = getMutexPrivileged();
259         try {
260             mp.enterWriteAccess();
261             StringTokenizer tok = new StringTokenizer(subcontextName, "/"); // NOI18N
262
BasicContext ctx = delegate;
263             while (tok.hasMoreTokens()) {
264                 String JavaDoc name = tok.nextToken();
265                 BasicContext ctx2 = ctx.getSubcontext(name);
266                 if (ctx2 != null) {
267                     ctx = ctx2;
268                 } else {
269                     ctx = ctx.createSubcontext(name);
270                 }
271             }
272             return getApiContext(ctx);
273         } finally {
274             mp.exitWriteAccess();
275         }
276     }
277     
278     /**
279      * Destroy subcontext of the given name. Destroying context deletes
280      * also all its data recursively, ie. all bindings, attributes
281      * and its subcontexts. The multi-level path is accepted
282      * (eg. "sub1/sub2/mysub").
283      *
284      * @param subcontextName multi-level name of existing subcontext
285      * @throws ContextException thrown when subcontext cannot be deleted
286      */

287     public void destroySubcontext(String JavaDoc subcontextName) throws ContextException {
288         int index = subcontextName.lastIndexOf('/');
289         BasicContext ctx = delegate;
290         if (index != -1) {
291             ctx = getSubcontext(subcontextName.substring(0, index)).delegate;
292             subcontextName = subcontextName.substring(index+1);
293         }
294         Mutex.Privileged mp = getMutexPrivileged();
295         try {
296             mp.enterWriteAccess();
297             ctx.destroySubcontext(subcontextName);
298         } finally {
299             mp.exitWriteAccess();
300         }
301     }
302
303
304     ///////////////////////////////
305
// Context enumeration methods:
306
///////////////////////////////
307

308     /**
309      * Retrieve names of all subcontexts of this context.
310      *
311      * @return collection of Strings, ie. names of all subcontexts in the context;
312      * cannot be null
313      */

314     public Collection/*<String>*/ getSubcontextNames() {
315         Mutex.Privileged mp = getMutexPrivileged();
316         try {
317             mp.enterReadAccess();
318             return delegate.getSubcontextNames();
319         } finally {
320             mp.exitReadAccess();
321         }
322     }
323     
324     /**
325      * Retrieve names of all bindings in this context.
326      *
327      * @return collection of Strings, ie. names of all bindings in the context;
328      * cannot be null
329      */

330     public Collection/*<String>*/ getBindingNames() {
331         Mutex.Privileged mp = getMutexPrivileged();
332         try {
333             mp.enterReadAccess();
334             return delegate.getBindingNames();
335         } finally {
336             mp.exitReadAccess();
337         }
338     }
339
340     /**
341      * Retrieve names of all attributes in this context.
342      *
343      * @return collection of Strings, ie. names of all attribute in the context;
344      * cannot be null
345      */

346     public Collection/*<String>*/ getAttributeNames(String JavaDoc bindingName) {
347         Mutex.Privileged mp = getMutexPrivileged();
348         try {
349             mp.enterReadAccess();
350             return delegate.getAttributeNames(bindingName);
351         } finally {
352             mp.exitReadAccess();
353         }
354     }
355
356     /////////////////////////////////////
357
// Ordered context enumerations methods:
358
/////////////////////////////////////
359

360     /** Store full order of the context content. The passed
361      * list can contain only String instances which are names
362      * of a context's binding or context's subcontext. The context's
363      * subcontext name must be appended with "/" character to distinguish subcontext
364      * name from binding name. For any other value the
365      * IllegalArgumentException will be thrown.
366      *
367      * @param names full order of the objects in the context; see above for
368      * expected values in the list
369      */

370     public void orderContext(List JavaDoc names) {
371         StringBuffer JavaDoc value = new StringBuffer JavaDoc();
372         Iterator it = names.iterator();
373         while (it.hasNext()) {
374             Object JavaDoc o = it.next();
375             if (!(o instanceof String JavaDoc)) {
376                 throw new IllegalArgumentException JavaDoc("OrderContext: Passed list contains item which is not String - "+o);
377             }
378             String JavaDoc item = (String JavaDoc)o;
379             // this checking might be ommited. the fullorder can contain invalid items
380
// and they will be ignored. therefore I'm not doing this under write lock as
381
// it should be and if there are perf or other problems the checkItem
382
// method can be removed completely.
383
checkItem(item);
384             value.append(item);
385             value.append(",");
386         }
387         if (value.length() > 0) {
388             value.setLength(value.length()-1);
389         }
390         setAttribute(null, "fullorder", value.toString());
391     }
392     
393     private void checkItem(String JavaDoc name) {
394         if (name.endsWith("/")) {
395             name = name.substring(0, name.length()-1);
396             if (getSubcontext(name) == null) {
397                 throw new IllegalArgumentException JavaDoc("OrderContext: Passed list contains non-existing subcontext - "+name);
398             }
399         } else {
400             if (!getBindingNames().contains(name)) {
401                 throw new IllegalArgumentException JavaDoc("OrderContext: Passed list contains non-existing binding - "+name);
402             }
403         }
404     }
405
406     /**
407      * Method for listing items of the context ordered. The returned list
408      * will contain instances of all direct subcontexts and all bound
409      * objects in this context.
410      *
411      * <p>See Javadoc overview for how the context items are sorted.
412      * If context content was ordered by {@link #orderContext} method
413      * then the items will be listed in this order (order of items which were
414      * not specified in the full order is undefined).
415      *
416      * @return collection of ordered Objects, ie. both instances of bound
417      * Objects and Contexts representing subcontexts are returned.
418      */

419     public List JavaDoc getOrderedObjects() {
420         Mutex.Privileged mp = getMutexPrivileged();
421         try {
422             mp.enterReadAccess();
423             List JavaDoc ar = new ArrayList();
424             Iterator it = OrderingSupport.DEFAULT.getOrderedNames(this).iterator();
425             while (it.hasNext()) {
426                 String JavaDoc item = (String JavaDoc)it.next();
427                 if (item.endsWith("/")) {
428                     Context ctx = getSubcontext(item.substring(0, item.length()-1));
429                     if (ctx != null) {
430                         ar.add(ctx);
431                     }
432                 } else {
433                     Object JavaDoc o = getObject(item, null);
434                     if (o != null) {
435                         ar.add(o);
436                     }
437                 }
438             }
439             return ar;
440         } finally {
441             mp.exitReadAccess();
442         }
443     }
444     
445     /**
446      * Method listing ordered names of the context items. The returned list
447      * will contain names of all direct subcontexts and all bound
448      * objects in this context. The subcontext names are appended
449      * with "/" character. It can be used to distinguish subcontext name
450      * and binding name when they are the same.
451      *
452      * <p>See the JavaDoc for {@link #getOrderedObjects} method for
453      * more details about ordering itself.
454      *
455      * @return collection of Strings; contains binding names and subcontext
456      * names appended with "/" character
457      *
458      * @since 1.4
459      */

460     public List JavaDoc getOrderedNames() {
461         Mutex.Privileged mp = getMutexPrivileged();
462         try {
463             mp.enterReadAccess();
464             return OrderingSupport.DEFAULT.getOrderedNames(this);
465         } finally {
466             mp.exitReadAccess();
467         }
468     }
469     
470     
471     ///////////////////////////////
472
// Bindings related methods:
473
///////////////////////////////
474

475     /**
476      * Retrieve named object from the context.
477      *
478      * <p>If retrieved object is instance of {@link ObjectRef} it is recursively
479      * dereferenced and the value of ObjectRef instance if returned instead.
480      * If dereferenced value is null or ObjectRef is invalid then the ObjectRef
481      * instance is returned. See {@link #getRef} if you need to retrieve
482      * ObjectRef directly.
483      *
484      * @param bindingName the name of the object to retrieve; cannot be empty
485      * @param defaultValue default value returned in case the binding does not
486      * exist.
487      * @return retrieved value or defaultValue if this binding does not exist
488      */

489     public Object JavaDoc getObject(String JavaDoc bindingName, Object JavaDoc defaultValue) {
490         Object JavaDoc o = getObject(bindingName);
491         
492         if (o instanceof ObjectRef) {
493             // it is ObjectRef -> dereference it:
494
Object JavaDoc origin = o;
495             while (o != null && o instanceof ObjectRef) {
496                 o = ((ObjectRef)o).getObject();
497             }
498             // if the resulted value is null then return ObjectRef:
499
if (o == null) {
500                 o = origin;
501             }
502         }
503         
504         if (o == null) {
505             return defaultValue;
506         } else {
507             return o;
508         }
509     }
510
511     /**
512      * Retrieve directly the bounded ObjectRef instance. The {@link #getObject}
513      * does recursive traversal of ObjectRef and returns directly the referenced value.
514      *
515      * @param bindingName the name of the object to retrieve; cannot be empty
516      * @return instance of the ObjectRef or null if bound object is not ObjectRef
517      */

518     public ObjectRef getRef(String JavaDoc bindingName) {
519         Object JavaDoc o = getObject(bindingName);
520         
521         if (o instanceof ObjectRef) {
522             return (ObjectRef)o;
523         } else {
524             return null;
525         }
526     }
527     
528     private Object JavaDoc getObject(String JavaDoc bindingName) {
529         Object JavaDoc o = null;
530         Mutex.Privileged mp = getMutexPrivileged();
531         try {
532             mp.enterReadAccess();
533             o = delegate.lookupObject(bindingName);
534         } catch (ContextException ex) {
535             if (errorManager.isLoggable(ErrorManager.INFORMATIONAL)) {
536                 errorManager.annotate(ex,
537                     NbBundle.getMessage(Context.class, "MSG_get_object", bindingName, getAbsoluteContextName()));
538                 errorManager.notify(ErrorManager.INFORMATIONAL, ex);
539             }
540         } finally {
541             mp.exitReadAccess();
542         }
543
544         return o;
545     }
546     
547     /**
548      * Binds a name to an object and store the object in context. Use null
549      * value to remove binding.
550      *
551      * <p>See class overview JavaDoc for more details about how
552      * the objects are stored and which object types are supported.
553      *
554      * @param bindingName the name to bind; cannot be empty
555      * @param value the object to bind; null is allowed and means
556      * deletion of the binding
557      */

558     public void putObject(String JavaDoc bindingName, Object JavaDoc value) {
559         Mutex.Privileged mp = getMutexPrivileged();
560         try {
561             mp.enterWriteAccess();
562             delegate.bindObject(bindingName, value);
563         } catch (ContextException ex) {
564             if (errorManager.isLoggable(ErrorManager.INFORMATIONAL)) {
565                 errorManager.annotate(ex,
566                     NbBundle.getMessage(Context.class, "MSG_put_object", bindingName, getAbsoluteContextName()));
567                 errorManager.notify(ErrorManager.INFORMATIONAL, ex);
568             }
569         } finally {
570             mp.exitWriteAccess();
571         }
572     }
573
574     
575     /**
576      * Retrieve String value.
577      *
578      * @param bindingName binding name
579      * @param defaultValue default value returned if this binding does not exist
580      * @return retrieved value or defaultValue if this binding does not exist
581      */

582     public String JavaDoc getString(String JavaDoc bindingName, String JavaDoc defaultValue) {
583         Object JavaDoc o = getObject(bindingName, null);
584         if (o == null || !(o instanceof String JavaDoc) ) {
585             return defaultValue;
586         } else {
587             return (String JavaDoc)o;
588         }
589     }
590     
591     /**
592      * Binds a name to the String and store it in the context. Use null
593      * value to remove binding.
594      *
595      * @param bindingName binding name
596      * @param value value
597      */

598     public void putString(String JavaDoc bindingName, String JavaDoc value) {
599         putObject(bindingName, value);
600     }
601     
602     /**
603      * Retrieve integer value.
604      *
605      * @param bindingName binding name
606      * @param defaultValue default value returned if this binding does not exist
607      * @return retrieved value or defaultValue if this binding does not exist
608      */

609     public int getInt(String JavaDoc bindingName, int defaultValue) {
610         Object JavaDoc o = getObject(bindingName, null);
611         if (o == null) {
612             return defaultValue;
613         } else if (o instanceof Integer JavaDoc) {
614             return ((Integer JavaDoc)o).intValue();
615         } else if (o instanceof String JavaDoc) {
616             return Integer.parseInt((String JavaDoc)o);
617         } else {
618             return defaultValue;
619         }
620     }
621     
622     /**
623      * This method converts the passed integer to Integer
624      * object and binds it into context.
625      * Use {@link #putObject} with null value to remove binding.
626      *
627      * @param bindingName binding name
628      * @param value value
629      */

630     public void putInt(String JavaDoc bindingName, int value) {
631         putObject(bindingName, new Integer JavaDoc(value));
632     }
633
634     /**
635      * Retrieve long value.
636      *
637      * @param bindingName binding name
638      * @param defaultValue default value returned if this binding does not exist
639      * @return retrieved value or defaultValue if this binding does not exist
640      */

641     public long getLong(String JavaDoc bindingName, long defaultValue) {
642         Object JavaDoc o = getObject(bindingName, null);
643         if (o == null) {
644             return defaultValue;
645         } else if (o instanceof Long JavaDoc) {
646             return ((Long JavaDoc)o).longValue();
647         } else if (o instanceof String JavaDoc) {
648             return Long.parseLong((String JavaDoc)o);
649         } else {
650             return defaultValue;
651         }
652     }
653     
654     /**
655      * This method converts the passed long to Long
656      * object and binds it into context.
657      * Use {@link #putObject} with null value to remove binding.
658      *
659      * @param bindingName binding name
660      * @param value value
661      */

662     public void putLong(String JavaDoc bindingName, long value) {
663         putObject(bindingName, new Long JavaDoc(value));
664     }
665
666     /**
667      * Retrieve boolean value.
668      *
669      * @param bindingName binding name
670      * @param defaultValue default value returned if this binding does not exist
671      * @return retrieved value or defaultValue if this binding does not exist
672      */

673     public boolean getBoolean(String JavaDoc bindingName, boolean defaultValue) {
674         Object JavaDoc o = getObject(bindingName, null);
675         if (o == null) {
676             return defaultValue;
677         } else if (o instanceof Boolean JavaDoc) {
678             return ((Boolean JavaDoc)o).booleanValue();
679         } else if (o instanceof String JavaDoc) {
680             return Boolean.valueOf((String JavaDoc)o).booleanValue();
681         } else {
682             return defaultValue;
683         }
684     }
685     
686     /**
687      * This method converts the passed boolean to Boolean
688      * object and binds it into context.
689      * Use {@link #putObject} with null value to remove binding.
690      *
691      * @param bindingName binding name
692      * @param value value
693      */

694     public void putBoolean(String JavaDoc bindingName, boolean value) {
695         putObject(bindingName, Boolean.valueOf(value));
696     }
697
698     /**
699      * Retrieve float value.
700      *
701      * @param bindingName binding name
702      * @param defaultValue default value returned if this binding does not exist
703      * @return retrieved value or defaultValue if this binding does not exist
704      */

705     public float getFloat(String JavaDoc bindingName, float defaultValue) {
706         Object JavaDoc o = getObject(bindingName, null);
707         if (o == null) {
708             return defaultValue;
709         } else if (o instanceof Float JavaDoc) {
710             return ((Float JavaDoc)o).floatValue();
711         } else if (o instanceof String JavaDoc) {
712             return Float.parseFloat((String JavaDoc)o);
713         } else {
714             return defaultValue;
715         }
716     }
717     
718     /**
719      * This method converts the passed float to Float
720      * object and binds it into context.
721      * Use {@link #putObject} with null value to remove binding.
722      *
723      * @param bindingName binding name
724      * @param value value
725      */

726     public void putFloat(String JavaDoc bindingName, float value) {
727         putObject(bindingName, new Float JavaDoc(value));
728     }
729
730     /**
731      * Retrieve double value.
732      *
733      * @param bindingName binding name
734      * @param defaultValue default value returned if this binding does not exist
735      * @return retrieved value or defaultValue if this binding does not exist
736      */

737     public double getDouble(String JavaDoc bindingName, double defaultValue) {
738         Object JavaDoc o = getObject(bindingName, null);
739         if (o == null) {
740             return defaultValue;
741         } else if (o instanceof Double JavaDoc) {
742             return ((Double JavaDoc)o).doubleValue();
743         } else if (o instanceof String JavaDoc) {
744             return Double.parseDouble((String JavaDoc)o);
745         } else {
746             return defaultValue;
747         }
748     }
749     
750     /**
751      * This method converts the passed double to Double
752      * object and binds it into context.
753      * Use {@link #putObject} with null value to remove binding.
754      *
755      * @param bindingName binding name
756      * @param value value
757      */

758     public void putDouble(String JavaDoc bindingName, double value) {
759         putObject(bindingName, new Double JavaDoc(value));
760     }
761
762     /**
763      * Retrieve font value.
764      *
765      * @param bindingName binding name
766      * @param defaultValue default value returned if this binding does not exist
767      * @return retrieved value or defaultValue if this binding does not exist
768      */

769     public Font getFont(String JavaDoc bindingName, Font defaultValue) {
770         Object JavaDoc o = getObject(bindingName, null);
771         if (o == null) {
772             return defaultValue;
773         } else if (o instanceof Font) {
774             return (Font)o;
775         } else if (o instanceof String JavaDoc) {
776             return Font.decode((String JavaDoc)o);
777         } else {
778             return defaultValue;
779         }
780     }
781     
782     /**
783      * This is just convenient method. Its functionality is equal
784      * to {@link #putObject}. Use null value to remove binding.
785      *
786      * @param bindingName binding name
787      * @param value value
788      */

789     public void putFont(String JavaDoc bindingName, Font value) {
790         putObject(bindingName, value);
791     }
792
793     /**
794      * Retrieve color value.
795      *
796      * @param bindingName binding name
797      * @param defaultValue default value returned if this binding does not exist
798      * @return retrieved value or defaultValue if this binding does not exist
799      */

800     public Color getColor(String JavaDoc bindingName, Color defaultValue) {
801         Object JavaDoc o = getObject(bindingName, null);
802         if (o == null) {
803             return defaultValue;
804         } else if (o instanceof Color) {
805             return (Color)o;
806         } else if (o instanceof String JavaDoc) {
807             return Color.decode((String JavaDoc)o);
808         } else {
809             return defaultValue;
810         }
811     }
812     
813     /**
814      * This is just convenient method. Its functionality is equal
815      * to {@link #putObject}. Use null value to remove binding.
816      *
817      * @param bindingName binding name
818      * @param value value
819      */

820     public void putColor(String JavaDoc bindingName, Color value) {
821         putObject(bindingName, value);
822     }
823
824     /**
825      * Retrieve URL value.
826      *
827      * @param bindingName binding name
828      * @param defaultValue default value returned if this binding does not exist
829      * @return retrieved value or defaultValue if this binding does not exist
830      */

831     public URL JavaDoc getURL(String JavaDoc bindingName, URL JavaDoc defaultValue) {
832         Object JavaDoc o = getObject(bindingName, null);
833         if (o == null) {
834             return defaultValue;
835         } else if (o instanceof URL JavaDoc) {
836             return (URL JavaDoc)o;
837         } else if (o instanceof String JavaDoc) {
838             try {
839                 return new URL JavaDoc((String JavaDoc)o);
840             } catch (MalformedURLException JavaDoc ex) {
841                 return defaultValue;
842             }
843         } else {
844             return defaultValue;
845         }
846     }
847     
848     /**
849      * This is just convenient method. Its functionality is equal
850      * to {@link #putObject}. Use null value to remove binding.
851      *
852      * @param bindingName binding name
853      * @param value value
854      */

855     public void putURL(String JavaDoc bindingName, URL JavaDoc value) {
856         putObject(bindingName, value);
857     }
858
859     /**
860      * Retrieve string array by reading stored string and splitting it by the
861      * given separator into array of Strings.
862      *
863      * @param bindingName binding name
864      * @param separator separtor character
865      * @param defaultValue default value returned if this binding does not exist
866      * @return retrieved value or defaultValue if this binding does not exist
867      */

868     public String JavaDoc[] getStringArray(String JavaDoc bindingName, char separator, String JavaDoc[] defaultValue) {
869         String JavaDoc value = getString(bindingName, null);
870         if (value == null) {
871             return defaultValue;
872         }
873         StringTokenizer tok = new StringTokenizer(value, Character.toString(separator));
874         String JavaDoc sa[] = new String JavaDoc[tok.countTokens()];
875         int index = 0;
876         while (tok.hasMoreTokens()) {
877             sa[index] = tok.nextToken();
878             index++;
879         }
880         return sa;
881     }
882     
883     /**
884      * Store array of strings. The strings are compound into one String and
885      * separated by separator. The rest is same as in putString() method.
886      * Use null value to remove binding.
887      *
888      * @param bindingName binding name
889      * @param value value
890      * @param separator separator character
891      */

892     public void putStringArray(String JavaDoc bindingName, char separator, String JavaDoc[] value) {
893         if (value == null) {
894             putString(bindingName, null);
895             return;
896         }
897         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
898         for (int i=0; i<value.length; i++) {
899             sb.append(value[i]);
900             if (i+1<value.length) {
901                 sb.append(separator);
902             }
903         }
904         putString(bindingName, sb.toString());
905     }
906
907     
908     ////////////////////////////////////
909
// Attributes related methods:
910
////////////////////////////////////
911

912     /**
913      * Retrieve value of the attribute. Attributes can be specified
914      * on binding or context.
915      *
916      * @param bindingName name of the binding for binding attribute
917      * or null for context attribute
918      * @param attributeName name of the attribute to retrieve; cannot be null
919      * @param defaultValue default value returned when attribute does not exist
920      * @return retrieved value or defaultValue if this attribute does not exist
921      */

922     public String JavaDoc getAttribute(String JavaDoc bindingName, String JavaDoc attributeName, String JavaDoc defaultValue) {
923         Mutex.Privileged mp = getMutexPrivileged();
924         String JavaDoc value = null;
925         try {
926             mp.enterReadAccess();
927             value = delegate.getAttribute(bindingName, attributeName);
928         } catch (ContextException ex) {
929             if (errorManager.isLoggable(ErrorManager.INFORMATIONAL)) {
930                 errorManager.annotate(ex,
931                     NbBundle.getMessage(Context.class, "MSG_get_attr",
932                     bindingName == null ? attributeName : bindingName+"\\"+attributeName,
933                     getAbsoluteContextName()));
934                 errorManager.notify(ErrorManager.INFORMATIONAL, ex);
935             }
936         } finally {
937             mp.exitReadAccess();
938         }
939         if (value == null) {
940             value = defaultValue;
941         }
942         return value;
943     }
944     
945     /**
946      * Modify value of the attribute. Attributes can be specified
947      * on binding or context. Attribute is deleted by passing null as attribute value.
948      *
949      * @param bindingName name of the binding for binding attribute
950      * or null for context attribute
951      * @param attributeName name of the attribute to modify; cannot be null
952      * @param value new value of the attribute; null is allowed and means
953      * deletion of attribute
954      */

955     public void setAttribute(String JavaDoc bindingName, String JavaDoc attributeName, String JavaDoc value) {
956         Mutex.Privileged mp = getMutexPrivileged();
957         try {
958             mp.enterWriteAccess();
959             delegate.setAttribute(bindingName, attributeName, value);
960         } catch (ContextException ex) {
961             if (errorManager.isLoggable(ErrorManager.INFORMATIONAL)) {
962                 errorManager.annotate(ex,
963                     NbBundle.getMessage(Context.class, "MSG_put_attr",
964                     bindingName == null ? attributeName : bindingName+"\\"+attributeName,
965                      getAbsoluteContextName()));
966                 errorManager.notify(ErrorManager.INFORMATIONAL, ex);
967             }
968         } finally {
969             mp.exitWriteAccess();
970         }
971     }
972
973     
974     //////////////////////////////
975
// Listeners related methods:
976
//////////////////////////////
977

978     /**
979      * Add listener for receiving events about
980      * context and all its descendant subcontexts changes.
981      *
982      * This listener will be notified about added/removed subcontext,
983      * added/modified/removed binding and added/modified/removed
984      * context or binding attribute in this context and all its subcontexts.
985      * The {@link ContextEvent#getContext} must be consulted to learn in which
986      * context the change really happened.
987      *
988      * @param l listener to add
989      */

990     public synchronized void addContextListener(ContextListener l) {
991         delegate.addContextListener(l);
992     }
993     
994     /**
995      * Remove listener for receiving events about
996      * context and all its descendant subcontexts changes.
997      *
998      * @param l listener to remove
999      */

1000    public synchronized void removeContextListener(ContextListener l) {
1001        delegate.removeContextListener(l);
1002    }
1003
1004    
1005    
1006    /////////////////////////////////
1007
// Resettability of the context:
1008
/////////////////////////////////
1009

1010    
1011    /**
1012     * Exist a default value for this binding or context?
1013     *
1014     * @param bindingName the binding name or null for the context examination
1015     * @return true if there is a default; false in opposite case or when backend does
1016     * not support defaults at all.
1017     */

1018    public boolean hasDefault(String JavaDoc bindingName) {
1019        if (delegate instanceof ResettableContext) {
1020            return ((ResettableContext)delegate).hasDefault(bindingName);
1021        }
1022        return false;
1023    }
1024
1025    /**
1026     * Check whether the value of this binding or context is modified.
1027     * The return value is
1028     * always true in case default
1029     * value does not exist, ie. {@link #hasDefault} is false.
1030     *
1031     * @param bindingName the binding name or null for the context
1032     * @return true if default value is modified; always returns true if
1033     * default value does not exist
1034     */

1035    public boolean isModified(String JavaDoc bindingName) {
1036        if (delegate instanceof ResettableContext) {
1037            Mutex.Privileged mp = getMutexPrivileged();
1038            try {
1039                mp.enterReadAccess();
1040                return ((ResettableContext)delegate).isModified(bindingName);
1041            } finally {
1042                mp.exitReadAccess();
1043            }
1044        }
1045        return true;
1046    }
1047
1048    /**
1049     * Revert modification of this binding or context. Will do something
1050     * only if value is modified
1051     * (ie. {@link #isModified} returns true). If there is no default
1052     * value (ie. {@link #hasDefault} returns false) the revert operation
1053     * is identical to unbinding of object or destroying of content of context.
1054     *
1055     * @param bindingName the binding name or null for the context
1056     * @throws ContextException can throw exception if there were problems
1057     * during removal of modified values
1058     */

1059    public void revert(String JavaDoc bindingName) throws ContextException {
1060        Mutex.Privileged mp = getMutexPrivileged();
1061        if (delegate instanceof ResettableContext) {
1062            try {
1063                mp.enterWriteAccess();
1064                ((ResettableContext)delegate).revert(bindingName);
1065            } finally {
1066                mp.exitWriteAccess();
1067            }
1068            return;
1069        }
1070        // resettable is not implemented, but try at least to delete all the values.
1071
if (bindingName != null) {
1072            putObject(bindingName, null);
1073        } else {
1074            try {
1075                mp.enterWriteAccess();
1076                BasicContext ctx = delegate.getParentContext();
1077                String JavaDoc name = delegate.getContextName();
1078                ctx.destroySubcontext(name);
1079                ctx.createSubcontext(name);
1080            } finally {
1081                mp.exitWriteAccess();
1082            }
1083            //TODO:
1084
// - enumerate all bindings in this context and delete them
1085
// - enumerate all attributes in this context and delete them
1086
// - enumerate all subcontexts in this context and delete them
1087
}
1088    }
1089    
1090    /**
1091     * Shared Mutex on which all contexts are
1092     * synchronized. The API clients does not need to synchronize access to context.
1093     * But it can be convenient for example to do several changes under one lock.
1094     *
1095     * @return mutex instance
1096     */

1097    public static synchronized Mutex getMutex() {
1098        // temporary solution until there will exist public:
1099
return mutex;
1100    }
1101        
1102    public String JavaDoc toString() {
1103        return "Context: [absoluteName="+getAbsoluteContextName()+"] " + super.toString();
1104    }
1105    
1106    //////////////////////////////
1107
// Private implementation
1108
//////////////////////////////
1109

1110    
1111    static synchronized Context getApiContext(BasicContext ctx) {
1112        if (ctx == null) {
1113            return null;
1114        }
1115        
1116        WeakReference JavaDoc weakRef = (WeakReference JavaDoc)contextCache.get(ctx);
1117        Context apiCtx = (weakRef != null) ? (Context)weakRef.get() : null;
1118        if (apiCtx == null) {
1119            apiCtx = new Context(ctx);
1120            contextCache.put(ctx, new WeakReference JavaDoc(apiCtx));
1121        }
1122        return apiCtx;
1123    }
1124
1125
1126    private Mutex.Privileged getMutexPrivileged() {
1127        return privilegedMutex;
1128    }
1129
1130    
1131    private static synchronized BasicContext getRC() {
1132        if (defaultRootContext == null) {
1133            defaultRootContext = (BasicContext)Lookup.getDefault().lookup(BasicContext.class);;
1134            if (defaultRootContext == null) {
1135                errorManager.log(ErrorManager.EXCEPTION,
1136                    "FATAL ERROR: RootContext was not found in the default lookup! "+ //NOI18N
1137
"All Registry API operations will fail!! "+ //NOI18N
1138
"CAUSE: Either the org-netbeans-core-registry-1-?.?.jar module does not exist "+ //NOI18N
1139
"or its implementation dependency on org-netbeans-modules-registry-1-?.?.jar "+ //NOI18N
1140
"could not be fulfilled and therefore it was not installed. "+ //NOI18N
1141
"SOLUTION: rebuild both modules together."); //NOI18N
1142
}
1143        }
1144        return defaultRootContext;
1145    }
1146    
1147}
1148
Popular Tags