From eb399860441bd6089885187d5f73ea278856c3c7 Mon Sep 17 00:00:00 2001 From: scottkurz Date: Mon, 15 Sep 2008 22:44:48 +0000 Subject: Commit changes for TUSCANY-2590. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@695676 13f79535-47bb-0310-9956-ffa450edef68 --- .../sca/databinding/jaxb/JAXBContextCache.java | 165 ++++++++++++++++++--- 1 file changed, 146 insertions(+), 19 deletions(-) (limited to 'branches/sca-java-1.3.2/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java') diff --git a/branches/sca-java-1.3.2/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java b/branches/sca-java-1.3.2/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java index 296c39c50f..c64ce81fdf 100644 --- a/branches/sca-java-1.3.2/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java +++ b/branches/sca-java-1.3.2/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java @@ -16,21 +16,26 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.tuscany.sca.databinding.jaxb; import java.awt.Image; +import java.lang.ref.SoftReference; import java.net.URI; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; +import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import javax.activation.DataHandler; import javax.xml.bind.JAXBContext; @@ -86,8 +91,8 @@ public class JAXBContextCache { */ protected LRUCache cache; - protected LRUCache upool; - protected LRUCache mpool; + protected Pool mpool; + protected Pool upool; // protected JAXBContext commonContext; protected JAXBContext defaultContext; @@ -98,8 +103,8 @@ public class JAXBContextCache { public JAXBContextCache(int contextSize, int marshallerSize, int unmarshallerSize) { cache = new LRUCache(contextSize); - upool = new LRUCache(unmarshallerSize); - mpool = new LRUCache(marshallerSize); + mpool = new Pool(); + upool = new Pool(); defaultContext = getDefaultJAXBContext(); } @@ -180,27 +185,38 @@ public class JAXBContextCache { } public Marshaller getMarshaller(JAXBContext context) throws JAXBException { - synchronized (mpool) { - Marshaller marshaller = mpool.get(context); - if (marshaller == null) { - marshaller = context.createMarshaller(); - mpool.put(context, marshaller); - } - return marshaller; + Marshaller marshaller = mpool.get(context); + if (marshaller == null) { + marshaller = context.createMarshaller(); } + marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + return marshaller; } + public void releaseJAXBMarshaller(JAXBContext context, Marshaller marshaller) { + if (marshaller != null) { + marshaller.setAttachmentMarshaller(null); + mpool.put(context, marshaller); + // No point unsetting marshaller's JAXB_FRAGMENT property, since we'll just reset it when + // doing the next get. + } + } + public Unmarshaller getUnmarshaller(JAXBContext context) throws JAXBException { - synchronized (upool) { - Unmarshaller unmarshaller = upool.get(context); - if (unmarshaller == null) { - unmarshaller = context.createUnmarshaller(); - upool.put(context, unmarshaller); - } - return unmarshaller; + Unmarshaller unmarshaller = upool.get(context); + if (unmarshaller == null) { + unmarshaller = context.createUnmarshaller(); } + return unmarshaller; } + public void releaseJAXBUnmarshaller(JAXBContext context, Unmarshaller unmarshaller) { + if (unmarshaller != null) { + unmarshaller.setAttachmentUnmarshaller(null); + upool.put(context, unmarshaller); + } + } + public LRUCache getCache() { return cache; } @@ -282,12 +298,123 @@ public class JAXBContextCache { synchronized (cache) { cache.clear(); } + /* synchronized (upool) { upool.clear(); } synchronized (upool) { upool.clear(); } + */ } + // + // This inner class is copied in its entirety from the Axis2 utility class, + // org.apache.axis2.jaxws.message.databinding.JAXBUtils. We could look into extending but it's such a basic data structure + // without other dependencies so we might be better off copying it and avoiding a new + // Axis2 dependency here. + // + + /** + * Pool a list of items for a specific key + * + * @param Key + * @param Pooled object + */ + private static class Pool { + private SoftReference>> softMap = + new SoftReference>>( + new ConcurrentHashMap>()); + + // The maps are freed up when a LOAD FACTOR is hit + private static int MAX_LIST_FACTOR = 50; + private static int MAX_LOAD_FACTOR = 32; // Maximum number of JAXBContext to store + + /** + * @param key + * @return removed item from pool or null. + */ + public V get(K key) { + List values = getValues(key); + synchronized (values) { + if (values.size()>0) { + V v = values.remove(values.size()-1); + return v; + + } + } + return null; + } + + /** + * Add item back to pool + * @param key + * @param value + */ + public void put(K key, V value) { + adjustSize(); + List values = getValues(key); + synchronized (values) { + if (values.size() < MAX_LIST_FACTOR) { + values.add(value); + } + } + } + + /** + * Get or create a list of the values for the key + * @param key + * @return list of values. + */ + private List getValues(K key) { + Map> map = softMap.get(); + List values = null; + if (map != null) { + values = map.get(key); + if(values !=null) { + return values; + } + } + synchronized (this) { + if (map != null) { + values = map.get(key); + } + if (values == null) { + if (map == null) { + map = new ConcurrentHashMap>(); + softMap = + new SoftReference>>(map); + } + values = new ArrayList(); + map.put(key, values); + + } + return values; + } + } + + /** + * AdjustSize + * When the number of keys exceeds the maximum load, half + * of the entries are deleted. + * + * The assumption is that the JAXBContexts, UnMarshallers, Marshallers, etc. require + * a large footprint. + */ + private void adjustSize() { + Map> map = softMap.get(); + if (map != null && map.size() > MAX_LOAD_FACTOR) { + // Remove every other Entry in the map. + Iterator it = map.entrySet().iterator(); + boolean removeIt = false; + while (it.hasNext()) { + it.next(); + if (removeIt) { + it.remove(); + } + removeIt = !removeIt; + } + } + } + } } -- cgit v1.2.3