package ibis.ipl.util.rpc; import ibis.ipl.Ibis; import ibis.ipl.IbisIdentifier; import ibis.ipl.ReadMessage; import ibis.ipl.ReceivePort; import ibis.ipl.SendPort; import ibis.ipl.WriteMessage; import java.io.IOException; import java.lang.reflect.InvocationHandler; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; class RPCInvocationHandler implements InvocationHandler { private static final Logger logger = LoggerFactory .getLogger(RPCInvocationHandler.class); private final Ibis ibis; private final IbisIdentifier ibisIdentifier; private final String name; RPCInvocationHandler(IbisIdentifier ibisIdentifier, String name, Ibis ibis) { this.ibisIdentifier = ibisIdentifier; this.name = name; this.ibis = ibis; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (logger.isDebugEnabled()) { logger.debug("calling remote object " + name + ", method = " + method.getName()); } // Create a send port for sending the request and connect. SendPort sendPort = ibis.createSendPort(RPC.rpcRequestPortType); sendPort.connect(ibisIdentifier, name); // Create a receive port for receiving the reply from the server // this receive port does not need a name, as we will send the // ReceivePortIdentifier to the server directly ReceivePort receivePort = ibis.createReceivePort( RPC.rpcReplyPortType, null); receivePort.enableConnections(); // Send the request message. This message contains the identifier of // our receive port so the server knows where to send the reply WriteMessage request = sendPort.newMessage(); request.writeObject(receivePort.identifier()); request.writeString(method.getName()); request.writeObject(method.getParameterTypes()); request.writeObject(args); request.finish(); ReadMessage reply = receivePort.receive(); boolean success = reply.readBoolean(); Object result = reply.readObject(); reply.finish(); if (logger.isDebugEnabled()) { logger.debug("remote object \"" + name + "\", method \"" + method.getName() + "\" result = " + result); } // Close ports. sendPort.close(); receivePort.close(); if (success) { return result; } else if (result instanceof InvocationTargetException) { InvocationTargetException exception = (InvocationTargetException) result; //throw user exception throw exception.getTargetException(); } else { //some error occured while doing remote call throw new RemoteException("exception while performing remote call", (Throwable) result); } } catch (IOException e) { throw new RemoteException("invocation failed", e); } } }