summaryrefslogtreecommitdiffstats
path: root/java/sca/modules/databinding/src/main/java/org
diff options
context:
space:
mode:
Diffstat (limited to 'java/sca/modules/databinding/src/main/java/org')
-rw-r--r--java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java28
-rw-r--r--java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java113
-rw-r--r--java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java405
-rw-r--r--java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java30
-rw-r--r--java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java49
5 files changed, 572 insertions, 53 deletions
diff --git a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
index d343fb2d46..6ebfc29121 100644
--- a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
+++ b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/DefaultDataBindingExtensionPoint.java
@@ -6,15 +6,15 @@
* 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.
+ * under the License.
*/
package org.apache.tuscany.sca.databinding;
@@ -28,6 +28,7 @@ import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding;
import org.apache.tuscany.sca.databinding.javabeans.JavaExceptionDataBinding;
import org.apache.tuscany.sca.extensibility.ServiceDeclaration;
@@ -39,10 +40,11 @@ import org.apache.tuscany.sca.interfacedef.util.XMLType;
/**
* The default implementation of a data binding extension point.
- *
+ *
* @version $Rev$ $Date$
*/
public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoint {
+ private ExtensionPointRegistry registry;
private final Map<String, DataBinding> bindings = new HashMap<String, DataBinding>();
private final List<DataBinding> databindings = new ArrayList<DataBinding>();
private static final Logger logger = Logger.getLogger(DefaultDataBindingExtensionPoint.class.getName());
@@ -51,6 +53,10 @@ public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoi
public DefaultDataBindingExtensionPoint() {
}
+ public DefaultDataBindingExtensionPoint(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ }
+
public DataBinding getDataBinding(String id) {
if (id == null) {
return null;
@@ -121,7 +127,7 @@ public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoi
* A data binding facade allowing data bindings to be lazily loaded and
* initialized.
*/
- private static class LazyDataBinding implements DataBinding {
+ private class LazyDataBinding implements DataBinding {
private String name;
private ServiceDeclaration dataBindingDeclaration;
@@ -134,7 +140,7 @@ public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoi
/**
* Load and instantiate the data binding class.
- *
+ *
* @return The data binding.
*/
@SuppressWarnings("unchecked")
@@ -142,8 +148,14 @@ public class DefaultDataBindingExtensionPoint implements DataBindingExtensionPoi
if (dataBinding == null) {
try {
Class<DataBinding> dataBindingClass = (Class<DataBinding>)dataBindingDeclaration.loadClass();
- Constructor<DataBinding> constructor = dataBindingClass.getConstructor();
- dataBinding = constructor.newInstance();
+ try {
+ Constructor<DataBinding> constructor = dataBindingClass.getConstructor();
+ dataBinding = constructor.newInstance();
+ } catch (NoSuchMethodException e) {
+ Constructor<DataBinding> constructor =
+ dataBindingClass.getConstructor(ExtensionPointRegistry.class);
+ dataBinding = constructor.newInstance(DefaultDataBindingExtensionPoint.this.registry);
+ }
} catch (Exception e) {
throw new IllegalStateException(e);
}
diff --git a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
index 6b8acfc7b4..8184d739a8 100644
--- a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
+++ b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/Mediator.java
@@ -6,25 +6,26 @@
* 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.
+ * under the License.
*/
package org.apache.tuscany.sca.databinding;
import java.util.Map;
import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
/**
* This interface will be used as a Tuscany system service to perform data mediations
- *
+ *
* Mediate the data from one type to the other one
*
* @version $Rev$ $Date$
@@ -36,10 +37,11 @@ public interface Mediator {
* @param source The data to be mediated
* @param sourceDataType Data type for the source data
* @param targetDataType Data type for the target data
- * @param context
+ * @param context
* @return
*/
Object mediate(Object source, DataType sourceDataType, DataType targetDataType, Map<String, Object> context);
+
/**
* Mediate the source data into the target which is a sink to receive the data
* @param source The data to be mediated
@@ -47,22 +49,105 @@ public interface Mediator {
* @param sourceDataType Data type for the source data
* @param targetDataType Data type for the target data
*/
- void mediate(
- Object source,
- Object target,
- DataType sourceDataType,
- DataType targetDataType,
- Map<String, Object> context);
-
+ void mediate(Object source,
+ Object target,
+ DataType sourceDataType,
+ DataType targetDataType,
+ Map<String, Object> context);
+
+ /**
+ * Transform the input parameters for the source operation to the expected parameters for
+ * the target operation
+ * @param input The input data, typically an array of parameters
+ * @param sourceOperation The source operation
+ * @param targetOperation The target operation
+ * @param metadata Additional metadata
+ * @return The transformed input data for the target operation
+ */
+ Object mediateInput(Object input, Operation sourceOperation, Operation targetOperation, Map<String, Object> metadata);
+
+ /**
+ * Transform the return value for the target operation to the expected return value for
+ * the source operation
+ * @param output The output data, typically the return value
+ * @param sourceOperation The source operation
+ * @param targetOperation The target operation
+ * @param metadata Additional metadata
+ * @return The transformed output data for the source operation
+ */
+ Object mediateOutput(Object output,
+ Operation sourceOperation,
+ Operation targetOperation,
+ Map<String, Object> metadata);
+
+ /**
+ * Transform the fault data for the target operation to the expected fault data for
+ * the source operation
+ * @param fault The fault data, such as Java exception or fault message
+ * @param sourceOperation The source operation
+ * @param targetOperation The target operation
+ * @param metadata Additional metadata
+ * @return The transformed fault data for the source operation
+ */
+ Object mediateFault(Object fault, Operation sourceOperation, Operation targetOperation, Map<String, Object> metadata);
+
+ /**
+ * Copy the data
+ * @param data The orginal data
+ * @param dataType The data type
+ * @return The copy
+ */
+ Object copy(Object data, DataType dataType);
+
+ /**
+ * Copy an array of data objects passed to an operation
+ * @param data array of objects to copy
+ * @return the copy
+ */
+ public Object copyInput(Object input, Operation operation);
+
+ /**
+ * Copy the output data
+ * @param data The orginal output
+ * @param operation The operation
+ * @return The copy
+ */
+ Object copyOutput(Object data, Operation operation);
+
+ /**
+ * Copy the fault data
+ * @param fault The orginal fault data
+ * @param operation The operation
+ * @return The copy
+ */
+ Object copyFault(Object fault, Operation operation);
+
/**
* Get the DataBindings used by this mediator.
* @return
*/
DataBindingExtensionPoint getDataBindings();
-
+
/**
* Get the Transformers used by this mediator.
* @return
*/
- TransformerExtensionPoint getTransformers();
+ TransformerExtensionPoint getTransformers();
+
+ /**
+ * Create an instance of TransformationContext
+ * @return
+ */
+ TransformationContext createTransformationContext();
+
+ /**
+ * Create an instance of TransformationContext
+ * @param sourceDataType
+ * @param targetDataType
+ * @param metadata
+ * @return
+ */
+ TransformationContext createTransformationContext(DataType sourceDataType,
+ DataType targetDataType,
+ Map<String, Object> metadata);
}
diff --git a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java
index b7ddf87a41..05ab381cc9 100644
--- a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java
+++ b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/MediatorImpl.java
@@ -6,23 +6,38 @@
* 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.
+ * under the License.
*/
package org.apache.tuscany.sca.databinding.impl;
+import static org.apache.tuscany.sca.databinding.DataBinding.IDL_FAULT;
+import static org.apache.tuscany.sca.databinding.DataBinding.IDL_OUTPUT;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
import java.security.AccessController;
import java.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.databinding.DataBinding;
import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint;
import org.apache.tuscany.sca.databinding.DataPipe;
import org.apache.tuscany.sca.databinding.DataPipeTransformer;
@@ -33,9 +48,15 @@ import org.apache.tuscany.sca.databinding.TransformationContext;
import org.apache.tuscany.sca.databinding.TransformationException;
import org.apache.tuscany.sca.databinding.Transformer;
import org.apache.tuscany.sca.databinding.TransformerExtensionPoint;
+import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding;
import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper;
import org.apache.tuscany.sca.interfacedef.Operation;
import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.util.FaultException;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.oasisopen.sca.ServiceRuntimeException;
+
/**
* Default Mediator implementation
@@ -43,20 +64,32 @@ import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
* @version $Rev$ $Date$
*/
public class MediatorImpl implements Mediator {
-
+ private static final String TARGET_OPERATION = "target.operation";
+ private static final String SOURCE_OPERATION = "source.operation";
+ private ExtensionPointRegistry registry;
private DataBindingExtensionPoint dataBindings;
private TransformerExtensionPoint transformers;
+ private FaultExceptionMapper faultExceptionMapper;
- public MediatorImpl(DataBindingExtensionPoint dataBindings, TransformerExtensionPoint transformers) {
+ MediatorImpl(DataBindingExtensionPoint dataBindings, TransformerExtensionPoint transformers) {
this.dataBindings = dataBindings;
this.transformers = transformers;
}
+ public MediatorImpl(ExtensionPointRegistry registry) {
+ this.registry = registry;
+ this.dataBindings = registry.getExtensionPoint(DataBindingExtensionPoint.class);
+ this.transformers = registry.getExtensionPoint(TransformerExtensionPoint.class);
+ this.faultExceptionMapper =
+ registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(FaultExceptionMapper.class);
+
+ }
+
@SuppressWarnings("unchecked")
public Object mediate(Object source, DataType sourceDataType, DataType targetDataType, Map<String, Object> metadata) {
if (sourceDataType == null || sourceDataType.getDataBinding() == null) {
if (source != null) {
- Operation operation = (Operation) metadata.get("source.operation");
+ Operation operation = (Operation)metadata.get(SOURCE_OPERATION);
sourceDataType = dataBindings.introspectType(source, operation);
}
}
@@ -103,7 +136,7 @@ public class MediatorImpl implements Mediator {
DataType targetType =
(index == size - 1) ? targetDataType : new DataTypeImpl<Object>(transformer.getTargetDataBinding(),
Object.class, targetDataType.getLogical());
-
+
//FIXME The ClassLoader should be passed in
// Allow privileged access to get ClassLoader. Requires RuntimePermission in security
// policy.
@@ -111,9 +144,15 @@ public class MediatorImpl implements Mediator {
public ClassLoader run() {
return Thread.currentThread().getContextClassLoader();
}
- });
-
- TransformationContext context = new TransformationContextImpl(sourceType, targetType, classLoader, metadata);
+ });
+
+ Map<String, Object> copy = new HashMap<String, Object>();
+ if (metadata != null) {
+ copy.putAll(metadata);
+ }
+ copy.put(ExtensionPointRegistry.class.getName(), registry);
+
+ TransformationContext context = new TransformationContextImpl(sourceType, targetType, classLoader, copy);
return context;
}
@@ -128,7 +167,7 @@ public class MediatorImpl implements Mediator {
return;
}
if (sourceDataType == null || sourceDataType.getDataBinding() == null) {
- Operation operation = (Operation) metadata.get("source.operation");
+ Operation operation = (Operation)metadata.get(SOURCE_OPERATION);
sourceDataType = dataBindings.introspectType(source, operation);
}
if (sourceDataType == null) {
@@ -179,4 +218,348 @@ public class MediatorImpl implements Mediator {
return transformers;
}
+ private DataType getFaultType(DataType exceptionType) {
+ return exceptionType == null ? null : (DataType)exceptionType.getLogical();
+ }
+
+ /**
+ * @param qn1
+ * @param qn2
+ */
+ private boolean matches(QName qn1, QName qn2) {
+ if (qn1 == qn2) {
+ return true;
+ }
+ if (qn1 == null || qn2 == null) {
+ return false;
+ }
+ String ns1 = qn1.getNamespaceURI();
+ String ns2 = qn2.getNamespaceURI();
+ String e1 = qn1.getLocalPart();
+ String e2 = qn2.getLocalPart();
+ if (e1.equals(e2) && (ns1.equals(ns2) || ns1.equals(ns2 + "/") || ns2.equals(ns1 + "/"))) {
+ // Tolerating the trailing / which is required by JAX-WS java package --> xml ns mapping
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @param source The source exception
+ * @param sourceExType The data type for the source exception
+ * @param targetExType The data type for the target exception
+ * @param sourceType The fault type for the source
+ * @param targetType The fault type for the target
+ * @return
+ */
+ private Object transformException(Object source,
+ DataType sourceExType,
+ DataType targetExType,
+ DataType sourceType,
+ DataType targetType,
+ Map<String, Object> metadata) {
+
+ if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) {
+ return source;
+ }
+
+ DataType<DataType> eSourceDataType =
+ new DataTypeImpl<DataType>(IDL_FAULT, sourceExType.getPhysical(), sourceType);
+ DataType<DataType> eTargetDataType =
+ new DataTypeImpl<DataType>(IDL_FAULT, targetExType.getPhysical(), targetType);
+
+ return mediate(source, eSourceDataType, eTargetDataType, metadata);
+ }
+
+ //
+ // Assumes we're going from target->source, knowing that we're throwing BACK an exception, rather than the more
+ // obvious source->target
+ //
+ public Object mediateFault(Object result,
+ Operation sourceOperation,
+ Operation targetOperation,
+ Map<String, Object> metadata) {
+
+ // FIXME: How to match fault data to a fault type for the
+ // operation?
+
+ // If the result is from an InvocationTargetException look at
+ // the actual cause.
+ if (result instanceof InvocationTargetException) {
+ result = ((InvocationTargetException)result).getCause();
+ }
+ DataType targetDataType = null;
+ for (DataType exType : targetOperation.getFaultTypes()) {
+ if (((Class)exType.getPhysical()).isInstance(result)) {
+ if (result instanceof FaultException) {
+ DataType faultType = (DataType)exType.getLogical();
+ if (((FaultException)result).isMatchingType(faultType.getLogical())) {
+ targetDataType = exType;
+ break;
+ }
+ } else {
+ targetDataType = exType;
+ break;
+ }
+ }
+ }
+
+ /*
+ if (targetDataType == null) {
+ // Not a business exception
+ return resultMsg;
+ }
+ */
+
+ DataType targetFaultType = getFaultType(targetDataType);
+ if (targetFaultType == null) {
+ // No matching fault type, it's a system exception
+ Throwable cause = (Throwable)result;
+ throw new ServiceRuntimeException(cause);
+ }
+
+ // FIXME: How to match a source fault type to a target fault
+ // type?
+ DataType sourceDataType = null;
+ DataType sourceFaultType = null;
+ for (DataType exType : sourceOperation.getFaultTypes()) {
+ DataType faultType = getFaultType(exType);
+ // Match by the QName (XSD element) of the fault type
+ if (faultType != null && typesMatch(targetFaultType.getLogical(), faultType.getLogical())) {
+ sourceDataType = exType;
+ sourceFaultType = faultType;
+ break;
+ }
+ }
+
+ if (sourceFaultType == null) {
+ // No matching fault type, it's a system exception
+ Throwable cause = (Throwable)result;
+ throw new ServiceRuntimeException(cause);
+ }
+
+ Object newResult =
+ transformException(result, targetDataType, sourceDataType, targetFaultType, sourceFaultType, metadata);
+
+ return newResult;
+
+ }
+
+ private boolean typesMatch(Object first, Object second) {
+ if (first.equals(second)) {
+ return true;
+ }
+ if (first instanceof XMLType && second instanceof XMLType) {
+ XMLType t1 = (XMLType)first;
+ XMLType t2 = (XMLType)second;
+ // TUSCANY-2113, we should compare element names only
+ return matches(t1.getElementName(), t2.getElementName());
+ }
+ return false;
+ }
+
+ /**
+ * @param output
+ * @param sourceOperation
+ * @param targetOperation
+ * @return
+ */
+ public Object mediateOutput(Object output,
+ Operation sourceOperation,
+ Operation targetOperation,
+ Map<String, Object> metadata) {
+ // Create a data type to represent the ouput produced by the target operation
+ DataType<DataType> targetType =
+ new DataTypeImpl<DataType>(IDL_OUTPUT, Object.class, targetOperation.getOutputType());
+
+ // Create a data type to represent the ouput expected by the source operation
+ DataType<DataType> sourceType =
+ new DataTypeImpl<DataType>(IDL_OUTPUT, Object.class, sourceOperation.getOutputType());
+
+ if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) {
+ return output;
+ }
+ Map<String, Object> context = new HashMap<String, Object>();
+ if (metadata != null) {
+ context.putAll(metadata);
+ }
+ if (targetOperation != null) {
+ context.put(SOURCE_OPERATION, targetOperation);
+ }
+ if (sourceOperation != null) {
+ context.put(TARGET_OPERATION, sourceOperation);
+ }
+ return mediate(output, targetType, sourceType, context);
+ }
+
+ public Object mediateInput(Object input,
+ Operation sourceOperation,
+ Operation targetOperation,
+ Map<String, Object> metadata) {
+ // Get the data type to represent the input passed in by the source operation
+ DataType sourceType = sourceOperation.getInputType();
+
+ // Get the data type to represent the input expected by the target operation
+ DataType targetType = targetOperation.getInputType();
+
+ if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) {
+ return input;
+ }
+ Map<String, Object> context = new HashMap<String, Object>();
+ if (metadata != null) {
+ context.putAll(metadata);
+ }
+ if (sourceOperation != null) {
+ context.put(SOURCE_OPERATION, sourceOperation);
+ }
+ if (targetOperation != null) {
+ context.put(TARGET_OPERATION, targetOperation);
+ }
+ return mediate(input, sourceType, targetType, context);
+ }
+
+ public TransformationContext createTransformationContext() {
+ return new TransformationContextImpl();
+ }
+
+ public TransformationContext createTransformationContext(DataType sourceDataType,
+ DataType targetDataType,
+ Map<String, Object> metadata) {
+ return new TransformationContextImpl(sourceDataType, targetDataType, metadata);
+ }
+
+ public Object copy(Object data, DataType dataType) {
+ return copy(data, dataType, null);
+ }
+
+ /**
+ * Copy data using the specified databinding.
+ * @param data input data
+ * @param dataType
+ * @return a copy of the data
+ */
+ private Object copy(Object data, DataType dataType, Operation operation) {
+ if (data == null) {
+ return null;
+ }
+ Class<?> clazz = data.getClass();
+ if (String.class == clazz || clazz.isPrimitive()
+ || Number.class.isAssignableFrom(clazz)
+ || Boolean.class.isAssignableFrom(clazz)
+ || Character.class.isAssignableFrom(clazz)
+ || Byte.class.isAssignableFrom(clazz)
+ || URI.class == clazz
+ || UUID.class == clazz
+ || QName.class == clazz) {
+ // Immutable classes
+ return data;
+ }
+
+ DataBinding javaBeansDataBinding = dataBindings.getDataBinding(JavaBeansDataBinding.NAME);
+ // FIXME: The JAXB databinding is hard-coded here
+ DataBinding jaxbDataBinding = dataBindings.getDataBinding("javax.xml.bind.JAXBElement");
+ DataBinding dataBinding = dataBindings.getDataBinding(dataType.getDataBinding());
+ // If no databinding was specified, introspect the given arg to
+ // determine its databinding
+ if (dataBinding == null) {
+ dataType = dataBindings.introspectType(data, operation);
+ if (dataType != null) {
+ String db = dataType.getDataBinding();
+ dataBinding = dataBindings.getDataBinding(db);
+ if (dataBinding == null && db != null) {
+ return data;
+ }
+ }
+ if (dataBinding == null) {
+
+ // Default to the JavaBean databinding
+ dataBinding = dataBindings.getDataBinding(JavaBeansDataBinding.NAME);
+ }
+ }
+
+ // Use the JAXB databinding to copy non-Serializable data
+ if (dataBinding == javaBeansDataBinding) {
+
+ // If the input data is an array containing non Serializable elements
+ // use JAXB
+ clazz = data.getClass();
+ if (clazz.isArray()) {
+ if (Array.getLength(data) != 0) {
+ Object element = Array.get(data, 0);
+ if (element != null && !(element instanceof Serializable)) {
+ dataBinding = jaxbDataBinding;
+ }
+ }
+ } else {
+
+ // If the input data is not Serializable use JAXB
+ if (!((data instanceof Serializable) || (data instanceof Cloneable))) {
+ dataBinding = jaxbDataBinding;
+ }
+ }
+ }
+
+ if (dataBinding != null) {
+ return dataBinding.copy(data, dataType, operation);
+ } else {
+ return data;
+ }
+ }
+
+ /**
+ * Copy an array of data objects passed to an operation
+ * @param data array of objects to copy
+ * @return the copy
+ */
+ public Object copyInput(Object input, Operation operation) {
+ if (input == null) {
+ return null;
+ }
+ Object[] data = (input instanceof Object[]) ? (Object[])input : new Object[] {input};
+ List<DataType> inputTypes = operation.getInputType().getLogical();
+ Object[] copy = new Object[data.length];
+ Map<Object, Object> map = new IdentityHashMap<Object, Object>();
+ for (int i = 0, size = inputTypes.size(); i < size; i++) {
+ Object arg = data[i];
+ if (arg == null) {
+ copy[i] = null;
+ } else {
+ Object copiedArg = map.get(arg);
+ if (copiedArg != null) {
+ copy[i] = copiedArg;
+ } else {
+ copiedArg = copy(arg, inputTypes.get(i));
+ map.put(arg, copiedArg);
+ copy[i] = copiedArg;
+ }
+ }
+ }
+ return copy;
+ }
+
+ public Object copyOutput(Object data, Operation operation) {
+ return copy(data, operation.getOutputType(), operation);
+ }
+
+ public Object copyFault(Object fault, Operation operation) {
+ if (faultExceptionMapper == null) {
+ return fault;
+ }
+ for (DataType et : operation.getFaultTypes()) {
+ if (et.getPhysical().isInstance(fault)) {
+ Throwable ex = (Throwable)fault;
+ DataType<DataType> exType =
+ new DataTypeImpl<DataType>(ex.getClass(), new DataTypeImpl<XMLType>(ex.getClass(), XMLType.UNKNOWN));
+ faultExceptionMapper.introspectFaultDataType(exType, operation, false);
+ DataType faultType = exType.getLogical();
+ Object faultInfo = faultExceptionMapper.getFaultInfo(ex, faultType.getPhysical(), operation);
+ faultInfo = copy(faultInfo, faultType);
+ fault =
+ faultExceptionMapper.wrapFaultInfo(exType, ex.getMessage(), faultInfo, ex.getCause(), operation);
+ return fault;
+ }
+ }
+ return fault;
+ }
+
}
diff --git a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java
index a6c0639411..a5b8e0a0bd 100644
--- a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java
+++ b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/impl/TransformationContextImpl.java
@@ -6,15 +6,15 @@
* 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.
+ * under the License.
*/
package org.apache.tuscany.sca.databinding.impl;
@@ -27,6 +27,10 @@ import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Operation;
public class TransformationContextImpl implements TransformationContext {
+ private static final String SOURCE_OPERATION = "source.operation";
+
+ private static final String TARGET_OPERATION = "target.operation";
+
private DataType sourceDataType;
private DataType targetDataType;
@@ -54,6 +58,18 @@ public class TransformationContextImpl implements TransformationContext {
}
}
+ public TransformationContextImpl(DataType sourceDataType,
+ DataType targetDataType,
+ Map<String, Object> metadata) {
+ super();
+ this.sourceDataType = sourceDataType;
+ this.targetDataType = targetDataType;
+ setClassLoader(Thread.currentThread().getContextClassLoader());
+ if (metadata != null) {
+ this.metadata.putAll(metadata);
+ }
+ }
+
public DataType getSourceDataType() {
return sourceDataType;
}
@@ -86,28 +102,28 @@ public class TransformationContextImpl implements TransformationContext {
* @return the sourceOperation
*/
public Operation getSourceOperation() {
- return (Operation) metadata.get("source.operation");
+ return (Operation) metadata.get(SOURCE_OPERATION);
}
/**
* @param sourceOperation the sourceOperation to set
*/
public void setSourceOperation(Operation sourceOperation) {
- this.metadata.put("source.operation", sourceOperation);
+ this.metadata.put(SOURCE_OPERATION, sourceOperation);
}
/**
* @return the targetOperation
*/
public Operation getTargetOperation() {
- return (Operation) metadata.get("target.operation");
+ return (Operation) metadata.get(TARGET_OPERATION);
}
/**
* @param targetOperation the targetOperation to set
*/
public void setTargetOperation(Operation targetOperation) {
- this.metadata.put("target.operation", targetOperation);
+ this.metadata.put(TARGET_OPERATION, targetOperation);
}
}
diff --git a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java
index c7d21ebc66..2234aa07c2 100644
--- a/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java
+++ b/java/sca/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/javabeans/JavaBeansDataBinding.java
@@ -6,15 +6,15 @@
* 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.
+ * under the License.
*/
package org.apache.tuscany.sca.databinding.javabeans;
@@ -28,6 +28,9 @@ import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.logging.Logger;
import org.apache.tuscany.sca.databinding.impl.BaseDataBinding;
import org.apache.tuscany.sca.interfacedef.DataType;
@@ -39,6 +42,7 @@ import org.apache.tuscany.sca.interfacedef.Operation;
* @version $Rev$ $Date$
*/
public class JavaBeansDataBinding extends BaseDataBinding {
+ private final static Logger logger = Logger.getLogger(JavaBeansDataBinding.class.getName());
/**
* Defining a weight to a very high number so that the transformer won't be picked
* up by other paths unless it's the only available path
@@ -53,7 +57,7 @@ public class JavaBeansDataBinding extends BaseDataBinding {
protected JavaBeansDataBinding(String name, Class<?> baseType) {
super(name, baseType);
}
-
+
@Override
public Object copy(Object arg, DataType dataType, Operation operation) {
if (arg == null) {
@@ -82,7 +86,7 @@ public class JavaBeansDataBinding extends BaseDataBinding {
// * The ThreadContext ClassLoader if the ClassLoader of arg is the System ClassLoader
// because Collection classes are loaded by the System ClassLoader but their contents
// may be loaded from another ClassLoader
- //
+ //
ClassLoader classLoaderToUse = clazz.getClassLoader();
if (classLoaderToUse == null)
{
@@ -90,20 +94,39 @@ public class JavaBeansDataBinding extends BaseDataBinding {
// instead
classLoaderToUse = Thread.currentThread().getContextClassLoader();
}
-
+
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
ObjectInputStream ois = getObjectInputStream(bis, classLoaderToUse);
Object objectCopy = ois.readObject();
ois.close();
bis.close();
return objectCopy;
- } else {
- // return arg;
- throw new IllegalArgumentException("Argument type '" + arg.getClass().getCanonicalName() + "' is not Serializable. " +
- " Pass-by-value cannot be performed on this argument");
+ } else if (arg instanceof Cloneable) {
+ Method clone;
+ try {
+ clone = arg.getClass().getMethod("clone");
+ try {
+ return clone.invoke(arg, (Object[])null);
+ } catch (InvocationTargetException e) {
+ if (e.getTargetException() instanceof CloneNotSupportedException) {
+ // Ignore
+ } else {
+ throw new IllegalArgumentException(e);
+ }
+ } catch (Exception e) {
+ throw new IllegalArgumentException(e);
+ }
+ } catch (NoSuchMethodException e) {
+ // Ignore it
+ }
}
- } catch (Exception e) {
- throw new IllegalArgumentException("Pass-by-value is not supported for the given object", e);
+ // return arg;
+ logger.warning("Argument type '" + arg.getClass().getName()
+ + "' is not Serializable or Cloneable. Pass-by-value is skipped.");
+ return arg;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Pass-by-value is not supported for the given object: " + arg.getClass()
+ .getName(), e);
}
}
@@ -135,5 +158,5 @@ public class JavaBeansDataBinding extends BaseDataBinding {
};
return ois;
}
-
+
}