package jadex.base.service.remote.commands; import jadex.base.service.remote.IRemoteCommand; import jadex.base.service.remote.RemoteReference; import jadex.base.service.remote.RemoteServiceManagementService; import jadex.commons.Future; import jadex.commons.IFuture; import jadex.commons.SReflect; import jadex.commons.concurrent.IResultListener; import jadex.micro.IMicroExternalAccess; import java.lang.reflect.Method; /** * Command for executing a remote method. */ public class RemoteMethodInvocationCommand implements IRemoteCommand { //-------- attributes -------- /** The remote reference. */ protected RemoteReference rr; /** The methodname. */ protected String methodname; /** The parameter types. */ protected Class[] parametertypes; /** The parameter values. */ protected Object[] parametervalues; /** The call identifier. */ protected String callid; //-------- constructors -------- /** * Create a new remote method invocation command. */ public RemoteMethodInvocationCommand() { } /** * Create a new remote method invocation command. */ public RemoteMethodInvocationCommand(RemoteReference rr, String methodname, Class[] parametertypes, Object[] parametervalues, String callid) { this.rr = rr; this.methodname = methodname; this.parametertypes = parametertypes; this.parametervalues = parametervalues; this.callid = callid; } //-------- methods -------- /** * Execute the command. * @param lrms The local remote management service. * @return An optional result command that will be * sent back to the command origin. */ public IFuture execute(IMicroExternalAccess component, RemoteServiceManagementService rsms) { final Future ret = new Future(); rsms.getRemoteReferenceModule().getTargetObject(getRemoteReference()) .addResultListener(new IResultListener() // todo: createResultListener?! { public void resultAvailable(Object source, Object result) { invokeMethod(result, ret); } public void exceptionOccurred(Object source, Exception exception) { ret.setResult(new RemoteResultCommand(null, new RuntimeException("Target object not found: "+getRemoteReference()), callid)); } }); // if(getRemoteReference().getTargetIdentifier() instanceof String) // { // Object target = rsms.getRemoteReferenceModule().getTargetObject(getRemoteReference()); // if(target!=null) // { // invokeMethod(target, ret); // } // else // { // ret.setResult(new RemoteResultCommand(null, new RuntimeException("Target object not found: "+tid), callid)); // } // } // else if(getRemoteReference().getTargetIdentifier() instanceof IServiceIdentifier) // { // IServiceIdentifier sid = (IServiceIdentifier)getRemoteReference().getTargetIdentifier(); // // // fetch service via its id // SServiceProvider.getService(component.getServiceProvider(), sid) // .addResultListener(new IResultListener() // { // public void resultAvailable(Object source, Object result) // { // invokeMethod(result, ret); // } // // public void exceptionOccurred(Object source, Exception exception) // { // ret.setResult(new RemoteResultCommand(null, exception, callid)); // } // }); // } // else if(getRemoteReference().getTargetIdentifier() instanceof IComponentIdentifier) // { // final IComponentIdentifier cid = (IComponentIdentifier)getRemoteReference().getTargetIdentifier(); // // // fetch component via target component id // SServiceProvider.getServiceUpwards(component.getServiceProvider(), IComponentManagementService.class) // .addResultListener(new IResultListener() //// .addResultListener(component.createResultListener(new IResultListener() // { // public void resultAvailable(Object source, Object result) // { // IComponentManagementService cms = (IComponentManagementService)result; // // // fetch target component via component identifier. // cms.getExternalAccess(cid).addResultListener(new IResultListener() // { // public void resultAvailable(Object source, Object result) // { // IExternalAccess exta = (IExternalAccess)result; // // // invoke method directly on external access // invokeMethod(exta, ret); // } // // public void exceptionOccurred(Object source, Exception exception) // { // ret.setResult(new RemoteResultCommand(null, exception, callid)); // } // }); // } // // public void exceptionOccurred(Object source, Exception exception) // { // ret.setResult(new RemoteResultCommand(null, exception, callid)); // } // }); // } // else // { // System.out.println("remote invocation error, not target could be found: "+getRemoteReference().getTargetIdentifier()); // } return ret; } /** * Invoke remote method. * @param target The target object. * @param ret The result future. */ public void invokeMethod(Object target, final Future ret) { try { // fetch method on service and invoke method Method m = target.getClass().getMethod(methodname, parametertypes); // Necessary due to Java inner class bug 4071957 if(SReflect.isAnonymousInnerClass(target.getClass())) m.setAccessible(true); Object res = m.invoke(target, parametervalues); if(res instanceof IFuture) { ((IFuture)res).addResultListener(new IResultListener() { public void resultAvailable(Object source, Object result) { ret.setResult(new RemoteResultCommand(result, null, callid)); } public void exceptionOccurred(Object source, Exception exception) { ret.setResult(new RemoteResultCommand(null, exception, callid)); } }); } else { ret.setResult(new RemoteResultCommand(res, null, callid)); } } catch(Exception exception) { ret.setResult(new RemoteResultCommand(null, exception, callid)); } } //-------- getter/setter methods -------- /** * Get the methodname. * @return the methodname. */ public String getMethodName() { return methodname; } /** * Set the methodname. * @param methodname The methodname to set. */ public void setMethodName(String methodname) { this.methodname = methodname; } /** * Get the parametertypes. * @return the parametertypes. */ public Class[] getParameterTypes() { return parametertypes; } /** * Set the parametertypes. * @param parametertypes The parametertypes to set. */ public void setParameterTypes(Class[] parametertypes) { this.parametertypes = parametertypes; } /** * Get the parametervalues. * @return the parametervalues. */ public Object[] getParameterValues() { return parametervalues; } /** * Set the parametervalues. * @param parametervalues The parametervalues to set. */ public void setParameterValues(Object[] parametervalues) { this.parametervalues = parametervalues; } /** * Get the callid. * @return the callid. */ public String getCallId() { return callid; } /** * Set the callid. * @param callid The callid to set. */ public void setCallId(String callid) { this.callid = callid; } /** * Get the remote reference. * @return The remote reference. */ public RemoteReference getRemoteReference() { return rr; } /** * Set the remote reference. * @param rr The remote reference to set. */ public void setRemoteReference(RemoteReference rr) { this.rr = rr; } /** * Get the string representation. */ public String toString() { return "RemoteMethodInvocationCommand(remote reference=" + rr + ", methodname=" + methodname + ", callid=" + callid + ")"; } }