diff options
Diffstat (limited to 'java/sca/modules/databinding/src/main/java/org')
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;
}
-
+
}
|