summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 23:11:59 +0000
committereea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 23:11:59 +0000
commit5d089e7886f85b6a5d64740fa9bb6ee7e0f7b128 (patch)
tree1a3080a30b0d0510ac65158f4dd02bc6b9dcbbab
parent358dc412371b0a8658af2e0bbdea43a8e138c063 (diff)
downloadATCD-5d089e7886f85b6a5d64740fa9bb6ee7e0f7b128.tar.gz
Updated source files for netsvcs.
-rw-r--r--java/JACE/netsvcs/Handler.java185
-rw-r--r--java/JACE/netsvcs/Server.java356
-rw-r--r--java/JACE/netsvcs/package.html11
3 files changed, 552 insertions, 0 deletions
diff --git a/java/JACE/netsvcs/Handler.java b/java/JACE/netsvcs/Handler.java
new file mode 100644
index 00000000000..7bf73f01206
--- /dev/null
+++ b/java/JACE/netsvcs/Handler.java
@@ -0,0 +1,185 @@
+package JACE.netsvcs;
+
+import java.io.*;
+import java.net.*;
+import JACE.OS.*;
+import JACE.Connection.*;
+
+/**
+ * Abstract class representing a handler for a Server. Provides
+ * default implementations and template methods.
+ *
+ *@see Server
+ *@author Everett Anderson
+ */
+public abstract class Handler extends SvcHandler
+{
+ /**
+ * Initialize this Handler. The default implementation sets the
+ * done flag to false.
+ *
+ *@return -1 on failure, 0 on success
+ */
+ public int open (Object obj)
+ {
+ done_ = false;
+ return 0;
+ }
+
+ /**
+ * Shut down this handler. Default implementation calls close ().
+ */
+ public int close (long flags)
+ {
+ return close ();
+ }
+
+ /**
+ * Shut down this handler, setting the done flag, and removing it
+ * from the parent Server's handler list.
+ */
+ public synchronized int close ()
+ {
+ if (!done ()) {
+ try {
+ done_ = true;
+ parent_.removeHandler (this);
+ peer ().close ();
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns the name of the host that is connected to this handler,
+ * or null if not connected.
+ */
+ public String hostName ()
+ {
+ if (done ())
+ return null;
+ else
+ return this.peer().socket().getInetAddress().getHostName();
+ }
+
+ /**
+ * Process a single request and handle any errors. The default
+ * implementation calls handleRequest with an Object from
+ * newRequest ().
+ */
+ public void handleRequest ()
+ {
+ handleRequest (newRequest ());
+ }
+
+ /**
+ * Process a single request and handle any errors. The default
+ * implementation calls processRequest with the given request
+ * Object, and then handles exceptions appropriately. Subclasses
+ * normally just implement processRequest rather than override
+ * this method.
+ *
+ *@param request request to process
+ */
+ public void handleRequest (Object request)
+ {
+ try {
+
+ processRequest (request);
+
+ } catch (NullPointerException e) {
+ if (!done ()) {
+ ACE.ERROR("Failure: " + e);
+ close ();
+ }
+ } catch (SocketException e) {
+ if (!done ()) {
+ ACE.DEBUG (hostName () + " disconnected");
+ close ();
+ }
+ } catch (EOFException e) {
+ if (!done ()) {
+ ACE.DEBUG (hostName () + " disconnected");
+ close ();
+ }
+ } catch (IOException e) {
+ if (!done ()) {
+ ACE.ERROR ("Lost connection: " + e);
+ close ();
+ }
+ }
+ }
+
+ /**
+ * Process a single request (including reading it from the wire)
+ * without handling errors. Subclasses must define the behavior.
+ *
+ *@param requestObject request to process
+ *@exception SocketException problem with the socket
+ *@exception EOFException end of connection,
+ * usually means client disconnected
+ *@exception IOException error during transmission
+ */
+ protected abstract void processRequest (Object requestObject)
+ throws SocketException, EOFException, IOException;
+
+ /**
+ * Returns a new instance of a request object. Subclasses must
+ * define the behavior.
+ */
+ public abstract Object newRequest ();
+
+ /**
+ * Called by the JVM when a Handler is run in its own Thread. The
+ * default implementation creates a single request object which is
+ * reused during multiple handleRequest calls. The loop exits
+ * when the Handler's done() method returns true.
+ */
+ public void run()
+ {
+ Object request = newRequest ();
+
+ while (!done ())
+ handleRequest (request);
+
+ close ();
+ }
+
+ /**
+ * Set the Server parent of this Handler.
+ */
+ public void parent (Server parent)
+ {
+ parent_ = parent;
+ }
+
+ /**
+ * Return the Server parent of this Handler.
+ */
+ public Server parent ()
+ {
+ return parent_;
+ }
+
+ /**
+ * Check to see if this Handler should shut down.
+ */
+ protected synchronized boolean done ()
+ {
+ return done_;
+ }
+
+ /**
+ * Closes the handler, freeing resources.
+ */
+ protected void finalize () throws Throwable
+ {
+ close ();
+ }
+
+ private boolean done_ = true;
+ private Server parent_;
+}
diff --git a/java/JACE/netsvcs/Server.java b/java/JACE/netsvcs/Server.java
new file mode 100644
index 00000000000..199a830d0c5
--- /dev/null
+++ b/java/JACE/netsvcs/Server.java
@@ -0,0 +1,356 @@
+package JACE.netsvcs;
+
+import java.io.*;
+import java.net.*;
+import java.util.*;
+import JACE.OS.*;
+import JACE.Connection.*;
+import JACE.Misc.GetOpt;
+import JACE.ServiceConfigurator.Service;
+
+/**
+ * Abstract class providing default implementations for several
+ * Service methods. Currently, all the network services
+ * descend from this class. The real work for a service is done
+ * by a Handler.
+ * <P>
+ * Inner classes are provided for thread per connection
+ * and single threaded server activation strategies. Currently,
+ * specifying a single threaded strategy means that the server will
+ * disconnect the client after handling one request. Acceptor and
+ * EventHandler may be changed later to incorporate handleInput to
+ * address this. Thus, the default activation strategy is thread
+ * per connection.
+ *
+ *@see Handler
+ *@see JACE.Connection.ActivateStrategy
+ *@author Everett Anderson
+ */
+public abstract class Server extends Acceptor implements Runnable
+{
+ /**
+ * Safely shuts down all the handlers as well as the accepting socket.
+ *
+ *@return -1 on failure, 0 on success
+ */
+ public synchronized int fini ()
+ {
+ if (!done ()) {
+ ACE.DEBUG ("Shutting down " + name ());
+ try {
+ this.done_ = true;
+ for (int i = handlers_.size () - 1; i >= 0; i--)
+ ((Handler)handlers_.elementAt (i)).close ();
+
+ this.sockAcceptor_.close();
+ } catch (IOException e) {
+ ACE.ERROR(e);
+ return -1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Returns information about the state of the service such as
+ * suspended, not running, or running.
+ */
+ public String info ()
+ {
+ if (suspended ())
+ return "suspended";
+ else
+ if (done ())
+ return "not running";
+ else
+ return "running on port " + port_;
+ }
+
+ /**
+ * Provided for extra initialization in subclasses after the
+ * command line arguments have been parsed but before starting the
+ * service. This is a good place to set the default ActivateStrategy
+ * since you can make sure it wasn't set in parseArgs. The default
+ * implementation sets the strategy to Server.ThreadPerConnection.
+ *
+ *@return -1 on error, 0 on success
+ */
+ protected int initialize ()
+ {
+ if (activateStrategy_ == null)
+ activateStrategy (new Server.ThreadPerConnection ());
+
+ return 0;
+ }
+
+ /**
+ * Template method for initialization. Calls parseArgs, initialize,
+ * sets the done() state to false, and starts this Server in its own
+ * thread. If parseArgs fails, this calls printUsage.
+ *
+ *@param args command line arguments
+ *@return -1 on failure, 0 on success
+ */
+ public int init (String [] args)
+ {
+ // Parse arguments
+ if (this.parseArgs (args) == -1) {
+ printUsage ();
+ return -1;
+ }
+
+ if (initialize () < 0) {
+ ACE.ERROR (name () + " failed initializing");
+ return -1;
+ }
+
+ ACE.DEBUG ("Using " + activateStrategy_.getClass().getName ());
+ ACE.DEBUG ("Starting " + name () + " on port: " + this.port_);
+
+ done_ = false;
+
+ // Run in own thread of control so that we don't block the caller
+ new Thread (this).start();
+ return 0;
+ }
+
+ /**
+ * Called by the JVM when this Server starts running in its own
+ * thread.
+ */
+ public void run ()
+ {
+ try {
+ this.open (this.port_);
+ while (!this.done ()) {
+ this.accept ();
+ }
+ } catch (InstantiationException e) {
+ ACE.ERROR (e);
+ } catch (IllegalAccessException e) {
+ ACE.ERROR (e);
+ } catch (IOException e) {
+ if (!done ())
+ ACE.ERROR (e);
+ } finally {
+ fini ();
+ }
+ }
+
+ /**
+ * Calls the appropriate activation strategy with the given
+ * service handler. This assumes the SvcHandler is an instance
+ * of type Handler, and sets its parent accordingly.
+ *
+ *@param sh SvcHandler (assumed to be a Handler) to activate
+ *@return -1 on failure, 0 on success
+ */
+ protected int activateSvcHandler (SvcHandler sh)
+ {
+ if (done ())
+ return -1;
+
+ addHandler (sh);
+ ((Handler)sh).parent (this);
+
+ while (suspended () && !done ())
+ Thread.yield ();
+
+ if (activateStrategy_.activateSvcHandler (sh) != 0) {
+ removeHandler (sh);
+ return -1;
+ }
+
+ return 0;
+ }
+
+ /**
+ * Add the given SvcHandler to this Servers list of handlers.
+ * @param sh service handler to add (assumed to be a Handler)
+ */
+ protected void addHandler (SvcHandler sh)
+ {
+ handlers_.addElement (sh);
+ }
+
+ /**
+ * Called by Handler instances during their close () method.
+ *@param sh service handler to remove
+ */
+ public void removeHandler (SvcHandler sh)
+ {
+ handlers_.removeElement (sh);
+ }
+
+ /**
+ * Parses the command line arguments. Subclasses must override
+ * this.
+ *
+ *@param args command line arguments
+ *@return -1 on failure, 0 on success
+ */
+ protected abstract int parseArgs (String [] args);
+
+ /**
+ * Create the appropriate Handler. Subclasses must override this,
+ * returning a new instance of the proper subclass of Handler.
+ *
+ *@return new Handler instance
+ */
+ protected abstract SvcHandler makeSvcHandler ();
+
+ /**
+ * Print out the correct syntax and meaning of the command line
+ * arguments.
+ */
+ protected abstract void printUsage ();
+
+ /**
+ * Set the ActivateStrategy for handlers.
+ *
+ *@param strategy new ActivateStrategy to use
+ *@see JACE.Connection.ActivateStrategy
+ */
+ protected void activateStrategy (ActivateStrategy strategy)
+ {
+ activateStrategy_ = strategy;
+ }
+
+ /**
+ * Return the current ActivateStrategy for handlers.
+ *
+ *@return current ActivateStrategy instance
+ */
+ protected ActivateStrategy activateStrategy ()
+ {
+ return activateStrategy_;
+ }
+
+ /**
+ * Check to see if this Server has been shut down.
+ */
+ protected synchronized boolean done ()
+ {
+ return done_;
+ }
+
+ /**
+ * Useful method for subclasses when parsing the port command
+ * line option.
+ *
+ *@param port String gathered from the command line representing the port
+ *@return false if there was an error, true if successful
+ */
+ protected boolean port (String port)
+ {
+ try {
+
+ this.port_ = Integer.parseInt (port);
+
+ } catch (NumberFormatException e) {
+ ACE.ERROR("Invalid port specified: " + e.getMessage ());
+ return false;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ ACE.ERROR("Port option requires an argument");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Useful method for subclasses when trying to load and instantiate
+ * a certain class from a command line argument. This can be used
+ * when a possible command line argument is what kind of activation
+ * strategy is used for handlers.
+ *
+ *@param classname name of the class to load and create an instance of
+ *@param descrption descrption of what type of class it is
+ *@return null if failed loading, a new instance of the class on success
+ */
+ protected Object newStrategyInstance (String classname,
+ String description)
+ {
+ try {
+ Class factory = Class.forName (classname);
+
+ return factory.newInstance ();
+
+ } catch (ClassNotFoundException e) {
+ ACE.ERROR("Unable to find " + description + ": "
+ + e.getMessage ());
+ } catch (InstantiationException e) {
+ ACE.ERROR ("Instantiating " + description + ": "
+ + e.getMessage ());
+ } catch (IllegalAccessException e) {
+ ACE.ERROR ("Illegal access on " + description + ": "
+ + e.getMessage ());
+ }
+
+ return null;
+ }
+
+ /**
+ * Shuts down the Server if it wasn't already done
+ */
+ protected void finalize () throws Throwable
+ {
+ fini ();
+ }
+
+ private boolean done_ = true;
+
+ /**
+ * List of currently active Handlers
+ */
+ protected Vector handlers_ = new Vector ();
+ private ActivateStrategy activateStrategy_ = null;
+
+ /**
+ * Activation strategy in which each Handler is run in its own
+ * Thread.
+ */
+ public static class ThreadPerConnection extends ActivateStrategy
+ {
+ /**
+ * Opens the given service handler, and runs it in its own
+ * Thread.
+ *@param sh service handler to activate
+ *@return -1 on failure, 0 on success
+ */
+ public int activateSvcHandler (SvcHandler sh)
+ {
+ if (sh.open (null) < 0)
+ return -1;
+
+ new Thread (sh).start ();
+ return 0;
+ }
+ }
+
+ /**
+ * Activation strategy in which all Handlers are run in the
+ * Server Thread in sequence. This assumes that the given
+ * SvcHandler is a Handler instance.
+ */
+ public static class SingleThreaded extends ActivateStrategy
+ {
+ /**
+ * Opens the given service handler, calls Handler.handleRequest, and
+ * then Handler.close before returning.
+ *@param sh service handler to activate (assumed to be a Handler)
+ *@return -1 on failure, 0 on success
+ */
+ public int activateSvcHandler (SvcHandler sh)
+ {
+ if (sh.open (null) < 0)
+ return -1;
+
+ ((Handler)sh).handleRequest ();
+ ((Handler)sh).close ();
+
+ return 0;
+ }
+ }
+}
diff --git a/java/JACE/netsvcs/package.html b/java/JACE/netsvcs/package.html
new file mode 100644
index 00000000000..a806080aece
--- /dev/null
+++ b/java/JACE/netsvcs/package.html
@@ -0,0 +1,11 @@
+<!-- $Id$ -->
+<HTML>
+<BODY>
+Bases classes for the network services and two activation strategies.
+<P>
+Services can be loaded and managed via the Service Configurator.
+
+@see JACE.ServiceConfigurator
+@see <a href="http://www.cs.wustl.edu/~schmidt/ACE-netsvcs.html">ACE Network Services</a>
+</BODY>
+</HTML>