/**
 * Licensed to the Austrian Association for Software Tool Integration (AASTI)
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. The AASTI 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.openengsb.core.services.internal;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import org.openengsb.core.api.OpenEngSBService;
import org.openengsb.core.api.remote.MethodCall;
import org.openengsb.core.api.remote.MethodReturn;
import org.openengsb.core.api.remote.MethodReturn.ReturnType;
import org.openengsb.core.api.remote.RequestHandler;
import org.openengsb.core.common.OpenEngSBCoreServices;

public class RequestHandlerImpl implements RequestHandler {

    @Override
    public MethodReturn handleCall(MethodCall call) {
        String serviceId = call.getMetaData().get("serviceId");
        if (serviceId == null) {
            throw new IllegalArgumentException("missing definition of serviceid in methodcall");
        }
        OpenEngSBService service;
        service = OpenEngSBCoreServices.getServiceUtilsService().getServiceWithId(OpenEngSBService.class, serviceId);

        Object[] args = call.getArgs();
        Method method = findMethod(service, call.getMethodName(), getArgTypes(args));

        return invokeMethod(service, method, args);
    }

    private MethodReturn invokeMethod(OpenEngSBService service, Method method, Object[] args) {
        MethodReturn resultContainer = new MethodReturn();
        try {
            Object result = method.invoke(service, args);
            if (method.getReturnType().getName().equals("void")) {
                resultContainer.setType(ReturnType.Void);
            } else {
                resultContainer.setType(ReturnType.Object);
                resultContainer.setArg(result);
            }
        } catch (InvocationTargetException e) {
            resultContainer.setType(ReturnType.Exception);
            resultContainer.setArg(e.getCause());
        } catch (IllegalAccessException e) {
            resultContainer.setType(ReturnType.Exception);
            resultContainer.setArg(e);
        }
        return resultContainer;
    }

    private Method findMethod(OpenEngSBService service, String methodName, Class<?>[] argTypes) {
        Method method;
        try {
            method = service.getClass().getMethod(methodName, argTypes);
        } catch (NoSuchMethodException e) {
            throw new IllegalArgumentException(e);
        }
        return method;
    }

    private Class<?>[] getArgTypes(Object[] args) {
        Class<?>[] result = new Class[args.length];
        for (int i = 0; i < args.length; i++) {
            result[i] = args[i].getClass();
        }
        return result;
    }

}

@@ -986,32 +986,25 @@
 ore.api.
-OpenEngSBService
+Constants
 ;%0Aimport
@@ -1267,16 +1267,141 @@
 ervices;
+%0Aimport org.osgi.framework.Filter;%0Aimport org.osgi.framework.FrameworkUtil;%0Aimport org.osgi.framework.InvalidSyntaxException;
 %0A%0Apublic
@@ -1535,22 +1535,22 @@
     
-String
+Object
  service
 Id =
@@ -1549,47 +1549,40 @@
 vice
-Id
  = 
-call.getMetaData().get(%22s
+retrieveOpenEngSBS
 ervice
-Id%22
+(call
 );%0A 
@@ -1592,428 +1592,832 @@
     
-if (serviceId == null) %7B%0A            throw new IllegalArgumentException(%22missing definition of 
+Object%5B%5D args = call.getArgs();%0A        Method method = findMethod(service, call.getMethodName(), getArgTypes(args));%0A        return invokeMethod(
 service
-id in
+,
  method
-call%22);%0A   
+, args);%0A
     
- 
 %7D%0A
-  
+%0A
     
-  OpenEngSBService service;%0A        service = OpenEngSBCoreServices.getServiceUtilsService().getServiceWithId(OpenEngSBService.class, serviceId);%0A%0A        Object%5B%5D args = call.getArgs();%0A        Method method = findMethod(service, call.getMethodName(), getArgTypes(args));%0A%0A
+private Object retrieveOpenEngSBService(MethodCall call) %7B%0A        String serviceId = retrieveServiceId(call);%0A        Filter filter = createFilterForServiceId(serviceId);%0A        return OpenEngSBCoreServices.getServiceUtilsService().getService(filter);%0A    %7D%0A%0A    private String retrieveServiceId(MethodCall call) %7B%0A        String serviceId = call.getMetaData().get(%22serviceId%22);%0A        if (serviceId == null) %7B%0A            throw new IllegalArgumentException(%22missing definition of serviceid in methodcall%22);%0A        %7D%0A        return serviceId;%0A    %7D%0A%0A    private Filter createFilterForServiceId(String serviceId) %7B%0A        try %7B%0A   
         
 retu
@@ -2416,51 +2416,208 @@
     
+ 
 return 
-invokeMethod(service, method, args);
+FrameworkUtil.createFilter(String.format(%22(%25s=%25s)%22, Constants.SERVICE_ID, serviceId));%0A        %7D catch (InvalidSyntaxException e) %7B%0A            throw new IllegalArgumentException(e);%0A        %7D
 %0A   
@@ -2655,39 +2655,29 @@
 vokeMethod(O
-penEngSBService
+bject
  service, Me
@@ -3485,31 +3485,21 @@
 Method(O
-penEngSBService
+bject
  service

Allow all services to be called in call-router