diff options
author | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2008-07-18 18:29:28 +0000 |
---|---|---|
committer | rfeng <rfeng@13f79535-47bb-0310-9956-ffa450edef68> | 2008-07-18 18:29:28 +0000 |
commit | 7f87032072bad92962601c8f9ece5f71b2d4a1ef (patch) | |
tree | f5d675f60fb31c7ed6d61d3d7f2fa007eb5f2f07 /java/sca/modules | |
parent | 3d43862fc293982f39996fe09d94971b20521a2b (diff) |
Apply the patch from Wojtek for TUSCANY-2397 (operations-mapping-jira-2357-15-july.patch)
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@677993 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java/sca/modules')
16 files changed, 1034 insertions, 77 deletions
diff --git a/java/sca/modules/binding-corba-runtime/pom.xml b/java/sca/modules/binding-corba-runtime/pom.xml index a54ddc1444..1d3c0c84b0 100644 --- a/java/sca/modules/binding-corba-runtime/pom.xml +++ b/java/sca/modules/binding-corba-runtime/pom.xml @@ -29,32 +29,37 @@ <name>Apache Tuscany SCA CORBA Binding Runtime</name> <dependencies> - <dependency> - <groupId>org.apache.tuscany.sca</groupId> - <artifactId>tuscany-binding-corba</artifactId> - <version>1.4-SNAPSHOT</version> - </dependency> - - <dependency> - <groupId>org.apache.tuscany.sca</groupId> - <artifactId>tuscany-host-corba</artifactId> - <version>1.4-SNAPSHOT</version> - </dependency> - - <dependency> - <groupId>org.apache.tuscany.sca</groupId> - <artifactId>tuscany-host-corba-jdk</artifactId> - <version>1.4-SNAPSHOT</version> - <scope>test</scope> - </dependency> + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-interface-java</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-binding-corba</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> + + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-host-corba</artifactId> + <version>1.4-SNAPSHOT</version> + </dependency> - <dependency> - <groupId>cglib</groupId> - <artifactId>cglib-nodep</artifactId> - <version>2.1_3</version> - <scope>compile</scope> - </dependency> - + <dependency> + <groupId>org.apache.tuscany.sca</groupId> + <artifactId>tuscany-host-corba-jdk</artifactId> + <version>1.4-SNAPSHOT</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>cglib</groupId> + <artifactId>cglib-nodep</artifactId> + <version>2.1_3</version> + <scope>compile</scope> + </dependency> </dependencies> <build> diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaInvoker.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaInvoker.java index 43c471d3bc..f1640329e8 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaInvoker.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaInvoker.java @@ -19,6 +19,9 @@ package org.apache.tuscany.sca.binding.corba.impl; +import java.lang.reflect.Method; +import java.util.Map; + import org.apache.tuscany.sca.binding.corba.impl.exceptions.RequestConfigurationException; import org.apache.tuscany.sca.binding.corba.impl.reference.DynaCorbaRequest; import org.apache.tuscany.sca.binding.corba.impl.reference.DynaCorbaResponse; @@ -34,9 +37,13 @@ import org.osoa.sca.ServiceRuntimeException; public class CorbaInvoker implements Invoker { private Object remoteObject; + private Class<?> referenceClass; + private Map<Method, String> operationsMap; - public CorbaInvoker(Object remoteObject) { + public CorbaInvoker(Object remoteObject, Class<?> referenceClass, Map<Method, String> operationsMap) { this.remoteObject = remoteObject; + this.referenceClass = referenceClass; + this.operationsMap = operationsMap; } /** @@ -45,6 +52,8 @@ public class CorbaInvoker implements Invoker { public Message invoke(Message msg) { try { DynaCorbaRequest request = new DynaCorbaRequest(remoteObject, msg.getOperation().getName()); + request.setReferenceClass(referenceClass); + request.setOperationsMap(operationsMap); if (msg.getOperation().getOutputType() != null) { request.setOutputType(msg.getOperation().getOutputType().getPhysical()); } diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaReferenceBindingProvider.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaReferenceBindingProvider.java index dec015be38..3eb665d599 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaReferenceBindingProvider.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/CorbaReferenceBindingProvider.java @@ -19,10 +19,15 @@ package org.apache.tuscany.sca.binding.corba.impl; +import java.lang.reflect.Method; +import java.util.Map; + import org.apache.tuscany.sca.binding.corba.CorbaBinding; +import org.apache.tuscany.sca.binding.corba.impl.util.OperationMapper; import org.apache.tuscany.sca.host.corba.CorbaHost; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.provider.ReferenceBindingProvider; import org.apache.tuscany.sca.runtime.RuntimeComponentReference; @@ -37,11 +42,15 @@ public class CorbaReferenceBindingProvider implements ReferenceBindingProvider { private CorbaHost host; private RuntimeComponentReference reference; private Object remoteObject; + private Class<?> referenceClass; + private Map<Method, String> operationsMap = null; public CorbaReferenceBindingProvider(CorbaBinding binding, CorbaHost host, RuntimeComponentReference reference) { this.binding = binding; this.host = host; this.reference = reference; + this.referenceClass = ((JavaInterface)reference.getInterfaceContract().getInterface()).getJavaClass(); + operationsMap = OperationMapper.mapMethodToOperation(referenceClass); } /** @@ -52,7 +61,7 @@ public class CorbaReferenceBindingProvider implements ReferenceBindingProvider { if (remoteObject == null) { remoteObject = host.lookup(binding.getCorbaname()); } - return new CorbaInvoker(remoteObject); + return new CorbaInvoker(remoteObject, referenceClass, operationsMap); } catch (Exception e) { } return null; diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/DynaCorbaRequest.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/DynaCorbaRequest.java index fd310a85a8..f4f82c9b88 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/DynaCorbaRequest.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/DynaCorbaRequest.java @@ -19,7 +19,10 @@ package org.apache.tuscany.sca.binding.corba.impl.reference; +import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.tuscany.sca.binding.corba.impl.exceptions.CorbaException; @@ -28,6 +31,7 @@ import org.apache.tuscany.sca.binding.corba.impl.types.TypeTree; import org.apache.tuscany.sca.binding.corba.impl.types.TypeTreeCreator; import org.apache.tuscany.sca.binding.corba.impl.types.util.TypeHelpersProxy; import org.apache.tuscany.sca.binding.corba.impl.types.util.Utils; +import org.apache.tuscany.sca.binding.corba.impl.util.MethodFinder; import org.omg.CORBA.BAD_OPERATION; import org.omg.CORBA.BAD_PARAM; import org.omg.CORBA.Object; @@ -44,10 +48,13 @@ public class DynaCorbaRequest { private TypeTree returnTree; private Map<String, TypeTree> exceptions = new HashMap<String, TypeTree>(); - private OutputStream outputStream; private InputStream inputStream; private ObjectImpl remoteObject; private String operation; + private List<java.lang.Object> arguments = new ArrayList<java.lang.Object>(); + private List<TypeTree> argumentsTypes = new ArrayList<TypeTree>(); + private Class<?> referenceClass; + private Map<Method, String> operationsMap; /** * Creates request. @@ -56,20 +63,48 @@ public class DynaCorbaRequest { * @param operation operation to invoke */ public DynaCorbaRequest(Object remoteObject, String operation) { - outputStream = ((ObjectImpl)remoteObject)._request(operation, true); this.remoteObject = (ObjectImpl)remoteObject; this.operation = operation; + } + + /** + * Sets class which will be backed by this reference request + * @param referenceClass + */ + public void setReferenceClass(Class<?> referenceClass) { + this.referenceClass = referenceClass; + } + /** + * Sets method to operation names mapping + * @param operationsMap + */ + public void setOperationsMap(Map<Method, String> operationsMap) { + this.operationsMap = operationsMap; } /** - * Adds operation argument + * Adds operation argument - stores arguments and caches its TypeTree * * @param argument */ public void addArgument(java.lang.Object argument) throws RequestConfigurationException { TypeTree tree = TypeTreeCreator.createTypeTree(argument.getClass()); - TypeHelpersProxy.write(tree.getRootNode(), outputStream, argument); + argumentsTypes.add(tree); + arguments.add(argument); + } + + /** + * Passing stored arguments to CORBA communication output stream + * + * @param outputStream + * @throws RequestConfigurationException + */ + private void passArguments(OutputStream outputStream) throws RequestConfigurationException { + for (int i = 0; i < arguments.size(); i++) { + TypeTree tree = argumentsTypes.get(i); + TypeHelpersProxy.write(tree.getRootNode(), outputStream, arguments.get(i)); + } } /** @@ -88,7 +123,7 @@ public class DynaCorbaRequest { */ public void addExceptionType(Class<?> forClass) throws RequestConfigurationException { TypeTree tree = TypeTreeCreator.createTypeTree(forClass); - String exceptionId = Utils.getExceptionId(forClass); + String exceptionId = Utils.getTypeId(forClass); exceptions.put(exceptionId, tree); } @@ -142,12 +177,35 @@ public class DynaCorbaRequest { } /** + * Gets operation name which is includes mapping rules + * @return + */ + private String getFinalOperationName() { + String result = operation; + if (referenceClass != null) { + Class<?>[] argumentTypes = new Class<?>[arguments.size()]; + for (int i = 0; i < arguments.size(); i++) { + argumentTypes[i] = arguments.get(i).getClass(); + } + Method method = MethodFinder.findMethod(referenceClass, operation, argumentTypes); + String newOperation = (String)operationsMap.get(method); + if (newOperation != null) { + result = newOperation; + } + } + return result; + } + + /** * Invokes previously configured request * * @return */ public DynaCorbaResponse invoke() throws Exception { DynaCorbaResponse response = new DynaCorbaResponse(); + String finalOperationName = getFinalOperationName(); + OutputStream outputStream = ((ObjectImpl)remoteObject)._request(finalOperationName, true); + passArguments(outputStream); try { inputStream = remoteObject._invoke(outputStream); if (inputStream != null && returnTree != null) { @@ -164,8 +222,11 @@ public class DynaCorbaRequest { } return response; } - - public void release() { + + /** + * Releases request resources + */ + private void release() { remoteObject._releaseReply(inputStream); } diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceInstanceCreator.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceInstanceCreator.java index 7965ecb86a..514d7055a8 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceInstanceCreator.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceInstanceCreator.java @@ -59,7 +59,7 @@ public class InterfaceInstanceCreator { enhancer.setCallbackTypes(new Class[] {NoOp.class, MethodInterceptor.class}); Class<?> newClass = enhancer.createClass(); Enhancer.registerStaticCallbacks(newClass, new Callback[] {NoOp.INSTANCE, - new InterfaceMethodInterceptor(reference)}); + new InterfaceMethodInterceptor(reference, forClass)}); result = newClass.newInstance(); } catch (Exception e) { e.printStackTrace(); diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceMethodInterceptor.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceMethodInterceptor.java index 2642601057..7fba091b41 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceMethodInterceptor.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/reference/InterfaceMethodInterceptor.java @@ -33,9 +33,11 @@ import org.omg.CORBA.Object; public class InterfaceMethodInterceptor implements MethodInterceptor { private Object reference; + private Class<?> javaClass; - public InterfaceMethodInterceptor(Object reference) { + public InterfaceMethodInterceptor(Object reference, Class<?> javaClass) { this.reference = reference; + this.javaClass = javaClass; } /** @@ -47,6 +49,7 @@ public class InterfaceMethodInterceptor implements MethodInterceptor { java.lang.Object[] arguments, MethodProxy arg3) throws Throwable { DynaCorbaRequest request = new DynaCorbaRequest(reference, method.getName()); + request.setReferenceClass(javaClass); for (int i = 0; i < arguments.length; i++) { request.addArgument(arguments[i]); } diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/service/DynaCorbaServant.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/service/DynaCorbaServant.java index cece057baa..6c7e2b1238 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/service/DynaCorbaServant.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/service/DynaCorbaServant.java @@ -20,6 +20,7 @@ package org.apache.tuscany.sca.binding.corba.impl.service; import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -31,8 +32,10 @@ import org.apache.tuscany.sca.binding.corba.impl.types.TypeTree; import org.apache.tuscany.sca.binding.corba.impl.types.TypeTreeCreator; import org.apache.tuscany.sca.binding.corba.impl.types.util.TypeHelpersProxy; import org.apache.tuscany.sca.binding.corba.impl.types.util.Utils; +import org.apache.tuscany.sca.binding.corba.impl.util.OperationMapper; import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.runtime.RuntimeComponentService; import org.omg.CORBA.MARSHAL; import org.omg.CORBA.portable.InputStream; @@ -46,19 +49,63 @@ import org.omg.CORBA.portable.ResponseHandler; */ public class DynaCorbaServant extends ObjectImpl implements InvokeHandler { - private static String[] DEFAULT_IDS = {"IDL:default:1.0"}; private RuntimeComponentService service; private Binding binding; - private String[] ids = DEFAULT_IDS; - private Map<String, OperationTypes> operationsCache = new HashMap<String, OperationTypes>(); + private String[] ids; + private Map<Operation, OperationTypes> operationsCache = new HashMap<Operation, OperationTypes>(); + private Class<?> javaClass; + private Map<String, Method> operationsMap; + private Map<Method, Operation> methodOperationMapping; public DynaCorbaServant(RuntimeComponentService service, Binding binding) throws RequestConfigurationException { this.service = service; this.binding = binding; + this.javaClass = ((JavaInterface)service.getInterfaceContract().getInterface()).getJavaClass(); + this.operationsMap = OperationMapper.mapOperationToMethod(javaClass); cacheOperationTypes(service.getInterfaceContract().getInterface().getOperations()); + createMethod2OperationMapping(); + setDefaultIds(); + } + /** + * Maps Java methods to Tuscany operations + */ + private void createMethod2OperationMapping() { + // for every operation find all methods with the same name, then + // compare operations and methods parameters + this.methodOperationMapping = new HashMap<Method, Operation>(); + for (Operation operation : service.getInterfaceContract().getInterface().getOperations()) { + List<DataType> inputTypes = operation.getInputType().getLogical(); + Method[] methods = javaClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(operation.getName()) && inputTypes.size() == methods[i] + .getParameterTypes().length) { + Class<?>[] parameterTypes = methods[i].getParameterTypes(); + int j = 0; + boolean parameterMatch = true; + for (DataType dataType : inputTypes) { + if (!dataType.getPhysical().equals(parameterTypes[j])) { + parameterMatch = false; + break; + } + j++; + } + if (parameterMatch) { + // match found + methodOperationMapping.put(methods[i], operation); + break; + } + } + } + + } } + /** + * Caches TypeTree for every operation in backed component + * @param operations + * @throws RequestConfigurationException + */ private void cacheOperationTypes(List<Operation> operations) throws RequestConfigurationException { for (Operation operation : operations) { try { @@ -80,41 +127,39 @@ public class DynaCorbaServant extends ObjectImpl implements InvokeHandler { } operationTypes.setInputType(inputInstances); - operationsCache.put(operation.getName(), operationTypes); + operationsCache.put(operation, operationTypes); } catch (RequestConfigurationException e) { throw e; } } } + /** + * Sets CORBA object ID + * @param ids + */ public void setIds(String[] ids) { for (int i = 0; i < ids.length; i++) { if (ids[i] == null || ids[i].length() == 0) { - this.ids = DEFAULT_IDS; + // if invalid id was passed then set to default + setDefaultIds(); return; } } this.ids = ids; } - public OutputStream _invoke(String method, InputStream in, ResponseHandler rh) { - + public OutputStream _invoke(String operationName, InputStream in, ResponseHandler rh) { Operation operation = null; - - List<Operation> operations = service.getInterfaceContract().getInterface().getOperations(); + Method method = operationsMap.get(operationName); // searching for proper operation - for (Operation oper : operations) { - if (oper.getName().equals(method)) { - operation = oper; - break; - } - } + operation = methodOperationMapping.get(method); if (operation == null) { // operation wasn't found throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE); } else { List<Object> inputInstances = new ArrayList<Object>(); - OperationTypes types = operationsCache.get(operation.getName()); + OperationTypes types = operationsCache.get(operation); try { // retrieving in arguments for (TypeTree tree : types.getInputType()) { @@ -129,19 +174,19 @@ public class DynaCorbaServant extends ObjectImpl implements InvokeHandler { try { // invocation and sending result Object result = service.getRuntimeWire(binding).invoke(operation, inputInstances.toArray()); + OutputStream out = rh.createReply(); if (types.getOutputType() != null) { - OutputStream out = rh.createReply(); TypeTree tree = types.getOutputType(); TypeHelpersProxy.write(tree.getRootNode(), out, result); - return out; } + return out; } catch (InvocationTargetException ie) { // handling user exception try { OutputStream out = rh.createExceptionReply(); Class<?> exceptionClass = ie.getTargetException().getClass(); TypeTree tree = TypeTreeCreator.createTypeTree(exceptionClass); - String exceptionId = Utils.getExceptionId(exceptionClass); + String exceptionId = Utils.getTypeId(exceptionClass); out.write_string(exceptionId); TypeHelpersProxy.write(tree.getRootNode(), out, ie.getTargetException()); return out; @@ -163,4 +208,12 @@ public class DynaCorbaServant extends ObjectImpl implements InvokeHandler { return ids; } + /** + * Sets servant ID to default, based on Java class name + */ + private void setDefaultIds() { + String id = Utils.getTypeId(javaClass); + this.ids = new String[] {id}; + } + } diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/types/util/Utils.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/types/util/Utils.java index 4c1467d3c3..de381f995b 100644 --- a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/types/util/Utils.java +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/types/util/Utils.java @@ -26,7 +26,7 @@ public class Utils { * @param forClass * @return */ - public static String getExceptionId(Class<?> forClass) { + public static String getTypeId(Class<?> forClass) { String result = forClass.getName().replace('.', '/'); result = result.replaceAll("Package", ""); result = "IDL:" + result + ":1.0"; diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/MethodFinder.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/MethodFinder.java new file mode 100644 index 0000000000..ea18a33ce0 --- /dev/null +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/MethodFinder.java @@ -0,0 +1,96 @@ +/* + * 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.binding.corba.impl.util; + +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; + +/** + * Utility for finding method in given class. + */ +public class MethodFinder { + + private static Map<Class<?>, Class<?>> boxingMapping; + + static { + boxingMapping = new HashMap<Class<?>, Class<?>>(); + boxingMapping.put(boolean.class, Boolean.class); + boxingMapping.put(byte.class, Byte.class); + boxingMapping.put(short.class, Short.class); + boxingMapping.put(char.class, Character.class); + boxingMapping.put(int.class, Integer.class); + boxingMapping.put(long.class, Long.class); + boxingMapping.put(float.class, Float.class); + boxingMapping.put(double.class, Double.class); + } + + /** + * Converts primitive class to its object equivalent. + * + * @param parameter class to convert + * @return object equivalent for primitive type. If parameter wasn't + * primitive then returns parameter. + */ + private static Class<?> normalizePrimitive(Class<?> parameter) { + Class<?> result = boxingMapping.get(parameter); + if (result != null) { + return result; + } else { + // not a primitive - no need to normalize + return parameter; + } + } + + /** + * Finds appropriate method. This method ignores difference between + * primitive types and theirs object equivalents. Ie. if we want to find + * method "get" in java.util.List with only one parameter, which type is + * Integer then we'll obtain method get(int). + * + * @param forClass class which possibly contains desired method + * @param methodName desired methods name + * @param parameterTypes desired methods parameter types + * @return desired method, if no method was found then null will be returned + */ + public static Method findMethod(Class<?> forClass, String methodName, Class<?>[] parameterTypes) { + Method[] methods = forClass.getMethods(); + for (int i = 0; i < methods.length; i++) { + if (methods[i].getName().equals(methodName)) { + Class<?>[] methodPTypes = methods[i].getParameterTypes(); + if (methodPTypes.length == parameterTypes.length) { + boolean parameterMatch = true; + for (int j = 0; j < methodPTypes.length; j++) { + Class<?> nMethodPType = normalizePrimitive(methodPTypes[j]); + Class<?> nParameterType = normalizePrimitive(parameterTypes[j]); + if (!nMethodPType.equals(nParameterType)) { + parameterMatch = false; + break; + } + } + if (parameterMatch) { + return methods[i]; + } + } + } + } + return null; + } +} diff --git a/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/OperationMapper.java b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/OperationMapper.java new file mode 100644 index 0000000000..d5f31dd723 --- /dev/null +++ b/java/sca/modules/binding-corba-runtime/src/main/java/org/apache/tuscany/sca/binding/corba/impl/util/OperationMapper.java @@ -0,0 +1,516 @@ +/* + * 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.binding.corba.impl.util; + +import java.lang.reflect.Method; +import java.rmi.RemoteException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.omg.CORBA.portable.IDLEntity; + +/** + * @version $Rev$ $Date$ + * @see UtilInitializer + */ +public final class OperationMapper { + + private static Set<Class<?>> getAllInterfaces(Class<?> intfClass) { + Set<Class<?>> allInterfaces = new LinkedHashSet<Class<?>>(); + + LinkedList<Class<?>> stack = new LinkedList<Class<?>>(); + stack.addFirst(intfClass); + + while (!stack.isEmpty()) { + Class<?> intf = stack.removeFirst(); + allInterfaces.add(intf); + stack.addAll(0, Arrays.asList(intf.getInterfaces())); + } + + return allInterfaces; + } + + @SuppressWarnings("unchecked") + public static Map<Method, String> mapMethodToOperation(Class<?> intfClass) { + return iiopMap(intfClass, false); + } + + @SuppressWarnings("unchecked") + public static Map<String, Method> mapOperationToMethod(Class<?> intfClass) { + return iiopMap(intfClass, true); + } + + @SuppressWarnings("unchecked") + private static Map iiopMap(Class<?> intfClass, boolean operationToMethod) { + Method[] methods = getAllMethods(intfClass); + + // find every valid getter + Map<Method, String> getterByMethod = new HashMap<Method, String>(methods.length); + Map<String, Method> getterByName = new HashMap<String, Method>(methods.length); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + String methodName = method.getName(); + + // no arguments allowed + if (method.getParameterTypes().length != 0) { + continue; + } + + // must start with get or is + String verb; + if (methodName.startsWith("get") && methodName.length() > 3 && method.getReturnType() != void.class) { + verb = "get"; + } else if (methodName.startsWith("is") && methodName.length() > 2 && method.getReturnType() == boolean.class) { + verb = "is"; + } else { + continue; + } + + // must only throw Remote or Runtime Exceptions + boolean exceptionsValid = true; + Class[] exceptionTypes = method.getExceptionTypes(); + for (int j = 0; j < exceptionTypes.length; j++) { + Class<?> exceptionType = exceptionTypes[j]; + if (!RemoteException.class.isAssignableFrom(exceptionType) && + !RuntimeException.class.isAssignableFrom(exceptionType) && + !Error.class.isAssignableFrom(exceptionType)) { + exceptionsValid = false; + break; + } + } + if (!exceptionsValid) { + continue; + } + + String propertyName; + if (methodName.length() > verb.length() + 1 && Character.isUpperCase(methodName.charAt(verb.length() + 1))) { + propertyName = methodName.substring(verb.length()); + } else { + propertyName = Character.toLowerCase(methodName.charAt(verb.length())) + methodName.substring(verb.length() + 1); + } + getterByMethod.put(method, propertyName); + getterByName.put(propertyName, method); + } + + Map<Method, String> setterByMethod = new HashMap<Method, String>(methods.length); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + String methodName = method.getName(); + + // must have exactally one arg + if (method.getParameterTypes().length != 1) { + continue; + } + + // must return non void + if (method.getReturnType() != void.class) { + continue; + } + + // must start with set + if (!methodName.startsWith("set") || methodName.length() <= 3) { + continue; + } + + // must only throw Remote or Runtime Exceptions + boolean exceptionsValid = true; + Class<?>[] exceptionTypes = method.getExceptionTypes(); + for (int j = 0; j < exceptionTypes.length; j++) { + Class<?> exceptionType = exceptionTypes[j]; + if (!RemoteException.class.isAssignableFrom(exceptionType) && + !RuntimeException.class.isAssignableFrom(exceptionType) && + !Error.class.isAssignableFrom(exceptionType)) { + exceptionsValid = false; + break; + } + } + if (!exceptionsValid) { + continue; + } + + String propertyName; + if (methodName.length() > 4 && Character.isUpperCase(methodName.charAt(4))) { + propertyName = methodName.substring(3); + } else { + propertyName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4); + } + + // must have a matching getter + Method getter = (Method) getterByName.get(propertyName); + if (getter == null) { + continue; + } + + // setter property must match getter return value + if (!method.getParameterTypes()[0].equals(getter.getReturnType())) { + continue; + } + setterByMethod.put(method, propertyName); + } + + // index the methods by name... used to determine which methods are overloaded + HashMap<String, List<Method>> overloadedMethods = new HashMap<String, List<Method>>(methods.length); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (getterByMethod.containsKey(method) || setterByMethod.containsKey(method)) { + continue; + } + String methodName = method.getName(); + List<Method> methodList = overloadedMethods.get(methodName); + if (methodList == null) { + methodList = new LinkedList<Method>(); + overloadedMethods.put(methodName, methodList); + } + methodList.add(method); + } + + // index the methods by lower case name... used to determine which methods differ only by case + Map<String, Set<String>> caseCollisionMethods = new HashMap<String, Set<String>>(methods.length); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + if (getterByMethod.containsKey(method) || setterByMethod.containsKey(method)) { + continue; + } + String lowerCaseMethodName = method.getName().toLowerCase(); + Set<String> methodSet = caseCollisionMethods.get(lowerCaseMethodName); + if (methodSet == null) { + methodSet = new HashSet<String>(); + caseCollisionMethods.put(lowerCaseMethodName, methodSet); + } + methodSet.add(method.getName()); + } + + String className = getClassName(intfClass); + Map iiopMap = new HashMap(methods.length); + for (int i = 0; i < methods.length; i++) { + Method method = methods[i]; + + String iiopName = (String) getterByMethod.get(method); + if (iiopName != null) { + // if we have a leading underscore prepend with J + if (iiopName.charAt(0) == '_') { + iiopName = "J_get_" + iiopName.substring(1); + } else { + iiopName = "_get_" + iiopName; + } + } else { + iiopName = (String) setterByMethod.get(method); + if (iiopName != null) { + // if we have a leading underscore prepend with J + if (iiopName.charAt(0) == '_') { + iiopName = "J_set_" + iiopName.substring(1); + } else { + iiopName = "_set_" + iiopName; + } + } else { + iiopName = method.getName(); + + // if we have a leading underscore prepend with J + if (iiopName.charAt(0) == '_') { + iiopName = "J" + iiopName; + } + } + } + + // if this name only differs by case add the case index to the end + Set<String> caseCollisions = caseCollisionMethods.get(method.getName().toLowerCase()); + if (caseCollisions != null && caseCollisions.size() > 1) { + iiopName += upperCaseIndexString(iiopName); + } + + // if this is an overloaded method append the parameter string + List<Method> overloads = overloadedMethods.get(method.getName()); + if (overloads != null && overloads.size() > 1) { + iiopName += buildOverloadParameterString(method.getParameterTypes()); + } + + // if we have a leading underscore prepend with J + iiopName = replace(iiopName, '$', "U0024"); + + // if we have matched a keyword prepend with an underscore + if (keywords.contains(iiopName.toLowerCase())) { + iiopName = "_" + iiopName; + } + + // if the name is the same as the class name, append an underscore + if (iiopName.equalsIgnoreCase(className)) { + iiopName += "_"; + } + + if (operationToMethod) { + iiopMap.put(iiopName, method); + } else { + iiopMap.put(method, iiopName); + } + } + + return iiopMap; + } + + private static Method[] getAllMethods(Class<?> intfClass) { + List<Method> methods = new LinkedList<Method>(); + for (Iterator<Class<?>> iterator = getAllInterfaces(intfClass).iterator(); iterator.hasNext();) { + Class<?> intf = iterator.next(); + methods.addAll(Arrays.asList(intf.getDeclaredMethods())); + } + + return (Method[]) methods.toArray(new Method[methods.size()]); + } + + /** + * Return the a string containing an underscore '_' index of each uppercase + * character in the IIOP name. This is used for distinction of names that + * only differ by case, since CORBA does not support case sensitive names. + */ + private static String upperCaseIndexString(String iiopName) { + StringBuffer stringBuffer = new StringBuffer(); + for (int i = 0; i < iiopName.length(); i++) { + char c = iiopName.charAt(i); + if (Character.isUpperCase(c)) { + stringBuffer.append('_').append(i); + } + } + return stringBuffer.toString(); + } + + /** + * Replaces any occurances of the specified "oldChar" with the new string. + * This is used to replace occurances if '$' in CORBA names since '$' is a + * special character + */ + private static String replace(String source, char oldChar, String newString) { + StringBuffer stringBuffer = new StringBuffer(source.length()); + for (int i = 0; i < source.length(); i++) { + char c = source.charAt(i); + if (c == oldChar) { + stringBuffer.append(newString); + } else { + stringBuffer.append(c); + } + } + return stringBuffer.toString(); + } + + /** + * Return the a string containing a double underscore '__' list of parameter + * types encoded using the Java to IDL rules. This is used for distinction + * of methods that only differ by parameter lists. + */ + private static String buildOverloadParameterString(Class<?>[] parameterTypes) { + String name = ""; + if (parameterTypes.length == 0) { + name += "__"; + } else { + for (int i = 0; i < parameterTypes.length; i++) { + Class<?> parameterType = parameterTypes[i]; + name += buildOverloadParameterString(parameterType); + } + } + return name.replace('.', '_'); + } + + /** + * Returns a single parameter type encoded using the Java to IDL rules. + */ + private static String buildOverloadParameterString(Class<?> parameterType) { + String name = "_"; + + int arrayDimensions = 0; + while (parameterType.isArray()) { + arrayDimensions++; + parameterType = parameterType.getComponentType(); + } + + // arrays start with org_omg_boxedRMI_ + if (arrayDimensions > 0) { + name += "_org_omg_boxedRMI"; + } + + // IDLEntity types must be prefixed with org_omg_boxedIDL_ + if (IDLEntity.class.isAssignableFrom(parameterType)) { + name += "_org_omg_boxedIDL"; + } + + // add package... some types have special mappings in corba + String packageName = (String)specialTypePackages.get(parameterType.getName()); + if (packageName == null) { + packageName = getPackageName(parameterType.getName()); + } + if (packageName.length() > 0) { + name += "_" + packageName; + } + + // arrays now contain a dimension indicator + if (arrayDimensions > 0) { + name += "_" + "seq" + arrayDimensions; + } + + // add the class name + String className = (String)specialTypeNames.get(parameterType.getName()); + if (className == null) { + className = buildClassName(parameterType); + } + name += "_" + className; + + return name; + } + + /** + * Returns a string containing an encoded class name. + */ + private static String buildClassName(Class<?> type) { + if (type.isArray()) { + throw new IllegalArgumentException("type is an array: " + type); + } + + // get the classname + String typeName = type.getName(); + int endIndex = typeName.lastIndexOf('.'); + if (endIndex < 0) { + return typeName; + } + StringBuffer className = new StringBuffer(typeName.substring(endIndex + 1)); + + // for innerclasses replace the $ separator with two underscores + // we can't just blindly replace all $ characters since class names can + // contain the $ character + if (type.getDeclaringClass() != null) { + String declaringClassName = getClassName(type.getDeclaringClass()); + assert className.toString().startsWith(declaringClassName + "$"); + className.replace(declaringClassName.length(), declaringClassName.length() + 1, "__"); + } + + // if we have a leading underscore prepend with J + if (className.charAt(0) == '_') { + className.insert(0, "J"); + } + return className.toString(); + } + + private static String getClassName(Class<?> type) { + if (type.isArray()) { + throw new IllegalArgumentException("type is an array: " + type); + } + + // get the classname + String typeName = type.getName(); + int endIndex = typeName.lastIndexOf('.'); + if (endIndex < 0) { + return typeName; + } + return typeName.substring(endIndex + 1); + } + + private static String getPackageName(String interfaceName) { + int endIndex = interfaceName.lastIndexOf('.'); + if (endIndex < 0) { + return ""; + } + return interfaceName.substring(0, endIndex); + } + + private static final Map<String, String> specialTypeNames; + private static final Map<String, String> specialTypePackages; + private static final Set<String> keywords; + + static { + specialTypeNames = new HashMap<String, String>(); + specialTypeNames.put("boolean", "boolean"); + specialTypeNames.put("char", "wchar"); + specialTypeNames.put("byte", "octet"); + specialTypeNames.put("short", "short"); + specialTypeNames.put("int", "long"); + specialTypeNames.put("long", "long_long"); + specialTypeNames.put("float", "float"); + specialTypeNames.put("double", "double"); + specialTypeNames.put("java.lang.Class", "ClassDesc"); + specialTypeNames.put("java.lang.String", "WStringValue"); + specialTypeNames.put("org.omg.CORBA.Object", "Object"); + + specialTypePackages = new HashMap<String, String>(); + specialTypePackages.put("boolean", ""); + specialTypePackages.put("char", ""); + specialTypePackages.put("byte", ""); + specialTypePackages.put("short", ""); + specialTypePackages.put("int", ""); + specialTypePackages.put("long", ""); + specialTypePackages.put("float", ""); + specialTypePackages.put("double", ""); + specialTypePackages.put("java.lang.Class", "javax.rmi.CORBA"); + specialTypePackages.put("java.lang.String", "CORBA"); + specialTypePackages.put("org.omg.CORBA.Object", ""); + + keywords = new HashSet<String>(); + keywords.add("abstract"); + keywords.add("any"); + keywords.add("attribute"); + keywords.add("boolean"); + keywords.add("case"); + keywords.add("char"); + keywords.add("const"); + keywords.add("context"); + keywords.add("custom"); + keywords.add("default"); + keywords.add("double"); + keywords.add("enum"); + keywords.add("exception"); + keywords.add("factory"); + keywords.add("false"); + keywords.add("fixed"); + keywords.add("float"); + keywords.add("in"); + keywords.add("inout"); + keywords.add("interface"); + keywords.add("long"); + keywords.add("module"); + keywords.add("native"); + keywords.add("object"); + keywords.add("octet"); + keywords.add("oneway"); + keywords.add("out"); + keywords.add("private"); + keywords.add("public"); + keywords.add("raises"); + keywords.add("readonly"); + keywords.add("sequence"); + keywords.add("short"); + keywords.add("string"); + keywords.add("struct"); + keywords.add("supports"); + keywords.add("switch"); + keywords.add("true"); + keywords.add("truncatable"); + keywords.add("typedef"); + keywords.add("union"); + keywords.add("unsigned"); + keywords.add("valuebase"); + keywords.add("valuetype"); + keywords.add("void"); + keywords.add("wchar"); + keywords.add("wstring"); + } + +} diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/CorbaTypesTestCase.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/CorbaTypesTestCase.java index 4419dce132..e41a60d86a 100644 --- a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/CorbaTypesTestCase.java +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/CorbaTypesTestCase.java @@ -558,8 +558,6 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } try { @@ -568,8 +566,6 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } try { @@ -578,17 +574,13 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } - + try { request = new DynaCorbaRequest(refArraysSetter, "whatever"); request.setOutputType(SomeStruct.class); } catch (Exception e) { fail(); - } finally { - request.release(); } } @@ -604,8 +596,6 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } try { @@ -614,8 +604,6 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } try { @@ -624,8 +612,6 @@ public class CorbaTypesTestCase { fail(); } catch (Exception e) { assertTrue(e instanceof RequestConfigurationException); - } finally { - request.release(); } try { @@ -633,8 +619,6 @@ public class CorbaTypesTestCase { request.setOutputType(Color.class); } catch (Exception e) { fail(); - } finally { - request.release(); } } diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MappingTestInterface.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MappingTestInterface.java new file mode 100644 index 0000000000..11bcdc195e --- /dev/null +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MappingTestInterface.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 org.apache.tuscany.sca.binding.corba.testing; + +/** + * Interface that can be tested for operations mapping + */ +public interface MappingTestInterface { + + int getIntField(); + + void setIntField(int intField); + + boolean isBoolField(); + + void setBoolField(boolean boolField); + + void overloadedName(); + + void overloadedName(String arg1); + + void overloadedName(String arg1, int arg2); + + void caseCollision(); + + void CaseCollision(); + +} diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MethodFinderTestCase.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MethodFinderTestCase.java new file mode 100644 index 0000000000..fa64afca8b --- /dev/null +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/MethodFinderTestCase.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.binding.corba.testing; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import java.lang.reflect.Method; + +import org.apache.tuscany.sca.binding.corba.impl.util.MethodFinder; +import org.junit.Test; + +/** + * Various tests for MethodFinder + */ +public class MethodFinderTestCase { + + /** + * Tests finding existing methods + */ + @Test + public void test_findExistingMethod() { + try { + String methodName = "rotateLeft"; + Method sample = Integer.class.getMethod(methodName, new Class<?>[] {int.class, int.class}); + Method m1 = MethodFinder.findMethod(Integer.class, methodName, new Class<?>[] {int.class, int.class}); + Method m2 = + MethodFinder.findMethod(Integer.class, methodName, new Class<?>[] {Integer.class, Integer.class}); + assertEquals(sample, m1); + assertEquals(sample, m2); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + + /** + * Tests null result value for not existing method + */ + @Test + public void test_findNotExistingMethod() { + try { + String methodName = "rotateLeft"; + Method method = MethodFinder.findMethod(Integer.class, methodName, new Class<?>[] {}); + assertEquals(null, method); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + +} diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/OperationMappingTestCase.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/OperationMappingTestCase.java new file mode 100644 index 0000000000..8d3f34f48c --- /dev/null +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/OperationMappingTestCase.java @@ -0,0 +1,66 @@ +/* + * 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.binding.corba.testing; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Method; +import java.util.Map; + +import org.apache.tuscany.sca.binding.corba.impl.util.OperationMapper; +import org.junit.Test; + +/** + * Various tests for OperationsMapping + */ +public class OperationMappingTestCase { + + /** + * Tests if Java2IDLUtil maps methods to operations correctly + */ + @Test + public void test_mappingRules() { + Map<Method, String> met2op = OperationMapper.mapMethodToOperation(MappingTestInterface.class); + for (Method method : met2op.keySet()) { + String name = method.getName(); + String translatedName = met2op.get(method); + if (name.equals("getIntField")) { + assertEquals("_get_intField", translatedName); + } else if (name.equals("setIntField")) { + assertEquals("_set_intField", translatedName); + } else if (name.equals("isBoolField")) { + assertEquals("_get_boolField", translatedName); + } else if (name.equals("setBoolField")) { + assertEquals("_set_boolField", translatedName); + } else if (name.equals("overloadedName") && method.getParameterTypes().length == 0) { + assertEquals("overloadedName__", translatedName); + } else if (name.equals("overloadedName") && method.getParameterTypes().length == 1) { + assertEquals("overloadedName__CORBA_WStringValue", translatedName); + } else if (name.equals("overloadedName") && method.getParameterTypes().length == 2) { + assertEquals("overloadedName__CORBA_WStringValue__long", translatedName); + } else if (name.equals("caseCollision")) { + assertEquals("caseCollision_4", translatedName); + } else if (name.equals("CaseCollision")) { + assertEquals("CaseCollision_0_4", translatedName); + } + } + } + +} diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestInterface.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestInterface.java index 8c74fd3a8c..1fcacca732 100644 --- a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestInterface.java +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestInterface.java @@ -21,8 +21,10 @@ package org.apache.tuscany.sca.binding.corba.testing.service.mocks; import java.util.List; -import org.apache.tuscany.sca.interfacedef.Interface; +import javax.xml.namespace.QName; + import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.policy.Intent; import org.apache.tuscany.sca.policy.IntentAttachPointType; import org.apache.tuscany.sca.policy.PolicySet; @@ -30,12 +32,14 @@ import org.apache.tuscany.sca.policy.PolicySet; /** * Mock TestInterface implementation. Only few methods needs to be implemented. */ -public class TestInterface implements Interface { +public class TestInterface implements JavaInterface { private List<Operation> operations; + private Class<?> javaClass; - public TestInterface(List<Operation> opearations) { + public TestInterface(List<Operation> opearations, Class<?> javaClass) { this.operations = opearations; + this.javaClass = javaClass; } public List<Operation> getOperations() { @@ -94,4 +98,41 @@ public class TestInterface implements Interface { return null; } + public Class<?> getCallbackClass() { + return null; + } + + public Class<?> getJavaClass() { + return javaClass; + } + + public String getName() { + return null; + } + + public QName getQName() { + return null; + } + + public void setCallbackClass(Class<?> arg0) { + } + + public void setJavaClass(Class<?> javaClass) { + this.javaClass = javaClass; + } + + public void setName(String arg0) { + } + + public void setQName(QName arg0) { + + } + + public boolean isUnresolved() { + return false; + } + + public void setUnresolved(boolean arg0) { + } + } diff --git a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeComponentService.java b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeComponentService.java index 58793c044e..e105c5f3de 100644 --- a/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeComponentService.java +++ b/java/sca/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestRuntimeComponentService.java @@ -73,7 +73,7 @@ public class TestRuntimeComponentService implements RuntimeComponentService { operation.setName(methods[i].getName()); } } - TestInterface iface = new TestInterface(operations); + TestInterface iface = new TestInterface(operations, invocationTarget.getClass()); interfaceContract = new TestInterfaceContract(); interfaceContract.setInterface(iface); } |