Added a bunch of javadoc and changed the names of one of the
method sets to be a little less confusing.
This commit is contained in:
parent
95aa2d72d0
commit
3a4624a5fe
@ -41,7 +41,9 @@ import static java.lang.annotation.RetentionPolicy.*;
|
|||||||
/**
|
/**
|
||||||
* Indicates that a given method should be executed asynchronously
|
* Indicates that a given method should be executed asynchronously
|
||||||
* through the RMI service. This must annotate the method on the
|
* 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
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
public enum CallType {
|
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
|
||||||
}
|
}
|
||||||
|
@ -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
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
|
@ -40,7 +40,8 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Internal registry of shared types and their ClassInfo and MethodInfo
|
||||||
|
* objects.
|
||||||
*
|
*
|
||||||
* @author Paul Speed
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
|
@ -39,7 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Used internally to remotely invoke methods on RMI shared objects.
|
||||||
*
|
*
|
||||||
* @author Paul Speed
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
|
@ -41,7 +41,23 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* A service that can be added to the client to support a simple
|
||||||
|
* shared objects protocol.
|
||||||
*
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
*
|
*
|
||||||
* @author Paul Speed
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
@ -64,18 +80,42 @@ public class RmiClientService extends AbstractClientService {
|
|||||||
this.rmiObjectId = rmiObjectId;
|
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 <T> void share( T object, Class<? super T> type ) {
|
public <T> void share( T object, Class<? super T> type ) {
|
||||||
share(defaultChannel, object, 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 <T> void share( byte channel, T object, Class<? super T> type ) {
|
public <T> void share( byte channel, T object, Class<? super T> type ) {
|
||||||
share(channel, type.getName(), object, 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 <T> void share( String name, T object, Class<? super T> type ) {
|
public <T> void share( String name, T object, Class<? super T> type ) {
|
||||||
share(defaultChannel, name, object, 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 <T> void share( byte channel, String name, T object, Class<? super T> type ) {
|
public <T> void share( byte channel, String name, T object, Class<? super T> type ) {
|
||||||
if( !isStarted ) {
|
if( !isStarted ) {
|
||||||
synchronized(pending) {
|
synchronized(pending) {
|
||||||
@ -90,10 +130,18 @@ public class RmiClientService extends AbstractClientService {
|
|||||||
rmi.share(channel, name, object, type);
|
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> T getRemoteObject( Class<T> type ) {
|
public <T> T getRemoteObject( Class<T> type ) {
|
||||||
return rmi.getRemoteObject(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> T getRemoteObject( String name, Class<T> type ) {
|
public <T> T getRemoteObject( String name, Class<T> type ) {
|
||||||
return rmi.getRemoteObject(name, type);
|
return rmi.getRemoteObject(name, type);
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,10 @@ import com.jme3.network.HostedConnection;
|
|||||||
public class RmiContext {
|
public class RmiContext {
|
||||||
private static final ThreadLocal<HostedConnection> connection = new ThreadLocal<HostedConnection>();
|
private static final ThreadLocal<HostedConnection> connection = new ThreadLocal<HostedConnection>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the HostedConnection that is responsible for any
|
||||||
|
* RMI-related calls on this thread.
|
||||||
|
*/
|
||||||
public static HostedConnection getRmiConnection() {
|
public static HostedConnection getRmiConnection() {
|
||||||
return connection.get();
|
return connection.get();
|
||||||
}
|
}
|
||||||
|
@ -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.
|
||||||
*
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
|
*
|
||||||
|
* <p>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.</p>
|
||||||
*
|
*
|
||||||
* @author Paul Speed
|
* @author Paul Speed
|
||||||
*/
|
*/
|
||||||
@ -74,14 +97,34 @@ public class RmiHostedService extends AbstractHostedService {
|
|||||||
Serializer.registerClasses(ClassInfo.class, MethodInfo.class);
|
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 <T> void shareGlobal( T object, Class<? super T> type ) {
|
public <T> void shareGlobal( T object, Class<? super T> type ) {
|
||||||
shareGlobal(defaultChannel, type.getName(), object, 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 <T> void shareGlobal( String name, T object, Class<? super T> type ) {
|
public <T> void shareGlobal( String name, T object, Class<? super T> type ) {
|
||||||
shareGlobal(defaultChannel, name, object, 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 <T> void shareGlobal( byte channel, String name, T object, Class<? super T> type ) {
|
public <T> void shareGlobal( byte channel, String name, T object, Class<? super T> type ) {
|
||||||
GlobalShare share = new GlobalShare(channel, object, type);
|
GlobalShare share = new GlobalShare(channel, object, type);
|
||||||
GlobalShare existing = globalShares.put(name, share);
|
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 ) {
|
public void setAutoHost( boolean b ) {
|
||||||
this.autoHost = b;
|
this.autoHost = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if RMI hosting is automatically started for all new connections.
|
||||||
|
*/
|
||||||
public boolean getAutoHost() {
|
public boolean getAutoHost() {
|
||||||
return autoHost;
|
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 ) {
|
public RmiRegistry getRmiRegistry( HostedConnection hc ) {
|
||||||
return hc.getAttribute(ATTRIBUTE_NAME);
|
return hc.getAttribute(ATTRIBUTE_NAME);
|
||||||
}
|
}
|
||||||
|
@ -87,18 +87,45 @@ public class RmiRegistry {
|
|||||||
rpc.registerHandler(rmiId, rmiHandler);
|
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 <T> void share( T object, Class<? super T> type ) {
|
public <T> void share( T object, Class<? super T> type ) {
|
||||||
share(defaultChannel, object, 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 <T> void share( byte channel, T object, Class<? super T> type ) {
|
public <T> void share( byte channel, T object, Class<? super T> type ) {
|
||||||
share(channel, type.getName(), object, 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 <T> void share( String name, T object, Class<? super T> type ) {
|
public <T> void share( String name, T object, Class<? super T> type ) {
|
||||||
share(defaultChannel, name, object, 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 <T> void share( byte channel, String name, T object, Class<? super T> type ) {
|
public <T> void share( byte channel, String name, T object, Class<? super T> type ) {
|
||||||
|
|
||||||
ClassInfo typeInfo = classCache.getClassInfo(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> T getSharedObject( Class<T> type ) {
|
public <T> T getLocalObject( Class<T> type ) {
|
||||||
return getSharedObject(type.getName(), 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> T getSharedObject( String name, Class<T> type ) {
|
public <T> T getLocalObject( String name, Class<T> type ) {
|
||||||
local.lock.readLock().lock();
|
local.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
return type.cast(local.byName.get(name));
|
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> T getRemoteObject( Class<T> type ) {
|
public <T> T getRemoteObject( Class<T> type ) {
|
||||||
return getRemoteObject(type.getName(), 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> T getRemoteObject( String name, Class<T> type ) {
|
public <T> T getRemoteObject( String name, Class<T> type ) {
|
||||||
remote.lock.readLock().lock();
|
remote.lock.readLock().lock();
|
||||||
try {
|
try {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user