package org.jboss.util.property;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.List;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Map;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Collections;
import java.util.Properties;
import javax.naming.Context;
import javax.naming.ldap.LdapContext;
import org.jboss.util.NullArgumentException;
public class PropertyMap
extends Properties
{
public static final String PROPERTY_NAME_SEPARATOR = ".";
public static final String[] EMPTY_ARRAY_PROPERTY = new String[0];
protected transient List unboundListeners;
protected transient Map boundListeners;
private transient Map jndiMap;
private final static Object NULL_VALUE = new Object();
public PropertyMap(Properties defaults)
{
super(defaults);
init();
}
public PropertyMap()
{
this(null);
}
private void init()
{
unboundListeners = Collections.synchronizedList(new ArrayList());
boundListeners = Collections.synchronizedMap(new HashMap());
Object value;
jndiMap = new HashMap();
value = System.getProperty(Context.PROVIDER_URL);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.PROVIDER_URL, value);
value = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.INITIAL_CONTEXT_FACTORY, value);
value = System.getProperty(Context.OBJECT_FACTORIES);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.OBJECT_FACTORIES, value);
value = System.getProperty(Context.URL_PKG_PREFIXES);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.URL_PKG_PREFIXES, value);
value = System.getProperty(Context.STATE_FACTORIES);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.STATE_FACTORIES, value);
value = System.getProperty(Context.DNS_URL);
if (value == null) value = NULL_VALUE;
jndiMap.put(Context.DNS_URL, value);
value = System.getProperty(LdapContext.CONTROL_FACTORIES);
if (value == null) value = NULL_VALUE;
jndiMap.put(LdapContext.CONTROL_FACTORIES, value);
}
private void updateJndiCache(String name, String value)
{
if( name == null )
return;
boolean isJndiProperty = name.equals(Context.PROVIDER_URL)
|| name.equals(Context.INITIAL_CONTEXT_FACTORY)
|| name.equals(Context.OBJECT_FACTORIES)
|| name.equals(Context.URL_PKG_PREFIXES)
|| name.equals(Context.STATE_FACTORIES)
|| name.equals(Context.DNS_URL)
|| name.equals(LdapContext.CONTROL_FACTORIES)
;
if( isJndiProperty == true )
jndiMap.put(name, value);
}
public Object put(Object name, Object value)
{
if (name == null)
throw new NullArgumentException("name");
boolean add = !containsKey(name);
Object prev = super.put(name, value);
PropertyEvent event =
new PropertyEvent(this, name.toString(), value.toString());
if (add)
{
firePropertyAdded(event);
}
else
{
firePropertyChanged(event);
}
return prev;
}
public Object remove(Object name)
{
if (name == null)
throw new NullArgumentException("name");
boolean contains = containsKey(name);
Object value = null;
if (contains)
{
value = super.remove(name);
if (defaults != null)
{
Object obj = defaults.remove(name);
if (value == null)
{
value = obj;
}
}
jndiMap.remove(name);
PropertyEvent event = new PropertyEvent(this, name.toString(), value.toString());
firePropertyRemoved(event);
}
return value;
}
public Set keySet(final boolean includeDefaults)
{
if (includeDefaults)
{
Set set = new HashSet();
set.addAll(defaults.keySet());
set.addAll(super.keySet());
return Collections.synchronizedSet(set);
}
return super.keySet();
}
public Set entrySet(final boolean includeDefaults)
{
if (includeDefaults)
{
Set set = new HashSet();
set.addAll(defaults.entrySet());
set.addAll(super.entrySet());
return Collections.synchronizedSet(set);
}
return super.entrySet();
}
public void addPropertyListener(PropertyListener listener)
{
if (listener == null)
throw new NullArgumentException("listener");
if (listener instanceof BoundPropertyListener)
{
addPropertyListener((BoundPropertyListener) listener);
}
else
{
if (!unboundListeners.contains(listener))
unboundListeners.add(listener);
}
}
protected void addPropertyListener(BoundPropertyListener listener)
{
String name = listener.getPropertyName();
List list = (List) boundListeners.get(name);
if (list == null)
{
list = Collections.synchronizedList(new ArrayList());
boundListeners.put(name, list);
}
if (!list.contains(listener))
{
list.add(listener);
listener.propertyBound(this);
}
}
public void addPropertyListeners(PropertyListener[] listeners)
{
if (listeners == null)
throw new NullArgumentException("listeners");
for (int i = 0; i < listeners.length; i++)
{
addPropertyListener(listeners[i]);
}
}
public boolean removePropertyListener(PropertyListener listener)
{
if (listener == null)
throw new NullArgumentException("listener");
boolean removed = false;
if (listener instanceof BoundPropertyListener)
{
removed = removePropertyListener((BoundPropertyListener) listener);
}
else
{
removed = unboundListeners.remove(listener);
}
return removed;
}
protected boolean removePropertyListener(BoundPropertyListener listener)
{
String name = listener.getPropertyName();
List list = (List) boundListeners.get(name);
boolean removed = false;
if (list != null)
{
removed = list.remove(listener);
if (removed) listener.propertyUnbound(this);
}
return removed;
}
private void firePropertyAdded(List list, PropertyEvent event)
{
if (list == null) return;
int size = list.size();
for (int i = 0; i < size; i++)
{
PropertyListener listener = (PropertyListener) list.get(i);
listener.propertyAdded(event);
}
}
protected void firePropertyAdded(PropertyEvent event)
{
if (boundListeners != null)
{
List list = (List) boundListeners.get(event.getPropertyName());
if (list != null)
{
firePropertyAdded(list, event);
}
}
firePropertyAdded(unboundListeners, event);
}
private void firePropertyRemoved(List list, PropertyEvent event)
{
if (list == null) return;
int size = list.size();
for (int i = 0; i < size; i++)
{
PropertyListener listener = (PropertyListener) list.get(i);
listener.propertyRemoved(event);
}
}
protected void firePropertyRemoved(PropertyEvent event)
{
if (boundListeners != null)
{
List list = (List) boundListeners.get(event.getPropertyName());
if (list != null)
{
firePropertyRemoved(list, event);
}
}
firePropertyRemoved(unboundListeners, event);
}
private void firePropertyChanged(List list, PropertyEvent event)
{
if (list == null) return;
int size = list.size();
for (int i = 0; i < size; i++)
{
PropertyListener listener = (PropertyListener) list.get(i);
listener.propertyChanged(event);
}
}
protected void firePropertyChanged(PropertyEvent event)
{
if (boundListeners != null)
{
List list = (List) boundListeners.get(event.getPropertyName());
if (list != null)
{
firePropertyChanged(list, event);
}
}
firePropertyChanged(unboundListeners, event);
}
protected String makePrefixedPropertyName(String base, String prefix)
{
String name = base;
if (prefix != null)
{
StringBuffer buff = new StringBuffer(base);
if (prefix != null)
{
buff.insert(0, PROPERTY_NAME_SEPARATOR);
buff.insert(0, prefix);
}
return buff.toString();
}
return name;
}
public void load(String prefix, Map map) throws PropertyException
{
if (map == null)
throw new NullArgumentException("map");
Iterator iter = map.keySet().iterator();
while (iter.hasNext())
{
String key = String.valueOf(iter.next());
String name = makePrefixedPropertyName(key, prefix);
String value = String.valueOf(map.get(name));
setProperty(name, value);
}
}
public void load(Map map) throws PropertyException
{
load(null, map);
}
public void load(PropertyReader reader) throws PropertyException, IOException
{
if (reader == null)
throw new NullArgumentException("reader");
load(reader.readProperties());
}
public void load(String className) throws PropertyException, IOException
{
if (className == null)
throw new NullArgumentException("className");
PropertyReader reader = null;
try
{
Class type = Class.forName(className);
reader = (PropertyReader) type.newInstance();
}
catch (Exception e)
{
throw new PropertyException(e);
}
load(reader);
}
public Object setProperty(String name, String value)
{
updateJndiCache(name, value);
return put(name, value);
}
public String getProperty(String name)
{
Object value = jndiMap.get(name);
if (value != null)
{
return (value == NULL_VALUE) ? null : (String) value;
}
return super.getProperty(name);
}
public String removeProperty(String name)
{
return (String) remove(name);
}
protected String makeIndexPropertyName(String base, int index)
{
return base + PROPERTY_NAME_SEPARATOR + index;
}
public String[] getArrayProperty(String base, String[] defaultValues)
{
if (base == null)
throw new NullArgumentException("base");
List list = new LinkedList();
int i = 0;
while (true)
{
String name = makeIndexPropertyName(base, i);
String value = getProperty(name);
if (value != null)
{
list.add(value);
}
else if (i >= 0)
{
break; }
i++;
}
String values[] = defaultValues;
if (list.size() != 0)
{
values = (String[]) list.toArray(new String[list.size()]);
}
return values;
}
public String[] getArrayProperty(String name)
{
return getArrayProperty(name, EMPTY_ARRAY_PROPERTY);
}
public Iterator names()
{
return keySet().iterator();
}
public boolean containsProperty(String name)
{
return containsKey(name);
}
public PropertyGroup getPropertyGroup(String basename)
{
return new PropertyGroup(basename, this);
}
public PropertyGroup getPropertyGroup(String basename, int index)
{
String name = makeIndexPropertyName(basename, index);
return getPropertyGroup(name);
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException
{
init();
stream.defaultReadObject();
}
private void writeObject(ObjectOutputStream stream)
throws IOException
{
stream.defaultWriteObject();
}
}