Index: src/org/apache/axis/encoding/TypeMappingImpl.java =================================================================== --- src/org/apache/axis/encoding/TypeMappingImpl.java (revision 413341) +++ src/org/apache/axis/encoding/TypeMappingImpl.java (working copy) @@ -30,6 +30,7 @@ import org.apache.axis.utils.Messages; import org.apache.axis.utils.ClassUtils; import org.apache.axis.utils.JavaUtils; +import org.apache.axis.utils.SynchronizedMap; import org.apache.axis.wsdl.toJava.Utils; import org.apache.axis.wsdl.fromJava.Namespaces; import org.apache.axis.wsdl.fromJava.Types; @@ -40,8 +41,10 @@ import java.lang.reflect.Array; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.io.Serializable; /** @@ -115,10 +118,11 @@ } } - private HashMap qName2Pair; // QName to Pair Mapping - private HashMap class2Pair; // Class Name to Pair Mapping - private HashMap pair2SF; // Pair to Serialization Factory - private HashMap pair2DF; // Pair to Deserialization Factory + private Object mutex; // mutex to synchronize the maps + private Map qName2Pair; // QName to Pair Mapping + private Map class2Pair; // Class Name to Pair Mapping + private Map pair2SF; // Pair to Serialization Factory + private Map pair2DF; // Pair to Deserialization Factory private ArrayList namespaces; // Supported namespaces protected Boolean doAutoTypes = null; @@ -127,10 +131,12 @@ * Construct TypeMapping */ public TypeMappingImpl() { - qName2Pair = new HashMap(); - class2Pair = new HashMap(); - pair2SF = new HashMap(); - pair2DF = new HashMap(); + mutex = new Object(); + + qName2Pair = new SynchronizedMap(new HashMap(), mutex); + class2Pair = new SynchronizedMap(new HashMap(), mutex); + pair2SF = new SynchronizedMap(new HashMap(), mutex); + pair2DF = new SynchronizedMap(new HashMap(), mutex); namespaces = new ArrayList(); } @@ -149,8 +155,10 @@ * styles and XML schema namespaces. */ public String[] getSupportedEncodings() { - String[] stringArray = new String[namespaces.size()]; - return (String[]) namespaces.toArray(stringArray); + synchronized(namespaces) { + String[] stringArray = new String[namespaces.size()]; + return (String[]) namespaces.toArray(stringArray); + } } /** @@ -161,10 +169,12 @@ * @param namespaceURIs String[] of namespace URI's */ public void setSupportedEncodings(String[] namespaceURIs) { - namespaces.clear(); - for (int i =0; i< namespaceURIs.length; i++) { - if (!namespaces.contains(namespaceURIs[i])) { - namespaces.add(namespaceURIs[i]); + synchronized(namespaces) { + namespaces.clear(); + for (int i =0; i< namespaceURIs.length; i++) { + if (!namespaces.contains(namespaceURIs[i])) { + namespaces.add(namespaceURIs[i]); + } } } } @@ -222,7 +232,14 @@ } /** + *

* Internal version of register(), which allows null factories. + *

+ *

+ * synchronize to atomically modify qName2Pair, + * pair2SF, class2Pairn and pair2DF + * instance variables + *

* * @param javaType * @param xmlType @@ -260,13 +277,15 @@ // In particular, the mapping for java.lang.Object --> anyType // was coming out in WSDL generation under the 1999 XML Schema // namespace, which .NET doesn't understand (and is not great anyway). - qName2Pair.put(xmlType, pair); - class2Pair.put(javaType, pair); + synchronized (mutex) { + qName2Pair.put(xmlType, pair); + class2Pair.put(javaType, pair); - if (sf != null) - pair2SF.put(pair, sf); - if (dsf != null) - pair2DF.put(pair, dsf); + if (sf != null) + pair2SF.put(pair, sf); + if (dsf != null) + pair2DF.put(pair, dsf); + } } /** Index: src/org/apache/axis/utils/SynchronizedMap.java =================================================================== --- src/org/apache/axis/utils/SynchronizedMap.java (revision 0) +++ src/org/apache/axis/utils/SynchronizedMap.java (revision 0) @@ -0,0 +1,146 @@ +/* + * Copyright 2001-2004 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. + */ + +package org.apache.axis.utils; + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Set; + +/** + *

+ * Enhancement of {@link Collections#synchronizedMap(Map)} method to provide the + * ability to specify the ability to specify the mutex used for + * the synchronization. + *

+ * + * @see Collections#synchronizedMap(Map) + * @author Cyrille Le Clerc + */ +public class SynchronizedMap implements Map, Serializable { + + private static final long serialVersionUID = 1L; + + private Map wrapped; + + private Object mutex; + + /** + *

+ * Synchronize the given map against the given + * mutex. + *

+ * + * @param map + * to synchronize + * @param mutex + * to synchronize the given map + */ + public SynchronizedMap(Map map, Object mutex) { + if (map == null) { + throw new NullPointerException("Map can not be null"); + } + if (mutex == null) { + throw new NullPointerException("Mutex can not be null"); + } + this.wrapped = map; + this.mutex = mutex; + } + + public void clear() { + wrapped.clear(); + } + + public boolean containsKey(Object key) { + synchronized (mutex) { + return wrapped.containsKey(key); + } + } + + public boolean containsValue(Object value) { + synchronized (mutex) { + return wrapped.containsValue(value); + } + } + + public Set entrySet() { + synchronized (mutex) { + return wrapped.entrySet(); + } + } + + public boolean equals(Object o) { + synchronized (mutex) { + return wrapped.equals(o); + } + } + + public Object get(Object key) { + synchronized (mutex) { + return wrapped.get(key); + } + } + + public int hashCode() { + synchronized (mutex) { + return wrapped.hashCode(); + } + } + + public boolean isEmpty() { + synchronized (mutex) { + return wrapped.isEmpty(); + } + } + + public Set keySet() { + synchronized (mutex) { + return wrapped.keySet(); + } + } + + public Object put(Object key, Object value) { + synchronized (mutex) { + return wrapped.put(key, value); + } + } + + public void putAll(Map map) { + synchronized (mutex) { + wrapped.putAll(map); + } + } + + public Object remove(Object key) { + synchronized (mutex) { + return wrapped.remove(key); + } + } + + public int size() { + synchronized (mutex) { + return wrapped.size(); + } + } + + public Collection values() { + synchronized (mutex) { + return wrapped.values(); + } + } +}