|
What this is
Other links
The source code/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2003 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.api.registry; import org.netbeans.modules.registry.ApiContextFactory; import org.netbeans.modules.registry.OrderingSupport; import org.netbeans.spi.registry.BasicContext; import org.netbeans.spi.registry.MergedContextProvider; import org.netbeans.spi.registry.ResettableContext; import org.netbeans.spi.registry.SpiUtils; import org.openide.ErrorManager; import org.openide.util.Lookup; import org.openide.util.Mutex; import org.openide.util.NbBundle; import java.awt.*; import java.beans.PropertyChangeListener; import java.lang.ref.WeakReference; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.List; /** * This API class is representing a context which consists of a set of * name-to-object bindings. It contains methods for examining and * updating these bindings. The contexts are composed into * hierarchical collection which form configuration system. The * configuration system allows applicatioRootns to store and retrieve * data. How data are stored is not specified by the Registry API. * It is up to provided implementation of Registry SPI to properly * document it and that documentation must be consulted. * *
Getters do not throw exceptions. They accept default value parameter which * is returned if value does not exist or it could not be read. The exceptions are logged. * * Putting null value removes the binding. * * Rename of binding is not supported because no useful usecase was found. * * All methods are properly synchronized and can be accessed from multiple * threads without any synchronization on the client side. During the modification is * whole hierarchy of contexts exclusively locked. * * TBD: Names restrictions: length, valid characters, etc. * The context name nor binding name cannot contain "/" character. * * @author David Konecny */ public final class Context { /** SPI context to which this API context delegates most of the calls. */ BasicContext delegate; /** Cache of the created API contexts. The key is is SPI context and * value is WeakReference to API context. */ private static WeakHashMap contextCache = new WeakHashMap(); // This should theoretically be in ApiContextFactoryImpl, but that would // mean that variable ApiContextFactory.DEFAULT would not initialized // before ApiContextFactoryImpl was loaded into VM what can be sometimes // too late. On the other hand Context class is loaded as one of the first classes. // That's why it is here. private static final Mutex.Privileged privilegedMutex = new Mutex.Privileged(); private static final Mutex mutex = new Mutex (privilegedMutex); static { ApiContextFactory.DEFAULT = new ApiContextFactoryImpl(); } private static BasicContext defaultRootContext; private Context(BasicContext delegate) { this.delegate = delegate; } /////////////////////////// // Context related methods: /////////////////////////// /** * Getter for default instance of registry. * * Application specific documentation must be consulted to learn which
* exact implementation will be returned by this method. For example for
* NetBeans it can be implementation working on top of the root of
* SystemFileSystem.
*
* @return default root context
*/
public static Context getDefault() {
return Context.getApiContext(getRC());
}
/**
* Returns context, that merges all its delegates. See JavaDoc overview for more details.
* @param delegates array of contexts that should be merged
* @return merged context
* @since 1.6
*/
public static Context merge (final Context[] delegates) {
BasicContext mergedBasic = SpiUtils.merge(new MergedContextProvider() {
public void addPropertyChangeListener(PropertyChangeListener listener) {
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
}
public BasicContext[] getDelegates() {
List basicDelegates = new ArrayList();
for (int i = 0; i < delegates.length; i++) {
Context delegate = delegates[i];
basicDelegates.add(delegate.delegate);
}
return (BasicContext[])basicDelegates.toArray(new BasicContext[0]);
}
});
return SpiUtils.createContext(mergedBasic);
}
/**
* Name of the context.
*
* @return name of the context; cannot be null
*/
public String getContextName() {
return delegate.getContextName();
}
/**
* Gets root context.
*
* @return root context
*/
public Context getRootContext() {
return getApiContext(delegate.getRootContext());
}
/**
* Getter for the absolute name of the context, eg. "/mymodule/mysettings".
* It is full path from the root context.
*
* @return absolute name of this context; cannot be null
*/
public String getAbsoluteContextName() {
BasicContext ctx = delegate;
StringBuffer sb = new StringBuffer(ctx.getContextName());
while (ctx.getParentContext() != null) {
ctx = ctx.getParentContext();
if (ctx.getContextName().equals("/")) {
sb.insert(0, ctx.getContextName());
} else {
sb.insert(0, "/");
sb.insert(0, ctx.getContextName());
}
}
return sb.toString();
}
/**
* Retrieve subcontext of the given name. The multi-level path
* is accepted as subcontext name (eg. "sub1/sub2/mysub").
*
* @param subcontextName multi-level subcontext name to retrieve
* @return Context or null if subcontext does not exist
*/
public Context getSubcontext(String subcontextName) {
Mutex.Privileged mp = getMutexPrivileged();
try {
mp.enterReadAccess();
StringTokenizer tok = new StringTokenizer(subcontextName, "/"); // NOI18N
BasicContext ctx = delegate;
while (tok.hasMoreTokens() && ctx != null) {
String name = tok.nextToken();
ctx = ctx.getSubcontext(name);
}
return getApiContext(ctx);
} finally {
mp.exitReadAccess();
}
}
/**
* Retrieve parent context.
*
* @return parent context or null in case of root context
*/
public Context getParentContext() {
Mutex.Privileged mp = getMutexPrivileged();
try {
mp.enterReadAccess();
return getApiContext(delegate.getParentContext());
} finally {
mp.exitReadAccess();
}
}
/**
* Create subcontext of the given name. The multi-level path
* is accepted as subcontext name (eg. "sub1/sub2/mysub"). All
* intermediate subcontexts which do not exist will be created. If
* subcontext already exist it is just retrieved.
*
* @param subcontextName multi-level subcontext name to create
* @return created or retrieved context
* @throws ContextException thrown when subcontext cannot be created
*/
public Context createSubcontext(String subcontextName) throws ContextException {
Mutex.Privileged mp = getMutexPrivileged();
try {
mp.enterWriteAccess();
StringTokenizer tok = new StringTokenizer(subcontextName, "/"); // NOI18N
BasicContext ctx = delegate;
while (tok.hasMoreTokens()) {
String name = tok.nextToken();
BasicContext ctx2 = ctx.getSubcontext(name);
if (ctx2 != null) {
ctx = ctx2;
} else {
ctx = ctx.createSubcontext(name);
}
}
return getApiContext(ctx);
} finally {
mp.exitWriteAccess();
}
}
/**
* Destroy subcontext of the given name. Destroying context deletes
* also all its data recursively, ie. all bindings, attributes
* and its subcontexts. The multi-level path is accepted
* (eg. "sub1/sub2/mysub").
*
* @param subcontextName multi-level name of existing subcontext
* @throws ContextException thrown when subcontext cannot be deleted
*/
public void destroySubcontext(String subcontextName) throws ContextException {
int index = subcontextName.lastIndexOf('/');
BasicContext ctx = delegate;
if (index != -1) {
ctx = getSubcontext(subcontextName.substring(0, index)).delegate;
subcontextName = subcontextName.substring(index+1);
}
Mutex.Privileged mp = getMutexPrivileged();
try {
mp.enterWriteAccess();
ctx.destroySubcontext(subcontextName);
} finally {
mp.exitWriteAccess();
}
}
///////////////////////////////
// Context enumeration methods:
///////////////////////////////
/**
* Retrieve names of all subcontexts of this context.
*
* @return collection of Strings, ie. names of all subcontexts in the context;
* cannot be null
*/
public Collection/* See Javadoc overview for how the context items are sorted. * If context content was ordered by {@link #orderContext} method * then the items will be listed in this order (order of items which were * not specified in the full order is undefined). * * @return collection of ordered Objects, ie. both instances of bound * Objects and Contexts representing subcontexts are returned. */ public List getOrderedObjects() { Mutex.Privileged mp = getMutexPrivileged(); try { mp.enterReadAccess(); List ar = new ArrayList(); Iterator it = OrderingSupport.DEFAULT.getOrderedNames(this).iterator(); while (it.hasNext()) { String item = (String)it.next(); if (item.endsWith("/")) { Context ctx = getSubcontext(item.substring(0, item.length()-1)); if (ctx != null) { ar.add(ctx); } } else { Object o = getObject(item, null); if (o != null) { ar.add(o); } } } return ar; } finally { mp.exitReadAccess(); } } /** * Method listing ordered names of the context items. The returned list * will contain names of all direct subcontexts and all bound * objects in this context. The subcontext names are appended * with "/" character. It can be used to distinguish subcontext name * and binding name when they are the same. * * See the JavaDoc for {@link #getOrderedObjects} method for * more details about ordering itself. * * @return collection of Strings; contains binding names and subcontext * names appended with "/" character * * @since 1.4 */ public List getOrderedNames() { Mutex.Privileged mp = getMutexPrivileged(); try { mp.enterReadAccess(); return OrderingSupport.DEFAULT.getOrderedNames(this); } finally { mp.exitReadAccess(); } } /////////////////////////////// // Bindings related methods: /////////////////////////////// /** * Retrieve named object from the context. * * If retrieved object is instance of {@link ObjectRef} it is recursively * dereferenced and the value of ObjectRef instance if returned instead. * If dereferenced value is null or ObjectRef is invalid then the ObjectRef * instance is returned. See {@link #getRef} if you need to retrieve * ObjectRef directly. * * @param bindingName the name of the object to retrieve; cannot be empty * @param defaultValue default value returned in case the binding does not * exist. * @return retrieved value or defaultValue if this binding does not exist */ public Object getObject(String bindingName, Object defaultValue) { Object o = getObject(bindingName); if (o instanceof ObjectRef) { // it is ObjectRef -> dereference it: Object origin = o; while (o != null && o instanceof ObjectRef) { o = ((ObjectRef)o).getObject(); } // if the resulted value is null then return ObjectRef: if (o == null) { o = origin; } } if (o == null) { return defaultValue; } else { return o; } } /** * Retrieve directly the bounded ObjectRef instance. The {@link #getObject} * does recursive traversal of ObjectRef and returns directly the referenced value. * * @param bindingName the name of the object to retrieve; cannot be empty * @return instance of the ObjectRef or null if bound object is not ObjectRef */ public ObjectRef getRef(String bindingName) { Object o = getObject(bindingName); if (o instanceof ObjectRef) { return (ObjectRef)o; } else { return null; } } private Object getObject(String bindingName) { Object o = null; Mutex.Privileged mp = getMutexPrivileged(); try { mp.enterReadAccess(); o = delegate.lookupObject(bindingName); } catch (ContextException ex) { ErrorManager.getDefault().annotate(ex, NbBundle.getMessage(Context.class, "MSG_get_object", bindingName, getAbsoluteContextName())); ErrorManager.getDefault().notify(ErrorManager.ERROR, ex); } finally { mp.exitReadAccess(); } return o; } /** * Binds a name to an object and store the object in context. Use null * value to remove binding. * * See class overview JavaDoc for more details about how
* the objects are stored and which object types are supported.
*
* @param bindingName the name to bind; cannot be empty
* @param value the object to bind; null is allowed and means
* deletion of the binding
*/
public void putObject(String bindingName, Object value) {
Mutex.Privileged mp = getMutexPrivileged();
try {
mp.enterWriteAccess();
delegate.bindObject(bindingName, value);
} catch (ContextException ex) {
ErrorManager.getDefault().annotate(ex,
NbBundle.getMessage(Context.class, "MSG_put_object", bindingName, getAbsoluteContextName()));
ErrorManager.getDefault().notify(ErrorManager.ERROR, ex);
} finally {
mp.exitWriteAccess();
}
}
/**
* Retrieve String value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public String getString(String bindingName, String defaultValue) {
Object o = getObject(bindingName, null);
if (o == null || !(o instanceof String) ) {
return defaultValue;
} else {
return (String)o;
}
}
/**
* Binds a name to the String and store it in the context. Use null
* value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putString(String bindingName, String value) {
putObject(bindingName, value);
}
/**
* Retrieve integer value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public int getInt(String bindingName, int defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Integer) {
return ((Integer)o).intValue();
} else if (o instanceof String) {
return Integer.parseInt((String)o);
} else {
return defaultValue;
}
}
/**
* This method converts the passed integer to Integer
* object and binds it into context.
* Use {@link #putObject} with null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putInt(String bindingName, int value) {
putObject(bindingName, new Integer(value));
}
/**
* Retrieve long value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public long getLong(String bindingName, long defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Long) {
return ((Long)o).longValue();
} else if (o instanceof String) {
return Long.parseLong((String)o);
} else {
return defaultValue;
}
}
/**
* This method converts the passed long to Long
* object and binds it into context.
* Use {@link #putObject} with null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putLong(String bindingName, long value) {
putObject(bindingName, new Long(value));
}
/**
* Retrieve boolean value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public boolean getBoolean(String bindingName, boolean defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Boolean) {
return ((Boolean)o).booleanValue();
} else if (o instanceof String) {
return Boolean.valueOf((String)o).booleanValue();
} else {
return defaultValue;
}
}
/**
* This method converts the passed boolean to Boolean
* object and binds it into context.
* Use {@link #putObject} with null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putBoolean(String bindingName, boolean value) {
putObject(bindingName, Boolean.valueOf(value));
}
/**
* Retrieve float value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public float getFloat(String bindingName, float defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Float) {
return ((Float)o).floatValue();
} else if (o instanceof String) {
return Float.parseFloat((String)o);
} else {
return defaultValue;
}
}
/**
* This method converts the passed float to Float
* object and binds it into context.
* Use {@link #putObject} with null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putFloat(String bindingName, float value) {
putObject(bindingName, new Float(value));
}
/**
* Retrieve double value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public double getDouble(String bindingName, double defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Double) {
return ((Double)o).doubleValue();
} else if (o instanceof String) {
return Double.parseDouble((String)o);
} else {
return defaultValue;
}
}
/**
* This method converts the passed double to Double
* object and binds it into context.
* Use {@link #putObject} with null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putDouble(String bindingName, double value) {
putObject(bindingName, new Double(value));
}
/**
* Retrieve font value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public Font getFont(String bindingName, Font defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Font) {
return (Font)o;
} else if (o instanceof String) {
return Font.decode((String)o);
} else {
return defaultValue;
}
}
/**
* This is just convenient method. Its functionality is equal
* to {@link #putObject}. Use null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putFont(String bindingName, Font value) {
putObject(bindingName, value);
}
/**
* Retrieve color value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public Color getColor(String bindingName, Color defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof Color) {
return (Color)o;
} else if (o instanceof String) {
return Color.decode((String)o);
} else {
return defaultValue;
}
}
/**
* This is just convenient method. Its functionality is equal
* to {@link #putObject}. Use null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putColor(String bindingName, Color value) {
putObject(bindingName, value);
}
/**
* Retrieve URL value.
*
* @param bindingName binding name
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public URL getURL(String bindingName, URL defaultValue) {
Object o = getObject(bindingName, null);
if (o == null) {
return defaultValue;
} else if (o instanceof URL) {
return (URL)o;
} else if (o instanceof String) {
try {
return new URL((String)o);
} catch (MalformedURLException ex) {
return defaultValue;
}
} else {
return defaultValue;
}
}
/**
* This is just convenient method. Its functionality is equal
* to {@link #putObject}. Use null value to remove binding.
*
* @param bindingName binding name
* @param value value
*/
public void putURL(String bindingName, URL value) {
putObject(bindingName, value);
}
/**
* Retrieve string array by reading stored string and splitting it by the
* given separator into array of Strings.
*
* @param bindingName binding name
* @param separator separtor character
* @param defaultValue default value returned if this binding does not exist
* @return retrieved value or defaultValue if this binding does not exist
*/
public String[] getStringArray(String bindingName, char separator, String[] defaultValue) {
String value = getString(bindingName, null);
if (value == null) {
return defaultValue;
}
StringTokenizer tok = new StringTokenizer(value, Character.toString(separator));
String sa[] = new String[tok.countTokens()];
int index = 0;
while (tok.hasMoreTokens()) {
sa[index] = tok.nextToken();
index++;
}
return sa;
}
/**
* Store array of strings. The strings are compound into one String and
* separated by separator. The rest is same as in putString() method.
* Use null value to remove binding.
*
* @param bindingName binding name
* @param value value
* @param separator separator character
*/
public void putStringArray(String bindingName, char separator, String[] value) {
if (value == null) {
putString(bindingName, null);
return;
}
StringBuffer sb = new StringBuffer();
for (int i=0; i |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.