diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java
index 8deada70b..a26d09635 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/Asynchronous.java
@@ -41,7 +41,9 @@ import static java.lang.annotation.RetentionPolicy.*;
/**
* Indicates that a given method should be executed asynchronously
* through the RMI service. This must annotate the method on the
- * shared interface for it to have an effect.
+ * shared interface for it to have an effect. If reliable=false
+ * is specified then remote method invocation is done over UDP
+ * instead of TCP, ie: unreliably... but faster.
*
* @author Paul Speed
*/
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java
index 6b218891d..5167bd7eb 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/CallType.java
@@ -34,10 +34,27 @@ package com.jme3.network.service.rmi;
/**
- *
+ * Internal type denoting the type of call to make when remotely
+ * invoking methods.
*
* @author Paul Speed
*/
public enum CallType {
- Synchronous, Asynchronous, Unreliable
+ /**
+ * Caller will block until a response is received and returned.
+ */
+ Synchronous,
+
+ /**
+ * Caller does not block or wait for a response. The other end
+ * of the connection will also not send one.
+ */
+ Asynchronous,
+
+ /**
+ * Similar to asynchronous in that no response is expected or sent
+ * but differs in that the call will be sent over UDP and so may
+ * not make it to the other end.
+ */
+ Unreliable
}
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java
index 88d91a686..4f7f7de32 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfo.java
@@ -39,7 +39,8 @@ import java.util.List;
/**
- *
+ * Internal information about a shared class. This is the information
+ * that is sent over the wire for shared types.
*
* @author Paul Speed
*/
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java
index 557948042..addc03593 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/ClassInfoRegistry.java
@@ -40,7 +40,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
- *
+ * Internal registry of shared types and their ClassInfo and MethodInfo
+ * objects.
*
* @author Paul Speed
*/
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java
index a0138556d..9b324a6c3 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/MethodInfo.java
@@ -39,7 +39,8 @@ import javax.jws.Oneway;
/**
- *
+ * Internal information about shared methods. This is part of the data that
+ * is passed over the wire when an object is shared.
*
* @author Paul Speed
*/
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java
index 03309a4fa..f42ada84f 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RemoteObjectHandler.java
@@ -39,7 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
/**
- *
+ * Used internally to remotely invoke methods on RMI shared objects.
*
* @author Paul Speed
*/
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java
index 437a697f2..ea1506f72 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiClientService.java
@@ -41,7 +41,23 @@ import java.util.List;
/**
+ * A service that can be added to the client to support a simple
+ * shared objects protocol.
*
+ *
Objects are shared by adding them to the RmiRegistry with one of the
+ * share() methods. Shared objects must have a separate interface and implementation.
+ * The interface is what the other end of the connection will use to interact
+ * with the object and that interface class must be available on both ends of
+ * the connection. The implementing class need only be on the sharing end.
+ *
+ * Shared objects can be accessed on the other end of the connection by
+ * using one of the RmiRegistry's getRemoteObject() methods. These can be
+ * used to lookup an object by class if it is a shared singleton or by name
+ * if it was registered with a name.
+ *
+ * Note: This RMI implementation is not as advanced as Java's regular
+ * RMI as it won't marshall shared references, ie: you can't pass
+ * a shared objects as an argument to another shared object's method.
*
* @author Paul Speed
*/
@@ -64,18 +80,42 @@ public class RmiClientService extends AbstractClientService {
this.rmiObjectId = rmiObjectId;
}
+ /**
+ * Shares the specified object with the server and associates it with the
+ * specified type. Objects shared in this way are available in the connection-specific
+ * RMI registry on the server and are not available to other connections.
+ */
public void share( T object, Class super T> type ) {
share(defaultChannel, object, type);
}
+ /**
+ * Shares the specified object with the server and associates it with the
+ * specified type. Objects shared in this way are available in the connection-specific
+ * RMI registry on the server and are not available to other connections.
+ * All object related communication will be done over the specified connection
+ * channel.
+ */
public void share( byte channel, T object, Class super T> type ) {
share(channel, type.getName(), object, type);
}
+ /**
+ * Shares the specified object with the server and associates it with the
+ * specified name. Objects shared in this way are available in the connection-specific
+ * RMI registry on the server and are not available to other connections.
+ */
public void share( String name, T object, Class super T> type ) {
share(defaultChannel, name, object, type);
}
+ /**
+ * Shares the specified object with the server and associates it with the
+ * specified name. Objects shared in this way are available in the connection-specific
+ * RMI registry on the server and are not available to other connections.
+ * All object related communication will be done over the specified connection
+ * channel.
+ */
public void share( byte channel, String name, T object, Class super T> type ) {
if( !isStarted ) {
synchronized(pending) {
@@ -90,10 +130,18 @@ public class RmiClientService extends AbstractClientService {
rmi.share(channel, name, object, type);
}
+ /**
+ * Looks up a remote object on the server by type and returns a local proxy to the
+ * remote object that was shared on the other end of the network connection.
+ */
public T getRemoteObject( Class type ) {
return rmi.getRemoteObject(type);
}
+ /**
+ * Looks up a remote object on the server by name and returns a local proxy to the
+ * remote object that was shared on the other end of the network connection.
+ */
public T getRemoteObject( String name, Class type ) {
return rmi.getRemoteObject(name, type);
}
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java
index 47d115d5b..547e83dd4 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiContext.java
@@ -45,7 +45,11 @@ import com.jme3.network.HostedConnection;
*/
public class RmiContext {
private static final ThreadLocal connection = new ThreadLocal();
-
+
+ /**
+ * Returns the HostedConnection that is responsible for any
+ * RMI-related calls on this thread.
+ */
public static HostedConnection getRmiConnection() {
return connection.get();
}
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java
index 647fe4fb6..997658a77 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiHostedService.java
@@ -46,7 +46,30 @@ import java.util.logging.Logger;
/**
+ * A service that can be added to the host to support a simple
+ * shared objects protocol.
*
+ * Objects are shared by adding them to the RmiRegistry with one of the
+ * share() methods. Shared objects must have a separate interface and implementation.
+ * The interface is what the other end of the connection will use to interact
+ * with the object and that interface class must be available on both ends of
+ * the connection. The implementing class need only be on the sharing end.
+ *
+ * Shared objects can be accessed on the other end of the connection by
+ * using one of the RmiRegistry's getRemoteObject() methods. These can be
+ * used to lookup an object by class if it is a shared singleton or by name
+ * if it was registered with a name.
+ *
+ * On the hosting side, a special shardGlobal() method is provided that
+ * will register shared objects that will automatically be provided to every
+ * new joining client and they will all be calling the same server-side instance.
+ * Normally, shared objects themselves are connection specific and handled
+ * at the connection layer. The shareGlobal() space is a way to have global
+ * resources passed directly though the need is relatively rare.
+ *
+ * Note: This RMI implementation is not as advanced as Java's regular
+ * RMI as it won't marshall shared references, ie: you can't pass
+ * a shared objects as an argument to another shared object's method.
*
* @author Paul Speed
*/
@@ -74,14 +97,34 @@ public class RmiHostedService extends AbstractHostedService {
Serializer.registerClasses(ClassInfo.class, MethodInfo.class);
}
+ /**
+ * Shares a server-wide object associated with the specified type. All connections
+ * with RMI hosting started will have access to this shared object as soon as they
+ * connect and they will all share the same instance. It is up to the shared object
+ * to handle any multithreading that might be required.
+ */
public void shareGlobal( T object, Class super T> type ) {
shareGlobal(defaultChannel, type.getName(), object, type);
}
+ /**
+ * Shares a server-wide object associated with the specified name. All connections
+ * with RMI hosting started will have access to this shared object as soon as they
+ * connect and they will all share the same instance. It is up to the shared object
+ * to handle any multithreading that might be required.
+ */
public void shareGlobal( String name, T object, Class super T> type ) {
shareGlobal(defaultChannel, name, object, type);
}
+ /**
+ * Shares a server-wide object associated with the specified name over the specified
+ * channel. All connections with RMI hosting started will have access to this shared
+ * object as soon as they connect and they will all share the same instance. It is up
+ * to the shared object to handle any multithreading that might be required.
+ * All network communcation associated with the shared object will be done over
+ * the specified channel.
+ */
public void shareGlobal( byte channel, String name, T object, Class super T> type ) {
GlobalShare share = new GlobalShare(channel, object, type);
GlobalShare existing = globalShares.put(name, share);
@@ -99,14 +142,30 @@ public class RmiHostedService extends AbstractHostedService {
}
}
+ /**
+ * Set to true if all new connections should automatically have RMI hosting started.
+ * Set to false if the game-specific connection setup will call startHostingOnConnection()
+ * after some connection setup is done (for example, logging in). Note: generally
+ * is is safe to autohost RMI as long as callers are careful about what they've added
+ * using shareGlobal(). One reasonable use-case is to shareGlobal() some kind of login
+ * service and nothing else. All other shared objects would then be added as connection
+ * specific objects during successful login processing.
+ */
public void setAutoHost( boolean b ) {
this.autoHost = b;
}
+ /**
+ * Returns true if RMI hosting is automatically started for all new connections.
+ */
public boolean getAutoHost() {
return autoHost;
}
+ /**
+ * Returns the RMI registry for the specific HostedConection. Each connection
+ * has its own registry with its own connection-specific shared objects.
+ */
public RmiRegistry getRmiRegistry( HostedConnection hc ) {
return hc.getAttribute(ATTRIBUTE_NAME);
}
diff --git a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java
index 6d1722307..c04a8c7b3 100644
--- a/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java
+++ b/jme3-networking/src/main/java/com/jme3/network/service/rmi/RmiRegistry.java
@@ -87,18 +87,45 @@ public class RmiRegistry {
rpc.registerHandler(rmiId, rmiHandler);
}
+ /**
+ * Exposes the specified object to the other end of the connection as
+ * the specified interface type. The object can be looked up by type
+ * on the other end.
+ */
public void share( T object, Class super T> type ) {
share(defaultChannel, object, type);
}
+ /**
+ * Exposes, through a specific connection channel, the specified object
+ * to the other end of the connection as the specified interface type.
+ * The object can be looked up by type on the other end.
+ * The specified channel will be used for all network communication
+ * specific to this object.
+ */
public void share( byte channel, T object, Class super T> type ) {
share(channel, type.getName(), object, type);
}
+ /**
+ * Exposes the specified object to the other end of the connection as
+ * the specified interface type and associates it with the specified name.
+ * The object can be looked up by the associated name on the other end of
+ * the connection.
+ */
public void share( String name, T object, Class super T> type ) {
share(defaultChannel, name, object, type);
}
+ /**
+ * Exposes, through a specific connection channel, the specified object to
+ * the other end of the connection as the specified interface type and associates
+ * it with the specified name.
+ * The object can be looked up by the associated name on the other end of
+ * the connection.
+ * The specified channel will be used for all network communication
+ * specific to this object.
+ */
public void share( byte channel, String name, T object, Class super T> type ) {
ClassInfo typeInfo = classCache.getClassInfo(type);
@@ -153,16 +180,18 @@ public class RmiRegistry {
}
/**
- * Returns an object that was previously registered with share().
+ * Returns a local object that was previously registered with share() using
+ * just type registration.
*/
- public T getSharedObject( Class type ) {
- return getSharedObject(type.getName(), type);
+ public T getLocalObject( Class type ) {
+ return getLocalObject(type.getName(), type);
}
/**
- * Returns an object that was previously registered with share().
+ * Returns a local object that was previously registered with share() using
+ * name registration.
*/
- public T getSharedObject( String name, Class type ) {
+ public T getLocalObject( String name, Class type ) {
local.lock.readLock().lock();
try {
return type.cast(local.byName.get(name));
@@ -171,10 +200,24 @@ public class RmiRegistry {
}
}
+ /**
+ * Looks up a remote object by type and returns a local proxy to the remote object
+ * that was shared on the other end of the network connection. If this is called
+ * from a client then it is accessing a shared object registered on the server.
+ * If this is called from the server then it is accessing a shared object registered
+ * on the client.
+ */
public T getRemoteObject( Class type ) {
return getRemoteObject(type.getName(), type);
}
+ /**
+ * Looks up a remote object by name and returns a local proxy to the remote object
+ * that was shared on the other end of the network connection. If this is called
+ * from a client then it is accessing a shared object registered on the server.
+ * If this is called from the server then it is accessing a shared object registered
+ * on the client.
+ */
public T getRemoteObject( String name, Class type ) {
remote.lock.readLock().lock();
try {