diff options
Diffstat (limited to '')
-rw-r--r-- | sca-java-2.x/branches/2.0-Beta1/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/sca-java-2.x/branches/2.0-Beta1/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java b/sca-java-2.x/branches/2.0-Beta1/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java new file mode 100644 index 0000000000..a9a2fdbd0b --- /dev/null +++ b/sca-java-2.x/branches/2.0-Beta1/modules/implementation-osgi-runtime/src/main/java/org/apache/tuscany/sca/implementation/osgi/runtime/OSGiTargetInvoker.java @@ -0,0 +1,210 @@ +/* + * 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.implementation.osgi.runtime; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Hashtable; +import java.util.List; + +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Interface; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; +import org.apache.tuscany.sca.invocation.Invoker; +import org.apache.tuscany.sca.invocation.Message; +import org.apache.tuscany.sca.runtime.RuntimeComponent; +import org.apache.tuscany.sca.runtime.RuntimeComponentService; +import org.osgi.framework.Constants; + +/** + * The Invoker looks up the corresponding OSGi service from the OSGi service registry + * and delegate the call to it. + * + * @version $Rev$ $Date$ + */ +public class OSGiTargetInvoker implements Invoker { + + private Operation operation; + + private final OSGiImplementationProvider provider; + private final RuntimeComponent component; + private final RuntimeComponentService service; + + public OSGiTargetInvoker(Operation operation, OSGiImplementationProvider provider, RuntimeComponentService service) { + + this.operation = operation; + this.service = service; + this.provider = provider; + this.component = provider.getComponent(); + + } + + private Object invokeTarget(Message msg) throws InvocationTargetException { + + Operation op = msg.getOperation(); + if (op == null) { + op = this.operation; + } + + try { + Object instance = provider.getOSGiService(service); + Method m = findMethod(instance.getClass(), operation); + + Object ret = invokeMethod(instance, m, msg); + + return ret; + } catch (InvocationTargetException e) { + throw e; + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + + protected Object invokeMethod(Object instance, Method m, Message msg) throws InvocationTargetException { + + try { + + Object payload = msg.getBody(); + + if (payload != null && !payload.getClass().isArray()) { + return m.invoke(instance, payload); + } else { + return m.invoke(instance, (Object[])payload); + } + + } catch (InvocationTargetException e) { + throw e; + } catch (Exception e) { + throw new InvocationTargetException(e); + } + } + + public Message invoke(Message msg) { + try { + Object resp = invokeTarget(msg); + msg.setBody(resp); + } catch (InvocationTargetException e) { + msg.setFaultBody(e.getCause()); + } + return msg; + } + + private String getOSGiFilter(Hashtable<String, Object> props) { + Object serviceID = props.get(Constants.SERVICE_ID); + if (serviceID != null) { + return "(" + Constants.SERVICE_ID + "=" + serviceID + ")"; + } + + String filter = ""; + + if (props != null && props.size() > 0) { + int propCount = 0; + for (String propName : props.keySet()) { + String value = String.valueOf(props.get(propName)); + StringBuffer buf = new StringBuffer(); + for (char c : value.toCharArray()) { + if (c == '(' || c == ')') { + buf.append("\\" + c); + } else { + buf.append(c); + } + } + filter = filter + "(" + propName + "=" + buf.toString() + ")"; + propCount++; + } + + if (propCount > 1) { + filter = "(&" + filter + ")"; + } + } else { + filter = null; + } + return filter; + } + + /** + * @Deprecated + */ + private static Class<?>[] getPhysicalTypes(Operation operation) { + DataType<List<DataType>> inputType = operation.getInputType(); + if (inputType == null) { + return new Class<?>[] {}; + } + List<DataType> types = inputType.getLogical(); + Class<?>[] javaTypes = new Class<?>[types.size()]; + for (int i = 0; i < javaTypes.length; i++) { + Type physical = types.get(i).getPhysical(); + if (physical instanceof Class<?>) { + javaTypes[i] = (Class<?>)physical; + } else { + throw new UnsupportedOperationException(); + } + } + return javaTypes; + } + + /** + * Return the method on the implementation class that matches the operation. + * + * @param implClass the implementation class or interface + * @param operation the operation to match + * @return the method described by the operation + * @throws NoSuchMethodException if no such method exists + * @Deprecated + */ + public static Method findMethod(Class<?> implClass, Operation operation) throws NoSuchMethodException { + String name = operation.getName(); + if (operation instanceof JavaOperation) { + name = ((JavaOperation)operation).getJavaMethod().getName(); + } + Interface interface1 = operation.getInterface(); + int numParams = operation.getInputType().getLogical().size(); + if (interface1 != null && interface1.isRemotable()) { + List<Method> matchingMethods = new ArrayList<Method>(); + for (Method m : implClass.getMethods()) { + if (m.getName().equals(name) && m.getParameterTypes().length == numParams) { + matchingMethods.add(m); + } + } + + // TUSCANY-2180 If there is only one method then we just match on the name + // (this is the same as the existing behaviour) + if (matchingMethods.size() == 1) { + return matchingMethods.get(0); + } + if (matchingMethods.size() > 1) { + // TUSCANY-2180 We need to check the parameter types too + Class<?>[] paramTypes = getPhysicalTypes(operation); + return implClass.getMethod(name, paramTypes); + } + + // No matching method found + throw new NoSuchMethodException("No matching method for operation " + operation.getName() + + " is found on " + + implClass); + } + Class<?>[] paramTypes = getPhysicalTypes(operation); + return implClass.getMethod(name, paramTypes); + } + +} |