|
|
@ -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); |
|
|
|
} |
|
|
|
} |
|
|
|