summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottkurz <scottkurz@13f79535-47bb-0310-9956-ffa450edef68>2008-09-15 19:56:00 +0000
committerscottkurz <scottkurz@13f79535-47bb-0310-9956-ffa450edef68>2008-09-15 19:56:00 +0000
commitdc9136faadf8ea7891790947912ffda30bee7fd4 (patch)
tree442949e6486c69c73e2899ae0a95ecc228e7a27b
parent6e273517868e587a4884f41374b224b8020345ea (diff)
Commit changes for TUSCANY-2590.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@695598 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java36
-rw-r--r--java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java17
-rw-r--r--java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java165
-rw-r--r--java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java8
4 files changed, 189 insertions, 37 deletions
diff --git a/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java b/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java
index dd9fbfbfd0..b6fa362ed9 100644
--- a/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java
+++ b/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/JAXBDataSource.java
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.tuscany.sca.databinding.jaxb.axiom;
import java.io.OutputStream;
@@ -37,6 +36,7 @@ import javax.xml.stream.XMLStreamWriter;
import org.apache.axiom.om.OMDataSource;
import org.apache.axiom.om.OMOutputFormat;
import org.apache.axiom.om.util.StAXUtils;
+import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper;
/**
*
@@ -55,11 +55,14 @@ public class JAXBDataSource implements OMDataSource {
private Marshaller getMarshaller() throws JAXBException {
if (marshaller == null) {
// For thread safety, not sure we can cache the marshaller
- // marshaller = JAXBContextHelper.getMarshaller(context);
- marshaller = context.createMarshaller();
+ marshaller = JAXBContextHelper.getMarshaller(context);
}
return marshaller;
}
+
+ private void releaseMarshaller(Marshaller marshaller) {
+ JAXBContextHelper.releaseJAXBMarshaller(context, marshaller);
+ }
public XMLStreamReader getReader() throws XMLStreamException {
// FIXME: [rfeng] This is a quick and dirty implementation
@@ -75,11 +78,12 @@ public class JAXBDataSource implements OMDataSource {
// marshaller.setProperty(Marshaller.JAXB_ENCODING, format.getCharSetEncoding());
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
- Marshaller marshaller = getMarshaller();
- // Set the FRAGEMENT property to avoid duplicate XML declaration
- marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
- marshaller.marshal(element, xmlWriter);
- marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.FALSE);
+ try {
+ Marshaller marshaller = getMarshaller();
+ marshaller.marshal(element, xmlWriter);
+ } finally {
+ releaseMarshaller(marshaller);
+ }
return null;
}
});
@@ -93,8 +97,12 @@ public class JAXBDataSource implements OMDataSource {
// marshaller.setProperty(Marshaller.JAXB_ENCODING, format.getCharSetEncoding());
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
- Marshaller marshaller = getMarshaller();
- marshaller.marshal(element, output);
+ try {
+ Marshaller marshaller = getMarshaller();
+ marshaller.marshal(element, output);
+ } finally {
+ releaseMarshaller(marshaller);
+ }
return null;
}
});
@@ -107,8 +115,12 @@ public class JAXBDataSource implements OMDataSource {
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
- Marshaller marshaller = getMarshaller();
- marshaller.marshal(element, writer);
+ try {
+ Marshaller marshaller = getMarshaller();
+ marshaller.marshal(element, writer);
+ } finally {
+ releaseMarshaller(marshaller);
+ }
return null;
}
});
diff --git a/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java b/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java
index 00e99aaacd..827a1684bc 100644
--- a/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java
+++ b/java/sca/modules/databinding-jaxb-axiom/src/main/java/org/apache/tuscany/sca/databinding/jaxb/axiom/OMElement2JAXB.java
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.apache.tuscany.sca.databinding.jaxb.axiom;
import java.security.AccessController;
@@ -51,15 +50,21 @@ public class OMElement2JAXB extends BaseTransformer<OMElement, Object> implement
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws JAXBException, XMLStreamException {
+ Unmarshaller unmarshaller = null;
+ XMLStreamReader reader = null;
+ Object result = null;
// Marshalling directly to the output stream is faster than marshalling through the
// XMLStreamWriter.
// Take advantage of this optimization if there is an output stream.
JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false);
- Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
- XMLStreamReader reader = source.getXMLStreamReaderWithoutCaching();
- Object result =
- unmarshaller.unmarshal(reader, JAXBContextHelper.getJavaType(context.getTargetDataType()));
- reader.close();
+ try {
+ unmarshaller = JAXBContextHelper.getUnmarshaller(jaxbContext);
+ reader = source.getXMLStreamReaderWithoutCaching();
+ result = unmarshaller.unmarshal(reader, JAXBContextHelper.getJavaType(context.getTargetDataType()));
+ } finally {
+ reader.close();
+ JAXBContextHelper.releaseJAXBUnmarshaller(jaxbContext, unmarshaller);
+ }
return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result);
}
});
diff --git a/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java b/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
index 296c39c50f..c64ce81fdf 100644
--- a/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
+++ b/java/sca/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<Object, JAXBContext> cache;
- protected LRUCache<JAXBContext, Unmarshaller> upool;
- protected LRUCache<JAXBContext, Marshaller> mpool;
+ protected Pool<JAXBContext, Marshaller> mpool;
+ protected Pool<JAXBContext, Unmarshaller> 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<Object, JAXBContext>(contextSize);
- upool = new LRUCache<JAXBContext, Unmarshaller>(unmarshallerSize);
- mpool = new LRUCache<JAXBContext, Marshaller>(marshallerSize);
+ mpool = new Pool<JAXBContext, Marshaller>();
+ upool = new Pool<JAXBContext, Unmarshaller>();
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<Object, JAXBContext> 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 <K> Key
+ * @param <V> Pooled object
+ */
+ private static class Pool<K,V> {
+ private SoftReference<Map<K,List<V>>> softMap =
+ new SoftReference<Map<K,List<V>>>(
+ new ConcurrentHashMap<K, List<V>>());
+
+ // 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<V> 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<V> 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<V> getValues(K key) {
+ Map<K,List<V>> map = softMap.get();
+ List<V> 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<K, List<V>>();
+ softMap =
+ new SoftReference<Map<K,List<V>>>(map);
+ }
+ values = new ArrayList<V>();
+ 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<K,List<V>> 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;
+ }
+ }
+ }
+ }
}
diff --git a/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java b/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
index ef832bfb68..7297399f5e 100644
--- a/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
+++ b/java/sca/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
@@ -112,10 +112,18 @@ public class JAXBContextHelper {
return cache.getUnmarshaller(context);
}
+ public static void releaseJAXBUnmarshaller(JAXBContext context, Unmarshaller unmarshaller) {
+ cache.releaseJAXBUnmarshaller(context, unmarshaller);
+ }
+
public static Marshaller getMarshaller(JAXBContext context) throws JAXBException {
return cache.getMarshaller(context);
}
+ public static void releaseJAXBMarshaller(JAXBContext context, Marshaller marshaller) {
+ cache.releaseJAXBMarshaller(context, marshaller);
+ }
+
@SuppressWarnings("unchecked")
public static Object createJAXBElement(JAXBContext context, DataType dataType, Object value) {
Class<?> type = dataType == null ? value.getClass() : dataType.getPhysical();