summaryrefslogtreecommitdiffstats
path: root/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java313
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java378
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java60
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java75
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java69
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java77
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java84
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java288
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java429
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java132
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java301
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java236
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java56
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java151
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java166
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java73
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java74
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java80
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java52
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java286
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java77
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding19
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer32
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint17
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java45
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBContextCacheTestCase.java123
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBDataBindingTestCase.java130
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBReflectionTestCase.java94
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBTestCase.java175
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBWrapperHandlerTestCase.java90
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyBean.java162
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterface.java29
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterfaceImpl.java67
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MySubBean.java35
-rw-r--r--sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/POJOTestCase.java250
-rwxr-xr-xsandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/resources/ipo.xsd136
36 files changed, 4861 insertions, 0 deletions
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java
new file mode 100644
index 0000000000..730f9e4a66
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/BeanXMLStreamReaderImpl.java
@@ -0,0 +1,313 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.databinding.xml.SimpleXmlNodeImpl;
+import org.apache.tuscany.sca.databinding.xml.XmlNode;
+import org.apache.tuscany.sca.databinding.xml.XmlTreeStreamReaderImpl;
+import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
+import org.jvnet.jaxb.reflection.model.annotation.RuntimeInlineAnnotationReader;
+import org.jvnet.jaxb.reflection.model.core.Ref;
+import org.jvnet.jaxb.reflection.model.impl.RuntimeModelBuilder;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimeClassInfo;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimePropertyInfo;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet;
+import org.jvnet.jaxb.reflection.runtime.IllegalAnnotationsException;
+import org.jvnet.jaxb.reflection.runtime.JAXBContextImpl;
+
+
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class BeanXMLStreamReaderImpl extends XmlTreeStreamReaderImpl {
+ private static final Comparator<Accessor> COMPARATOR = new Comparator<Accessor>() {
+ public int compare(Accessor o1, Accessor o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ };
+
+ private static final String XSI_PREFIX = "xsi";
+ private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
+
+ private static XmlNode getXSIType(QName realType) {
+ QName xsiType = new QName(XSI_NS, "type", XSI_PREFIX);
+ String prefix = realType.getPrefix();
+ String typeName = realType.getLocalPart();
+ if (prefix != null && !prefix.equals("")) {
+ typeName = prefix + ":" + realType.getLocalPart();
+ }
+ return new SimpleXmlNodeImpl(xsiType, XmlNode.Type.ATTRIBUTE);
+ }
+
+ /**
+ * Represent a Map.Entry XML node
+ * @version $Rev$ $Date$
+ */
+ public static class MapEntryXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode {
+ private Map.Entry entry;
+
+ public MapEntryXmlNodeImpl(Entry entry) {
+ super(new QName("", "entry"), entry);
+ this.entry = entry;
+ }
+
+ public Iterator<XmlNode> children() {
+ List<XmlNode> nodes = new ArrayList<XmlNode>();
+ XmlNode key = new BeanXmlNodeImpl(new QName("", "key"), entry.getKey());
+ XmlNode value = new BeanXmlNodeImpl(new QName("", "value"), entry.getValue());
+ nodes.add(key);
+ nodes.add(value);
+ return nodes.iterator();
+ }
+ }
+
+ public static class BeanXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode {
+ private static final Object[] NULL = null;
+ private static final SimpleTypeMapperImpl MAPPER = new SimpleTypeMapperImpl();
+
+ public BeanXmlNodeImpl(Object bean) {
+ super(getName(bean == null ? null : bean.getClass()), bean);
+ }
+
+ public BeanXmlNodeImpl(QName name, Object bean) {
+ super(name, bean);
+ }
+
+ private static boolean isSimpleType(Class<?> javaType) {
+ return SimpleTypeMapperImpl.getXMLType(javaType) != null;
+ }
+
+ private static String getStringValue(Object o) {
+ if (o == null) {
+ return null;
+ }
+ TypeInfo info = SimpleTypeMapperImpl.getXMLType(o.getClass());
+ if (info != null) {
+ return MAPPER.toXMLLiteral(info.getQName(), o, null);
+ } else {
+ return String.valueOf(o);
+ }
+ }
+
+ public Iterator<XmlNode> children() {
+ if (name == null) {
+ return null;
+ }
+ if (value == null) {
+ return super.children();
+ }
+ if (isSimpleType(value.getClass())) {
+ XmlNode textNode = new BeanXmlNodeImpl(null, value);
+ return Arrays.asList(textNode).iterator();
+ }
+ if (Map.class.isAssignableFrom(value.getClass())) {
+ List<XmlNode> entries = new ArrayList<XmlNode>();
+ Map map = (Map)value;
+ if (map != null) {
+ for (Object e : map.entrySet()) {
+ Map.Entry entry = (Map.Entry)e;
+ entries.add(new MapEntryXmlNodeImpl(entry));
+ }
+ }
+ return entries.iterator();
+ }
+ try {
+ Map<String, Accessor> accessorMap = getAccessors(value);
+ List<Accessor> accessorList = new ArrayList<Accessor>(accessorMap.values());
+ Collections.sort(accessorList, COMPARATOR);
+
+ List<XmlNode> props = new ArrayList<XmlNode>();
+ for (Accessor accessor : accessorList) {
+ Class<?> pType = accessor.getType();
+
+ QName pName = new QName(name.getNamespaceURI(), accessor.getName());
+ Object pValue = accessor.getValue();
+ if (pType.isArray()) {
+ if (pValue != null) {
+ int i1 = Array.getLength(pValue);
+ for (int j = 0; j < i1; j++) {
+ Object o = Array.get(pValue, j);
+ props.add(new BeanXmlNodeImpl(pName, o));
+ }
+ } else {
+ // TODO: How to handle null?
+ }
+ } else if (Collection.class.isAssignableFrom(pType)) {
+ Collection objList = (Collection)pValue;
+ if (objList != null && objList.size() > 0) {
+ for (Iterator j = objList.iterator(); j.hasNext();) {
+ Object o = j.next();
+ props.add(new BeanXmlNodeImpl(pName, o));
+ }
+
+ } else {
+ // How to handle null
+ }
+ } else {
+ props.add(new BeanXmlNodeImpl(pName, pValue));
+ }
+ }
+ return props.iterator();
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ public QName getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return getStringValue(value);
+ }
+
+ public static QName getName(Class<?> cls) {
+ if (cls == null) {
+ return null;
+ }
+ Package pkg = cls.getPackage();
+ if (pkg == null) {
+ return new QName("", cls.getSimpleName());
+ }
+ StringBuffer ns = new StringBuffer("http://");
+ String[] names = pkg.getName().split("\\.");
+ for (int i = names.length - 1; i >= 0; i--) {
+ ns.append(names[i]);
+ if (i != 0) {
+ ns.append('.');
+ }
+ }
+ ns.append('/');
+ return new QName(ns.toString(), cls.getSimpleName());
+ }
+
+ }
+
+ public BeanXMLStreamReaderImpl(QName name, Object bean) {
+ super(getXmlNode(name, bean));
+ }
+
+ private static BeanXmlNodeImpl getXmlNode(QName name, Object bean) {
+ BeanXmlNodeImpl root = null;
+ if (name != null) {
+ root = new BeanXmlNodeImpl(name, bean);
+ } else {
+ root = new BeanXmlNodeImpl(bean);
+ }
+ return root;
+ }
+
+ public static interface Accessor {
+ String getName();
+
+ Class<?> getType();
+
+ Object getValue() throws Exception;
+
+ void setValue(Object value) throws Exception;
+ }
+
+ private static RuntimeTypeInfoSet create(Class... classes) throws Exception {
+ IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder();
+ RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader();
+ JAXBContextImpl context =
+ new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false);
+ RuntimeModelBuilder builder =
+ new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null);
+ builder.setErrorHandler(errorListener);
+ for (Class c : classes)
+ builder.getTypeInfo(new Ref<Type, Class>(c));
+
+ RuntimeTypeInfoSet r = builder.link();
+ errorListener.check();
+ return r;
+ }
+
+ private static class JAXBAccessor implements Accessor {
+ private Object target;
+ private RuntimePropertyInfo prop;
+
+ public JAXBAccessor(Object target, RuntimePropertyInfo field) {
+ super();
+ this.target = target;
+ this.prop = field;
+ }
+
+ public String getName() {
+ return prop.getName();
+ }
+
+ public Object getValue() throws Exception {
+ return prop.getAccessor().get(target);
+ }
+
+ public void setValue(Object value) throws Exception {
+ prop.getAccessor().set(target, value);
+ }
+
+ public Class<?> getType() {
+ Type type = prop.getRawType();
+ if (type instanceof Class) {
+ return (Class<?>)type;
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType)type;
+ type = pType.getRawType();
+ if (type instanceof Class) {
+ return (Class<?>)type;
+ }
+ }
+ return Object.class;
+ }
+
+ }
+
+ private static Map<String, Accessor> getAccessors(Object target) throws Exception {
+ if (target == null) {
+ return Collections.emptyMap();
+ }
+ Map<String, Accessor> map = new HashMap<String, Accessor>();
+ Class<?> type = target.getClass();
+ RuntimeTypeInfoSet set = create(type);
+ RuntimeClassInfo clsInfo = (RuntimeClassInfo)set.getTypeInfo(type);
+ for (RuntimePropertyInfo f : clsInfo.getProperties()) {
+ map.put(f.getName(), new JAXBAccessor(target, f));
+ }
+ return map;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java
new file mode 100644
index 0000000000..003b4fb992
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DataConverter.java
@@ -0,0 +1,378 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.awt.Image;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.activation.DataHandler;
+import javax.imageio.ImageIO;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * Provides utilities to convert an object into a different kind of Object. For example, convert a
+ * String[] into a List<String>
+ */
+public class DataConverter {
+
+ /**
+ * This method should return true if the convert method will succeed.
+ * <p/>
+ * Note that any changes to isConvertable() must also be accompanied by similar changes to
+ * convert()
+ *
+ * @param obj source object or class
+ * @param dest destination class
+ * @return boolean true if convert(..) can convert obj to the destination class
+ */
+ public static boolean isConvertable(Object obj, Class dest) {
+ Class src = null;
+
+ if (obj != null) {
+ if (obj instanceof Class) {
+ src = (Class)obj;
+ } else {
+ src = obj.getClass();
+ }
+ }
+
+ if (dest == null) {
+ return false;
+ }
+
+ if (src == null) {
+ return true;
+ }
+
+ // If we're directly assignable, we're good.
+ if (dest.isAssignableFrom(src)) {
+ return true;
+ }
+
+ // If it's a wrapping conversion, we're good.
+ if (getWrapperClass(src) == dest) {
+ return true;
+ }
+ if (getWrapperClass(dest) == src) {
+ return true;
+ }
+
+ // If it's List -> Array or vice versa, we're good.
+ if ((Collection.class.isAssignableFrom(src) || src.isArray()) && (Collection.class.isAssignableFrom(dest) || dest
+ .isArray())) {
+
+ // TODO this should consider the component types instead of returning true.
+ return true;
+ }
+
+ // Allow mapping of HashMaps to Hashtables
+ if (src == HashMap.class && dest == Hashtable.class)
+ return true;
+
+ // Allow mapping of Calendar to Date
+ if (Calendar.class.isAssignableFrom(src) && dest == Date.class) {
+ return true;
+ }
+
+ if (src.isPrimitive()) {
+ return isConvertable(getWrapperClass(src), dest);
+ }
+
+ if (InputStream.class.isAssignableFrom(src) && dest == byte[].class) {
+ return true;
+ }
+
+ if (Source.class.isAssignableFrom(src) && dest == byte[].class) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && isConvertable(byte[].class, dest)) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && dest == Image.class) {
+ return true;
+ }
+
+ if (DataHandler.class.isAssignableFrom(src) && dest == Source.class) {
+ return true;
+ }
+
+ if (byte[].class.isAssignableFrom(src) && dest == String.class) {
+ return true;
+ }
+
+ // If it's a MIME type mapping and we want a DataHandler,
+ // then we're good.
+ // REVIEW Do we want to support this
+ /*
+ if (dest.getName().equals("javax.activation.DataHandler")) {
+ String name = src.getName();
+ if (src == String.class
+ || src == java.awt.Image.class
+ || name.equals("javax.mail.internet.MimeMultipart")
+ || name.equals("javax.xml.transform.Source"))
+ return true;
+ }
+ */
+
+ return false;
+ }
+
+ /**
+ * Utility function to convert an Object to some desired Class.
+ * <p/>
+ * Normally this is used for T[] to List<T> processing. Other conversions are also done (i.e.
+ * HashMap <->Hashtable, etc.)
+ * <p/>
+ * Use the isConvertable() method to determine if conversion is possible. Note that any changes
+ * to convert() must also be accompanied by similar changes to isConvertable()
+ *
+ * @param arg the array to convert
+ * @param destClass the actual class we want
+ * @return object of destClass if conversion possible, otherwise returns arg
+ */
+ public static Object convert(Object arg, Class<?> destClass) {
+ if (destClass == null) {
+ return arg;
+ }
+
+ if (arg != null && destClass.isAssignableFrom(arg.getClass())) {
+ return arg;
+ }
+
+ // Convert between Calendar and Date
+ if (arg instanceof Calendar && destClass == Date.class) {
+ return ((Calendar)arg).getTime();
+ }
+
+ // Convert between HashMap and Hashtable
+ if (arg instanceof HashMap && destClass == Hashtable.class) {
+ return new Hashtable((HashMap)arg);
+ }
+
+ if (arg instanceof InputStream && destClass == byte[].class) {
+
+ try {
+ InputStream is = (InputStream)arg;
+ return getBytesFromStream(is);
+ } catch (IOException e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof Source && destClass == byte[].class) {
+ try {
+ if (arg instanceof StreamSource) {
+ InputStream is = ((StreamSource)arg).getInputStream();
+ if (is != null) {
+ return getBytesFromStream(is);
+ }
+ }
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ Result result = new StreamResult(out);
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ transformer.transform((Source)arg, result);
+ byte[] bytes = out.toByteArray();
+ return bytes;
+
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof DataHandler) {
+ try {
+ InputStream is = ((DataHandler)arg).getInputStream();
+ if (destClass == Image.class) {
+ return ImageIO.read(is);
+ } else if (destClass == Source.class) {
+ return new StreamSource(is);
+ }
+ byte[] bytes = getBytesFromStream(is);
+ return convert(bytes, destClass);
+ } catch (Exception e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ if (arg instanceof byte[] && destClass == String.class) {
+ return new String((byte[])arg);
+ }
+
+ // If the destination is an array and the source
+ // is a suitable component, return an array with
+ // the single item.
+ /* REVIEW do we need to support atomic to array conversion ?
+ if (arg != null &&
+ destClass.isArray() &&
+ !destClass.getComponentType().equals(Object.class) &&
+ destClass.getComponentType().isAssignableFrom(arg.getClass())) {
+ Object array =
+ Array.newInstance(destClass.getComponentType(), 1);
+ Array.set(array, 0, arg);
+ return array;
+ }
+ */
+
+ // Return if no conversion is available
+ if (!(arg instanceof Collection || (arg != null && arg.getClass().isArray()))) {
+ return arg;
+ }
+
+ if (arg == null) {
+ return null;
+ }
+
+ // The arg may be an array or List
+ Object destValue = null;
+ int length = 0;
+ if (arg.getClass().isArray()) {
+ length = Array.getLength(arg);
+ } else {
+ length = ((Collection)arg).size();
+ }
+
+ try {
+ if (destClass.isArray()) {
+ if (destClass.getComponentType().isPrimitive()) {
+
+ Object array = Array.newInstance(destClass.getComponentType(), length);
+ // Assign array elements
+ if (arg.getClass().isArray()) {
+ for (int i = 0; i < length; i++) {
+ Array.set(array, i, Array.get(arg, i));
+ }
+ } else {
+ int idx = 0;
+ for (Iterator i = ((Collection)arg).iterator(); i.hasNext();) {
+ Array.set(array, idx++, i.next());
+ }
+ }
+ destValue = array;
+
+ } else {
+ Object[] array;
+ try {
+ array = (Object[])Array.newInstance(destClass.getComponentType(), length);
+ } catch (Exception e) {
+ return arg;
+ }
+
+ // Use convert to assign array elements.
+ if (arg.getClass().isArray()) {
+ for (int i = 0; i < length; i++) {
+ array[i] = convert(Array.get(arg, i), destClass.getComponentType());
+ }
+ } else {
+ int idx = 0;
+ for (Iterator i = ((Collection)arg).iterator(); i.hasNext();) {
+ array[idx++] = convert(i.next(), destClass.getComponentType());
+ }
+ }
+ destValue = array;
+ }
+ } else if (Collection.class.isAssignableFrom(destClass)) {
+ Collection newList = null;
+ try {
+ // if we are trying to create an interface, build something
+ // that implements the interface
+ if (destClass == Collection.class || destClass == List.class) {
+ newList = new ArrayList();
+ } else if (destClass == Set.class) {
+ newList = new HashSet();
+ } else {
+ newList = (Collection)destClass.newInstance();
+ }
+ } catch (Exception e) {
+ // No FFDC code needed
+ // Couldn't build one for some reason... so forget it.
+ return arg;
+ }
+
+ if (arg.getClass().isArray()) {
+ for (int j = 0; j < length; j++) {
+ newList.add(Array.get(arg, j));
+ }
+ } else {
+ for (Iterator j = ((Collection)arg).iterator(); j.hasNext();) {
+ newList.add(j.next());
+ }
+ }
+ destValue = newList;
+ } else {
+ destValue = arg;
+ }
+ } catch (Throwable t) {
+ throw new ServiceRuntimeException(t);
+ }
+
+ return destValue;
+ }
+
+ private static byte[] getBytesFromStream(InputStream is) throws IOException {
+ // TODO This code assumes that available is the length of the stream.
+ byte[] bytes = new byte[is.available()];
+ is.read(bytes);
+ return bytes;
+ }
+
+ public static Class getWrapperClass(Class primitive) {
+ if (primitive == int.class) {
+ return java.lang.Integer.class;
+ } else if (primitive == short.class) {
+ return java.lang.Short.class;
+ } else if (primitive == boolean.class) {
+ return java.lang.Boolean.class;
+ } else if (primitive == byte.class) {
+ return java.lang.Byte.class;
+ } else if (primitive == long.class) {
+ return java.lang.Long.class;
+ } else if (primitive == double.class) {
+ return java.lang.Double.class;
+ } else if (primitive == float.class) {
+ return java.lang.Float.class;
+ } else if (primitive == char.class) {
+ return java.lang.Character.class;
+ }
+
+ return null;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java
new file mode 100644
index 0000000000..062da48206
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/DefaultXMLAdapterExtensionPoint.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class DefaultXMLAdapterExtensionPoint implements XMLAdapterExtensionPoint {
+ private Map<Class<?>, Class<? extends XmlAdapter>> adapters =
+ new ConcurrentHashMap<Class<?>, Class<? extends XmlAdapter>>();
+
+ public void addAdapter(Class<?> boundType, Class<? extends XmlAdapter> adapter) {
+ adapters.put(boundType, adapter);
+ }
+
+ public Class<? extends XmlAdapter> getAdapter(Class<?> boundType) {
+ Class<? extends XmlAdapter> cls = adapters.get(boundType);
+ if (cls != null) {
+ return cls;
+ }
+ for (Map.Entry<Class<?>, Class<? extends XmlAdapter>> e : adapters.entrySet()) {
+ if (e.getKey().isAssignableFrom(boundType)) {
+ return e.getValue();
+ }
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public Class<? extends XmlAdapter> removeAdapter(Class<?> boundType) {
+ return adapters.remove(boundType);
+ }
+
+ public Map<Class<?>, Class<? extends XmlAdapter>> getAdapters() {
+ return adapters;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java
new file mode 100644
index 0000000000..3e262c7d12
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2Node.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.impl.DOMHelper;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXB2Node extends BaseTransformer<Object, Node> implements PullTransformer<Object, Node> {
+
+ public Node transform(Object source, TransformationContext tContext) {
+// if (source == null) {
+// return null;
+// }
+ try {
+ JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true);
+ Marshaller marshaller = context.createMarshaller();
+ // FIXME: The default Marshaller doesn't support
+ // marshaller.getNode()
+ Document document = DOMHelper.newDocument();
+ Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source);
+ marshaller.marshal(jaxbElement, document);
+ return DOMHelper.adjustElementName(tContext, document.getDocumentElement());
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<Object> getSourceType() {
+ return Object.class;
+ }
+
+ @Override
+ protected Class<Node> getTargetType() {
+ return Node.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java
new file mode 100644
index 0000000000..097fc6124f
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2SAX.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+
+import org.apache.tuscany.sca.databinding.PushTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.xml.sax.ContentHandler;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JAXB2SAX extends BaseTransformer<Object, ContentHandler> implements
+ PushTransformer<Object, ContentHandler> {
+
+ @Override
+ protected Class<Object> getSourceType() {
+ return Object.class;
+ }
+
+ @Override
+ protected Class<ContentHandler> getTargetType() {
+ return ContentHandler.class;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, java.lang.Object, org.apache.tuscany.sca.databinding.TransformationContext)
+ */
+ public void transform(Object source, ContentHandler target, TransformationContext tContext) {
+ try {
+ JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true);
+ Marshaller marshaller = context.createMarshaller();
+ Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source);
+ marshaller.marshal(jaxbElement, target);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public int getWeight() {
+ return 20;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java
new file mode 100644
index 0000000000..29951a5e16
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2String.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Marshaller;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXB2String extends BaseTransformer<Object, String> implements PullTransformer<Object, String> {
+
+ public String transform(Object source, TransformationContext tContext) {
+ try {
+ JAXBContext context = JAXBContextHelper.createJAXBContext(tContext, true);
+ Marshaller marshaller = context.createMarshaller();
+ StringWriter writer = new StringWriter();
+ StreamResult result = new StreamResult(writer);
+ Object jaxbElement = JAXBContextHelper.createJAXBElement(context, tContext.getSourceDataType(), source);
+ marshaller.marshal(jaxbElement, result);
+ return writer.toString();
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<Object> getSourceType() {
+ return Object.class;
+ }
+
+ @Override
+ protected Class<String> getTargetType() {
+ return String.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return XMLStringDataBinding.NAME;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java
new file mode 100644
index 0000000000..e2151e23a1
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXB2XMLStreamReader.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXB2XMLStreamReader extends BaseTransformer<Object, XMLStreamReader> implements
+ PullTransformer<Object, XMLStreamReader> {
+
+ public JAXB2XMLStreamReader() {
+ super();
+ }
+
+ public XMLStreamReader transform(Object source, TransformationContext context) {
+ if (source == null) {
+ return null;
+ }
+ try {
+ QName name = null;
+ Object bean = null;
+ if (source instanceof JAXBElement) {
+ bean = ((JAXBElement)source).getValue();
+ name = ((JAXBElement)source).getName();
+ } else {
+ JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, true);
+ Object element = JAXBContextHelper.createJAXBElement(jaxbContext, context.getSourceDataType(), source);
+ name = jaxbContext.createJAXBIntrospector().getElementName(element);
+ bean = source;
+ }
+ BeanXMLStreamReaderImpl reader = new BeanXMLStreamReaderImpl(name, bean);
+ return reader;
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<Object> getSourceType() {
+ return Object.class;
+ }
+
+ @Override
+ protected Class<XMLStreamReader> getTargetType() {
+ return XMLStreamReader.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 10;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
new file mode 100644
index 0000000000..8b527bf079
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextCache.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.awt.Image;
+import java.net.URI;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlSchema;
+import javax.xml.transform.Source;
+
+import org.apache.tuscany.sca.databinding.util.LRUCache;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JAXBContextCache {
+ private static final int CACHE_SIZE = 128;
+
+ private static HashMap<String, Class<?>> loadClassMap = new HashMap<String, Class<?>>();
+
+ static {
+ loadClassMap.put("byte", byte.class);
+ loadClassMap.put("int", int.class);
+ loadClassMap.put("short", short.class);
+ loadClassMap.put("long", long.class);
+ loadClassMap.put("float", float.class);
+ loadClassMap.put("double", double.class);
+ loadClassMap.put("boolean", boolean.class);
+ loadClassMap.put("char", char.class);
+ loadClassMap.put("void", void.class);
+ }
+
+ protected static Class<?>[] JAXB_BUILTIN_CLASSES =
+ {byte[].class, boolean.class, byte.class, char.class, double.class, float.class, int.class, long.class,
+ short.class, void.class, java.awt.Image.class, java.io.File.class, java.lang.Boolean.class,
+ java.lang.Byte.class, java.lang.Character.class, java.lang.Class.class, java.lang.Double.class,
+ java.lang.Float.class, java.lang.Integer.class, java.lang.Long.class, java.lang.Object.class,
+ java.lang.Short.class, java.lang.String.class, java.lang.Void.class, java.math.BigDecimal.class,
+ java.math.BigInteger.class, java.net.URI.class, java.net.URL.class, java.util.Calendar.class,
+ java.util.Date.class, java.util.GregorianCalendar.class, java.util.UUID.class,
+ javax.activation.DataHandler.class, javax.xml.bind.JAXBElement.class, javax.xml.datatype.Duration.class,
+ javax.xml.datatype.XMLGregorianCalendar.class, javax.xml.namespace.QName.class,
+ javax.xml.transform.Source.class};
+
+ protected static final Set<Class<?>> BUILTIN_CLASSES_SET = new HashSet<Class<?>>(Arrays.asList(JAXB_BUILTIN_CLASSES));
+
+ protected static Class<?>[] COMMON_ARRAY_CLASSES =
+ new Class[] {char[].class, short[].class, int[].class, long[].class, float[].class, double[].class,
+ String[].class
+ };
+
+ protected static final Set<Class<?>> COMMON_CLASSES_SET = new HashSet<Class<?>>(Arrays.asList(COMMON_ARRAY_CLASSES));
+
+ protected LRUCache<Object, JAXBContext> cache;
+ protected LRUCache<JAXBContext, Unmarshaller> upool;
+ protected LRUCache<JAXBContext, Marshaller> mpool;
+ protected JAXBContext commonContext;
+
+ public JAXBContextCache() {
+ this(CACHE_SIZE, CACHE_SIZE, CACHE_SIZE);
+ }
+
+ 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);
+ commonContext = getCommonJAXBContext();
+ }
+
+ public static JAXBContext getCommonJAXBContext() {
+ try {
+ return JAXBContext.newInstance(COMMON_CLASSES_SET.toArray(new Class<?>[COMMON_CLASSES_SET.size()]));
+ } catch (JAXBException e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ /**
+ * @param name of primitive type
+ * @return primitive Class or null
+ */
+ public static Class<?> getPrimitiveClass(String text) {
+ return loadClassMap.get(text);
+ }
+
+ /**
+ * Return the class for this name
+ *
+ * @return Class
+ */
+ private static Class<?> forName(final String className, final boolean initialize, final ClassLoader classloader)
+ throws ClassNotFoundException {
+ // NOTE: This method must remain private because it uses AccessController
+ Class<?> cl = null;
+ try {
+ cl = AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
+ public Class<?> run() throws ClassNotFoundException {
+ // Class.forName does not support primitives
+ Class<?> cls = getPrimitiveClass(className);
+ if (cls == null) {
+ cls = Class.forName(className, initialize, classloader);
+ }
+ return cls;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw (ClassNotFoundException)e.getException();
+ }
+
+ return cl;
+ }
+
+ /**
+ * @param p Package
+ * @param cl
+ * @return true if each package has a ObjectFactory class or package-info
+ */
+ public static boolean checkPackage(String p, ClassLoader cl) {
+
+ // Each package must have an ObjectFactory
+ try {
+ Class<?> cls = forName(p + ".ObjectFactory", false, cl);
+ if (cls != null) {
+ return true;
+ }
+ //Catch Throwable as ClassLoader can throw an NoClassDefFoundError that
+ //does not extend Exception. So we will absorb any Throwable exception here.
+ } catch (Throwable e) {
+ // Ignore
+ }
+
+ try {
+ Class<?> cls = forName(p + ".package-info", false, cl);
+ if (cls != null) {
+ return cls.isAnnotationPresent(XmlSchema.class);
+ }
+ //Catch Throwable as ClassLoader can throw an NoClassDefFoundError that
+ //does not extend Exception. So we will absorb any Throwable exception here.
+ } catch (Throwable e) {
+ // Ignore
+ }
+
+ return false;
+ }
+
+ 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;
+ }
+ }
+
+ 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;
+ }
+ }
+
+ public LRUCache<Object, JAXBContext> getCache() {
+ return cache;
+ }
+
+ public JAXBContext getJAXBContext(Class<?> cls) throws JAXBException {
+ if (COMMON_CLASSES_SET.contains(cls) || BUILTIN_CLASSES_SET.contains(cls)) {
+ return commonContext;
+ }
+ synchronized (cache) {
+ JAXBContext context = cache.get(cls);
+ if (context != null) {
+ return context;
+ }
+ Package pkg = cls.getPackage();
+ if (pkg != null) {
+ context = cache.get(pkg);
+ if (context != null) {
+ return context;
+ }
+ }
+
+ if (pkg != null && checkPackage(pkg.getName(), cls.getClassLoader())) {
+ context = JAXBContext.newInstance(pkg.getName(), cls.getClassLoader());
+ cache.put(pkg, context);
+ } else {
+ context = JAXBContext.newInstance(cls);
+ cache.put(cls, context);
+ }
+ return context;
+
+ }
+ }
+
+ public JAXBContext getJAXBContext(Class<?>[] classes) throws JAXBException {
+ Set<Class<?>> classSet = new HashSet<Class<?>>(Arrays.asList(classes));
+ return getJAXBContext(classSet);
+ }
+
+ public JAXBContext getJAXBContext(Set<Class<?>> classes) throws JAXBException {
+ // Remove the JAXB built-in types to maximize the cache hit
+ Set<Class<?>> classSet = new HashSet<Class<?>>(classes);
+ classSet.removeAll(BUILTIN_CLASSES_SET);
+
+ // FIXME: [rfeng] Remove java classes that are mapped to the same XSD type to avoid
+ // conflicts
+ if (classSet.contains(Date[].class)) {
+ classSet.remove(Calendar[].class);
+ }
+
+ if (classSet.contains(URI[].class)) {
+ classSet.remove(UUID[].class);
+ }
+
+ if (classSet.contains(Source[].class)) {
+ classSet.remove(Image[].class);
+ }
+
+ // Is the common one
+ if (COMMON_CLASSES_SET.containsAll(classSet)) {
+ return commonContext;
+ }
+
+ // For single class
+ if (classSet.size() == 1) {
+ return getJAXBContext(classSet.iterator().next());
+ }
+ synchronized (cache) {
+ JAXBContext context = cache.get(classSet);
+ if (context != null) {
+ return context;
+ }
+ context = JAXBContext.newInstance(classSet.toArray(new Class<?>[classSet.size()]));
+ cache.put(classSet, context);
+ return context;
+ }
+ }
+
+ public void clear() {
+ synchronized (cache) {
+ cache.clear();
+ }
+ synchronized (upool) {
+ upool.clear();
+ }
+ synchronized (upool) {
+ upool.clear();
+ }
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
new file mode 100644
index 0000000000..6d66f10a8e
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBContextHelper.java
@@ -0,0 +1,429 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.beans.Introspector;
+import java.io.IOException;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.JAXBIntrospector;
+import javax.xml.bind.Marshaller;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlEnum;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchema;
+import javax.xml.bind.annotation.XmlType;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Result;
+import javax.xml.transform.dom.DOMResult;
+
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl;
+import org.apache.tuscany.sca.databinding.util.LRUCache;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+// FIXME: [rfeng] We probably should turn this into a pluggable system service
+public class JAXBContextHelper {
+ // public static final String JAXB_CLASSES = "jaxb.classes";
+
+ // public static final String JAXB_CONTEXT_PATH = "jaxb.contextPath";
+
+ private static final JAXBContextCache cache = new JAXBContextCache();
+
+ private JAXBContextHelper() {
+ }
+
+ /**
+ * Create a JAXBContext for a given class
+ * @param cls
+ * @return
+ * @throws JAXBException
+ */
+ public static JAXBContext createJAXBContext(Class<?> cls) throws JAXBException {
+ return cache.getJAXBContext(cls);
+ }
+
+ public static JAXBContext createJAXBContext(TransformationContext tContext, boolean source) throws JAXBException {
+ if (tContext == null)
+ throw new TransformationException("JAXB context is not set for the transformation.");
+
+ // TODO: [rfeng] Need to figure out what's the best grantularity to create the JAXBContext
+ // per interface, operation or parameter
+ Operation op = source ? tContext.getSourceOperation() : tContext.getTargetOperation();
+ if (op != null) {
+ synchronized (op) {
+ JAXBContext context = op.getInputType().getMetaData(JAXBContext.class);
+ if (context == null) {
+ context = createJAXBContext(getDataTypes(op, true));
+ op.getInputType().setMetaData(JAXBContext.class, context);
+ }
+ return context;
+ }
+ }
+
+ // For property transformation, the operation can be null
+ DataType<?> dataType = source ? tContext.getSourceDataType() : tContext.getTargetDataType();
+ return createJAXBContext(dataType);
+
+ }
+
+ public static JAXBContext createJAXBContext(DataType dataType) throws JAXBException {
+ return createJAXBContext(findClasses(dataType));
+ }
+
+ public static Unmarshaller getUnmarshaller(JAXBContext context) throws JAXBException {
+ return cache.getUnmarshaller(context);
+ }
+
+ public static Marshaller getMarshaller(JAXBContext context) throws JAXBException {
+ return cache.getMarshaller(context);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Object createJAXBElement(JAXBContext context, DataType dataType, Object value) {
+ Class<?> type = dataType == null ? value.getClass() : dataType.getPhysical();
+ QName name = JAXBDataBinding.ROOT_ELEMENT;
+ if (context != null) {
+ Object logical = dataType == null ? null : dataType.getLogical();
+ if (logical instanceof XMLType) {
+ XMLType xmlType = (XMLType)logical;
+ if (xmlType.isElement()) {
+ name = xmlType.getElementName();
+ } else {
+ /**
+ * Set the declared type to Object.class so that xsi:type
+ * will be produced
+ */
+ type = Object.class;
+ }
+ } else {
+ type = Object.class;
+ }
+ }
+
+ JAXBIntrospector introspector = context.createJAXBIntrospector();
+ Object element = null;
+ if (value != null && introspector.isElement(value)) {
+ // NOTE: [rfeng] We cannot wrap an element in a JAXBElement
+ element = value;
+ }
+ if (element == null) {
+ element = new JAXBElement(name, type, value);
+ }
+ return element;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Object createReturnValue(JAXBContext context, DataType dataType, Object value) {
+ Class<?> cls = getJavaType(dataType);
+ if (cls == JAXBElement.class) {
+ return createJAXBElement(context, dataType, value);
+ } else {
+ if (value instanceof JAXBElement) {
+ return ((JAXBElement)value).getValue();
+ } else {
+ return value;
+ }
+ }
+ }
+
+ /**
+ * Create a JAXContext for an array of classes
+ * @param classes
+ * @return
+ * @throws JAXBException
+ */
+ public static JAXBContext createJAXBContext(Class<?>[] classes) throws JAXBException {
+ return cache.getJAXBContext(classes);
+ }
+
+ public static JAXBContext createJAXBContext(Set<Class<?>> classes) throws JAXBException {
+ return cache.getJAXBContext(classes);
+ }
+
+ /**
+ * Create a JAXBContext for a given java interface
+ * @param intf
+ * @return
+ * @throws JAXBException
+ */
+ public static JAXBContext createJAXBContext(Interface intf, boolean useWrapper) throws JAXBException {
+ synchronized (cache) {
+ LRUCache<Object, JAXBContext> map = cache.getCache();
+ Integer key = new Integer(System.identityHashCode(intf));
+ JAXBContext context = map.get(key);
+ if (context != null) {
+ return context;
+ }
+ List<DataType> dataTypes = getDataTypes(intf, useWrapper);
+ context = createJAXBContext(dataTypes);
+ map.put(key, context);
+ return context;
+ }
+ }
+
+ public static JAXBContext createJAXBContext(List<DataType> dataTypes) throws JAXBException {
+ JAXBContext context;
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+ Set<Type> visited = new HashSet<Type>();
+ for (DataType d : dataTypes) {
+ findClasses(d, classes, visited);
+ }
+
+ context = createJAXBContext(classes);
+ return context;
+ }
+
+ private static Set<Class<?>> findClasses(DataType d) {
+ Set<Class<?>> classes = new HashSet<Class<?>>();
+ Set<Type> visited = new HashSet<Type>();
+ findClasses(d, classes, visited);
+ return classes;
+ }
+
+ private static void findClasses(DataType d, Set<Class<?>> classes, Set<Type> visited) {
+ if (d == null) {
+ return;
+ }
+ String db = d.getDataBinding();
+ if (JAXBDataBinding.NAME.equals(db) || (db != null && db.startsWith("java:")) || db == null) {
+ if (!d.getPhysical().isInterface() && !JAXBElement.class.isAssignableFrom(d.getPhysical())) {
+ classes.add(d.getPhysical());
+ }
+ }
+ if (d.getPhysical() != d.getGenericType()) {
+ findClasses(d.getGenericType(), classes, visited);
+ }
+ }
+
+ /**
+ * Find referenced classes in the generic type
+ * @param type
+ * @param classSet
+ * @param visited
+ */
+ private static void findClasses(Type type, Set<Class<?>> classSet, Set<Type> visited) {
+ if (visited.contains(type) || type == null) {
+ return;
+ }
+ visited.add(type);
+ if (type instanceof Class) {
+ Class<?> cls = (Class<?>)type;
+ if (!cls.isInterface()) {
+ classSet.add(cls);
+ }
+ return;
+ } else if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType)type;
+ findClasses(pType.getRawType(), classSet, visited);
+ for (Type t : pType.getActualTypeArguments()) {
+ findClasses(t, classSet, visited);
+ }
+ } else if (type instanceof TypeVariable) {
+ TypeVariable<?> tv = (TypeVariable<?>)type;
+ for (Type t : tv.getBounds()) {
+ findClasses(t, classSet, visited);
+ }
+ } else if (type instanceof GenericArrayType) {
+ GenericArrayType gType = (GenericArrayType)type;
+ findClasses(gType, classSet, visited);
+ } else if (type instanceof WildcardType) {
+ WildcardType wType = (WildcardType)type;
+ for (Type t : wType.getLowerBounds()) {
+ findClasses(t, classSet, visited);
+ }
+ for (Type t : wType.getUpperBounds()) {
+ findClasses(t, classSet, visited);
+ }
+ }
+ }
+
+ public static JAXBContext createJAXBContext(Interface intf) throws JAXBException {
+ return createJAXBContext(intf, true);
+ }
+
+ /**
+ * @param intf
+ * @param useWrapper Use wrapper classes?
+ * @return
+ */
+ private static List<DataType> getDataTypes(Interface intf, boolean useWrapper) {
+ List<DataType> dataTypes = new ArrayList<DataType>();
+ for (Operation op : intf.getOperations()) {
+ getDataTypes(dataTypes, op, useWrapper);
+ }
+ return dataTypes;
+ }
+
+ private static List<DataType> getDataTypes(Operation op, boolean useWrapper) {
+ List<DataType> dataTypes = new ArrayList<DataType>();
+ getDataTypes(dataTypes, op, useWrapper);
+ return dataTypes;
+ }
+
+ private static void getDataTypes(List<DataType> dataTypes, Operation op, boolean useWrapper) {
+ WrapperInfo wrapper = op.getWrapper();
+ if (useWrapper && wrapper != null) {
+ DataType dt1 = wrapper.getInputWrapperType();
+ if (dt1 != null) {
+ dataTypes.add(dt1);
+ }
+ DataType dt2 = wrapper.getOutputWrapperType();
+ if (dt2 != null) {
+ dataTypes.add(dt2);
+ }
+ }
+ // FIXME: [rfeng] We may need to find the referenced classes in the child types
+ // else
+ {
+ for (DataType dt1 : op.getInputType().getLogical()) {
+ dataTypes.add(dt1);
+ }
+ DataType dt2 = op.getOutputType();
+ if (dt2 != null) {
+ dataTypes.add(dt2);
+ }
+ }
+ for (DataType<DataType> dt3 : op.getFaultTypes()) {
+ DataType dt4 = dt3.getLogical();
+ if (dt4 != null) {
+ dataTypes.add(dt4);
+ }
+ }
+ }
+
+ public static Class<?> getJavaType(DataType<?> dataType) {
+ if (dataType == null) {
+ return null;
+ }
+ Class type = dataType.getPhysical();
+ if (JAXBElement.class.isAssignableFrom(type)) {
+ Type generic = dataType.getGenericType();
+ type = Object.class;
+ }
+ if (type == Object.class && dataType.getLogical() instanceof XMLType) {
+ XMLType xType = (XMLType)dataType.getLogical();
+ Class javaType = SimpleTypeMapperImpl.getJavaType(xType.getTypeName());
+ if (javaType != null) {
+ type = javaType;
+ }
+ }
+ return type;
+ }
+
+ public static XMLType getXmlTypeName(Class<?> javaType) {
+ if (javaType.isInterface()) {
+ // JAXB doesn't support interfaces
+ return null;
+ }
+ String namespace = null;
+ String name = null;
+ Package pkg = javaType.getPackage();
+ if (pkg != null) {
+ XmlSchema schema = pkg.getAnnotation(XmlSchema.class);
+ if (schema != null) {
+ namespace = schema.namespace();
+ }
+ }
+
+ QName elementQName = null;
+ QName typeQName = null;
+ XmlRootElement rootElement = javaType.getAnnotation(XmlRootElement.class);
+ if (rootElement != null) {
+ String elementName = rootElement.name();
+ String elementNamespace = rootElement.namespace();
+ if (elementNamespace.equals("##default")) {
+ elementNamespace = namespace;
+ }
+ if (elementName.equals("##default")) {
+ elementName = Introspector.decapitalize(javaType.getSimpleName());
+ }
+ elementQName = new QName(elementNamespace, elementName);
+ }
+ XmlType type = javaType.getAnnotation(XmlType.class);
+ if (type != null) {
+ String typeNamespace = type.namespace();
+ String typeName = type.name();
+
+ if (typeNamespace.equals("##default")) {
+ // namespace is from the package
+ typeNamespace = namespace;
+ }
+
+ if (typeName.equals("##default")) {
+ typeName = Introspector.decapitalize(javaType.getSimpleName());
+ }
+ typeQName = new QName(typeNamespace, typeName);
+ } else {
+ XmlEnum xmlEnum = javaType.getAnnotation(XmlEnum.class);
+ if (xmlEnum != null) {
+ name = Introspector.decapitalize(javaType.getSimpleName());
+ typeQName = new QName(namespace, name);
+ }
+ }
+ if (elementQName == null && typeQName == null) {
+ return null;
+ }
+ return new XMLType(elementQName, typeQName);
+ }
+
+ public static Node generateSchema(JAXBContext context) throws Exception {
+ SchemaOutputResolverImpl resolver = new SchemaOutputResolverImpl();
+ context.generateSchema(resolver);
+ return resolver.getSchema();
+ }
+
+ public static class SchemaOutputResolverImpl extends SchemaOutputResolver {
+ private DOMResult result = new DOMResult();
+
+ @Override
+ public Result createOutput(String ns, String file) throws IOException {
+ result.setSystemId("sca:dom");
+ return result;
+ }
+
+ public Node getSchema() {
+ return result != null ? result.getNode() : null;
+ }
+
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java
new file mode 100644
index 0000000000..471bb54bbd
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBDataBinding.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.databinding.WrapperHandler;
+import org.apache.tuscany.sca.databinding.XMLTypeHelper;
+import org.apache.tuscany.sca.databinding.impl.BaseDataBinding;
+import org.apache.tuscany.sca.databinding.impl.DOMHelper;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.w3c.dom.Document;
+
+/**
+ * JAXB DataBinding
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXBDataBinding extends BaseDataBinding {
+ public static final String NAME = JAXBElement.class.getName();
+ public static final String[] ALIASES = new String[] {"jaxb"};
+
+ public static final String ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/jaxb/1.0";
+ public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root");
+
+ private JAXBWrapperHandler wrapperHandler;
+ private JAXBTypeHelper xmlTypeHelper;
+
+ public JAXBDataBinding() {
+ super(NAME, ALIASES, JAXBElement.class);
+ this.wrapperHandler = new JAXBWrapperHandler();
+ this.xmlTypeHelper = new JAXBTypeHelper();
+ }
+
+ @Override
+ public boolean introspect(DataType dataType, Operation operation) {
+ Class javaType = dataType.getPhysical();
+ if (JAXBElement.class.isAssignableFrom(javaType)) {
+ Type type = javaType.getGenericSuperclass();
+ if (type instanceof ParameterizedType) {
+ ParameterizedType parameterizedType = ((ParameterizedType)type);
+ Type rawType = parameterizedType.getRawType();
+ if (rawType == JAXBElement.class) {
+ Type actualType = parameterizedType.getActualTypeArguments()[0];
+ if (actualType instanceof Class) {
+ XMLType xmlType = JAXBContextHelper.getXmlTypeName((Class)actualType);
+ dataType.setLogical(xmlType);
+ dataType.setDataBinding(NAME);
+ return true;
+ }
+ }
+ }
+ if (dataType.getLogical() == null) {
+ dataType.setLogical(XMLType.UNKNOWN);
+ }
+ dataType.setDataBinding(NAME);
+ return true;
+ }
+
+ XMLType xmlType = JAXBContextHelper.getXmlTypeName(javaType);
+ if (xmlType == null) {
+ return false;
+ }
+ dataType.setLogical(xmlType);
+ dataType.setDataBinding(NAME);
+ return true;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public Object copy(Object arg, DataType dataType, Operation operation) {
+ try {
+ boolean isElement = false;
+ if (dataType == null) {
+ Class cls = arg.getClass();
+ if (arg instanceof JAXBElement) {
+ isElement = true;
+ cls = ((JAXBElement)arg).getDeclaredType();
+ }
+ dataType = new DataTypeImpl<XMLType>(NAME, cls, XMLType.UNKNOWN);
+ }
+ JAXBContext context = JAXBContextHelper.createJAXBContext(dataType);
+ arg = JAXBContextHelper.createJAXBElement(context, dataType, arg);
+ Document doc = DOMHelper.newDocument();
+ context.createMarshaller().marshal(arg, doc);
+ Object value = context.createUnmarshaller().unmarshal(doc, dataType.getPhysical());
+ if (isElement && value instanceof JAXBElement) {
+ return value;
+ }
+ return JAXBContextHelper.createReturnValue(context, dataType, value);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ @Override
+ public WrapperHandler getWrapperHandler() {
+ return wrapperHandler;
+ }
+
+ @Override
+ public XMLTypeHelper getXMLTypeHelper() {
+ return new JAXBTypeHelper();
+ // return xmlTypeHelper;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java
new file mode 100644
index 0000000000..b85cbb0f42
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBPropertyDescriptor.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.beans.IndexedPropertyDescriptor;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * A PropertyDescriptor provides acesss to a bean property. Values can be queried/changed using the
+ * read and writer methods of the PropertyDescriptor.
+ * <p/>
+ * A PropertyDescriptorPlus object wraps a PropertyDescriptor and supplies enhanced set/get methods
+ * that match JAXB semantis.
+ * <p/>
+ * For example, the set(..) method is smart enough to add lists, arrays and atomic values on JAXB
+ * beans.
+ * <p/>
+ * The PropertyDescriptorPlus object also stores the xmlName of the property.
+ *
+ * @See XMLRootElementUtil.createPropertyDescriptorMap , which creates the PropertyDescriptorPlus
+ * objects
+ */
+public class JAXBPropertyDescriptor implements Comparable<JAXBPropertyDescriptor> {
+ PropertyDescriptor descriptor;
+ QName xmlName = null;
+ int index;
+
+ /**
+ * Package protected constructor. Only created by XMLRootElementUtil.createPropertyDescriptorMap
+ * @param descriptor
+ * @param index TODO
+ * @param propertyName
+ *
+ * @see XMLRootElementUtil.createPropertyDescriptorMap
+ */
+ JAXBPropertyDescriptor(PropertyDescriptor descriptor, QName xmlName, int index) {
+ super();
+ this.descriptor = descriptor;
+ this.xmlName = xmlName;
+ }
+
+ /**
+ * Package protected constructor. Only created by XMLRootElementUtil.createPropertyDescriptorMap
+ * @param descriptor
+ * @param index TODO
+ * @param propertyName
+ *
+ * @see XMLRootElementUtil.createPropertyDescriptorMap
+ */
+ JAXBPropertyDescriptor(PropertyDescriptor descriptor, String xmlName, int index) {
+ super();
+ this.descriptor = descriptor;
+ this.xmlName = new QName("", xmlName);
+ }
+
+ public int compareTo(JAXBPropertyDescriptor o) {
+ return index - o.index;
+ }
+
+ /** @return xmlname */
+ public String getXmlName() {
+ return xmlName.getLocalPart();
+ }
+
+ public QName getXmlQName() {
+ return xmlName;
+ }
+
+ /** @return property type */
+ public Class<?> getPropertyType() {
+ return descriptor.getPropertyType();
+ }
+
+ /** @return property name */
+ public String getPropertyName() {
+ return descriptor.getName();
+ }
+
+ /**
+ * Get the object
+ *
+ * @param targetBean
+ * @return Object for this property or null
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ */
+ public Object get(Object targetBean) throws InvocationTargetException, IllegalAccessException {
+ Method method = descriptor.getReadMethod();
+ if (method == null && descriptor.getPropertyType() == Boolean.class) {
+ String propertyName = descriptor.getName();
+ if (propertyName != null) {
+ String methodName = "is";
+ methodName =
+ methodName + ((propertyName.length() > 0) ? propertyName.substring(0, 1).toUpperCase() : "");
+ methodName = methodName + ((propertyName.length() > 1) ? propertyName.substring(1) : "");
+ try {
+ method = targetBean.getClass().getMethod(methodName);
+ } catch (NoSuchMethodException e) {
+ }
+ }
+ }
+ if (method == null) {
+ throw new ServiceRuntimeException("No getter is found");
+ }
+ Object ret = method.invoke(targetBean);
+ if (method.getReturnType() == JAXBElement.class) {
+ ret = ((JAXBElement<?>)ret).getValue();
+ }
+ return ret;
+ }
+
+ /**
+ * Set the object
+ *
+ * @param targetBean
+ * @param propValue
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws JAXBWrapperException
+ */
+ public void set(Object targetBean, Object propValue) throws InvocationTargetException, IllegalAccessException,
+ JAXBWrapperException {
+
+ Method writeMethod = null;
+ try {
+ // No set occurs if the value is null
+ if (propValue == null) {
+ return;
+ }
+
+ // There are 3 different types of setters that can occur.
+ // 1) Normal Attomic Setter : setFoo(type)
+ // 2) Indexed Array Setter : setFoo(type[])
+ // 3) No Setter case if the property is a List<T>.
+
+ writeMethod = descriptor.getWriteMethod();
+ if (descriptor instanceof IndexedPropertyDescriptor) {
+ // Set for indexed T[]
+ setIndexedArray(targetBean, propValue, writeMethod);
+ } else if (writeMethod == null) {
+ // Set for List<T>
+ setList(targetBean, propValue);
+ } else if (descriptor.getPropertyType() == JAXBElement.class) {
+ if (propValue != null) {
+ Class<?> clazz = propValue.getClass();
+ JAXBElement<?> element = new JAXBElement(xmlName, clazz, propValue);
+ setAtomic(targetBean, element, writeMethod);
+ }
+ } else {
+ // Normal case
+ setAtomic(targetBean, propValue, writeMethod);
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ }
+ }
+
+ /**
+ * Set the property value onto targetBean using the writeMethod
+ *
+ * @param targetBean
+ * @param propValue
+ * @param writeMethod (set(T))
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws JAXBWrapperException
+ */
+ private void setAtomic(Object targetBean, Object propValue, Method writeMethod) throws InvocationTargetException,
+ IllegalAccessException, JAXBWrapperException {
+ // JAXB provides setters for atomic value.
+
+ if (propValue != null) {
+ // Normal case
+ Object[] SINGLE_PARAM = new Object[1];
+ SINGLE_PARAM[0] = propValue;
+ writeMethod.invoke(targetBean, SINGLE_PARAM);
+ } else {
+ Class<?>[] paramTypes = writeMethod.getParameterTypes();
+
+ if (paramTypes != null && paramTypes.length == 1) {
+ Class<?> paramType = paramTypes[0];
+ if (paramType.isPrimitive() && propValue == null) {
+ //Ignoring null value for primitive type, this could potentially be the way of a customer indicating to set
+ //default values defined in JAXBObject/xmlSchema.
+ return;
+ }
+ }
+ }
+
+ }
+
+ /**
+ * Set the property value using the indexed array setter
+ *
+ * @param targetBean
+ * @param propValue
+ * @param writeMethod set(T[])
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws JAXBWrapperException
+ */
+ private void setIndexedArray(Object targetBean, Object propValue, Method writeMethod)
+ throws InvocationTargetException, IllegalAccessException, JAXBWrapperException {
+
+ Class<?> paramType = writeMethod.getParameterTypes()[0];
+ Object value = asArray(propValue, paramType);
+ // JAXB provides setters for atomic value.
+ Object[] SINGLE_PARAM = new Object[1];
+ SINGLE_PARAM[0] = value;
+
+ writeMethod.invoke(targetBean, SINGLE_PARAM);
+ }
+
+ /**
+ * Set the property value for the collection case.
+ *
+ * @param targetBean
+ * @param propValue
+ * @throws InvocationTargetException
+ * @throws IllegalAccessException
+ * @throws JAXBWrapperException
+ */
+ private void setList(Object targetBean, Object propValue) throws InvocationTargetException, IllegalAccessException,
+ JAXBWrapperException {
+ // For the List<T> case, there is no setter.
+ // You are supposed to use the getter to obtain access to the collection and then add the collection
+
+ Collection value = asCollection(propValue, descriptor.getPropertyType());
+ Collection collection = (Collection)get(targetBean);
+
+ // Now add our our object to the collection
+ collection.clear();
+ if (propValue != null) {
+ collection.addAll(value);
+ }
+ }
+
+ /**
+ * @param propValue
+ * @param destType
+ * @return propValue as a Collection
+ */
+ private static Collection asCollection(Object propValue, Class<?> destType) {
+ // TODO Missing function
+ // Convert the object into an equivalent object that is a collection
+ if (DataConverter.isConvertable(propValue, destType)) {
+ return (Collection)DataConverter.convert(propValue, destType);
+ } else {
+ String objectClass = (propValue == null) ? "null" : propValue.getClass().getName();
+ throw new ServiceRuntimeException("Cannot convert " + objectClass);
+ }
+ }
+
+ /**
+ * @param propValue
+ * @param destType T[]
+ * @return array of component type
+ */
+ private static Object asArray(Object propValue, Class<?> destType) {
+ if (DataConverter.isConvertable(propValue, destType)) {
+ return DataConverter.convert(propValue, destType);
+ } else {
+ String objectClass = (propValue == null) ? "null" : propValue.getClass().getName();
+ throw new ServiceRuntimeException("Cannot convert " + objectClass);
+
+ }
+ }
+
+ public String toString() {
+ String value = "PropertyDescriptorPlus[";
+ value += " name=" + this.getPropertyName();
+ value += " type=" + this.getPropertyType().getName();
+ value += " propertyDecriptor=" + this.descriptor;
+ return value + "]";
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java
new file mode 100644
index 0000000000..f5189345f7
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBTypeHelper.java
@@ -0,0 +1,236 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.beans.Introspector;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Result;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.tuscany.sca.contribution.resolver.ModelResolver;
+import org.apache.tuscany.sca.databinding.XMLTypeHelper;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Interface;
+import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
+import org.apache.tuscany.sca.interfacedef.util.TypeInfo;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.apache.tuscany.sca.xsd.XSDFactory;
+import org.apache.tuscany.sca.xsd.XSDefinition;
+import org.apache.ws.commons.schema.resolver.URIResolver;
+import org.osoa.sca.ServiceRuntimeException;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+
+public class JAXBTypeHelper implements XMLTypeHelper {
+ private static final String SCHEMA_NS = "http://www.w3.org/2001/XMLSchema";
+ private static final String ANYTYPE_NAME = "anyType";
+ private static final QName ANYTYPE_QNAME = new QName(SCHEMA_NS, ANYTYPE_NAME);
+
+ // private List<Class<?>> types = new ArrayList<Class<?>>();
+
+ public JAXBTypeHelper() {
+ super();
+ }
+
+ public TypeInfo getTypeInfo(Class javaType, Object logical) {
+ QName xmlType = JavaXMLMapper.getXMLType(javaType);
+ if (xmlType != null) {
+ return new TypeInfo(xmlType, true, null);
+ } else if (javaType.isInterface()) {
+ return new TypeInfo(ANYTYPE_QNAME, true, null);
+ } else {
+ // types.add(javaType);
+ if (logical instanceof XMLType) {
+ xmlType = ((XMLType)logical).getTypeName();
+ }
+ if (xmlType == null) {
+ xmlType =
+ new QName(JavaXMLMapper.getNamespace(javaType), Introspector.decapitalize(javaType.getSimpleName()));
+ }
+ return new TypeInfo(xmlType, false, null);
+ }
+ }
+
+ /*
+ public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver) {
+ List<XSDefinition> definitions = new ArrayList<XSDefinition>();
+ generateJAXBSchemas(definitions, factory);
+ return definitions;
+ }
+ */
+
+ public static Map<String, String> generateSchema(JAXBContext context) throws IOException {
+ StringResolverImpl resolver = new StringResolverImpl();
+ context.generateSchema(resolver);
+ Map<String, String> xsds = new HashMap<String, String>();
+ for (Map.Entry<String, StreamResult> xsd : resolver.getResults().entrySet()) {
+ xsds.put(xsd.getKey(), xsd.getValue().getWriter().toString());
+ }
+ return xsds;
+ }
+
+ private static class XSDResolver implements URIResolver {
+ private Map<String, String> xsds;
+
+ public XSDResolver(Map<String, String> xsds) {
+ super();
+ this.xsds = xsds;
+ }
+
+ public InputSource resolveEntity(java.lang.String namespace,
+ java.lang.String schemaLocation,
+ java.lang.String baseUri) {
+ String xsd = xsds.get(schemaLocation);
+ if (xsd == null) {
+ return null;
+ }
+ return new InputSource(new StringReader(xsd));
+ }
+
+ }
+
+ /*
+ private void generateJAXBSchemas1(List<XSDefinition> definitions, XSDFactory factory) {
+ if (types.size() > 0) {
+ try {
+ XmlSchemaCollection collection = new XmlSchemaCollection();
+ Class[] typesArray = new Class[types.size()];
+ typesArray = types.toArray(typesArray);
+ JAXBContext context = JAXBContextHelper.createJAXBContext(typesArray);
+ Map<String, String> results = generateSchema(context);
+ collection.setSchemaResolver(new XSDResolver(results));
+
+ for (Map.Entry<String, String> entry : results.entrySet()) {
+ XSDefinition definition = factory.createXSDefinition();
+ int index = entry.getKey().lastIndexOf('#');
+ String ns = entry.getKey().substring(0, index);
+ String file = entry.getKey().substring(index + 1);
+ definition.setUnresolved(true);
+ definition.setNamespace(ns);
+ definition.setSchema(collection.read(new StringReader(entry.getValue()), null));
+ definition.setSchemaCollection(collection);
+ definition.setUnresolved(false);
+ definitions.add(definition);
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ */
+
+ private static class DOMResolverImpl extends SchemaOutputResolver {
+ private Map<String, DOMResult> results = new HashMap<String, DOMResult>();
+
+ @Override
+ public Result createOutput(String ns, String file) throws IOException {
+ DOMResult result = new DOMResult();
+ result.setSystemId(ns + file);
+ results.put(ns, result);
+ return result;
+ }
+
+ public Map<String, DOMResult> getResults() {
+ return results;
+ }
+ }
+
+ /*
+ private void generateJAXBSchemas(List<XSDefinition> definitions, XSDFactory factory) {
+ if (types.size() > 0) {
+ try {
+ Class<?>[] typesArray = new Class<?>[types.size()];
+ typesArray = types.toArray(typesArray);
+ JAXBContext context = JAXBContext.newInstance(typesArray);
+ generateSchemas(definitions, factory, context);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ */
+
+ private void generateSchemas(List<XSDefinition> definitions, XSDFactory factory, JAXBContext context)
+ throws IOException {
+ DOMResolverImpl resolver = new DOMResolverImpl();
+ context.generateSchema(resolver);
+ Map<String, DOMResult> results = resolver.getResults();
+ for (Map.Entry<String, DOMResult> entry : results.entrySet()) {
+ XSDefinition definition = factory.createXSDefinition();
+ definition.setUnresolved(true);
+ definition.setDocument((Document)entry.getValue().getNode());
+ definition.setNamespace(entry.getKey());
+ definitions.add(definition);
+ }
+ }
+
+ private static class StringResolverImpl extends SchemaOutputResolver {
+ private Map<String, StreamResult> results = new HashMap<String, StreamResult>();
+
+ @Override
+ public Result createOutput(String ns, String file) throws IOException {
+ StringWriter sw = new StringWriter();
+ StreamResult result = new StreamResult(sw);
+ String sysId = ns + '#' + file;
+ result.setSystemId(sysId);
+ results.put(sysId, result);
+ return result;
+ }
+
+ public Map<String, StreamResult> getResults() {
+ return results;
+ }
+ }
+
+ public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, Interface intf) {
+ try {
+ JAXBContext context = JAXBContextHelper.createJAXBContext(intf, false);
+ List<XSDefinition> definitions = new ArrayList<XSDefinition>();
+ generateSchemas(definitions, factory, context);
+ return definitions;
+ } catch (Throwable e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+ public List<XSDefinition> getSchemaDefinitions(XSDFactory factory, ModelResolver resolver, List<DataType> dataTypes) {
+ try {
+
+ JAXBContext context = JAXBContextHelper.createJAXBContext(dataTypes);
+ List<XSDefinition> definitions = new ArrayList<XSDefinition>();
+ generateSchemas(definitions, factory, context);
+ return definitions;
+ } catch (Throwable e) {
+ throw new ServiceRuntimeException(e);
+ }
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java
new file mode 100644
index 0000000000..f83c7f09d9
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperException.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import org.osoa.sca.ServiceRuntimeException;
+
+public class JAXBWrapperException extends ServiceRuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ *
+ */
+ public JAXBWrapperException() {
+ super();
+
+ }
+
+ /**
+ * @param message
+ * @param cause
+ */
+ public JAXBWrapperException(String message, Throwable cause) {
+ super(message, cause);
+
+ }
+
+ /** @param message */
+ public JAXBWrapperException(String message) {
+ super(message);
+
+ }
+
+ /** @param cause */
+ public JAXBWrapperException(Throwable cause) {
+ super(cause);
+
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java
new file mode 100644
index 0000000000..a1f4c12c8f
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHandler.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.WrapperHandler;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.util.ElementInfo;
+import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
+
+/**
+ * JAXB WrapperHandler implementation
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXBWrapperHandler implements WrapperHandler<Object> {
+ private JAXBWrapperHelper helper = new JAXBWrapperHelper();
+
+ public Object create(Operation operation, boolean input) {
+ WrapperInfo wrapperInfo = operation.getWrapper();
+ ElementInfo element = input ? wrapperInfo.getInputWrapperElement() : wrapperInfo.getOutputWrapperElement();
+ final Class<?> wrapperClass = input ? wrapperInfo.getInputWrapperClass() : wrapperInfo.getOutputWrapperClass();
+ try {
+ if (wrapperClass == null) {
+ return null;
+ }
+ return AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ public Object run() throws Exception {
+ return wrapperClass.newInstance();
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ public void setChildren(Object wrapper, Object[] childObjects, Operation operation, boolean input) {
+ List<ElementInfo> childElements =
+ input ? operation.getWrapper().getInputChildElements() : operation.getWrapper().getOutputChildElements();
+ List<String> childNames = new ArrayList<String>();
+ Map<String, Object> values = new HashMap<String, Object>();
+ for (int i = 0; i < childElements.size(); i++) {
+ ElementInfo e = childElements.get(i);
+ String name = e.getQName().getLocalPart();
+ childNames.add(name);
+ values.put(name, childObjects[i]);
+ }
+ // Get the property descriptor map
+ Map<String, JAXBPropertyDescriptor> pdMap = null;
+ try {
+ pdMap = XMLRootElementUtil.createPropertyDescriptorMap(wrapper.getClass());
+ } catch (Throwable t) {
+ throw new JAXBWrapperException(t);
+ }
+ helper.wrap(wrapper, childNames, values, pdMap);
+ }
+
+ public void setChild(Object wrapper, int i, ElementInfo childElement, Object value) {
+ Object wrapperValue = wrapper;
+ Class<?> wrapperClass = wrapperValue.getClass();
+
+ // FIXME: We probably should use the jaxb-reflection to handle the properties
+ try {
+ String prop = childElement.getQName().getLocalPart();
+ boolean collection = (value instanceof Collection);
+ Method getter = null;
+ for (Method m : wrapperClass.getMethods()) {
+ Class<?>[] paramTypes = m.getParameterTypes();
+ if (paramTypes.length == 1 && m.getName().equals("set" + capitalize(prop))) {
+ m.invoke(wrapperValue, new Object[] {value});
+ return;
+ }
+ if (collection && paramTypes.length == 0 && m.getName().equals("get" + capitalize(prop))) {
+ getter = m;
+ }
+ }
+ if (getter != null && Collection.class.isAssignableFrom(getter.getReturnType())) {
+ ((Collection)getter.invoke(wrapperValue)).addAll((Collection)value);
+ }
+
+ } catch (Throwable e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ private static String capitalize(String name) {
+ char first = Character.toUpperCase(name.charAt(0));
+ return first + name.substring(1);
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.databinding.WrapperHandler#getChildren(java.lang.Object, Operation, boolean)
+ */
+ public List getChildren(Object wrapper, Operation operation, boolean input) {
+ List<ElementInfo> childElements = input? operation.getWrapper().getInputChildElements():
+ operation.getWrapper().getOutputChildElements();
+
+ List<String> childNames = new ArrayList<String>();
+ for (ElementInfo e : childElements) {
+ childNames.add(e.getQName().getLocalPart());
+ }
+ return Arrays.asList(helper.unwrap(wrapper, childNames));
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean)
+ */
+ public DataType getWrapperType(Operation operation, boolean input) {
+ WrapperInfo wrapper = operation.getWrapper();
+ DataType dt = input ? wrapper.getInputWrapperType() : wrapper.getOutputWrapperType();
+ return dt;
+ }
+
+ /**
+ * @see org.apache.tuscany.sca.databinding.WrapperHandler#isInstance(java.lang.Object, Operation, boolean)
+ */
+ public boolean isInstance(Object wrapper, Operation operation, boolean input) {
+ Class<?> wrapperClass =
+ input ? operation.getWrapper().getInputWrapperClass() : operation.getWrapper().getOutputWrapperClass();
+ return wrapperClass == null ? false : wrapperClass.isInstance(wrapper);
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java
new file mode 100644
index 0000000000..5f90aa4d7a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/JAXBWrapperHelper.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * The JAXBWrapper tool is used to create a JAXB Object from a series of child objects (wrap) or get
+ * the child objects from a JAXB Object (unwrap)
+ */
+public class JAXBWrapperHelper {
+
+ /**
+ * unwrap Returns the list of child objects of the jaxb object
+ *
+ * @param jaxbObject that represents the type
+ * @param childNames list of xml child names as String
+ * @param pdMap PropertyDescriptor map for this jaxbObject
+ * @return list of Objects in the same order as the element names.
+ */
+ public Object[] unwrap(Object jaxbObject, List<String> childNames, Map<String, JAXBPropertyDescriptor> pdMap)
+ throws JAXBWrapperException {
+
+ // Get the object that will have the property descriptors (i.e. the object representing the complexType)
+ Object jaxbComplexTypeObj = jaxbObject;
+
+ // Get the PropertyDescriptorPlus map.
+ // The method makes sure that each child name has a matching jaxb property
+ // checkPropertyDescriptorMap(jaxbComplexTypeObj.getClass(), childNames, pdMap);
+
+ // Get the corresponsing objects from the jaxb bean
+ ArrayList<Object> objList = new ArrayList<Object>();
+ int index = 0;
+ for (String childName : childNames) {
+ JAXBPropertyDescriptor propInfo = getPropertyDescriptor(pdMap, childName, index);
+
+ Object object = null;
+ try {
+ object = propInfo.get(jaxbComplexTypeObj);
+ } catch (Throwable e) {
+ throw new JAXBWrapperException(e);
+ }
+
+ objList.add(object);
+ index++;
+ }
+ Object[] jaxbObjects = objList.toArray();
+ objList = null;
+ return jaxbObjects;
+
+ }
+
+ private JAXBPropertyDescriptor getPropertyDescriptor(Map<String, JAXBPropertyDescriptor> pdMap,
+ String childName,
+ int index) {
+ JAXBPropertyDescriptor propInfo = pdMap.get(childName);
+ if (propInfo == null) {
+ // FIXME: [rfeng] Sometimes the child element names don't match. Get chilld by location?
+ List<JAXBPropertyDescriptor> props = new ArrayList<JAXBPropertyDescriptor>(pdMap.values());
+ // Sort the properties by index. We might need to take propOrder into consideration
+ Collections.sort(props);
+ propInfo = props.get(index);
+ }
+ return propInfo;
+ }
+
+ /**
+ * wrap Creates a jaxb object that is initialized with the child objects.
+ * <p/>
+ * Note that the jaxbClass must be the class the represents the complexType. (It should never be
+ * JAXBElement)
+ *
+ * @param jaxbClass
+ * @param childNames list of xml child names as String
+ * @param childObjects, component type objects
+ * @param pdMap PropertyDescriptor map for this jaxbObject
+ */
+ public Object wrap(Class<?> jaxbClass,
+ List<String> childNames,
+ Map<String, Object> childObjects,
+ Map<String, JAXBPropertyDescriptor> pdMap) throws JAXBWrapperException {
+
+ // Just like unWrap, get the property info map
+ // checkPropertyDescriptorMap(jaxbClass, childNames, pdMap);
+
+ // The jaxb object always has a default constructor. Create the object
+ Object jaxbObject = null;
+ try {
+ jaxbObject = jaxbClass.newInstance();
+ } catch (Throwable t) {
+ throw new JAXBWrapperException(t);
+ }
+
+ wrap(jaxbObject, childNames, childObjects, pdMap);
+
+ // Return the jaxb object
+ return jaxbObject;
+ }
+
+ public void wrap(Object jaxbObject,
+ List<String> childNames,
+ Map<String, Object> childObjects,
+ Map<String, JAXBPropertyDescriptor> pdMap) {
+ // Now set each object onto the jaxb object
+ int index = 0;
+ for (String childName : childNames) {
+ JAXBPropertyDescriptor propInfo = getPropertyDescriptor(pdMap, childName, index);
+ Object value = childObjects.get(childName);
+ try {
+ propInfo.set(jaxbObject, value);
+ } catch (Throwable t) {
+ throw new JAXBWrapperException(t);
+ }
+ index++;
+ }
+ }
+
+ public Object[] unwrap(Object jaxbObject, List<String> childNames) throws JAXBWrapperException {
+ // Get the property descriptor map for this JAXBClass
+ Class<?> jaxbClass = jaxbObject.getClass();
+ Map<String, JAXBPropertyDescriptor> pdMap = null;
+ try {
+ pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
+ } catch (Throwable t) {
+ throw new JAXBWrapperException(t);
+ }
+
+ // Delegate
+ return unwrap(jaxbObject, childNames, pdMap);
+ }
+
+ public Object wrap(Class<?> jaxbClass, List<String> childNames, Map<String, Object> childObjects)
+ throws JAXBWrapperException {
+ // Get the property descriptor map
+ Map<String, JAXBPropertyDescriptor> pdMap = null;
+ try {
+ pdMap = XMLRootElementUtil.createPropertyDescriptorMap(jaxbClass);
+ } catch (Throwable t) {
+ throw new JAXBWrapperException(t);
+ }
+
+ // Delegate
+ return wrap(jaxbClass, childNames, childObjects, pdMap);
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java
new file mode 100644
index 0000000000..e375a9b85e
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Node2JAXB.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.w3c.dom.Node;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class Node2JAXB extends BaseTransformer<Node, Object> implements PullTransformer<Node, Object> {
+
+ public Node2JAXB() {
+ super();
+ }
+
+ public Object transform(Node source, TransformationContext context) {
+ if (source == null)
+ return null;
+ try {
+ JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ Object result = unmarshaller.unmarshal(source, JAXBContextHelper.getJavaType(context.getTargetDataType()));
+ return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<Node> getSourceType() {
+ return Node.class;
+ }
+
+ @Override
+ protected Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java
new file mode 100644
index 0000000000..840edfd234
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/Reader2JAXB.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.io.Reader;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class Reader2JAXB extends BaseTransformer<Reader, Object> implements
+ PullTransformer<Reader, Object> {
+
+ public Object transform(final Reader source, final TransformationContext context) {
+ if (source == null) {
+ return null;
+ }
+ try {
+ JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ StreamSource streamSource = new StreamSource(source);
+ Object result = unmarshaller.unmarshal(streamSource, JAXBContextHelper.getJavaType(context.getTargetDataType()));
+ return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<Reader> getSourceType() {
+ return Reader.class;
+ }
+
+ @Override
+ protected Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java
new file mode 100644
index 0000000000..5559690de8
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/String2JAXB.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.io.StringReader;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+import org.apache.tuscany.sca.databinding.xml.XMLStringDataBinding;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class String2JAXB extends BaseTransformer<String, Object> implements
+ PullTransformer<String, Object> {
+
+ public Object transform(final String source, final TransformationContext context) {
+ if (source == null) {
+ return null;
+ }
+ try {
+ JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ StreamSource streamSource = new StreamSource(new StringReader(source));
+ Object result = unmarshaller.unmarshal(streamSource, JAXBContextHelper.getJavaType(context.getTargetDataType()));
+ return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ protected Class<String> getSourceType() {
+ return String.class;
+ }
+
+ @Override
+ protected Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 30;
+ }
+
+ @Override
+ public String getSourceDataBinding() {
+ return XMLStringDataBinding.NAME;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java
new file mode 100644
index 0000000000..5fa98b5ed1
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLAdapterExtensionPoint.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.util.Map;
+
+import javax.xml.bind.annotation.adapters.XmlAdapter;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface XMLAdapterExtensionPoint {
+ /**
+ * @param boundType
+ * @param adapter
+ */
+ void addAdapter(Class<?> boundType, Class<? extends XmlAdapter> adapter);
+
+ /**
+ * @param boundType
+ * @return
+ */
+ Class<? extends XmlAdapter> getAdapter(Class<?> boundType);
+
+ /**
+ * @param boundType
+ * @return
+ */
+ Class<? extends XmlAdapter> removeAdapter(Class<?> boundType);
+
+ /**
+ * @return
+ */
+ Map<Class<?>, Class<? extends XmlAdapter>> getAdapters();
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java
new file mode 100644
index 0000000000..ad4bd04084
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLRootElementUtil.java
@@ -0,0 +1,286 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import java.beans.IntrospectionException;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Field;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
+import javax.xml.bind.annotation.XmlEnumValue;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlSchema;
+import javax.xml.namespace.QName;
+
+/**
+ *
+ */
+public class XMLRootElementUtil {
+
+ /** Constructor is intentionally private. This class only provides static utility methods */
+ private XMLRootElementUtil() {
+
+ }
+
+ /**
+ * @param clazz
+ * @return namespace of root element qname or null if this is not object does not represent a
+ * root element
+ */
+ public static QName getXmlRootElementQNameFromObject(Object obj) {
+
+ // A JAXBElement stores its name
+ if (obj instanceof JAXBElement) {
+ return ((JAXBElement<?>)obj).getName();
+ }
+
+ Class<?> clazz = (obj instanceof java.lang.Class) ? (Class<?>)obj : obj.getClass();
+ return getXmlRootElementQName(clazz);
+ }
+
+ /**
+ * @param clazz
+ * @return namespace of root element qname or null if this is not object does not represent a
+ * root element
+ */
+ public static QName getXmlRootElementQName(Class<?> clazz) {
+
+ // See if the object represents a root element
+ XmlRootElement root = (XmlRootElement)getAnnotation(clazz, XmlRootElement.class);
+ if (root == null) {
+ return null;
+ }
+
+ String name = root.name();
+ String namespace = root.namespace();
+
+ // The name may need to be defaulted
+ if (name == null || name.length() == 0 || name.equals("##default")) {
+ name = getSimpleName(clazz.getCanonicalName());
+ }
+
+ // The namespace may need to be defaulted
+ if (namespace == null || namespace.length() == 0 || namespace.equals("##default")) {
+ Package pkg = clazz.getPackage();
+ XmlSchema schema = (XmlSchema)getAnnotation(pkg, XmlSchema.class);
+ if (schema != null) {
+ namespace = schema.namespace();
+ } else {
+ namespace = "";
+ }
+ }
+
+ return new QName(namespace, name);
+ }
+
+ /**
+ * @param clazz
+ * @return namespace of root element qname or null if this is not object does not represent a root element
+ */
+ public static String getEnumValue(Enum<?> myEnum) {
+ Field f;
+ String value;
+ try {
+ f = myEnum.getClass().getField(myEnum.name());
+
+ f.setAccessible(true);
+
+ XmlEnumValue xev = (XmlEnumValue)getAnnotation(f, XmlEnumValue.class);
+ if (xev == null) {
+ value = f.getName();
+ } else {
+ value = xev.value();
+ }
+ } catch (SecurityException e) {
+ value = null;
+ } catch (NoSuchFieldException e) {
+ value = null;
+ }
+
+ return value;
+ }
+
+ /**
+ * utility method to get the last token in a "."-delimited package+classname string
+ *
+ * @return
+ */
+ private static String getSimpleName(String in) {
+ if (in == null || in.length() == 0) {
+ return in;
+ }
+ String out = null;
+ StringTokenizer tokenizer = new StringTokenizer(in, ".");
+ if (tokenizer.countTokens() == 0)
+ out = in;
+ else {
+ while (tokenizer.hasMoreTokens()) {
+ out = tokenizer.nextToken();
+ }
+ }
+ return out;
+ }
+
+ /**
+ * The JAXBClass has a set of bean properties each represented by a PropertyDescriptor Each of
+ * the fields of the class has an associated xml name. The method returns a map where the key is
+ * the xml name and value is the PropertyDescriptor
+ *
+ * @param jaxbClass
+ * @return map
+ */
+ public static Map<String, JAXBPropertyDescriptor> createPropertyDescriptorMap(Class<?> jaxbClass)
+ throws NoSuchFieldException, IntrospectionException {
+
+ PropertyDescriptor[] pds = Introspector.getBeanInfo(jaxbClass).getPropertyDescriptors();
+ Map<String, JAXBPropertyDescriptor> map = new HashMap<String, JAXBPropertyDescriptor>();
+
+ // Unfortunately the element names are stored on the fields.
+ // Get all of the fields in the class and super classes
+
+ List<Field> fields = getFields(jaxbClass);
+
+ // Now match up the fields with the property descriptors...Sigh why didn't JAXB put the @XMLElement annotations on the
+ // property methods!
+ for (PropertyDescriptor pd : pds) {
+
+ // Skip over the class property..it is never represented as an xml element
+ if (pd.getName().equals("class")) {
+ continue;
+ }
+
+ // For the current property, find a matching field...so that we can get the xml name
+ boolean found = false;
+
+ int index = 0;
+ for (Field field : fields) {
+ String fieldName = field.getName();
+
+ // Use the name of the field and property to find the match
+ if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || fieldName.equalsIgnoreCase(pd.getName())) {
+ // Get the xmlElement name for this field
+ QName xmlName = getXmlElementRefOrElementQName(field.getDeclaringClass(), field);
+ found = true;
+ map.put(xmlName.getLocalPart(), new JAXBPropertyDescriptor(pd, xmlName, index));
+ index++;
+ break;
+ }
+
+ // Unfortunately, sometimes the field name is preceeded by an underscore
+ if (fieldName.startsWith("_")) {
+ fieldName = fieldName.substring(1);
+ if (fieldName.equalsIgnoreCase(pd.getDisplayName()) || fieldName.equalsIgnoreCase(pd.getName())) {
+ // Get the xmlElement name for this field
+ QName xmlName = getXmlElementRefOrElementQName(field.getDeclaringClass(), field);
+ found = true;
+
+ map.put(xmlName.getLocalPart(), new JAXBPropertyDescriptor(pd, xmlName, index));
+ index++;
+ break;
+ }
+ }
+ }
+
+ // We didn't find a field. Default the xmlname to the property name
+ if (!found) {
+ String xmlName = pd.getName();
+
+ map.put(xmlName, new JAXBPropertyDescriptor(pd, xmlName, index));
+ index++;
+ }
+
+ }
+ return map;
+ }
+
+ /**
+ * Gets all of the fields in this class and the super classes
+ *
+ * @param beanClass
+ * @return
+ */
+ static private List<Field> getFields(final Class<?> beanClass) {
+ // This class must remain private due to Java 2 Security concerns
+ List<Field> fields = AccessController.doPrivileged(new PrivilegedAction<List<Field>>() {
+ public List<Field> run() {
+ List<Field> fields = new ArrayList<Field>();
+ Class<?> cls = beanClass;
+ while (cls != null) {
+ Field[] fieldArray = cls.getDeclaredFields();
+ for (Field field : fieldArray) {
+ fields.add(field);
+ }
+ cls = cls.getSuperclass();
+ }
+ return fields;
+ }
+ });
+
+ return fields;
+ }
+
+ /**
+ * Get the name of the field by looking at the XmlElement annotation.
+ *
+ * @param jaxbClass
+ * @param fieldName
+ * @return
+ * @throws NoSuchFieldException
+ */
+ private static QName getXmlElementRefOrElementQName(Class<?> jaxbClass, Field field) throws NoSuchFieldException {
+ XmlElementRef xmlElementRef = (XmlElementRef)getAnnotation(field, XmlElementRef.class);
+ if (xmlElementRef != null) {
+ return new QName(xmlElementRef.namespace(), xmlElementRef.name());
+ }
+ XmlElement xmlElement = (XmlElement)getAnnotation(field, XmlElement.class);
+
+ // If XmlElement does not exist, default to using the field name
+ if (xmlElement == null || xmlElement.name().equals("##default")) {
+ return new QName("", field.getName());
+ }
+ return new QName(xmlElement.namespace(), xmlElement.name());
+ }
+
+ /**
+ * Get an annotation. This is wrappered to avoid a Java2Security violation.
+ * @param cls Class that contains annotation
+ * @param annotation Class of requrested Annotation
+ * @return annotation or null
+ */
+ private static <T extends Annotation> T getAnnotation(final AnnotatedElement element, final Class<T> annotation) {
+ return AccessController.doPrivileged(new PrivilegedAction<T>() {
+ public T run() {
+ return element.getAnnotation(annotation);
+ }
+ });
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java
new file mode 100644
index 0000000000..af3fa3fb66
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/java/org/apache/tuscany/sca/databinding/jaxb/XMLStreamReader2JAXB.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.sca.databinding.jaxb;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.tuscany.sca.databinding.PullTransformer;
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.TransformationException;
+import org.apache.tuscany.sca.databinding.impl.BaseTransformer;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class XMLStreamReader2JAXB extends BaseTransformer<XMLStreamReader, Object> implements
+ PullTransformer<XMLStreamReader, Object> {
+
+ public XMLStreamReader2JAXB() {
+ super();
+ }
+
+ public Object transform(XMLStreamReader source, TransformationContext context) {
+ if (source == null) {
+ return null;
+ }
+ try {
+ JAXBContext jaxbContext = JAXBContextHelper.createJAXBContext(context, false);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+ // FIXME: [rfeng] If the java type is Object.class, the unmarshalled result will be
+ // a DOM Node
+ Object result = unmarshaller.unmarshal(source, JAXBContextHelper.getJavaType(context.getTargetDataType()));
+ source.close();
+ return JAXBContextHelper.createReturnValue(jaxbContext, context.getTargetDataType(), result);
+ } catch (Exception e) {
+ throw new TransformationException(e);
+ }
+ }
+
+ @Override
+ public Class<XMLStreamReader> getSourceType() {
+ return XMLStreamReader.class;
+ }
+
+ @Override
+ public Class<Object> getTargetType() {
+ return Object.class;
+ }
+
+ @Override
+ public int getWeight() {
+ return 10;
+ }
+
+ @Override
+ public String getTargetDataBinding() {
+ return JAXBDataBinding.NAME;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding
new file mode 100644
index 0000000000..58d6123373
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.DataBinding
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# implementation classes for the databindings
+org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding;type=javax.xml.bind.JAXBElement,name=jaxb
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer
new file mode 100644
index 0000000000..4e062e4c22
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.PullTransformer
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Implementation classes for the transformers
+org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=javax.xml.bind.JAXBElement,target=org.w3c.dom.Node,weight=500
+org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=javax.xml.bind.JAXBElement,weight=500
+org.apache.tuscany.sca.databinding.jaxb.Reader2JAXB;source=java.io.Reader,target=javax.xml.bind.JAXBElement,weight=510
+org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=javax.xml.bind.JAXBElement,weight=490
+
+org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=java:complexType,target=org.w3c.dom.Node,weight=90000
+org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=java:complexType,weight=90000
+
+org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;source=org.w3c.dom.Node,target=java:simpleType,weight=90000
+org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;source=java:simpleType,target=org.w3c.dom.Node,weight=90000
+
+org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=java:complexType,weight=90000
+org.apache.tuscany.sca.databinding.jaxb.XMLStreamReader2JAXB;source=javax.xml.stream.XMLStreamReader,target=java:simpleType,weight=90000
+
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint
new file mode 100644
index 0000000000..d1f6d9f1e3
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/main/resources/META-INF/services/org.apache.tuscany.sca.databinding.jaxb.XMLAdapterExtensionPoint
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+org.apache.tuscany.sca.databinding.jaxb.DefaultXMLAdapterExtensionPoint \ No newline at end of file
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java
new file mode 100644
index 0000000000..5c5c892f33
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/com/example/stock/StockQuoteOffer.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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 com.example.stock;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+/**
+ * <p>Java class for anonymous complex type.
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {"input"})
+@XmlRootElement(name = "stockQuoteOffer")
+public class StockQuoteOffer {
+
+ protected String input;
+
+ public String getInput() {
+ return this.input;
+ }
+
+ public void setInput(String input) {
+ this.input = input;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBContextCacheTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBContextCacheTestCase.java
new file mode 100644
index 0000000000..e5fbd50b30
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBContextCacheTestCase.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.JAXBException;
+import javax.xml.namespace.QName;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+
+import junit.framework.Assert;
+
+import org.apache.tuscany.sca.databinding.jaxb.JAXBContextCache;
+import org.apache.tuscany.sca.databinding.util.LRUCache;
+import org.junit.Test;
+
+import com.example.ipo.jaxb.Address;
+import com.example.ipo.jaxb.PurchaseOrderType;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JAXBContextCacheTestCase {
+ @Test
+ public void testCache() throws JAXBException {
+ JAXBContextCache cache = new JAXBContextCache();
+ JAXBContext context1 = cache.getJAXBContext(String.class);
+ JAXBContext context2 = cache.getJAXBContext(int.class);
+ JAXBContext context3 = cache.getJAXBContext(String[].class);
+ JAXBContext context4 = cache.getJAXBContext(Source.class);
+ Assert.assertSame(context1, context2);
+ Assert.assertSame(context2, context3);
+ Assert.assertSame(context3, context4);
+
+ QName name = new QName("http://example.com/ns1", "e1");
+ JAXBElement<String> element = new JAXBElement<String>(name, String.class, "123");
+ StringWriter sw = new StringWriter();
+ context4.createMarshaller().marshal(element, sw);
+ StreamSource source = new StreamSource(new StringReader(sw.toString()), null);
+ context4.createUnmarshaller().unmarshal(source, String.class);
+
+ JAXBContext context5 = cache.getJAXBContext(Address.class);
+ JAXBContext context6 = cache.getJAXBContext(PurchaseOrderType.class);
+ Assert.assertSame(context5, context6);
+ }
+
+ @Test
+ public void testLRUCache() {
+ LRUCache<String, String> cache = new LRUCache<String, String>(3);
+ cache.put("1", "A");
+ Assert.assertEquals(1, cache.size());
+ cache.put("2", "B");
+ Assert.assertEquals(2, cache.size());
+ cache.put("3", "C");
+ Assert.assertEquals(3, cache.size());
+ cache.put("4", "D");
+ Assert.assertEquals(3, cache.size());
+ String data = cache.get("1");
+ Assert.assertNull(data);
+ data = cache.get("2");
+ Assert.assertEquals("B", data);
+ cache.put("5", "E");
+ data = cache.get("2");
+ Assert.assertEquals("B", data);
+ }
+
+ @Test
+ public void testPerf() throws JAXBException {
+ JAXBContextCache cache = new JAXBContextCache();
+
+ // Test JAXBContext for simple java classes
+ long start = System.currentTimeMillis();
+ for (int i = 0; i < 100; i++) {
+ JAXBContext context = JAXBContext.newInstance(String.class);
+ }
+ long end = System.currentTimeMillis();
+ long d1 = end - start;
+ start = System.currentTimeMillis();
+ for (int i = 0; i < 100; i++) {
+ JAXBContext context = cache.getJAXBContext(String.class);
+ }
+ end = System.currentTimeMillis();
+ long d2 = end - start;
+ System.out.println(d1 + "ms vs. " + d2 + "ms");
+
+ // Test JAXBContext for generated JAXB classes
+ start = System.currentTimeMillis();
+ for (int i = 0; i < 20; i++) {
+ JAXBContext context = JAXBContext.newInstance(PurchaseOrderType.class);
+ }
+ end = System.currentTimeMillis();
+ d1 = end - start;
+ start = System.currentTimeMillis();
+ for (int i = 0; i < 20; i++) {
+ JAXBContext context = cache.getJAXBContext(PurchaseOrderType.class);
+ }
+ end = System.currentTimeMillis();
+ d2 = end - start;
+ System.out.println(d1 + "ms vs. " + d2 + "ms");
+
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBDataBindingTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBDataBindingTestCase.java
new file mode 100644
index 0000000000..8506bc296b
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBDataBindingTestCase.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+
+import com.example.ipo.jaxb.ObjectFactory;
+import com.example.ipo.jaxb.PurchaseOrderType;
+import com.example.ipo.jaxb.USAddress;
+import com.example.ipo.jaxb.USState;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXBDataBindingTestCase extends TestCase {
+ private JAXBDataBinding binding;
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ binding = new JAXBDataBinding();
+ }
+
+ /**
+ * Test method for
+ * {@link org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding#introspect(java.lang.Class, Operation)}.
+ */
+ public final void testIntrospect() {
+ DataType dataType = new DataTypeImpl<Class>(JAXBElement.class, null);
+ Operation op = null;
+ boolean yes = binding.introspect(dataType, op);
+ assertTrue(yes);
+ assertTrue(dataType.getDataBinding().equals(binding.getName()));
+ assertTrue(dataType.getPhysical() == JAXBElement.class && dataType.getLogical() == XMLType.UNKNOWN);
+ dataType = new DataTypeImpl<Class>(MockJAXBElement.class, null);
+ yes = binding.introspect(dataType, op);
+ assertTrue(yes);
+ assertEquals(MockJAXBElement.class, dataType.getPhysical());
+ assertEquals(new QName("http://www.example.com/IPO", "PurchaseOrderType"), ((XMLType)dataType.getLogical())
+ .getTypeName());
+ dataType = new DataTypeImpl<Class>(USAddress.class, null);
+ yes = binding.introspect(dataType, op);
+ assertTrue(yes);
+ assertEquals(USAddress.class, dataType.getPhysical());
+ assertEquals(new QName("http://www.example.com/IPO", "USAddress"), ((XMLType)dataType.getLogical())
+ .getTypeName());
+ dataType = new DataTypeImpl<Class>(USState.class, null);
+ yes = binding.introspect(dataType, op);
+ assertTrue(yes);
+ assertTrue(dataType.getDataBinding().equals(binding.getName()));
+ assertEquals(USState.class, dataType.getPhysical());
+ assertEquals(new QName("http://www.example.com/IPO", "USState"), ((XMLType)dataType.getLogical()).getTypeName());
+
+ }
+
+ private static class MockJAXBElement extends JAXBElement<PurchaseOrderType> {
+
+ private static final long serialVersionUID = -2767569071002707973L;
+
+ /**
+ * @param elementName
+ * @param type
+ * @param value
+ */
+ public MockJAXBElement(QName elementName, Class<PurchaseOrderType> type, PurchaseOrderType value) {
+ super(elementName, type, value);
+ }
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCopy() {
+ ObjectFactory factory = new ObjectFactory();
+ PurchaseOrderType poType = factory.createPurchaseOrderType();
+ JAXBElement<PurchaseOrderType> po = factory.createPurchaseOrder(poType);
+ JAXBElement<PurchaseOrderType> copy = (JAXBElement<PurchaseOrderType>)binding.copy(po, null, null);
+ assertEquals(new QName("http://www.example.com/IPO", "purchaseOrder"), copy.getName());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCopyNonElement() {
+ ObjectFactory factory = new ObjectFactory();
+ PurchaseOrderType poType = factory.createPurchaseOrderType();
+ poType.setComment("Comment");
+ PurchaseOrderType copy = (PurchaseOrderType)binding.copy(poType, null, null);
+ assertTrue(copy instanceof PurchaseOrderType);
+ assertEquals("Comment", (copy).getComment());
+ }
+
+ @SuppressWarnings("unchecked")
+ public void testCopyNonRoot() {
+ ObjectFactory factory = new ObjectFactory();
+ USAddress address = factory.createUSAddress();
+ address.setCity("San Jose");
+ USAddress copy = (USAddress)binding.copy(address, null, null);
+ assertTrue(copy instanceof USAddress);
+ assertEquals("San Jose", (copy).getCity());
+
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBReflectionTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBReflectionTestCase.java
new file mode 100644
index 0000000000..3ec6a6785a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBReflectionTestCase.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import java.lang.reflect.Type;
+import java.util.Collections;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.namespace.QName;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.databinding.jaxb.JAXBContextHelper;
+import org.apache.tuscany.sca.databinding.xml.Node2String;
+import org.jvnet.jaxb.reflection.model.annotation.RuntimeInlineAnnotationReader;
+import org.jvnet.jaxb.reflection.model.core.Ref;
+import org.jvnet.jaxb.reflection.model.impl.RuntimeModelBuilder;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimeClassInfo;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimePropertyInfo;
+import org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet;
+import org.jvnet.jaxb.reflection.runtime.IllegalAnnotationsException;
+import org.jvnet.jaxb.reflection.runtime.JAXBContextImpl;
+import org.w3c.dom.Node;
+
+import com.example.ipo.jaxb.ObjectFactory;
+import com.example.ipo.jaxb.PurchaseOrderType;
+import com.example.ipo.jaxb.USAddress;
+import com.example.ipo.jaxb.USState;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JAXBReflectionTestCase extends TestCase {
+
+ public void testGenerateSchema() throws Exception {
+ JAXBContext context = JAXBContext.newInstance("com.example.ipo.jaxb");
+ Node schema = JAXBContextHelper.generateSchema(context);
+ System.out.println(new Node2String().transform(schema, null));
+ }
+
+ /**
+ * This is a workaround for the NPE bug in jaxb-reflection
+ * @param classes
+ * @return
+ * @throws Exception
+ */
+ @SuppressWarnings("unchecked")
+ private static RuntimeTypeInfoSet create(Class... classes) throws Exception {
+ IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder();
+ RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader();
+ JAXBContextImpl context =
+ new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false);
+ RuntimeModelBuilder builder =
+ new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null);
+ builder.setErrorHandler(errorListener);
+ for (Class c : classes)
+ builder.getTypeInfo(new Ref<Type, Class>(c));
+
+ RuntimeTypeInfoSet r = builder.link();
+ errorListener.check();
+ return r;
+ }
+
+ public void testReflection() throws Exception {
+ org.jvnet.jaxb.reflection.model.runtime.RuntimeTypeInfoSet model = create(PurchaseOrderType.class);
+ RuntimeClassInfo type = (RuntimeClassInfo)model.getTypeInfo(PurchaseOrderType.class);
+ Assert.assertEquals(new QName("http://www.example.com/IPO", "PurchaseOrderType"), type.getTypeName());
+ type = (RuntimeClassInfo)model.getTypeInfo(USAddress.class);
+ Assert.assertEquals(new QName("http://www.example.com/IPO", "USAddress"), type.getTypeName());
+ RuntimePropertyInfo prop = type.getProperty("state");
+ Assert.assertNotNull(prop);
+ USAddress address = new ObjectFactory().createUSAddress();
+ prop.getAccessor().set(address, USState.CA);
+ Assert.assertEquals(USState.CA, address.getState());
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBTestCase.java
new file mode 100644
index 0000000000..21a745cd9a
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBTestCase.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+
+import java.io.StringReader;
+
+import javax.xml.namespace.QName;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.jaxb.JAXB2Node;
+import org.apache.tuscany.sca.databinding.jaxb.Node2JAXB;
+import org.apache.tuscany.sca.databinding.jaxb.Reader2JAXB;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.w3c.dom.Node;
+
+import com.example.ipo.jaxb.ObjectFactory;
+import com.example.ipo.jaxb.PurchaseOrderType;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXBTestCase extends TestCase {
+ private static final String IPO_XML =
+ "<?xml version=\"1.0\"?>" + "<ipo:purchaseOrder"
+ + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
+ + " xmlns:ipo=\"http://www.example.com/IPO\""
+ + " xsi:schemaLocation=\"http://www.example.com/IPO ipo.xsd\""
+ + " orderDate=\"1999-12-01\">"
+ + " <shipTo exportCode=\"1\" xsi:type=\"ipo:UKAddress\">"
+ + " <name>Helen Zoe</name>"
+ + " <street>47 Eden Street</street>"
+ + " <city>Cambridge</city>"
+ + " <postcode>CB1 1JR</postcode>"
+ + " </shipTo>"
+ + " <billTo xsi:type=\"ipo:USAddress\">"
+ + " <name>Robert Smith</name>"
+ + " <street>8 Oak Avenue</street>"
+ + " <city>Old Town</city>"
+ + " <state>PA</state>"
+ + " <zip>95819</zip>"
+ + " </billTo>"
+ + " <items>"
+ + " <item partNum=\"833-AA\">"
+ + " <productName>Lapis necklace</productName>"
+ + " <quantity>1</quantity>"
+ + " <USPrice>99.95</USPrice>"
+ + " <ipo:comment>Want this for the holidays</ipo:comment>"
+ + " <shipDate>1999-12-05</shipDate>"
+ + " </item>"
+ + " </items>"
+ + "</ipo:purchaseOrder>";
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void testTransform() throws Exception {
+ Reader2JAXB t0 = new Reader2JAXB();
+
+ DataType targetDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null);
+
+ TransformationContext tContext = createMock(TransformationContext.class);
+ expect(tContext.getTargetDataType()).andReturn(targetDataType).anyTimes();
+ expect(tContext.getTargetOperation()).andReturn(null).anyTimes();
+ replay(tContext);
+
+ Object object1 = t0.transform(new StringReader(IPO_XML), tContext);
+
+ DataType sourceDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null);
+
+ TransformationContext tContext1 = createMock(TransformationContext.class);
+ expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes();
+ expect(tContext1.getTargetDataType()).andReturn(null).anyTimes();
+ expect(tContext1.getSourceOperation()).andReturn(null).anyTimes();
+ expect(tContext1.getTargetOperation()).andReturn(null).anyTimes();
+ replay(tContext1);
+
+ JAXB2Node t1 = new JAXB2Node();
+ Node node = t1.transform(object1, tContext1);
+
+ Assert.assertNotNull(node);
+
+ Node2JAXB t2 = new Node2JAXB();
+ Object object2 = t2.transform(node, tContext);
+ Assert.assertNotNull(object2);
+
+ }
+
+ public void testTransform2() throws Exception {
+ Reader2JAXB t0 = new Reader2JAXB();
+
+ QName root = new QName("http://www.example.com/IPO", "purchaseOrder");
+ DataType targetDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(root, null));
+ // targetDataType.setMetadata(JAXBContextHelper.JAXB_CONTEXT_PATH, contextPath);
+
+ TransformationContext tContext = createMock(TransformationContext.class);
+ expect(tContext.getTargetDataType()).andReturn(targetDataType).anyTimes();
+ expect(tContext.getTargetOperation()).andReturn(null).anyTimes();
+ replay(tContext);
+
+ Object object1 = t0.transform(new StringReader(IPO_XML), tContext);
+
+ DataType sourceDataType = new DataTypeImpl<XMLType>(PurchaseOrderType.class, new XMLType(root, null));
+ // sourceDataType.setMetadata(JAXBContextHelper.JAXB_CONTEXT_PATH, contextPath);
+
+ TransformationContext tContext1 = createMock(TransformationContext.class);
+ expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes();
+ expect(tContext1.getTargetDataType()).andReturn(null).anyTimes();
+ expect(tContext1.getSourceOperation()).andReturn(null).anyTimes();
+ expect(tContext1.getTargetOperation()).andReturn(null).anyTimes();
+ replay(tContext1);
+
+ JAXB2Node t1 = new JAXB2Node();
+ Node node = t1.transform(object1, tContext1);
+
+ Assert.assertNotNull(node);
+
+ Node2JAXB t2 = new Node2JAXB();
+ Object object2 = t2.transform(node, tContext);
+ Assert.assertNotNull(object2);
+
+ }
+
+ public void testTransform3() throws Exception {
+
+ DataType sourceDataType = new DataTypeImpl<Class>(PurchaseOrderType.class, null);
+
+ TransformationContext tContext1 = createMock(TransformationContext.class);
+ expect(tContext1.getSourceDataType()).andReturn(sourceDataType).anyTimes();
+ expect(tContext1.getTargetDataType()).andReturn(null).anyTimes();
+ expect(tContext1.getSourceOperation()).andReturn(null).anyTimes();
+ expect(tContext1.getTargetOperation()).andReturn(null).anyTimes();
+ replay(tContext1);
+
+ JAXB2Node t1 = new JAXB2Node();
+ PurchaseOrderType po = new ObjectFactory().createPurchaseOrderType();
+ Node node = t1.transform(po, tContext1);
+
+ Assert.assertNotNull(node);
+
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBWrapperHandlerTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBWrapperHandlerTestCase.java
new file mode 100644
index 0000000000..10bc858d80
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/JAXBWrapperHandlerTestCase.java
@@ -0,0 +1,90 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding;
+import org.apache.tuscany.sca.databinding.jaxb.JAXBWrapperHandler;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.impl.OperationImpl;
+import org.apache.tuscany.sca.interfacedef.util.ElementInfo;
+import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+
+import com.example.stock.StockQuoteOffer;
+
+/**
+ * Test case for JAXBExceptionHandler
+ *
+ * @version $Rev$ $Date$
+ */
+public class JAXBWrapperHandlerTestCase extends TestCase {
+ private static final QName ELEMENT = new QName("http://www.example.com/stock", "stockQuoteOffer");
+ private static final QName INPUT = new QName("", "input");
+ private JAXBWrapperHandler handler;
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ this.handler = new JAXBWrapperHandler();
+ }
+
+ public void testCreate() {
+ ElementInfo element = new ElementInfo(ELEMENT, null);
+ Operation op = new OperationImpl();
+ WrapperInfo wrapperInfo = new WrapperInfo(JAXBDataBinding.NAME, element, null, null, null);
+ wrapperInfo.setInputWrapperType(new DataTypeImpl<XMLType>(JAXBDataBinding.NAME, StockQuoteOffer.class,
+ XMLType.UNKNOWN));
+ op.setWrapper(wrapperInfo);
+ Object offer = handler.create(op, true);
+ Assert.assertTrue(offer instanceof StockQuoteOffer);
+ }
+
+ public void testSetChild() {
+ StockQuoteOffer wrapper = new StockQuoteOffer();
+ handler.setChild(wrapper, 0, new ElementInfo(INPUT, null), "IBM");
+ Assert.assertEquals("IBM", wrapper.getInput());
+ }
+
+ public void testGetChildren() {
+ StockQuoteOffer wrapper = new StockQuoteOffer();
+ wrapper.setInput("IBM");
+ List<ElementInfo> elements = new ArrayList<ElementInfo>();
+ elements.add(new ElementInfo(INPUT, null));
+ WrapperInfo wrapperInfo = new WrapperInfo(JAXBDataBinding.NAME, null, null, elements, null);
+ Operation op = new OperationImpl();
+ op.setWrapper(wrapperInfo);
+ List children = handler.getChildren(wrapper, op, true);
+ assertNotNull(children);
+ assertEquals(1, children.size());
+ assertEquals("IBM", children.get(0));
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyBean.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyBean.java
new file mode 100644
index 0000000000..4b09f49246
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyBean.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class MyBean {
+ private int age;
+ private String name;
+ private float[] rates = new float[] {1.0f, 2.0f};
+ private List<String> notes = new ArrayList<String>();
+ private Map<String, Integer> map = new HashMap<String, Integer>();
+ private Object service;
+ private Object otherService;
+ private boolean good;
+
+ public int getAge() {
+ return age;
+ }
+
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<String> getNotes() {
+ return notes;
+ }
+
+ public void setNotes(List<String> notes) {
+ this.notes = notes;
+ }
+
+ public float[] getRates() {
+ return rates;
+ }
+
+ public void setRates(float[] rates) {
+ this.rates = rates;
+ }
+
+ public Map<String, Integer> getMap() {
+ return map;
+ }
+
+ public void setMap(Map<String, Integer> map) {
+ this.map = map;
+ }
+
+ public Object getService() {
+ return service;
+ }
+
+ public void setService(Object service) {
+ this.service = service;
+ }
+
+ public Object getOtherService() {
+ return otherService;
+ }
+
+ public void setOtherService(Object otherService) {
+ this.otherService = otherService;
+ }
+
+ public boolean isGood() {
+ return good;
+ }
+
+ public void setGood(boolean good) {
+ this.good = good;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + age;
+ result = prime * result + (good ? 1231 : 1237);
+ result = prime * result + ((map == null) ? 0 : map.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((notes == null) ? 0 : notes.hashCode());
+ result = prime * result + ((otherService == null) ? 0 : otherService.hashCode());
+ result = prime * result + Arrays.hashCode(rates);
+ result = prime * result + ((service == null) ? 0 : service.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final MyBean other = (MyBean)obj;
+ if (age != other.age)
+ return false;
+ if (good != other.good)
+ return false;
+ if (map == null) {
+ if (other.map != null)
+ return false;
+ } else if (!map.equals(other.map))
+ return false;
+ if (name == null) {
+ if (other.name != null)
+ return false;
+ } else if (!name.equals(other.name))
+ return false;
+ if (notes == null) {
+ if (other.notes != null)
+ return false;
+ } else if (!notes.equals(other.notes))
+ return false;
+ if (otherService == null) {
+ if (other.otherService != null)
+ return false;
+ } else if (!otherService.equals(other.otherService))
+ return false;
+ if (!Arrays.equals(rates, other.rates))
+ return false;
+ if (service == null) {
+ if (other.service != null)
+ return false;
+ } else if (!service.equals(other.service))
+ return false;
+ return true;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterface.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterface.java
new file mode 100644
index 0000000000..5f998c4b2c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterface.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public interface MyInterface {
+ void setId(String id);
+
+ String getId();
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterfaceImpl.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterfaceImpl.java
new file mode 100644
index 0000000000..928acb9f3c
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MyInterfaceImpl.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class MyInterfaceImpl implements MyInterface {
+ private String id;
+
+ /**
+ * @see org.apache.tuscany.databinding.jaxb.MyInterface#getId()
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * @see org.apache.tuscany.databinding.jaxb.MyInterface#setId(java.lang.String)
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ final MyInterfaceImpl other = (MyInterfaceImpl)obj;
+ if (id == null) {
+ if (other.id != null)
+ return false;
+ } else if (!id.equals(other.id))
+ return false;
+ return true;
+ }
+
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MySubBean.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MySubBean.java
new file mode 100644
index 0000000000..157d1065d4
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/MySubBean.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class MySubBean extends MyBean {
+ private String addtional;
+
+ public String getAddtional() {
+ return addtional;
+ }
+
+ public void setAddtional(String addtional) {
+ this.addtional = addtional;
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/POJOTestCase.java b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/POJOTestCase.java
new file mode 100644
index 0000000000..2735c650ee
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/java/org/apache/tuscany/databinding/jaxb/POJOTestCase.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.tuscany.databinding.jaxb;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.transform.stream.StreamSource;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.sca.databinding.TransformationContext;
+import org.apache.tuscany.sca.databinding.impl.TransformationContextImpl;
+import org.apache.tuscany.sca.databinding.jaxb.JAXB2XMLStreamReader;
+
+import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader;
+import com.sun.xml.bind.v2.model.core.Ref;
+import com.sun.xml.bind.v2.model.impl.RuntimeModelBuilder;
+import com.sun.xml.bind.v2.model.runtime.RuntimeClassInfo;
+import com.sun.xml.bind.v2.model.runtime.RuntimePropertyInfo;
+import com.sun.xml.bind.v2.model.runtime.RuntimeTypeInfoSet;
+import com.sun.xml.bind.v2.runtime.IllegalAnnotationsException;
+import com.sun.xml.bind.v2.runtime.JAXBContextImpl;
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public class POJOTestCase extends TestCase {
+ public void testPOJO() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(MyBean.class, MyInterfaceImpl.class);
+ StringWriter writer = new StringWriter();
+ MyBean bean = new MyBean();
+ bean.setName("Test");
+ bean.setAge(20);
+ bean.getNotes().add("1");
+ bean.getNotes().add("2");
+ bean.getMap().put("1", 1);
+ MyInterface service = new MyInterfaceImpl();
+ service.setId("ID001");
+ bean.setService(service);
+ bean.setOtherService(service);
+ JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, bean);
+ context.createMarshaller().marshal(element, writer);
+ // System.out.println(writer.toString());
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString()));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof MyBean);
+ MyBean newBean = (MyBean)e2.getValue();
+ assertEquals(bean, newBean);
+ }
+
+ public void testPOJOArray() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(MyBean[].class);
+ StringWriter writer = new StringWriter();
+ MySubBean bean = new MySubBean();
+ bean.setAddtional("SUB");
+ bean.setName("Test");
+ bean.setAge(20);
+ bean.getNotes().add("1");
+ bean.getNotes().add("2");
+ bean.getMap().put("1", 1);
+
+ JAXBElement<Object> element =
+ new JAXBElement<Object>(new QName("http://ns1", "beans"), Object.class, new MyBean[] {bean});
+ context.createMarshaller().marshal(element, writer);
+ System.out.println(writer.toString());
+
+ Object result =
+ context.createUnmarshaller().unmarshal(new StreamSource(new StringReader(writer.toString())),
+ MyBean[].class);
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof MyBean[]);
+ MyBean newBean = ((MyBean[])e2.getValue())[0];
+ assertFalse(newBean instanceof MySubBean);
+ }
+
+ public void testXMLStreamReader() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(MyBean.class, MyInterfaceImpl.class);
+
+ MyBean bean = new MyBean();
+ bean.setName("Test");
+ bean.setAge(20);
+ bean.getNotes().add("1");
+ bean.getNotes().add("2");
+ bean.getMap().put("1", 1);
+ MyInterface service = new MyInterfaceImpl();
+ service.setId("ID001");
+ bean.setService(service);
+ bean.setOtherService(service);
+ QName name = new QName("http://ns1", "bean");
+ JAXBElement<Object> element = new JAXBElement<Object>(name, Object.class, bean);
+ TransformationContext tContext = new TransformationContextImpl();
+ XMLStreamReader reader = new JAXB2XMLStreamReader().transform(element, tContext);
+
+// XMLStreamReader2String t2 = new XMLStreamReader2String();
+// String xml = t2.transform(reader, null);
+ // System.out.println(xml);
+ Object result = context.createUnmarshaller().unmarshal(reader, MyBean.class);
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof MyBean);
+ MyBean newBean = (MyBean)e2.getValue();
+ // FIXME :To be implemented
+ // assertEquals(bean, newBean);
+ }
+
+ public void testString() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(String.class);
+ StringWriter writer = new StringWriter();
+ JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, "ABC");
+ context.createMarshaller().marshal(element, writer);
+ // System.out.println(writer.toString());
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString()));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertEquals("ABC", e2.getValue());
+ }
+
+ public void testNull() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(String.class);
+ StringWriter writer = new StringWriter();
+ JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, null);
+ element.setNil(true);
+ context.createMarshaller().marshal(element, writer);
+ // System.out.println(writer.toString());
+ StreamSource source = new StreamSource(new StringReader(writer.toString()));
+ Object result = context.createUnmarshaller().unmarshal(source, String.class);
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertNull(e2.getValue());
+ }
+
+ public void testArray() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(String[].class);
+ StringWriter writer = new StringWriter();
+ JAXBElement<Object> element =
+ new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, new String[] {"ABC", "123"});
+ context.createMarshaller().marshal(element, writer);
+ // System.out.println(writer.toString());
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString()));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof String[]);
+ }
+
+ public void testByteArray() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(byte[].class);
+ StringWriter writer = new StringWriter();
+ JAXBElement<Object> element =
+ new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, "ABC".getBytes());
+ context.createMarshaller().marshal(element, writer);
+ String xml = writer.toString();
+ assertTrue(xml.contains("QUJD"));
+ assertTrue(xml.contains("base64Binary"));
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(xml));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof byte[]);
+ }
+
+ public void testPrimitive() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(int.class);
+ StringWriter writer = new StringWriter();
+ JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, 1);
+ context.createMarshaller().marshal(element, writer);
+ // System.out.println(writer.toString());
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString()));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertEquals(1, e2.getValue());
+ }
+
+ /*
+ public void testException() throws Exception {
+ JAXBContext context = JAXBContext.newInstance(IllegalArgumentException.class);
+ StringWriter writer = new StringWriter();
+ Exception e = new IllegalArgumentException("123");
+ JAXBElement<Object> element = new JAXBElement<Object>(new QName("http://ns1", "bean"), Object.class, e);
+ context.createMarshaller().marshal(element, writer);
+ System.out.println(writer.toString());
+
+ Object result = context.createUnmarshaller().unmarshal(new StringReader(writer.toString()));
+ assertTrue(result instanceof JAXBElement);
+ JAXBElement e2 = (JAXBElement)result;
+ assertTrue(e2.getValue() instanceof Exception);
+ }
+ */
+
+ private static RuntimeTypeInfoSet create(Class... classes) throws Exception {
+ IllegalAnnotationsException.Builder errorListener = new IllegalAnnotationsException.Builder();
+ RuntimeInlineAnnotationReader reader = new RuntimeInlineAnnotationReader();
+ JAXBContextImpl context =
+ new JAXBContextImpl(classes, null, Collections.<Class, Class> emptyMap(), null, false, reader, false, false);
+ RuntimeModelBuilder builder =
+ new RuntimeModelBuilder(context, reader, Collections.<Class, Class> emptyMap(), null);
+ builder.setErrorHandler(errorListener);
+ for (Class c : classes)
+ builder.getTypeInfo(new Ref<Type, Class>(c));
+
+ RuntimeTypeInfoSet r = builder.link();
+ errorListener.check();
+ return r;
+ }
+
+ public void testReflection() throws Exception {
+ MyBean bean = new MyBean();
+ RuntimeTypeInfoSet model = create(MyBean.class);
+ RuntimeClassInfo clsInfo = (RuntimeClassInfo)model.getTypeInfo(MyBean.class);
+ for (RuntimePropertyInfo p : clsInfo.getProperties()) {
+ // System.out.print(p.getName());
+ // System.out.println(" " + p.isCollection());
+ if (p.getName().equals("notes")) {
+ Collection c = (Collection)p.getAccessor().get(bean);
+ c.add("123");
+ }
+ }
+
+ }
+}
diff --git a/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/resources/ipo.xsd b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/resources/ipo.xsd
new file mode 100755
index 0000000000..241ec15d36
--- /dev/null
+++ b/sandbox/sebastien/java/sca-node/modules/databinding-jaxb/src/test/resources/ipo.xsd
@@ -0,0 +1,136 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+-->
+<schema targetNamespace="http://www.example.com/IPO"
+ xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ipo="http://www.example.com/IPO">
+
+ <annotation>
+ <documentation xml:lang="en">
+ International Purchase order schema for Example.com
+ Copyright 2000 Example.com. All rights reserved.
+ </documentation>
+ </annotation>
+
+
+ <element name="purchaseOrder" type="ipo:PurchaseOrderType" />
+
+ <element name="comment" type="string" />
+
+ <complexType name="PurchaseOrderType">
+ <sequence>
+ <element name="shipTo" type="ipo:Address" />
+ <element name="billTo" type="ipo:Address" />
+ <element ref="ipo:comment" minOccurs="0" />
+ <element name="items" type="ipo:Items" />
+ </sequence>
+ <attribute name="orderDate" type="date" />
+ </complexType>
+
+ <complexType name="Items">
+ <sequence>
+ <element name="item" minOccurs="0" maxOccurs="unbounded">
+ <complexType>
+ <sequence>
+ <element name="productName" type="string" />
+ <element name="quantity">
+ <simpleType>
+ <restriction base="positiveInteger">
+ <maxExclusive value="100" />
+ </restriction>
+ </simpleType>
+ </element>
+ <element name="USPrice" type="decimal" />
+ <element ref="ipo:comment" minOccurs="0" />
+ <element name="shipDate" type="date"
+ minOccurs="0" />
+ </sequence>
+ <attribute name="partNum" type="ipo:SKU"
+ use="required" />
+ </complexType>
+ </element>
+ </sequence>
+ </complexType>
+
+ <simpleType name="SKU">
+ <restriction base="string">
+ <pattern value="\d{3}-[A-Z]{2}" />
+ </restriction>
+ </simpleType>
+
+ <complexType name="Address">
+ <sequence>
+ <element name="name" type="string" />
+ <element name="street" type="string" />
+ <element name="city" type="string" />
+ </sequence>
+ </complexType>
+
+ <complexType name="USAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="state" type="ipo:USState" />
+ <element name="zip" type="positiveInteger" />
+ </sequence>
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <complexType name="UKAddress">
+ <complexContent>
+ <extension base="ipo:Address">
+ <sequence>
+ <element name="postcode" type="ipo:UKPostcode" />
+ </sequence>
+ <attribute name="exportCode" type="positiveInteger"
+ fixed="1" />
+ </extension>
+ </complexContent>
+ </complexType>
+
+ <!-- other Address derivations for more countries -->
+
+ <simpleType name="USState">
+ <restriction base="string">
+ <enumeration value="AK" />
+ <enumeration value="AL" />
+ <enumeration value="AR" />
+ <enumeration value="CA" />
+ <enumeration value="PA" />
+ <!-- and so on ... -->
+ </restriction>
+ </simpleType>
+
+ <simpleType name="Postcode">
+ <restriction base="string">
+ <length value="7" fixed="true" />
+ </restriction>
+ </simpleType>
+
+
+ <simpleType name="UKPostcode">
+ <restriction base="ipo:Postcode">
+ <pattern value="[A-Z]{2}\d\s\d[A-Z]{2}" />
+ </restriction>
+ </simpleType>
+
+
+
+</schema>
+