|
|
|
@ -42,25 +42,36 @@ import com.jme3.network.serializing.Serializer; |
|
|
|
|
import com.jme3.util.IntMap; |
|
|
|
|
import com.jme3.util.IntMap.Entry; |
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.lang.reflect.InvocationTargetException; |
|
|
|
|
import java.lang.reflect.Method; |
|
|
|
|
import java.lang.reflect.Proxy; |
|
|
|
|
import java.util.HashMap; |
|
|
|
|
import java.util.logging.Level; |
|
|
|
|
import java.util.logging.Logger; |
|
|
|
|
|
|
|
|
|
public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
|
|
|
|
|
private static final Logger logger = Logger.getLogger(ObjectStore.class.getName()); |
|
|
|
|
|
|
|
|
|
private static final class Invocation { |
|
|
|
|
|
|
|
|
|
Object retVal; |
|
|
|
|
boolean available = false; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public String toString(){ |
|
|
|
|
return "Invocation[" + retVal + "]"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private Client client; |
|
|
|
|
private Server server; |
|
|
|
|
|
|
|
|
|
// Local object ID counter
|
|
|
|
|
private short objectIdCounter = 0; |
|
|
|
|
private volatile short objectIdCounter = 0; |
|
|
|
|
|
|
|
|
|
// Local invocation ID counter
|
|
|
|
|
private short invocationIdCounter = 0; |
|
|
|
|
private volatile short invocationIdCounter = 0; |
|
|
|
|
|
|
|
|
|
// Invocations waiting ..
|
|
|
|
|
private IntMap<Invocation> pendingInvocations = new IntMap<Invocation>(); |
|
|
|
@ -120,10 +131,13 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
RemoteObjectDefMessage defMsg = new RemoteObjectDefMessage(); |
|
|
|
|
defMsg.objects = new ObjectDef[]{ makeObjectDef(localObj) }; |
|
|
|
|
|
|
|
|
|
if (client != null) |
|
|
|
|
if (client != null) { |
|
|
|
|
client.send(defMsg); |
|
|
|
|
else |
|
|
|
|
logger.log(Level.INFO, "Client: Sending {0}", defMsg); |
|
|
|
|
} else { |
|
|
|
|
server.broadcast(defMsg); |
|
|
|
|
logger.log(Level.INFO, "Server: Sending {0}", defMsg); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public <T> T getExposedObject(String name, Class<T> type, boolean waitFor) throws InterruptedException{ |
|
|
|
@ -140,7 +154,6 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object proxy = Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{ type }, ro); |
|
|
|
|
ro.loadMethods(type); |
|
|
|
|
return (T) proxy; |
|
|
|
@ -163,14 +176,17 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
if (needReturn){ |
|
|
|
|
call.invocationId = invocationIdCounter++; |
|
|
|
|
invoke = new Invocation(); |
|
|
|
|
// Note: could cause threading issues if used from multiple threads
|
|
|
|
|
pendingInvocations.put(call.invocationId, invoke); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try{ |
|
|
|
|
if (server != null){ |
|
|
|
|
remoteObj.client.send(call); |
|
|
|
|
logger.log(Level.INFO, "Server: Sending {0}", call); |
|
|
|
|
}else{ |
|
|
|
|
client.send(call); |
|
|
|
|
logger.log(Level.INFO, "Client: Sending {0}", call); |
|
|
|
|
} |
|
|
|
|
} catch (IOException ex){ |
|
|
|
|
ex.printStackTrace(); |
|
|
|
@ -186,6 +202,7 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
// Note: could cause threading issues if used from multiple threads
|
|
|
|
|
pendingInvocations.remove(call.invocationId); |
|
|
|
|
return invoke.retVal; |
|
|
|
|
}else{ |
|
|
|
@ -194,6 +211,9 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void messageReceived(Message message) { |
|
|
|
|
// Might want to do more strict validation of the data
|
|
|
|
|
// in the message to prevent crashes
|
|
|
|
|
|
|
|
|
|
if (message instanceof RemoteObjectDefMessage){ |
|
|
|
|
RemoteObjectDefMessage defMsg = (RemoteObjectDefMessage) message; |
|
|
|
|
|
|
|
|
@ -212,27 +232,38 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
}else if (message instanceof RemoteMethodCallMessage){ |
|
|
|
|
RemoteMethodCallMessage call = (RemoteMethodCallMessage) message; |
|
|
|
|
LocalObject localObj = localObjects.get(call.objectId); |
|
|
|
|
if (localObj == null) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if (call.methodId < 0 || call.methodId >= localObj.methods.length) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
Object obj = localObj.theObject; |
|
|
|
|
Method method = localObj.methods[call.methodId]; |
|
|
|
|
Object[] args = call.args; |
|
|
|
|
Object ret; |
|
|
|
|
Object ret = null; |
|
|
|
|
try { |
|
|
|
|
ret = method.invoke(obj, args); |
|
|
|
|
} catch (Exception ex){ |
|
|
|
|
throw new RuntimeException(ex); |
|
|
|
|
} catch (IllegalAccessException ex){ |
|
|
|
|
logger.log(Level.WARNING, "RMI: Error accessing method", ex); |
|
|
|
|
} catch (IllegalArgumentException ex){ |
|
|
|
|
logger.log(Level.WARNING, "RMI: Invalid arguments", ex); |
|
|
|
|
} catch (InvocationTargetException ex){ |
|
|
|
|
logger.log(Level.WARNING, "RMI: Invocation exception", ex); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (method.getReturnType() != void.class){ |
|
|
|
|
// send return value back
|
|
|
|
|
RemoteMethodReturnMessage retMsg = new RemoteMethodReturnMessage(); |
|
|
|
|
retMsg.invocationID = invocationIdCounter++; |
|
|
|
|
retMsg.invocationID = call.invocationId; |
|
|
|
|
retMsg.retVal = ret; |
|
|
|
|
try { |
|
|
|
|
if (server != null){ |
|
|
|
|
call.getClient().send(retMsg); |
|
|
|
|
logger.log(Level.INFO, "Server: Sending {0}", retMsg); |
|
|
|
|
} else{ |
|
|
|
|
client.send(retMsg); |
|
|
|
|
logger.log(Level.INFO, "Client: Sending {0}", retMsg); |
|
|
|
|
} |
|
|
|
|
} catch (IOException ex){ |
|
|
|
|
ex.printStackTrace(); |
|
|
|
@ -242,7 +273,8 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
RemoteMethodReturnMessage retMsg = (RemoteMethodReturnMessage) message; |
|
|
|
|
Invocation invoke = pendingInvocations.get(retMsg.invocationID); |
|
|
|
|
if (invoke == null){ |
|
|
|
|
throw new RuntimeException("Cannot find invocation ID: " + retMsg.invocationID); |
|
|
|
|
logger.log(Level.WARNING, "Cannot find invocation ID: {0}", retMsg.invocationID); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
synchronized (invoke){ |
|
|
|
@ -268,8 +300,10 @@ public class ObjectStore implements MessageListener, ConnectionListener { |
|
|
|
|
try { |
|
|
|
|
if (this.client != null){ |
|
|
|
|
this.client.send(defMsg); |
|
|
|
|
logger.log(Level.INFO, "Client: Sending {0}", defMsg); |
|
|
|
|
} else{ |
|
|
|
|
client.send(defMsg); |
|
|
|
|
logger.log(Level.INFO, "Server: Sending {0}", defMsg); |
|
|
|
|
} |
|
|
|
|
} catch (IOException ex){ |
|
|
|
|
ex.printStackTrace(); |
|
|
|
|