diff --git a/api.debugger/apichanges.xml b/api.debugger/apichanges.xml
--- a/api.debugger/apichanges.xml
+++ b/api.debugger/apichanges.xml
@@ -309,6 +309,25 @@
+
+
+ Support for providing initial values of properties.
+
+
+
+
+
+
+ Properties.Initializer interface introduced to provide initial
+ values of properties. This is necessary when properties are
+ accessed from more places and it's not practical to copy default
+ values to every such location.
+
+
+
+
+
+
diff --git a/api.debugger/manifest.mf b/api.debugger/manifest.mf
--- a/api.debugger/manifest.mf
+++ b/api.debugger/manifest.mf
@@ -1,4 +1,4 @@
Manifest-Version: 1.0
OpenIDE-Module: org.netbeans.api.debugger/1
OpenIDE-Module-Localizing-Bundle: org/netbeans/api/debugger/Bundle.properties
-OpenIDE-Module-Specification-Version: 1.16
+OpenIDE-Module-Specification-Version: 1.17
diff --git a/api.debugger/src/org/netbeans/api/debugger/Properties.java b/api.debugger/src/org/netbeans/api/debugger/Properties.java
--- a/api.debugger/src/org/netbeans/api/debugger/Properties.java
+++ b/api.debugger/src/org/netbeans/api/debugger/Properties.java
@@ -66,6 +66,7 @@
import org.openide.filesystems.FileLock;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
+import org.openide.util.Exceptions;
import org.openide.util.RequestProcessor;
@@ -355,7 +356,28 @@
*/
public void write (Object object, Properties properties);
}
-
+
+ /**
+ * Implementing this interface one can define initial values of properties.
+ */
+ public interface Initializer {
+
+ /**
+ * The list of supported property names.
+ * @return the property names supported by this initializer
+ */
+ String[] getSupportedPropertyNames();
+
+ /**
+ * Get the default value of property.
+ * @param propertyName The name of the property
+ * @return The default value
+ */
+ Object getDefaultPropertyValue(String propertyName);
+
+ }
+
+
private final static class PrimitiveRegister {
private HashMap properties = new HashMap ();
@@ -486,94 +508,160 @@
private static final Map BAD_MAP = new HashMap ();
private static final Collection BAD_COLLECTION = new ArrayList ();
private static final Object[] BAD_ARRAY = new Object [0];
-
- private List extends Reader> readersList;
- private HashMap register;
-
-
+
+ ServicesHolder readers = new ReaderHolder();
+ ServicesHolder initializers = new InitializerHolder();
+
+ private static abstract class ServicesHolder {
+
+ private Class clazz;
+ // Holds the list to prevent from garbage-collect. Do not remove!
+ private List extends T> servicesList;
+ protected HashMap register;
+
+ public ServicesHolder(Class clazz) {
+ this.clazz = clazz;
+ }
+
+ private final void init() {
+ register = new HashMap();
+ final List extends T> list = DebuggerManager.getDebuggerManager().lookup(null, clazz);
+ servicesList = list;
+ synchronized (list) {
+ for (T s : list) {
+ registerService(s);
+ }
+ }
+ ((Customizer) list).addPropertyChangeListener(
+ new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent evt) {
+ synchronized (ServicesHolder.this) {
+ Set registeredServices = new HashSet(register.values());
+ synchronized (list) {
+ for (T s : list) {
+ if (!registeredServices.remove(s)) {
+ registerService(s);
+ }
+ }
+ }
+ for (T s : registeredServices) {
+ unregisterService(s);
+ }
+ }
+ }
+ });
+ ((Customizer) list).setObject(Lookup.NOTIFY_LOAD_FIRST);
+ ((Customizer) list).setObject(Lookup.NOTIFY_UNLOAD_LAST);
+ }
+
+ protected abstract void registerService(T s);
+
+ protected abstract void unregisterService(T s);
+
+ public synchronized T find(String name) {
+ if (register == null) {
+ init();
+ }
+ return register.get(name);
+ }
+
+ }
+
+ private static final class ReaderHolder extends ServicesHolder {
+
+ public ReaderHolder() {
+ super(Reader.class);
+ }
+
+ @Override
+ protected void registerService(Reader r) {
+ //System.err.println("registerReader("+r+")");
+ String[] ns = r.getSupportedClassNames ();
+ int j, jj = ns.length;
+ for (j = 0; j < jj; j++) {
+ register.put (ns [j], r);
+ }
+ }
+
+ @Override
+ protected void unregisterService(Reader r) {
+ //System.err.println("unregisterReader("+r+")");
+ String[] ns = r.getSupportedClassNames ();
+ int j, jj = ns.length;
+ for (j = 0; j < jj; j++) {
+ register.remove (ns [j]);
+ }
+ }
+
+ @Override
+ public synchronized Reader find(String typeID) {
+
+ Reader r = super.find(typeID);
+ if (r != null) return r;
+
+ Class c = null;
+ try {
+ c = getClassLoader ().loadClass (typeID);
+ } catch (ClassNotFoundException e) {
+ ErrorManager.getDefault().notify(e);
+ return null;
+ }
+ while ((c != null) && (register.get (c.getName ()) == null)) {
+ c = c.getSuperclass ();
+ }
+ if (c != null)
+ r = (Reader) register.get (c.getName ());
+ return r;
+ }
+
+ }
+
+ private static final class InitializerHolder extends ServicesHolder {
+
+ public InitializerHolder() {
+ super(Initializer.class);
+ }
+
+ @Override
+ protected void registerService(Initializer i) {
+ //System.err.println("registerInitializer("+i+")");
+ String[] ns = i.getSupportedPropertyNames();
+ int j, jj = ns.length;
+ for (j = 0; j < jj; j++) {
+ register.put (ns [j], i);
+ }
+ }
+
+ @Override
+ protected void unregisterService(Initializer i) {
+ //System.err.println("unregisterInitializer("+i+")");
+ String[] ns = i.getSupportedPropertyNames ();
+ int j, jj = ns.length;
+ for (j = 0; j < jj; j++) {
+ register.remove (ns [j]);
+ }
+ }
+ }
+
+
private PrimitiveRegister impl = new PrimitiveRegister ();
- private void initReaders () {
- register = new HashMap();
- readersList = DebuggerManager.getDebuggerManager().lookup(null, Reader.class);
- synchronized (readersList) {
- for (Reader r : readersList) {
- registerReader(r);
+
+ private T getInitialValue(String propertyName, Class clazz) {
+ Initializer initializer = initializers.find(propertyName);
+ if (initializer != null) {
+ Object value = initializer.getDefaultPropertyValue(propertyName);
+ if (value != null && !clazz.isAssignableFrom(value.getClass())) {
+ Exceptions.printStackTrace(new IllegalStateException(
+ "Value ("+value+") of a bad type ("+value.getClass()+") returned by "+initializer+
+ " for property '"+propertyName+"'. It can not be cast to "+clazz));
+ value = null;
}
- }
- ((Customizer) readersList).addPropertyChangeListener(
- new PropertyChangeListener() {
- public void propertyChange(PropertyChangeEvent evt) {
- synchronized (PropertiesImpl.this) {
- Set registeredReaders = new HashSet(register.values());
- synchronized (readersList) {
- for (Reader r : readersList) {
- if (!registeredReaders.remove(r)) {
- registerReader(r);
- }
- }
- }
- for (Reader r : registeredReaders) {
- unregisterReader(r);
- }
- }
- }
- });
- ((Customizer) readersList).setObject(Lookup.NOTIFY_LOAD_FIRST);
- ((Customizer) readersList).setObject(Lookup.NOTIFY_UNLOAD_LAST);
- }
-
- private void registerReader(Reader r) {
- //System.err.println("registerReader("+r+")");
- String[] ns = r.getSupportedClassNames ();
- int j, jj = ns.length;
- for (j = 0; j < jj; j++) {
- register.put (ns [j], r);
+ return (T) value;
+ } else {
+ return null;
}
}
-
- private void unregisterReader(Reader r) {
- //System.err.println("unregisterReader("+r+")");
- String[] ns = r.getSupportedClassNames ();
- int j, jj = ns.length;
- for (j = 0; j < jj; j++) {
- register.remove (ns [j]);
- }
- }
-
- // Used from tests
- synchronized void addReader(Reader r) {
- if (register == null) {
- initReaders ();
- }
- registerReader(r);
- }
-
- private synchronized Reader findReader (String typeID) {
- if (register == null) {
- initReaders ();
- }
-
- Reader r = (Reader) register.get (typeID);
- if (r != null) return r;
-
- Class c = null;
- try {
- c = getClassLoader ().loadClass (typeID);
- } catch (ClassNotFoundException e) {
- ErrorManager.getDefault().notify(e);
- return null;
- }
- while ((c != null) && (register.get (c.getName ()) == null)) {
- c = c.getSuperclass ();
- }
- if (c != null)
- r = (Reader) register.get (c.getName ());
- return r;
- }
-
-
-
// primitive properties ....................................................................................
@@ -710,7 +798,13 @@
public Object getObject (String propertyName, Object defaultValue) {
synchronized(impl) {
String typeID = impl.getProperty (propertyName, null);
- if (typeID == null) return defaultValue;
+ if (typeID == null) {
+ Object initialValue = getInitialValue(propertyName, Object.class);
+ if (initialValue == null) {
+ initialValue = defaultValue;
+ }
+ return initialValue;
+ }
if (typeID.equals ("# null"))
return null;
if (!typeID.startsWith ("# ")) {
@@ -745,7 +839,7 @@
return co;
}
}
- Reader r = findReader (typeID);
+ Reader r = readers.find(typeID);
if (r == null) {
ErrorManager.getDefault().log("Can not read object. No reader registered for type " + typeID + ".");
return defaultValue;
@@ -778,7 +872,7 @@
}
// find register
- Reader r = findReader (value.getClass ().getName ());
+ Reader r = readers.find(value.getClass ().getName ());
if (r == null) {
ErrorManager.getDefault().log ("Can not write object " + value);
return;
@@ -794,8 +888,11 @@
synchronized(impl) {
String arrayType = impl.getProperty (propertyName + ".array_type", null);
if (arrayType == null) {
- ErrorManager.getDefault().log("Unknown array type for "+propertyName);
- return defaultValue;
+ Object[] initialValue = getInitialValue(propertyName, Object[].class);
+ if (initialValue == null) {
+ initialValue = defaultValue;
+ }
+ return initialValue;
}
Properties p = getProperties (propertyName);
int l = p.getInt ("length", -1);
@@ -834,7 +931,13 @@
public Collection getCollection (String propertyName, Collection defaultValue) {
synchronized(impl) {
String typeID = impl.getProperty (propertyName, null);
- if (typeID == null) return defaultValue;
+ if (typeID == null) {
+ Collection initialValue = getInitialValue(propertyName, Collection.class);
+ if (initialValue == null) {
+ initialValue = defaultValue;
+ }
+ return initialValue;
+ }
if (!typeID.startsWith ("# ")) return defaultValue;
Collection c = null;
try {
@@ -886,7 +989,13 @@
public Map getMap (String propertyName, Map defaultValue) {
synchronized(impl) {
String typeID = impl.getProperty (propertyName, null);
- if (typeID == null) return defaultValue;
+ if (typeID == null) {
+ Map initialValue = getInitialValue(propertyName, Map.class);
+ if (initialValue == null) {
+ initialValue = defaultValue;
+ }
+ return initialValue;
+ }
if (!typeID.startsWith ("# ")) return defaultValue;
Map m = null;
try {