Author: niallp
Date: Tue Aug 19 09:33:30 2008
New Revision: 687089
URL: http://svn.apache.org/viewvc?rev=687089&view=rev
Log:
BEANUTILS-291 Fix the thread isolation problem on PropertyUtilsBean,
ConvertUtilsBean and LocaleConvertUtilsBean - thanks to Clebert Suconic for
identifying this and the patch. I applied a slightly modified version of
Clebert's solution.
Added:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/WeakFastHashMap.java
- copied, changed from r686833,
commons/proper/beanutils/trunk/src/java/org/apache/commons/collections/FastHashMap.java
Modified:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/BeanUtils.java
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
Modified:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/BeanUtils.java
URL:
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/BeanUtils.java?rev=687089&r1=687088&r2=687089&view=diff
==============================================================================
---
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/BeanUtils.java
(original)
+++
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/BeanUtils.java
Tue Aug 19 09:33:30 2008
@@ -466,4 +466,36 @@
public static boolean initCause(Throwable throwable, Throwable cause) {
return BeanUtilsBean.getInstance().initCause(throwable, cause);
}
+
+ /**
+ * Create a cache.
+ * @return a new cache
+ */
+ public static Map createCache() {
+ return new WeakFastHashMap();
+ }
+
+ /**
+ * Return whether a Map is fast
+ * @param map The map
+ * @return Whether it is fast or not.
+ */
+ public static boolean getCacheFast(Map map) {
+ if (map instanceof WeakFastHashMap) {
+ return ((WeakFastHashMap)map).getFast();
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Set whether fast on a Map
+ * @param map The map
+ * @param fast Whether it should be fast or not.
+ */
+ public static void setCacheFast(Map map, boolean fast) {
+ if (map instanceof WeakFastHashMap) {
+ ((WeakFastHashMap)map).setFast(fast);
+ }
+ }
}
Modified:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
URL:
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java?rev=687089&r1=687088&r2=687089&view=diff
==============================================================================
---
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
(original)
+++
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/ConvertUtilsBean.java
Tue Aug 19 09:33:30 2008
@@ -27,8 +27,6 @@
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collection;
-import java.util.Map;
-import java.util.WeakHashMap;
import org.apache.commons.beanutils.converters.ArrayConverter;
import org.apache.commons.beanutils.converters.BigDecimalConverter;
@@ -151,7 +149,7 @@
* The set of [EMAIL PROTECTED] Converter}s that can be used to convert
Strings
* into objects of a specified Class, keyed by the destination Class.
*/
- private Map converters = new WeakHashMap();
+ private WeakFastHashMap converters = new WeakFastHashMap();
/**
* The <code>Log</code> instance for this class.
@@ -162,7 +160,9 @@
/** Construct a bean with standard converters registered */
public ConvertUtilsBean() {
+ converters.setFast(false);
deregister();
+ converters.setFast(true);
}
// --------------------------------------------------------- Public Methods
Modified:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
URL:
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java?rev=687089&r1=687088&r2=687089&view=diff
==============================================================================
---
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
(original)
+++
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/PropertyUtilsBean.java
Tue Aug 19 09:33:30 2008
@@ -30,7 +30,6 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import java.util.WeakHashMap;
import org.apache.commons.beanutils.expression.DefaultResolver;
import org.apache.commons.beanutils.expression.Resolver;
@@ -121,8 +120,8 @@
* The cache of PropertyDescriptor arrays for beans we have already
* introspected, keyed by the java.lang.Class of this object.
*/
- private Map descriptorsCache = new WeakHashMap();
- private Map mappedDescriptorsCache = new WeakHashMap();
+ private WeakFastHashMap descriptorsCache = null;
+ private WeakFastHashMap mappedDescriptorsCache = null;
private static final Class[] EMPTY_CLASS_PARAMETERS = new Class[0];
private static final Class[] LIST_CLASS_PARAMETER = new Class[]
{java.util.List.class};
@@ -136,6 +135,10 @@
/** Base constructor */
public PropertyUtilsBean() {
+ descriptorsCache = new WeakFastHashMap();
+ descriptorsCache.setFast(true);
+ mappedDescriptorsCache = new WeakFastHashMap();
+ mappedDescriptorsCache.setFast(true);
}
Copied:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/WeakFastHashMap.java
(from r686833,
commons/proper/beanutils/trunk/src/java/org/apache/commons/collections/FastHashMap.java)
URL:
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/WeakFastHashMap.java?p2=commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/WeakFastHashMap.java&p1=commons/proper/beanutils/trunk/src/java/org/apache/commons/collections/FastHashMap.java&r1=686833&r2=687089&rev=687089&view=diff
==============================================================================
---
commons/proper/beanutils/trunk/src/java/org/apache/commons/collections/FastHashMap.java
(original)
+++
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/WeakFastHashMap.java
Tue Aug 19 09:33:30 2008
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.commons.collections;
+package org.apache.commons.beanutils;
import java.util.Collection;
import java.util.ConcurrentModificationException;
@@ -22,6 +22,7 @@
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
+import java.util.WeakHashMap;
/**
* <p>A customized implementation of <code>java.util.HashMap</code> designed
@@ -63,17 +64,17 @@
* @author Craig R. McClanahan
* @author Stephen Colebourne
*/
-public class FastHashMap extends HashMap {
+class WeakFastHashMap extends HashMap {
/**
* The underlying map we are managing.
*/
- protected HashMap map = null;
+ private Map map = null;
/**
* Are we currently operating in "fast" mode?
*/
- protected boolean fast = false;
+ private boolean fast = false;
// Constructors
// ----------------------------------------------------------------------
@@ -81,9 +82,9 @@
/**
* Construct an empty map.
*/
- public FastHashMap() {
+ public WeakFastHashMap() {
super();
- this.map = new HashMap();
+ this.map = createMap();
}
/**
@@ -91,9 +92,9 @@
*
* @param capacity the initial capacity of the empty map
*/
- public FastHashMap(int capacity) {
+ public WeakFastHashMap(int capacity) {
super();
- this.map = new HashMap(capacity);
+ this.map = createMap(capacity);
}
/**
@@ -102,9 +103,9 @@
* @param capacity the initial capacity of the empty map
* @param factor the load factor of the new map
*/
- public FastHashMap(int capacity, float factor) {
+ public WeakFastHashMap(int capacity, float factor) {
super();
- this.map = new HashMap(capacity, factor);
+ this.map = createMap(capacity, factor);
}
/**
@@ -112,9 +113,9 @@
*
* @param map the map whose mappings are to be copied
*/
- public FastHashMap(Map map) {
+ public WeakFastHashMap(Map map) {
super();
- this.map = new HashMap(map);
+ this.map = createMap(map);
}
@@ -246,7 +247,7 @@
public Object put(Object key, Object value) {
if (fast) {
synchronized (this) {
- HashMap temp = (HashMap) map.clone();
+ Map temp = cloneMap(map);
Object result = temp.put(key, value);
map = temp;
return (result);
@@ -267,7 +268,7 @@
public void putAll(Map in) {
if (fast) {
synchronized (this) {
- HashMap temp = (HashMap) map.clone();
+ Map temp = cloneMap(map);
temp.putAll(in);
map = temp;
}
@@ -288,7 +289,7 @@
public Object remove(Object key) {
if (fast) {
synchronized (this) {
- HashMap temp = (HashMap) map.clone();
+ Map temp = cloneMap(map);
Object result = temp.remove(key);
map = temp;
return (result);
@@ -306,7 +307,7 @@
public void clear() {
if (fast) {
synchronized (this) {
- map = new HashMap();
+ map = createMap();
}
} else {
synchronized (map) {
@@ -417,12 +418,12 @@
* @return a clone of this map
*/
public Object clone() {
- FastHashMap results = null;
+ WeakFastHashMap results = null;
if (fast) {
- results = new FastHashMap(map);
+ results = new WeakFastHashMap(map);
} else {
synchronized (map) {
- results = new FastHashMap(map);
+ results = new WeakFastHashMap(map);
}
}
results.setFast(getFast());
@@ -457,6 +458,29 @@
return new Values();
}
+ // Abstractions on Map creations (for subclasses such as WeakFastHashMap)
+ // ----------------------------------------------------------------------
+
+ protected Map createMap() {
+ return new WeakHashMap();
+ }
+
+ protected Map createMap(int capacity) {
+ return new WeakHashMap(capacity);
+ }
+
+ protected Map createMap(int capacity, float factor) {
+ return new WeakHashMap(capacity, factor);
+ }
+
+ protected Map createMap(Map map) {
+ return new WeakHashMap(map);
+ }
+
+ protected Map cloneMap(Map map) {
+ return createMap(map);
+ }
+
// Map view inner classes
// ----------------------------------------------------------------------
@@ -474,8 +498,8 @@
public void clear() {
if (fast) {
- synchronized (FastHashMap.this) {
- map = new HashMap();
+ synchronized (WeakFastHashMap.this) {
+ map = createMap();
}
} else {
synchronized (map) {
@@ -486,8 +510,8 @@
public boolean remove(Object o) {
if (fast) {
- synchronized (FastHashMap.this) {
- HashMap temp = (HashMap) map.clone();
+ synchronized (WeakFastHashMap.this) {
+ Map temp = cloneMap(map);
boolean r = get(temp).remove(o);
map = temp;
return r;
@@ -501,8 +525,8 @@
public boolean removeAll(Collection o) {
if (fast) {
- synchronized (FastHashMap.this) {
- HashMap temp = (HashMap) map.clone();
+ synchronized (WeakFastHashMap.this) {
+ Map temp = cloneMap(map);
boolean r = get(temp).removeAll(o);
map = temp;
return r;
@@ -516,8 +540,8 @@
public boolean retainAll(Collection o) {
if (fast) {
- synchronized (FastHashMap.this) {
- HashMap temp = (HashMap) map.clone();
+ synchronized (WeakFastHashMap.this) {
+ Map temp = cloneMap(map);
boolean r = get(temp).retainAll(o);
map = temp;
return r;
@@ -657,11 +681,11 @@
throw new IllegalStateException();
}
if (fast) {
- synchronized (FastHashMap.this) {
+ synchronized (WeakFastHashMap.this) {
if (expected != map) {
throw new ConcurrentModificationException();
}
- FastHashMap.this.remove(lastReturned.getKey());
+ WeakFastHashMap.this.remove(lastReturned.getKey());
lastReturned = null;
expected = map;
}
Modified:
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
URL:
http://svn.apache.org/viewvc/commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java?rev=687089&r1=687088&r2=687089&view=diff
==============================================================================
---
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
(original)
+++
commons/proper/beanutils/trunk/src/java/org/apache/commons/beanutils/locale/LocaleConvertUtilsBean.java
Tue Aug 19 09:33:30 2008
@@ -17,6 +17,7 @@
package org.apache.commons.beanutils.locale;
+import org.apache.commons.beanutils.BeanUtils;
import
org.apache.commons.beanutils.locale.converters.BigDecimalLocaleConverter;
import
org.apache.commons.beanutils.locale.converters.BigIntegerLocaleConverter;
import org.apache.commons.beanutils.locale.converters.ByteLocaleConverter;
@@ -38,11 +39,9 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
-import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
-import java.util.WeakHashMap;
/**
* <p>Utility methods for converting locale-sensitive String scalar values to
objects of the
@@ -110,7 +109,7 @@
* key = locale
* value = FastHashMap of converters for the certain locale.
*/
- private FastHashMap mapConverters = new FastHashMap();
+ private FastHashMap mapConverters = new
DelegateFastHashMap(BeanUtils.createCache());
// --------------------------------------------------------- Constructors
@@ -119,7 +118,9 @@
* and then registers default locale converters.
*/
public LocaleConvertUtilsBean() {
+ mapConverters.setFast(false);
deregister();
+ mapConverters.setFast(true);
}
// --------------------------------------------------------- Properties
@@ -459,7 +460,7 @@
*/
protected FastHashMap create(Locale locale) {
- FastHashMap converter = new WeakFastHashMap();
+ FastHashMap converter = new
DelegateFastHashMap(BeanUtils.createCache());
converter.setFast(false);
converter.put(BigDecimal.class, new BigDecimalLocaleConverter(locale,
applyLocalized));
@@ -506,58 +507,60 @@
* releases (where FastHashMap is exposed in the API), but
* use WeakHashMap to resolve memory leaks.
*/
- private static class WeakFastHashMap extends FastHashMap {
+ private static class DelegateFastHashMap extends FastHashMap {
- private Map fastMap = new WeakHashMap();
- private Map slowMap = Collections.synchronizedMap(fastMap);
+ private final Map map;
- private WeakFastHashMap() {
- super(0);
+ private DelegateFastHashMap(Map map) {
+ this.map = map;
}
public void clear() {
- getMap().clear();
+ map.clear();
}
public boolean containsKey(Object key) {
- return getMap().containsKey(key);
+ return map.containsKey(key);
}
public boolean containsValue(Object value) {
- return getMap().containsValue(value);
+ return map.containsValue(value);
}
public Set entrySet() {
- return getMap().entrySet();
+ return map.entrySet();
}
public boolean equals(Object o) {
- return getMap().equals(o);
+ return map.equals(o);
}
public Object get(Object key) {
- return getMap().get(key);
+ return map.get(key);
}
public int hashCode() {
- return getMap().hashCode();
+ return map.hashCode();
}
public boolean isEmpty() {
- return getMap().isEmpty();
+ return map.isEmpty();
}
public Set keySet() {
- return getMap().keySet();
+ return map.keySet();
}
public Object put(Object key, Object value) {
- return getMap().put(key, value);
+ return map.put(key, value);
}
public void putAll(Map m) {
- getMap().putAll(m);
+ map.putAll(m);
}
public Object remove(Object key) {
- return getMap().remove(key);
+ return map.remove(key);
}
public int size() {
- return getMap().size();
+ return map.size();
}
public Collection values() {
- return getMap().values();
+ return map.values();
+ }
+ public boolean getFast() {
+ return BeanUtils.getCacheFast(map);
}
- private Map getMap() {
- return (getFast() ? fastMap : slowMap);
+ public void setFast(boolean fast) {
+ BeanUtils.setCacheFast(map, fast);
}
}
}