You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/06/28 21:34:40 UTC

svn commit: r417856 [4/22] - in /incubator/openjpa/trunk/openjpa-lib: java/ main/ main/java/ main/java/org/apache/openjpa/lib/ant/ main/java/org/apache/openjpa/lib/conf/ main/java/org/apache/openjpa/lib/jdbc/ main/java/org/apache/openjpa/lib/log/ main/...

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/Value.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/Value.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/Value.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/Value.java Wed Jun 28 12:34:33 2006
@@ -15,364 +15,359 @@
  */
 package org.apache.openjpa.lib.conf;
 
-
-import java.util.*;
-
 import org.apache.commons.lang.*;
 
 import org.apache.openjpa.lib.util.*;
 
+import java.util.*;
+
 
-/** 
+/**
  *  A configuration value.
- *  
- *  @author  Marc Prud'hommeaux
+ *
+ *  @author Marc Prud'hommeaux
  */
-public abstract class Value
-	implements Cloneable
-{
-	private static final String[] EMPTY_ALIASES = new String[0];
-	private static final Localizer s_loc = Localizer.forPackage (Value.class);
-
-	private String 			prop	= null;
-	private String 			def 	= null;
-	private String[] 		aliases	= null;
-	private ValueListener	listen	= null;
-	private boolean			aliasListComprehensive = false;
-
-
-	/**
-	 *  Constructor.  Supply the property name.
-	 *
-	 *	@see	#setProperty
-	 */
-	public Value (String prop)
-	{
-		setProperty (prop);
-	}
-
-
-	/**
-	 *	Default constructor.
-	 */
-	public Value ()
-	{
-	}
-
-
-	/** 
-	 *  The property name that will be used when setting or
-	 *  getting this value in a {@link Map}.
-	 */
-	public String getProperty ()
-	{
-		return prop;
-	}
-
-
-	/** 
-	 *  The property name that will be used when setting or
-	 *  getting this value in a {@link Map}.
-	 */
-	public void setProperty (String prop)
-	{
-		this.prop = prop;
-	}
-
-
-	/**
-	 *	Aliases for the value in the form key1, value1, key2, value2, ...
-	 *	All alias values must be in string form.
-	 */
-	public String[] getAliases ()
-	{
-		return (aliases == null) ? EMPTY_ALIASES : aliases;
-	}
-
-
-	/**
-	 *	Aliases for the value in the form key1, value1, key2, value2, ...
-	 *	All alias values must be in string form.
-	 */
-	public void setAliases (String[] aliases)
-	{
-		this.aliases = aliases;
-	}
-
-
-	/**
-	 *	Replaces an existing alias, or adds the given alias to the front of the
-	 *	alias list if it does not already exist.  All alias values must be in 
-	 *	string form.
-	 */
-	public void setAlias (String key, String value)
-	{
-		String[] aliases = getAliases ();
-		for (int i = 0; i < aliases.length; i += 2)
-		{
-			if (key.equals (aliases[i]))
-			{
-				aliases[i + 1] = value;
-				return;
-			}
-		}
-
-		// add as new alias
-		String[] newAliases = new String[aliases.length + 2];
-		System.arraycopy (aliases, 0, newAliases, 2, aliases.length);
-		newAliases[0] = key;
-		newAliases[1] = value;
-		this.aliases = newAliases;
-	}
-
-
-	/**
-	 *	Whether or not the alias list defines all possible settings for this
-	 *	value. If so, an error will be generated when attempting to invoke
-	 *	any method on this value with an unknown option.
-	 */
-	public boolean isAliasListComprehensive ()
-	{
-		return aliasListComprehensive;
-	}
-
-
-	/**
-	 *	Whether or not the alias list defines all possible settings for this
-	 *	value. If so, an error will be generated when attempting to invoke
-	 *	any method on this value with an unknown option.
-	 */
-	public void setAliasListComprehensive (boolean aliasListIsComprehensive)
-	{
-		this.aliasListComprehensive = aliasListIsComprehensive;
-	}
-
-
-	/**
-	 *	Alias the given setting.
-	 */
-	public String alias (String str)
-	{
-		return alias (str, aliases, false);
-	}
-
-
-	/**
-	 *	Alias the given setting.
-	 */
-	protected String alias (String str, String[] aliases, boolean nullNotFound)
-	{
-		if (str != null)
-			str = str.trim ();
-		if (aliases == null || aliases.length == 0)
-			return (nullNotFound) ? null : str;
-
-		boolean empty = str != null && str.length () == 0;
-		for (int i = 1; i < aliases.length; i += 2)
-			if (StringUtils.equals (str, aliases[i])
-				|| (empty && aliases[i] == null))
-				return aliases[i - 1];	
-		return (nullNotFound) ? null : str;
-	}
-
-
-	/**
-	 *	Unalias the given setting.
-	 */
-	public String unalias (String str)
-	{
-		return unalias (str, aliases, false);
-	}
-
-
-	/**
-	 *	Unalias the given setting.
-	 */
-	protected String unalias (String str, String[] aliases, 
-		boolean nullNotFound)
-	{
-		if (str != null)
-			str = str.trim ();
-
-		boolean empty = str != null && str.length () == 0;
-		if (str == null || (empty && def != null))
-			str = def;
-		if (aliases != null)
-			for (int i = 0; i < aliases.length; i += 2)
-				if (StringUtils.equals (str, aliases[i])
-					|| StringUtils.equals (str, aliases[i+1])
-					|| (empty && aliases[i] == null))
-					return aliases[i + 1];
-
-		if (isAliasListComprehensive () && aliases != null)
-			throw new ParseException (s_loc.get ("invalid-enumerated-config",
-				getProperty (), str, Arrays.asList (aliases)));
-
-		return (nullNotFound) ? null : str;
-	}
-
-
-	/**
-	 *	The default value for the property as a string.
-	 */
-	public String getDefault ()
-	{
-		return def;
-	}
-
-
-	/**
-	 *	The default value for the propert as a string.
-	 */
-	public void setDefault (String def)
-	{
-		this.def = def;
-	}
-
-
-	/**
-	 *	Return a stringified version of this value.  If the current value has
-	 *	a short alias key, the alias key is returned.
-	 */
-	public String getString ()
-	{
-		return alias (getInternalString ());
-	}
-
-
-	/**
-	 *	Set this value from the given string.  If the given string is null or
-	 *	empty and a default is defined, the default is used.  If the given 
-	 *	string (or default) is an alias key, it will be converted to the 
-	 *	corresponding value internally. 
-	 */
-	public void setString (String val)
-	{
-		String str = unalias (val);
-		try
-		{
-			setInternalString (str);
-		}
-		catch (ParseException pe)
-		{
-			throw pe;
-		}
-		catch (RuntimeException re)
-		{
-			throw new ParseException (prop + ": " + val, re);
-		}
-	}
-
-
-	/**
-	 *	Set this value as an object.
-	 */
-	public void setObject (Object obj)
-	{
-		// if setting to null set as string to get defaults into play
-		if (obj == null && def != null)
-			setString (null);
-		else
-		{
-			try
-			{
-				setInternalObject (obj);
-			}
-			catch (ParseException pe)
-			{
-				throw pe;
-			}
-			catch (RuntimeException re)
-			{
-				throw new ParseException (prop + ": " + obj, re);
-			}
-		}
-	}
-
-
-	/** 
-	 *  Returns the type of the property that this Value represents.
-	 */
-	public abstract Class getValueType ();
-
-
-	/**
- 	 *	Return the internal string form of this value.
-	 */
-	protected abstract String getInternalString ();
-
-
-	/**
-	 *	Set this value from the given string.
-	 */
-	protected abstract void setInternalString (String str);
-
-
-	/**
-	 *	Set this value from an object.
-	 */
-	protected abstract void setInternalObject (Object obj);
-
-
-	/**
-	 *	Listener for value changes.
-	 */
-	public ValueListener getListener ()
-	{
-		return this.listen;
-	}
-
-
-	/**
-	 *	Listener for value changes.
-	 */
-	public void setListener (ValueListener listen)
-	{
-		this.listen = listen;
-	}
-
-
-	/**
-	 *	Subclasses should call this method when their inernal value changes.
-	 */
-	public void valueChanged ()
-	{
-		if (listen != null)
-			listen.valueChanged (this);
-	}
-
-
-	public int hashCode ()
-	{
-		String str = getString ();
-		int strHash =  (str == null) ? 0 : str.hashCode ();
-		int propHash = (prop == null) ? 0 : prop.hashCode ();
-		return strHash ^ propHash;
-	}
-
-
-	public boolean equals (Object other)
-	{
-		if (other == this)
-			return true;
-		if (!(other instanceof Value))
-			return false;
-
-		Value o = (Value)other;
-		return StringUtils.equals (prop, o.getProperty ()) 
-			&& StringUtils.equals (getString (), o.getString ());	
-	}
-
-
-	public Object clone ()
-	{
-		try
-		{
-			return super.clone ();
-		}
-		catch (CloneNotSupportedException cnse)
-		{
-			return null;	
-		}
-	}
+public abstract class Value implements Cloneable {
+    private static final String[] EMPTY_ALIASES = new String[0];
+    private static final Localizer s_loc = Localizer.forPackage(Value.class);
+    private String prop = null;
+    private String def = null;
+    private String[] aliases = null;
+    private String getter = null;
+    private ValueListener listen = null;
+    private boolean aliasListComprehensive = false;
+    private Class scope = null;
+
+    /**
+     *  Constructor.  Supply the property name.
+     *
+     *  @see #setProperty
+     */
+    public Value(String prop) {
+        setProperty(prop);
+    }
+
+    /**
+     *  Default constructor.
+     */
+    public Value() {
+    }
+
+    /**
+     *  The property name that will be used when setting or
+     *  getting this value in a {@link Map}.
+     */
+    public String getProperty() {
+        return prop;
+    }
+
+    /**
+     *  The property name that will be used when setting or
+     *  getting this value in a {@link Map}.
+     */
+    public void setProperty(String prop) {
+        this.prop = prop;
+    }
+
+    /**
+     *  Aliases for the value in the form key1, value1, key2, value2, ...
+     *  All alias values must be in string form.
+     */
+    public String[] getAliases() {
+        return (aliases == null) ? EMPTY_ALIASES : aliases;
+    }
+
+    /**
+     *  Aliases for the value in the form key1, value1, key2, value2, ...
+     *  All alias values must be in string form.
+     */
+    public void setAliases(String[] aliases) {
+        this.aliases = aliases;
+    }
+
+    /**
+     *  Replaces an existing alias, or adds the given alias to the front of the
+     *  alias list if it does not already exist.  All alias values must be in
+     *  string form.
+     */
+    public void setAlias(String key, String value) {
+        aliases = setAlias(key, value, aliases);
+    }
+
+    /**
+     *  Set an alias into a current alias list, returning the new list.
+     */
+    protected String[] setAlias(String key, String value, String[] aliases) {
+        if (aliases == null) {
+            aliases = EMPTY_ALIASES;
+        }
+
+        for (int i = 0; i < aliases.length; i += 2) {
+            if (key.equals(aliases[i])) {
+                aliases[i + 1] = value;
+
+                return aliases;
+            }
+        }
+
+        // add as new alias
+        String[] newAliases = new String[aliases.length + 2];
+        System.arraycopy(aliases, 0, newAliases, 2, aliases.length);
+        newAliases[0] = key;
+        newAliases[1] = value;
+
+        return newAliases;
+    }
+
+    /**
+     *  Whether or not the alias list defines all possible settings for this
+     *  value. If so, an error will be generated when attempting to invoke
+     *  any method on this value with an unknown option.
+     */
+    public boolean isAliasListComprehensive() {
+        return aliasListComprehensive;
+    }
+
+    /**
+     *  Whether or not the alias list defines all possible settings for this
+     *  value. If so, an error will be generated when attempting to invoke
+     *  any method on this value with an unknown option.
+     */
+    public void setAliasListComprehensive(boolean aliasListIsComprehensive) {
+        this.aliasListComprehensive = aliasListIsComprehensive;
+    }
+
+    /**
+     *  Alias the given setting.
+     */
+    public String alias(String str) {
+        return alias(str, aliases, false);
+    }
+
+    /**
+     *  Alias the given setting.
+     */
+    protected String alias(String str, String[] aliases, boolean nullNotFound) {
+        if (str != null) {
+            str = str.trim();
+        }
+
+        if ((aliases == null) || (aliases.length == 0)) {
+            return (nullNotFound) ? null : str;
+        }
+
+        boolean empty = (str != null) && (str.length() == 0);
+
+        for (int i = 1; i < aliases.length; i += 2)
+            if (StringUtils.equals(str, aliases[i]) ||
+                    (empty && (aliases[i] == null))) {
+                return aliases[i - 1];
+            }
+
+        return (nullNotFound) ? null : str;
+    }
+
+    /**
+     *  Unalias the given setting.
+     */
+    public String unalias(String str) {
+        return unalias(str, aliases, false);
+    }
+
+    /**
+     *  Unalias the given setting.
+     */
+    protected String unalias(String str, String[] aliases, boolean nullNotFound) {
+        if (str != null) {
+            str = str.trim();
+        }
+
+        boolean empty = (str != null) && (str.length() == 0);
+
+        if ((str == null) || (empty && (def != null))) {
+            str = def;
+        }
+
+        if (aliases != null) {
+            for (int i = 0; i < aliases.length; i += 2)
+                if (StringUtils.equals(str, aliases[i]) ||
+                        StringUtils.equals(str, aliases[i + 1]) ||
+                        (empty && (aliases[i] == null))) {
+                    return aliases[i + 1];
+                }
+        }
+
+        if (isAliasListComprehensive() && (aliases != null)) {
+            throw new ParseException(s_loc.get("invalid-enumerated-config",
+                    getProperty(), str, Arrays.asList(aliases)));
+        }
+
+        return (nullNotFound) ? null : str;
+    }
+
+    /**
+     *  The default value for the property as a string.
+     */
+    public String getDefault() {
+        return def;
+    }
+
+    /**
+     *  The default value for the propert as a string.
+     */
+    public void setDefault(String def) {
+        this.def = def;
+    }
+
+    /**
+     *  The name of the getter method for the instantiated value of this
+     *  property (as opposed to the string value)
+     */
+    public String getInstantiatingGetter() {
+        return getter;
+    }
+
+    /**
+     *  The name of the getter method for the instantiated value of this
+     *  property (as opposed to the string value)
+     */
+    public void setInstantiatingGetter(String getter) {
+        this.getter = getter;
+    }
+
+    /**
+     * A class defining the scope in which this value is defined. This will
+     * be used by the configuration framework to look up metadata about
+     * the value.
+     */
+    public Class getScope() {
+        return scope;
+    }
+
+    /**
+     * A class defining the scope in which this value is defined. This will
+     * be used by the configuration framework to look up metadata about
+     * the value.
+     */
+    public void setScope(Class cls) {
+        scope = cls;
+    }
+
+    /**
+     *  Return a stringified version of this value.  If the current value has
+     *  a short alias key, the alias key is returned.
+     */
+    public String getString() {
+        return alias(getInternalString());
+    }
+
+    /**
+     *  Set this value from the given string.  If the given string is null or
+     *  empty and a default is defined, the default is used.  If the given
+     *  string (or default) is an alias key, it will be converted to the
+     *  corresponding value internally.
+     */
+    public void setString(String val) {
+        String str = unalias(val);
+
+        try {
+            setInternalString(str);
+        } catch (ParseException pe) {
+            throw pe;
+        } catch (RuntimeException re) {
+            throw new ParseException(prop + ": " + val, re);
+        }
+    }
+
+    /**
+     *  Set this value as an object.
+     */
+    public void setObject(Object obj) {
+        // if setting to null set as string to get defaults into play
+        if ((obj == null) && (def != null)) {
+            setString(null);
+        } else {
+            try {
+                setInternalObject(obj);
+            } catch (ParseException pe) {
+                throw pe;
+            } catch (RuntimeException re) {
+                throw new ParseException(prop + ": " + obj, re);
+            }
+        }
+    }
+
+    /**
+     *  Returns the type of the property that this Value represents.
+     */
+    public abstract Class getValueType();
+
+    /**
+      *  Return the internal string form of this value.
+     */
+    protected abstract String getInternalString();
+
+    /**
+     *  Set this value from the given string.
+     */
+    protected abstract void setInternalString(String str);
+
+    /**
+     *  Set this value from an object.
+     */
+    protected abstract void setInternalObject(Object obj);
+
+    /**
+     *  Listener for value changes.
+     */
+    public ValueListener getListener() {
+        return this.listen;
+    }
+
+    /**
+     *  Listener for value changes.
+     */
+    public void setListener(ValueListener listen) {
+        this.listen = listen;
+    }
+
+    /**
+     *  Subclasses should call this method when their inernal value changes.
+     */
+    public void valueChanged() {
+        if (listen != null) {
+            listen.valueChanged(this);
+        }
+    }
+
+    public int hashCode() {
+        String str = getString();
+        int strHash = (str == null) ? 0 : str.hashCode();
+        int propHash = (prop == null) ? 0 : prop.hashCode();
+
+        return strHash ^ propHash;
+    }
+
+    public boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        }
+
+        if (!(other instanceof Value)) {
+            return false;
+        }
+
+        Value o = (Value) other;
+
+        return StringUtils.equals(prop, o.getProperty()) &&
+        StringUtils.equals(getString(), o.getString());
+    }
+
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (CloneNotSupportedException cnse) {
+            return null;
+        }
+    }
 }

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/ValueListener.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/ValueListener.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/ValueListener.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/ValueListener.java Wed Jun 28 12:34:33 2006
@@ -17,15 +17,14 @@
 
 
 /**
- *	<p>Components can listen on {@link Value} objects for changes directly.</p>
+ *  <p>Components can listen on {@link Value} objects for changes directly.</p>
  *
- *	@author		Abe White
+ *  @author Abe White
  */
-public interface ValueListener
-{
-	/**
-	 *	Callback used by {@link Value} objects to notify listener of 
-	 *	change.
-	 */
-	public void valueChanged (Value val);
+public interface ValueListener {
+    /**
+     *  Callback used by {@link Value} objects to notify listener of
+     *  change.
+     */
+    public void valueChanged(Value val);
 }

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/package.html
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/package.html?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/package.html (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/conf/package.html Wed Jun 28 12:34:33 2006
@@ -1,18 +1,3 @@
-<!--
-  Copyright 2006 The Apache Software Foundation.
-
-  Licensed under the Apache License, Version 2.0 (the "License");
-  you may not use this file except in compliance with the License.
-  You may obtain a copy of the License at
-
-     http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
 <html>
 <body>
 	<p><strong>Configuration Framework</strong></p>

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/AbstractJDBCListener.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/AbstractJDBCListener.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/AbstractJDBCListener.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/AbstractJDBCListener.java Wed Jun 28 12:34:33 2006
@@ -16,106 +16,74 @@
 package org.apache.openjpa.lib.jdbc;
 
 
-/** 
+/**
  *  An abstract implementation of the {@link JDBCListener}
  *  listener. It allows simple implementation of fine-grained
  *  event handling.
  *
- *  @author  Marc Prud'hommeaux
+ *  @author Marc Prud'hommeaux
  */
-public class AbstractJDBCListener
-	implements JDBCListener
-{
-	/** 
-	 *  Catch-all for unhandled events.  This method is called by all other
-	 *	event methods if you do not override them.  Does nothing by default.
-	 */
-	protected void eventOccurred (JDBCEvent event)
-	{
-	}
-
-
-	public void beforePrepareStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterPrepareStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeCreateStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterCreateStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeExecuteStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterExecuteStatement (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeCommit (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterCommit (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeRollback (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterRollback (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeReturn (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterReturn (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void afterConnect (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
-
-
-	public void beforeClose (JDBCEvent event)
-	{
-		eventOccurred (event);
-	}
+public class AbstractJDBCListener implements JDBCListener {
+    /**
+     *  Catch-all for unhandled events.  This method is called by all other
+     *  event methods if you do not override them.  Does nothing by default.
+     */
+    protected void eventOccurred(JDBCEvent event) {
+    }
+
+    public void beforePrepareStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterPrepareStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeCreateStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterCreateStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeExecuteStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterExecuteStatement(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeCommit(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterCommit(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeRollback(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterRollback(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeReturn(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterReturn(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void afterConnect(JDBCEvent event) {
+        eventOccurred(event);
+    }
+
+    public void beforeClose(JDBCEvent event) {
+        eventOccurred(event);
+    }
 }
-

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConfiguringConnectionDecorator.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConfiguringConnectionDecorator.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConfiguringConnectionDecorator.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConfiguringConnectionDecorator.java Wed Jun 28 12:34:33 2006
@@ -15,195 +15,176 @@
  */
 package org.apache.openjpa.lib.jdbc;
 
-
 import java.sql.*;
 
+import javax.sql.*;
+
 
 /**
- *	<p>Connection decorator that can configure some properties of the 
- *	underlying connection.  Understands the following properties:
- *	<ul>
- *	<li>QueryTimeout</li>
- *	<li>TransactionIsolation ({@link Connection} constants)</li>
- *	<li>AutoCommit</li>
- *	</ul></p>
+ *  <p>Connection decorator that can configure some properties of the
+ *  underlying connection.  Understands the following properties:
+ *  <ul>
+ *  <li>QueryTimeout</li>
+ *  <li>TransactionIsolation ({@link Connection} constants)</li>
+ *  <li>AutoCommit</li>
+ *  </ul></p>
  *
- *	@author		Abe White
- *	@nojavadoc
- */
-public class ConfiguringConnectionDecorator
-	implements ConnectionDecorator
-{
-	private int 	_isolation 		= -1;
-	private int 	_queryTimeout	= -1;
-	private Boolean	_autoCommit		= null;
-
-
-	/**
-	 *	The number of seconds to wait for a query to execute before
-	 *	terminating it.
-	 */
-	public int getQueryTimeout ()
-	{
-		return _queryTimeout;
-	}
-
-
-	/**
-	 *	The number of seconds to wait for a query to execute before
-	 *	terminating it.
-	 */
-	public void setQueryTimeout (int timeout)
-	{
-		_queryTimeout = timeout;
-	}
-
-
-	/**
-	 *	The transaction isolation level.
-	 */
-	public int getTransactionIsolation ()
-	{
-		return _isolation;
-	}
-
-
-	/**
-	 *	The transaction isolation level.
-	 */
-	public void setTransactionIsolation (int isolation)
-	{
-		_isolation = isolation;
-	}
-
-
-	/**
-	 *	Whether auto commit should be on.  Use null to keep
-	 *	the connection's default setting.  Defaults to null.
-	 */
-	public Boolean getAutoCommit ()
-	{
-	 	return _autoCommit;
-	}
-
-
-	/**
-	 *	Whether auto commit should be on.  Use null to keep
-	 *	the connection's default setting.  Defaults to null.
-	 */
-	public void setAutoCommit (Boolean autoCommit)
-	{
-	 	_autoCommit = autoCommit;
-	}
-
-
-	public Connection decorate (Connection conn)
-		throws SQLException
-	{
-		if (_isolation == Connection.TRANSACTION_NONE || _queryTimeout != -1
-			|| _autoCommit != null)
-			conn = new ConfiguringConnection (conn);
-		if (_isolation != -1 && _isolation != Connection.TRANSACTION_NONE)
-			conn.setTransactionIsolation (_isolation);
-		return conn;
-	}
-
-
-	/**
-	 *	Decorator to configure connection components correctly.
-	 */
-	private class ConfiguringConnection
-		extends DelegatingConnection
-	{
-		private boolean _curAutoCommit = false;
-
-
-		public ConfiguringConnection (Connection conn)
-			throws SQLException
-		{
-			super (conn);
-			if (_autoCommit != null)
-			{
-				_curAutoCommit = ConfiguringConnection.this.getAutoCommit ();
-				if (_curAutoCommit != _autoCommit.booleanValue ())
-					setAutoCommit (_autoCommit.booleanValue ());
-			}
-		}
-
-
-		public void setAutoCommit (boolean auto)
-			throws SQLException
-		{
-			if (_isolation != TRANSACTION_NONE)
-			{
-				super.setAutoCommit (auto);
-				_curAutoCommit = auto;
-			}
-		}
-
-
-		public void commit ()
-			throws SQLException
-		{
-			if (_isolation != TRANSACTION_NONE)
-				super.commit ();
-			if (_autoCommit != null
-				&& _autoCommit.booleanValue () != _curAutoCommit)
-				setAutoCommit (_autoCommit.booleanValue ());
-		}
-
-
-		public void rollback ()
-			throws SQLException
-		{
-			if (_isolation != TRANSACTION_NONE)
-				super.rollback ();
-			if (_autoCommit != null
-				&& _autoCommit.booleanValue () != _curAutoCommit)
-				setAutoCommit (_autoCommit.booleanValue ());
-		}
-
-
-		protected PreparedStatement prepareStatement (String sql, boolean wrap)
-			throws SQLException
-		{
-			PreparedStatement stmnt = super.prepareStatement (sql, wrap);
-			if (_queryTimeout != -1)
-				stmnt.setQueryTimeout (_queryTimeout);
-			return stmnt;
-		}
-
-
-		protected PreparedStatement prepareStatement (String sql, int rsType,
-			int rsConcur, boolean wrap)
-			throws SQLException
-		{
-			PreparedStatement stmnt = super.prepareStatement (sql, rsType, 
-				rsConcur, wrap);
-			if (_queryTimeout != -1)
-				stmnt.setQueryTimeout (_queryTimeout);
-			return stmnt;
-		}
-
-
-		protected Statement createStatement (boolean wrap)
-			throws SQLException
-		{
-			Statement stmnt = super.createStatement (wrap);
-			if (_queryTimeout != -1)
-				stmnt.setQueryTimeout (_queryTimeout);
-			return stmnt;
-		}
-
-
-		protected Statement createStatement (int rsType, int rsConcur, 
-			boolean wrap)
-			throws SQLException
-		{
-			Statement stmnt = super.createStatement (rsType, rsConcur, wrap);
-			if (_queryTimeout != -1)
-				stmnt.setQueryTimeout (_queryTimeout);
-			return stmnt;
-		}
-	}
+ *  @author Abe White
+ *  @nojavadoc */
+public class ConfiguringConnectionDecorator implements ConnectionDecorator {
+    private int _isolation = -1;
+    private int _queryTimeout = -1;
+    private Boolean _autoCommit = null;
+
+    /**
+     *  The number of seconds to wait for a query to execute before
+     *  terminating it.
+     */
+    public int getQueryTimeout() {
+        return _queryTimeout;
+    }
+
+    /**
+     *  The number of seconds to wait for a query to execute before
+     *  terminating it.
+     */
+    public void setQueryTimeout(int timeout) {
+        _queryTimeout = timeout;
+    }
+
+    /**
+     *  The transaction isolation level.
+     */
+    public int getTransactionIsolation() {
+        return _isolation;
+    }
+
+    /**
+     *  The transaction isolation level.
+     */
+    public void setTransactionIsolation(int isolation) {
+        _isolation = isolation;
+    }
+
+    /**
+     *  Whether auto commit should be on.  Use null to keep
+     *  the connection's default setting.  Defaults to null.
+     */
+    public Boolean getAutoCommit() {
+        return _autoCommit;
+    }
+
+    /**
+     *  Whether auto commit should be on.  Use null to keep
+     *  the connection's default setting.  Defaults to null.
+     */
+    public void setAutoCommit(Boolean autoCommit) {
+        _autoCommit = autoCommit;
+    }
+
+    public Connection decorate(Connection conn) throws SQLException {
+        if ((_isolation == Connection.TRANSACTION_NONE) ||
+                (_queryTimeout != -1) || (_autoCommit != null)) {
+            conn = new ConfiguringConnection(conn);
+        }
+
+        if ((_isolation != -1) && (_isolation != Connection.TRANSACTION_NONE)) {
+            conn.setTransactionIsolation(_isolation);
+        }
+
+        return conn;
+    }
+
+    /**
+     *  Decorator to configure connection components correctly.
+     */
+    private class ConfiguringConnection extends DelegatingConnection {
+        private boolean _curAutoCommit = false;
+
+        public ConfiguringConnection(Connection conn) throws SQLException {
+            super(conn);
+
+            if (_autoCommit != null) {
+                _curAutoCommit = ConfiguringConnection.this.getAutoCommit();
+
+                if (_curAutoCommit != _autoCommit.booleanValue()) {
+                    setAutoCommit(_autoCommit.booleanValue());
+                }
+            }
+        }
+
+        public void setAutoCommit(boolean auto) throws SQLException {
+            if (_isolation != TRANSACTION_NONE) {
+                super.setAutoCommit(auto);
+                _curAutoCommit = auto;
+            }
+        }
+
+        public void commit() throws SQLException {
+            if (_isolation != TRANSACTION_NONE) {
+                super.commit();
+            }
+
+            if ((_autoCommit != null) &&
+                    (_autoCommit.booleanValue() != _curAutoCommit)) {
+                setAutoCommit(_autoCommit.booleanValue());
+            }
+        }
+
+        public void rollback() throws SQLException {
+            if (_isolation != TRANSACTION_NONE) {
+                super.rollback();
+            }
+
+            if ((_autoCommit != null) &&
+                    (_autoCommit.booleanValue() != _curAutoCommit)) {
+                setAutoCommit(_autoCommit.booleanValue());
+            }
+        }
+
+        protected PreparedStatement prepareStatement(String sql, boolean wrap)
+            throws SQLException {
+            PreparedStatement stmnt = super.prepareStatement(sql, wrap);
+
+            if (_queryTimeout != -1) {
+                stmnt.setQueryTimeout(_queryTimeout);
+            }
+
+            return stmnt;
+        }
+
+        protected PreparedStatement prepareStatement(String sql, int rsType,
+            int rsConcur, boolean wrap) throws SQLException {
+            PreparedStatement stmnt = super.prepareStatement(sql, rsType,
+                    rsConcur, wrap);
+
+            if (_queryTimeout != -1) {
+                stmnt.setQueryTimeout(_queryTimeout);
+            }
+
+            return stmnt;
+        }
+
+        protected Statement createStatement(boolean wrap)
+            throws SQLException {
+            Statement stmnt = super.createStatement(wrap);
+
+            if (_queryTimeout != -1) {
+                stmnt.setQueryTimeout(_queryTimeout);
+            }
+
+            return stmnt;
+        }
+
+        protected Statement createStatement(int rsType, int rsConcur,
+            boolean wrap) throws SQLException {
+            Statement stmnt = super.createStatement(rsType, rsConcur, wrap);
+
+            if (_queryTimeout != -1) {
+                stmnt.setQueryTimeout(_queryTimeout);
+            }
+
+            return stmnt;
+        }
+    }
 }

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConnectionDecorator.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConnectionDecorator.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConnectionDecorator.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/ConnectionDecorator.java Wed Jun 28 12:34:33 2006
@@ -15,21 +15,18 @@
  */
 package org.apache.openjpa.lib.jdbc;
 
-
 import java.sql.*;
 
 
 /**
- *	<p>A connection decorator can wrap {@link Connection}s before they are
- *	returned to the user to add functionality.</p>
+ *  <p>A connection decorator can wrap {@link Connection}s before they are
+ *  returned to the user to add functionality.</p>
  *
- *	@author	Abe White
+ *  @author Abe White
  */
-public interface ConnectionDecorator
-{
-	/**
-	 *	Decorate the given connection if desired.
-	 */
-	public Connection decorate (Connection conn)
-		throws SQLException;
+public interface ConnectionDecorator {
+    /**
+     *  Decorate the given connection if desired.
+     */
+    public Connection decorate(Connection conn) throws SQLException;
 }

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DataSourceLogs.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DataSourceLogs.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DataSourceLogs.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DataSourceLogs.java Wed Jun 28 12:34:33 2006
@@ -15,162 +15,139 @@
  */
 package org.apache.openjpa.lib.jdbc;
 
+import org.apache.openjpa.lib.log.*;
 
 import java.sql.*;
 
-import org.apache.openjpa.lib.log.*;
+import java.util.*;
 
+import javax.sql.*;
 
-/** 
+
+/**
  *  Provies basic logging facilities to a DataSource.
- *  
- *  @author  Marc Prud'hommeaux
- *	@nojavadoc
- */
-public class DataSourceLogs
-{
-	private Log _jdbcLog	= null;
-	private Log _sqlLog		= null;
-
-
-	public DataSourceLogs ()
-	{
-	}
-
-
-	public DataSourceLogs (Log jdbcLog, Log sqlLog)
-	{
-		_jdbcLog = jdbcLog;
-		_sqlLog = sqlLog;
-	}
-
-
-	/**
-	 *	The log to write JDBC messages to.
-	 */
-	public Log getJDBCLog ()
-	{
-		return (_jdbcLog == null) ? NoneLogFactory.NoneLog.getInstance () 
-			: _jdbcLog;
-	}
-
-
-	/**
-	 *	The log to write JDBC messages to.
-	 */
-	public void setJDBCLog (Log log)
-	{
-		_jdbcLog = log;
-	}
-
-
-	/**
-	 *	Return true if JDBC logging is enabled.
-	 */
-	public boolean isJDBCEnabled ()
-	{
-		return (_jdbcLog != null && _jdbcLog.isTraceEnabled ());
-	}
-
-
-	/**
-	 *	The log to write SQL messages to.
-	 */
-	public Log getSQLLog ()
-	{
-		return (_sqlLog == null) ? NoneLogFactory.NoneLog.getInstance () 
-			: _sqlLog;
-	}
-
-
-	/**
-	 *	The log to write SQL messages to.
-	 */
-	public void setSQLLog (Log log)
-	{
-		_sqlLog = log;
-	}
-
-
-	/**
-	 *	Return true if SQL logging is enabled.
-	 */
-	public boolean isSQLEnabled ()
-	{
-		return (_sqlLog != null && _sqlLog.isTraceEnabled ());
-	}
-
-
-	/**
-	 *	Log a JDBC message on behalf of the given connection.
-	 */
-	public void logJDBC (String msg, Connection conn)
-	{
-		log (msg, conn, _jdbcLog);
-	}
-
-
-	/**
-	 *	Log a JDBC message on behalf of the given connection.
-	 */
-	public void logJDBC (String msg, long startTime, Connection conn)
-	{
-		log (msg, conn, _jdbcLog, startTime);
-	}
-
-
-	/**
-	 *	Log a SQL message on behalf of the given connection.
-	 */
-	public void logSQL (String msg, Connection conn)
-	{
-		log (msg, conn, _sqlLog);
-	}
-
-
-	/**
-	 *	Log a SQL message on behalf of the given connection.
-	 */
-	public void logSQL (String msg, long startTime, Connection conn)
-	{
-		log (msg, conn, _sqlLog, startTime);
-	}
-
-
-	/**
-	 *	Log a message to the given logger.
-	 */
-	private static void log (String msg, Connection conn, Log log)
-	{
-		log (msg, conn, log, -1);
-	}
-
-
-	/**
-	 *	Log a message to the given logger.
-	 */
-	private static void log (String msg, Connection conn,
-		Log log, long startTime)
-	{
-		if (log == null || !log.isTraceEnabled ())
-			return;
-
-		long totalTime = -1;
-		if (startTime != -1)
-			totalTime = System.currentTimeMillis () - startTime;
-
-		StringBuffer buf = new StringBuffer (25 + msg.length ());
-		buf.append ("<t ").append (Thread.currentThread ().hashCode ());
-		if (conn != null)
-			buf.append (", ").append (conn);
-		buf.append ("> ");
-
-		// in the time != -1, append time profiling information
-		if (totalTime != -1)
-			buf.append ("[").append (totalTime).append (" ms] ");
-
-		buf.append (msg);
-		log.trace (buf.toString ());
-	}
+ *
+ *  @author Marc Prud'hommeaux
+ *  @nojavadoc */
+public class DataSourceLogs {
+    private Log _jdbcLog = null;
+    private Log _sqlLog = null;
+
+    public DataSourceLogs() {
+    }
+
+    public DataSourceLogs(Log jdbcLog, Log sqlLog) {
+        _jdbcLog = jdbcLog;
+        _sqlLog = sqlLog;
+    }
+
+    /**
+     *  The log to write JDBC messages to.
+     */
+    public Log getJDBCLog() {
+        return (_jdbcLog == null) ? NoneLogFactory.NoneLog.getInstance()
+                                  : _jdbcLog;
+    }
+
+    /**
+     *  The log to write JDBC messages to.
+     */
+    public void setJDBCLog(Log log) {
+        _jdbcLog = log;
+    }
+
+    /**
+     *  Return true if JDBC logging is enabled.
+     */
+    public boolean isJDBCEnabled() {
+        return ((_jdbcLog != null) && _jdbcLog.isTraceEnabled());
+    }
+
+    /**
+     *  The log to write SQL messages to.
+     */
+    public Log getSQLLog() {
+        return (_sqlLog == null) ? NoneLogFactory.NoneLog.getInstance() : _sqlLog;
+    }
+
+    /**
+     *  The log to write SQL messages to.
+     */
+    public void setSQLLog(Log log) {
+        _sqlLog = log;
+    }
+
+    /**
+     *  Return true if SQL logging is enabled.
+     */
+    public boolean isSQLEnabled() {
+        return ((_sqlLog != null) && _sqlLog.isTraceEnabled());
+    }
+
+    /**
+     *  Log a JDBC message on behalf of the given connection.
+     */
+    public void logJDBC(String msg, Connection conn) {
+        log(msg, conn, _jdbcLog);
+    }
+
+    /**
+     *  Log a JDBC message on behalf of the given connection.
+     */
+    public void logJDBC(String msg, long startTime, Connection conn) {
+        log(msg, conn, _jdbcLog, startTime);
+    }
+
+    /**
+     *  Log a SQL message on behalf of the given connection.
+     */
+    public void logSQL(String msg, Connection conn) {
+        log(msg, conn, _sqlLog);
+    }
+
+    /**
+     *  Log a SQL message on behalf of the given connection.
+     */
+    public void logSQL(String msg, long startTime, Connection conn) {
+        log(msg, conn, _sqlLog, startTime);
+    }
+
+    /**
+     *  Log a message to the given logger.
+     */
+    private static void log(String msg, Connection conn, Log log) {
+        log(msg, conn, log, -1);
+    }
+
+    /**
+     *  Log a message to the given logger.
+     */
+    private static void log(String msg, Connection conn, Log log, long startTime) {
+        if ((log == null) || !log.isTraceEnabled()) {
+            return;
+        }
+
+        long totalTime = -1;
+
+        if (startTime != -1) {
+            totalTime = System.currentTimeMillis() - startTime;
+        }
+
+        StringBuffer buf = new StringBuffer(25 + msg.length());
+        buf.append("<t ").append(Thread.currentThread().hashCode());
+
+        if (conn != null) {
+            buf.append(", ").append(conn);
+        }
+
+        buf.append("> ");
+
+        // in the time != -1, append time profiling information
+        if (totalTime != -1) {
+            buf.append("[").append(totalTime).append(" ms] ");
+        }
+
+        buf.append(msg);
+        log.trace(buf.toString());
+    }
 }
-

Modified: incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DecoratingDataSource.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DecoratingDataSource.java?rev=417856&r1=415364&r2=417856&view=diff
==============================================================================
--- incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DecoratingDataSource.java (original)
+++ incubator/openjpa/trunk/openjpa-lib/main/java/org/apache/openjpa/lib/jdbc/DecoratingDataSource.java Wed Jun 28 12:34:33 2006
@@ -15,158 +15,91 @@
  */
 package org.apache.openjpa.lib.jdbc;
 
+import org.apache.openjpa.lib.util.concurrent.*;
 
 import java.sql.*;
+
 import java.util.*;
+
 import javax.sql.*;
 
 
 /**
- *	<p>Delegating data source that maintains a list of 
- *	{@link ConnectionDecorator}s.</p>
+ *  <p>Delegating data source that maintains a list of
+ *  {@link ConnectionDecorator}s.</p>
  *
- *	@author		Abe White
- *	@nojavadoc
- */
-public class DecoratingDataSource
-	extends DelegatingDataSource
-{
-	private static final int INITIAL_SIZE = 7;
-
-	private volatile List 	_decorators	= null;
-	private boolean			_conf		= false;
-
-
-	/**
-	 *	Constructor.  Supply wrapped data source.
-	 */
-	public DecoratingDataSource (DataSource ds)
-	{
-		super (ds);
-	}
-
-
-	/**
-	 *	Whether the datasource is in configuration mode.  Configuration mode
-	 *	allows more efficient modification of the decorator chain.  No 
-	 *	connections can be obtained while in configuration mode.
-	 */
-	public boolean isConfiguring ()
-	{
-		return _conf;
-	}
-
-
-	/**
-	 *	Whether the datasource is in configuration mode.  Configuration mode
-	 *	allows more efficient modification of the decorator chain.  No 
-	 *	connections can be obtained while in configuration mode.
-	 */
-	public void setConfiguring (boolean conf)
-	{
-		_conf = conf;
-	}
-
-
-	/**
-	 *	Return a read-only list of connection decorators in the order they were
-	 *	added.
-	 */
-	public Collection getDecorators ()
-	{
-		return (_decorators == null) ? Collections.EMPTY_LIST
-			: Collections.unmodifiableCollection (_decorators);
-	}
-
-
-	/**
-	 *	Add a connection decorator.
-	 */
-	public synchronized void addDecorator (ConnectionDecorator decorator)
-	{
-		if (decorator == null)
-			throw new NullPointerException ("decorator == null");
-
-		if (_conf)
-		{
-			if (_decorators == null)
-				_decorators = new ArrayList (INITIAL_SIZE);
-			_decorators.add (decorator);
-		}
-		else
-		{
-			// copy so we don't have to synchronize iteration in decorate
-			int size = (_decorators == null) ? 1 : _decorators.size () + 1;
-			List copy = new ArrayList (Math.max (INITIAL_SIZE, size));
-			if (_decorators != null)
-				copy.addAll (_decorators);		
-			copy.add (decorator);
-			_decorators = copy;
-		}
-	}
-
-
-	/**
-	 *	Remove a connection decorator.
-	 */
-	public synchronized boolean removeDecorator (ConnectionDecorator decorator)
-	{
-		if (decorator == null || _decorators == null 
-			|| !_decorators.contains (decorator))
-			return false;
-
-		if (_conf)
-			_decorators.remove (decorator);
-		else
-		{
-			// copy so we don't have to synchronize iteration in decorate
-			List copy = new ArrayList (Math.max (INITIAL_SIZE, 
-				_decorators.size () - 1));
-			for (int i = 0; i < _decorators.size (); i++)
-				if (_decorators.get (i) != decorator)
-					copy.add (_decorators.get (i));
-			_decorators = copy;
-		}
-		return true;
-	}
-
-
-	/**
-	 *	Clear all decorators.
-	 */
-	public synchronized void clearDecorators ()
-	{
-		_decorators = null;
-	}
-
-
-	public Connection getConnection ()
-		throws SQLException
-	{
-		Connection conn = super.getConnection ();
-		return decorate (conn);
-	}
-
-
-	public Connection getConnection (String user, String pass)
-		throws SQLException
-	{
-		Connection conn = super.getConnection (user, pass);
-		return decorate (conn);
-	}
-
-
-	private Connection decorate (Connection conn)
-		throws SQLException
-	{
-		if (_conf)
-			throw new IllegalStateException ();
-
-		// use local in case _decorators replaced during loop
-		List dec = _decorators;
-		if (dec != null)
-			for (int i = 0; i < dec.size (); i++)
-				conn = ((ConnectionDecorator) dec.get (i)).decorate (conn);	
-		return conn;
-	}
+ *  @author Abe White
+ *  @nojavadoc */
+public class DecoratingDataSource extends DelegatingDataSource {
+    private List _decorators = new CopyOnWriteArrayList();
+    private boolean _conf = false;
+
+    /**
+     *  Constructor.  Supply wrapped data source.
+     */
+    public DecoratingDataSource(DataSource ds) {
+        super(ds);
+    }
+
+    /**
+     *  Return a read-only list of connection decorators in the order they were
+     *  added.
+     */
+    public Collection getDecorators() {
+        return Collections.unmodifiableCollection(_decorators);
+    }
+
+    /**
+     *  Add a connection decorator.
+     */
+    public void addDecorator(ConnectionDecorator decorator) {
+        if (decorator != null) {
+            _decorators.add(decorator);
+        }
+    }
+
+    /**
+     *  Add multiple connection decorators efficiently.
+     */
+    public void addDecorators(Collection decorators) {
+        if (decorators != null) {
+            _decorators.addAll(decorators);
+        }
+    }
+
+    /**
+     *  Remove a connection decorator.
+     */
+    public boolean removeDecorator(ConnectionDecorator decorator) {
+        return _decorators.remove(decorator);
+    }
+
+    /**
+     *  Clear all decorators.
+     */
+    public void clearDecorators() {
+        _decorators.clear();
+    }
+
+    public Connection getConnection() throws SQLException {
+        Connection conn = super.getConnection();
+
+        return decorate(conn);
+    }
+
+    public Connection getConnection(String user, String pass)
+        throws SQLException {
+        Connection conn = super.getConnection(user, pass);
+
+        return decorate(conn);
+    }
+
+    private Connection decorate(Connection conn) throws SQLException {
+        if (!_decorators.isEmpty()) {
+            for (Iterator itr = _decorators.iterator(); itr.hasNext();)
+                conn = ((ConnectionDecorator) itr.next()).decorate(conn);
+        }
+
+        return conn;
+    }
 }