diff options
author | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2009-05-01 04:21:18 +0000 |
---|---|---|
committer | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2009-05-01 04:21:18 +0000 |
commit | 51e4f54ea42fc2009a99577e98f1af048d7841bd (patch) | |
tree | 79260a36adae220da73218bb068eb3054205bc1f /branches/sca-java-1.x/modules/core-databinding/src/main/java | |
parent | df8ecc73cce17513125b56be898fce433b339b14 (diff) |
Refactor the data transformation and copy logic into Mediator utility
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@770532 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.x/modules/core-databinding/src/main/java')
4 files changed, 35 insertions, 393 deletions
diff --git a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java index 9e926506f4..4e0e58e6a1 100644 --- a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java +++ b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/module/DataBindingModuleActivator.java @@ -62,6 +62,7 @@ public class DataBindingModuleActivator implements ModuleActivator { xmlAdapterExtensionPoint.addAdapter(CallableReference.class, CallableReferenceXMLAdapter.class); xmlAdapterExtensionPoint.addAdapter(OMElement.class, OMElementXMLAdapter.class); FaultExceptionMapper faultExceptionMapper = new JAXWSFaultExceptionMapper(dataBindings, xmlAdapterExtensionPoint); + registry.getExtensionPoint(UtilityExtensionPoint.class).addUtility(faultExceptionMapper); Mediator mediator = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(Mediator.class); diff --git a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java index 4e67c4dee0..bad2be6679 100644 --- a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.java +++ b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataBindingRuntimeWireProcessor.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.core.databinding.wire; @@ -37,7 +37,7 @@ import org.apache.tuscany.sca.runtime.RuntimeWireProcessor; /** * This processor is responsible to add an interceptor to invocation chain if * the source and target operations have different databinding requirements - * + * * @version $Rev$ $Date$ */ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { @@ -88,7 +88,7 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { if (source.isInputWrapperStyle() != target.isInputWrapperStyle()) { return true; } - + if (source.isOutputWrapperStyle() != target.isOutputWrapperStyle()) { return true; } @@ -153,14 +153,13 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { // Add the interceptor to the source side because multiple // references can be wired to the same service interceptor = - new DataTransformationInterceptor(wire, sourceOperation, targetOperation, mediator, - faultExceptionMapper); + new DataTransformationInterceptor(wire, sourceOperation, targetOperation, mediator); } else { // assume pass-by-values copies are required if interfaces are remotable and there is no data binding // transformation, i.e. a transformation will result in a copy so another pass-by-value copy is unnecessary if (!isOnMessage(targetOperation) && isRemotable(chain, sourceOperation, targetOperation)) { interceptor = - new PassByValueInterceptor(dataBindings, faultExceptionMapper, chain, targetOperation); + new PassByValueInterceptor(mediator, chain, targetOperation); } } if (interceptor != null) { @@ -176,7 +175,7 @@ public class DataBindingRuntimeWireProcessor implements RuntimeWireProcessor { /** * FIXME: TUSCANY-2586, temporary work around till the JIRA is fixed to prevent * the PassByValueInterceptor being used for services when the binding protocol - * doesn't need the copies done. + * doesn't need the copies done. */ protected boolean isOnMessage(Operation op) { return "onMessage".equals(op.getName()); diff --git a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java index 66b5cabb11..79c442450b 100644 --- a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java +++ b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java @@ -19,28 +19,16 @@ package org.apache.tuscany.sca.core.databinding.wire; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; -import javax.xml.namespace.QName; - -import org.apache.tuscany.sca.databinding.DataBinding; import org.apache.tuscany.sca.databinding.Mediator; -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.java.JavaOperation; -import org.apache.tuscany.sca.interfacedef.util.FaultException; -import org.apache.tuscany.sca.interfacedef.util.XMLType; import org.apache.tuscany.sca.invocation.DataExchangeSemantics; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; import org.apache.tuscany.sca.runtime.RuntimeWire; -import org.osoa.sca.ServiceRuntimeException; /** * An interceptor to transform data across databindings on the wire @@ -55,24 +43,16 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS private Operation targetOperation; private RuntimeWire wire; private Mediator mediator; - private FaultExceptionMapper faultExceptionMapper; public DataTransformationInterceptor(RuntimeWire wire, Operation sourceOperation, Operation targetOperation, - Mediator mediator, - FaultExceptionMapper faultExceptionMapper) { + Mediator mediator) { super(); this.sourceOperation = sourceOperation; this.targetOperation = targetOperation; - if ( sourceOperation instanceof JavaOperation ) { - JavaOperation javaOp = (JavaOperation) sourceOperation; - Method sourceMethod = javaOp.getJavaMethod(); - } - this.mediator = mediator; this.wire = wire; - this.faultExceptionMapper = faultExceptionMapper; } public Invoker getNext() { @@ -80,9 +60,9 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS } public Message invoke(Message msg) { - // System.out.println( "DataTransformationInterceptor.invoke source input type=" + sourceOperation.getInputType() ); - // System.out.println( "DataTransformationInterceptor.invoke target input type =" + targetOperation.getInputType() ); - Object input = transform(msg.getBody(), sourceOperation.getInputType(), targetOperation.getInputType(), false); + Map<String, Object> metadata = new HashMap<String, Object>(); + metadata.put("wire", wire); + Object input = mediator.mediateInput(msg.getBody(), sourceOperation, targetOperation, metadata); msg.setBody(input); Message resultMsg = next.invoke(msg); if (sourceOperation.isNonBlocking()) { @@ -91,178 +71,28 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS } Object result = resultMsg.getBody(); - // FIXME: Should we fix the Operation model so that getOutputType - // returns DataType<DataType<T>>? - DataType<DataType> targetType = - new DataTypeImpl<DataType>(DataBinding.IDL_OUTPUT, Object.class, targetOperation.getOutputType()); - - DataType<DataType> sourceType = - new DataTypeImpl<DataType>(DataBinding.IDL_OUTPUT, Object.class, sourceOperation.getOutputType()); if (resultMsg.isFault()) { - - // FIXME: We need to figure out what fault type it is and then - // transform it - // back the source fault type - // throw new InvocationRuntimeException((Throwable) result); - + Object transformedFault = null; if ((result instanceof Exception) && !(result instanceof RuntimeException)) { - // 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); - if (newResult != result) { - resultMsg.setFaultBody(newResult); + transformedFault = mediator.mediateFault(result, sourceOperation, targetOperation, metadata); + if (transformedFault != result) { + resultMsg.setFaultBody(transformedFault); } } - + // + // Leave it to another layer to actually throw the Exception which constitutes + // the message body. We don't throw it here. + // } else { - // !resultMsg.isFault() assert !(result instanceof Throwable) : "Expected messages that are not throwable " + result; - - Object newResult = transform(result, targetType, sourceType, true); - if (newResult != result) { - resultMsg.setBody(newResult); - } + Object newResult = mediator.mediateOutput(result, sourceOperation, targetOperation, metadata); + resultMsg.setBody(newResult); } return resultMsg; } - private Object transform(Object source, DataType sourceType, DataType targetType, boolean isResponse) { - if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { - return source; - } - Map<String, Object> metadata = new HashMap<String, Object>(); - metadata.put("source.operation", isResponse ? targetOperation : sourceOperation); - metadata.put("target.operation", isResponse ? sourceOperation : targetOperation); - metadata.put("wire", wire); - return mediator.mediate(source, sourceType, targetType, metadata); - } - - private DataType getFaultType(DataType exceptionType) { - return exceptionType == null ? null : (DataType)exceptionType.getLogical(); - } - - 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 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) { - if (sourceType == targetType || (sourceType != null && sourceType.equals(targetType))) { - return source; - } - Map<String, Object> metadata = new HashMap<String, Object>(); - metadata.put("source.operation", targetOperation); - metadata.put("target.operation", sourceOperation); - metadata.put("wire", wire); - DataType<DataType> eSourceDataType = - new DataTypeImpl<DataType>("idl:fault", sourceExType.getPhysical(), sourceType); - DataType<DataType> eTargetDataType = - new DataTypeImpl<DataType>("idl:fault", targetExType.getPhysical(), targetType); - - return mediator.mediate(source, eSourceDataType, eTargetDataType, metadata); - } - public void setNext(Invoker next) { this.next = next; } diff --git a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java index 3586f54d71..44e5072e61 100644 --- a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java +++ b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/PassByValueInterceptor.java @@ -6,45 +6,25 @@ * 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.core.databinding.wire; -import java.io.Serializable; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URI; -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.databinding.DataBinding; -import org.apache.tuscany.sca.databinding.DataBindingExtensionPoint; -import org.apache.tuscany.sca.databinding.javabeans.JavaBeansDataBinding; -import org.apache.tuscany.sca.databinding.jaxb.JAXBDataBinding; -import org.apache.tuscany.sca.interfacedef.DataType; -import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; +import org.apache.tuscany.sca.databinding.Mediator; 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.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.InvocationChain; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; -import org.osoa.sca.ServiceRuntimeException; /** * Implementation of an interceptor that enforces pass-by-value semantics @@ -54,13 +34,7 @@ import org.osoa.sca.ServiceRuntimeException; */ public class PassByValueInterceptor implements Interceptor { - private DataBindingExtensionPoint dataBindings; - private FaultExceptionMapper faultExceptionMapper; - - private DataBinding[] inputDataBindings; - private DataBinding outputDataBinding; - private DataBinding javaBeanDataBinding; - private DataBinding jaxbDataBinding; + private Mediator mediator; private Operation operation; private Invoker nextInvoker; private InvocationChain chain; @@ -70,36 +44,10 @@ public class PassByValueInterceptor implements Interceptor { * @param dataBindings databinding extension point * @param operation the intercepted operation */ - public PassByValueInterceptor(DataBindingExtensionPoint dataBindings, - FaultExceptionMapper faultExceptionMapper, - InvocationChain chain, - Operation operation) { + public PassByValueInterceptor(Mediator mediator, InvocationChain chain, Operation operation) { + this.mediator = mediator; this.chain = chain; this.operation = operation; - - // Cache data bindings to use - this.dataBindings = dataBindings; - this.faultExceptionMapper = faultExceptionMapper; - - jaxbDataBinding = dataBindings.getDataBinding(JAXBDataBinding.NAME); - javaBeanDataBinding = dataBindings.getDataBinding(JavaBeansDataBinding.NAME); - - // Determine the input databindings - if (operation.getInputType() != null) { - List<DataType> inputTypes = operation.getInputType().getLogical(); - inputDataBindings = new DataBinding[inputTypes.size()]; - int i = 0; - for (DataType inputType : inputTypes) { - String id = inputType.getDataBinding(); - inputDataBindings[i++] = dataBindings.getDataBinding(id); - } - } - - // Determine the output databinding - if (operation.getOutputType() != null) { - String id = operation.getOutputType().getDataBinding(); - outputDataBinding = dataBindings.getDataBinding(id); - } } public Message invoke(Message msg) { @@ -107,156 +55,20 @@ public class PassByValueInterceptor implements Interceptor { return nextInvoker.invoke(msg); } - msg.setBody(copy((Object[])msg.getBody(), inputDataBindings, operation.getInputType().getLogical())); + msg.setBody(mediator.copyInput(msg.getBody(), operation)); Message resultMsg = nextInvoker.invoke(msg); - if (!msg.isFault() && operation.getOutputType() != null) { - resultMsg.setBody(copy(resultMsg.getBody(), outputDataBinding, operation.getOutputType())); + if (!resultMsg.isFault() && operation.getOutputType() != null) { + resultMsg.setBody(mediator.copyOutput(resultMsg.getBody(), operation)); } - if (msg.isFault()) { - msg.setFaultBody(copyFault(msg.getBody())); + if (resultMsg.isFault()) { + resultMsg.setFaultBody(mediator.copyFault(resultMsg.getBody(), operation)); } return resultMsg; } - private Object copyFault(Object fault) { - 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, dataBindings.getDataBinding(faultType.getDataBinding()), faultType); - fault = faultExceptionMapper.wrapFaultInfo(exType, ex.getMessage(), faultInfo, ex.getCause(), operation); - return fault; - } - } - return fault; - } - - /** - * Copy an array of data objects passed to an operation - * @param data array of objects to copy - * @return the copy - */ - private Object[] copy(Object[] data, DataBinding[] dataBindings, List<DataType> dataTypes) { - if (data == null) { - return null; - } - Object[] copy = new Object[data.length]; - Map<Object, Object> map = new IdentityHashMap<Object, Object>(); - for (int i = 0; i < data.length; 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, dataBindings[i], dataTypes.get(i)); - map.put(arg, copiedArg); - copy[i] = copiedArg; - } - } - } - return copy; - } - - /** - * Copy data using the specified databinding. - * @param data input data - * @param dataBinding databinding to use - * @param dataType TODO - * @return a copy of the data - */ - private Object copy(Object data, DataBinding dataBinding, DataType dataType) { - 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; - } - // 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 = javaBeanDataBinding; - } - } - - // Use the JAXB databinding to copy non-Serializable data - if (dataBinding == javaBeanDataBinding) { - - // 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)) { - dataBinding = jaxbDataBinding; - } - - if (data instanceof Cloneable) { - Method clone; - try { - clone = data.getClass().getMethod("clone", (Class[])null); - try { - return clone.invoke(data, (Object[])null); - } catch (InvocationTargetException e) { - if (e.getTargetException() instanceof CloneNotSupportedException) { - // Ignore - } else { - throw new ServiceRuntimeException(e); - } - } catch (Exception e) { - throw new ServiceRuntimeException(e); - } - } catch (NoSuchMethodException e) { - // Ignore it - } - } - } - } - - Object copy = dataBinding.copy(data, dataType, operation); - return copy; - } - public Invoker getNext() { return nextInvoker; } |