| /* |
| * 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); |
| } |
| |
| } |