/*
* Copyright (c) 2004 David Flanagan. All rights reserved.
* This code is from the book Java Examples in a Nutshell, 3nd Edition.
* It is provided AS-IS, WITHOUT ANY WARRANTY either expressed or implied.
* You may study, use, and modify it for any non-commercial purpose,
* including teaching and use in open-source projects.
* You may distribute it non-commercially as long as you retain this notice.
* For a commercial use license, or to purchase the book,
* please visit http://www.davidflanagan.com/javaexamples3.
*/
package je3.rmi;
import java.rmi.*;
import java.rmi.server.*;
import java.rmi.registry.*;
import java.io.*;
import java.util.Hashtable;
import java.util.zip.*;
import je3.rmi.Mud.*;
/**
* This class implements the RemoteMudServer interface. It also defines a
* main() method so you can run it as a standalone program that will
* set up and initialize a MUD server. Note that a MudServer maintains an
* entrance point to a MUD, but it is not the MUD itself. Most of the
* interesting MUD functionality is defined by the RemoteMudPlace interface
* and implemented by the RemotePlace class. In addition to being a remote
* object, this class is also Serializable, so that the state of the MUD
* can be saved to a file and later restored. Note that the main() method
* defines two ways of starting a MUD: one is to start it from scratch with
* a single initial place, and another is to restore an existing MUD from a
* file.
**/
public class MudServer extends UnicastRemoteObject
implements RemoteMudServer, Serializable
{
MudPlace entrance; // The standard entrance to this MUD
String password; // The password required to dump() the state of the MUD
String mudname; // The name that this MUD is registered under
Hashtable places; // A mapping of place names to places in this MUD
/**
* Start a MUD from scratch, with the given name and password. Create
* an initial MudPlace object as the entrance, giving it the specified
* name and description.
**/
public MudServer(String mudname, String password,
String placename, String description)
throws RemoteException
{
this.mudname = mudname;
this.password = password;
this.places = new Hashtable();
// Create the entrance place
try { this.entrance = new MudPlace(this, placename, description); }
catch (PlaceAlreadyExists e) {} // Should never happen
}
/** For serialization only. Never call this constructor. */
public MudServer() throws RemoteException {}
/** This remote method returns the name of the MUD */
public String getMudName() throws RemoteException { return mudname; }
/** This remote method returns the entrance place of the MUD */
public RemoteMudPlace getEntrance() throws RemoteException {
return entrance;
}
/**
* This remote method returns a RemoteMudPlace object for the named place.
* In this sense, a MudServer acts as like an RMI Registry object,
* returning remote objects looked up by name. It is simpler to do it this
* way than to use an actual Registry object. If the named place does not
* exist, it throws a NoSuchPlace exception
**/
public RemoteMudPlace getNamedPlace(String name)
throws RemoteException, NoSuchPlace
{
RemoteMudPlace p = (RemoteMudPlace) places.get(name);
if (p == null) throw new NoSuchPlace();
return p;
}
/**
* Define a new placename to place mapping in our hashtable.
* This is not a remote method. The MudPlace() constructor calls it
* to register the new place it is creating.
**/
public void setPlaceName(RemoteMudPlace place, String name)
throws PlaceAlreadyExists
{
if (places.containsKey(name)) throw new PlaceAlreadyExists();
places.put(name, place);
}
/**
* This remote method serializes and compresses the state of the MUD
* to a named file, if the specified password matches the one specified
* when the MUD was initially created. Note that the state of a MUD
* consists of all places in the MUD, with all things and exits in those
* places. The people in the MUD are not part of the state that is saved.
**/
public void dump(String password, String f)
throws RemoteException, BadPassword, IOException
{
if ((this.password != null)&& !this.password.equals(password))
throw new BadPassword();
ObjectOutputStream out = new ObjectOutputStream(
new GZIPOutputStream(new FileOutputStream(f)));
out.writeObject(this);
out.close();
}
/**
* This main() method defines the standalone program that starts up a MUD
* server. If invoked with a single argument, it treats that argument as
* the name of a file containing the serialized and compressed state of an
* existing MUD, and recreates it. Otherwise, it expects four command-line
* arguments: the name of the MUD, the password, the name of the entrance
* place for the MUD, and a description of that entrance place.
* Besides creating the MudServer object, this program sets an appropriate
* security manager, and uses the default rmiregistry to register the
* the MudServer under its given name.
**/
public static void main(String[] args) {
try {
MudServer server;
if (args.length == 1) {
// Read the MUD state in from a file
FileInputStream f = new FileInputStream(args[0]);
ObjectInputStream in =
new ObjectInputStream(new GZIPInputStream(f));
server = (MudServer) in.readObject();
}
// Otherwise, create an initial MUD from scratch
else server = new MudServer(args[0], args[1], args[2], args[3]);
Naming.rebind(Mud.mudPrefix + server.mudname, server);
}
// Display an error message if anything goes wrong.
catch (Exception e) {
System.out.println(e);
System.out.println("Usage: java MudServer <savefile>\n" +
" or: java MudServer <mudname> <password> " +
"<placename> <description>");
System.exit(1);
}
}
/** This constant is a version number for serialization */
static final long serialVersionUID = 7453281245880199453L;
}
|