package ibis.ipl.util.rpc; import ibis.ipl.Ibis; import ibis.ipl.MessageUpcall; import ibis.ipl.ReadMessage; import ibis.ipl.ReceivePort; import ibis.ipl.ReceivePortIdentifier; import ibis.ipl.SendPort; import ibis.ipl.WriteMessage; import java.io.IOException; import java.lang.reflect.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RemoteObject<InterfaceType> implements MessageUpcall { private static final Logger logger = LoggerFactory .getLogger(RemoteObject.class); private final Class<InterfaceType> interfaceClass; private final InterfaceType theObject; private final String name; public Class<InterfaceType> getInterfaceClass() { return interfaceClass; } public InterfaceType getObject() { return theObject; } public String getName() { return name; } public ReceivePort getReceivePort() { return receivePort; } private final Ibis ibis; private final ReceivePort receivePort; RemoteObject(Class<InterfaceType> interfaceClass, InterfaceType theObject, String name, Ibis ibis) throws RemoteException { this.interfaceClass = interfaceClass; this.theObject = theObject; this.ibis = ibis; // check if all methods of given interface throw a RemoteException for (Method method : interfaceClass.getDeclaredMethods()) { boolean found = false; for (Class<?> clazz : method.getExceptionTypes()) { if (clazz.equals(RemoteException.class)) { found = true; } } if (!found) { throw new RemoteException("required RemoteException not thrown" + " by remote method \"" + method.getName() + "\" in remote object interface \"" + interfaceClass.getName() + "\""); } } try { receivePort = ibis.createReceivePort(RPC.rpcRequestPortType, name, this); // enable connections receivePort.enableConnections(); // enable upcalls receivePort.enableMessageUpcalls(); // set after creating receive port in case of anonymous remote // object this.name = receivePort.name(); logger.debug("remote object " + this + " created"); } catch (IOException e) { throw new RemoteException( "cannot create receive port for remote object", e); } } public void unexport() throws IOException { receivePort.close(); } /** * Function called by Ibis to give us a newly arrived message. Not meant to * be called by users. */ public void upcall(ReadMessage message) throws IOException, ClassNotFoundException { // read request ReceivePortIdentifier requestor = (ReceivePortIdentifier) message .readObject(); String methodName = message.readString(); Class<?>[] parameterTypes = (Class<?>[]) message.readObject(); Object[] args = (Object[]) message.readObject(); message.finish(); if (logger.isDebugEnabled()) { logger.debug("received invocation for remote object. name = " + name + ", method name = " + methodName); } // create reply connection. SendPort replyPort = ibis.createSendPort(RPC.rpcReplyPortType); replyPort.connect(requestor); boolean success; Object result = null; try { Method method = interfaceClass.getDeclaredMethod(methodName, parameterTypes); result = method.invoke(theObject, args); success = true; } catch (Throwable exception) { // method threw an exception, return to caller result = exception; success = false; } // send reply message WriteMessage reply = replyPort.newMessage(); reply.writeBoolean(success); reply.writeObject(result); System.err.println("bytes send in reply = " + reply.finish()); // cleanup replyPort.close(); } public String toString() { return name; } }