summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoreea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 23:10:38 +0000
committereea1 <eea1@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>1999-08-24 23:10:38 +0000
commit3510b1fbc485d9f04e4d209637fcaa0d48bb61c4 (patch)
tree3c67b96e6b4c23d872d68a2e09bd884f1d2f970e
parente4012b2dc8297540c9501a10daa8b8746d55297e (diff)
downloadATCD-3510b1fbc485d9f04e4d209637fcaa0d48bb61c4.tar.gz
Updated source files for Connection.
-rw-r--r--java/JACE/Connection/AcceptStrategy.java87
-rw-r--r--java/JACE/Connection/Acceptor.java215
-rw-r--r--java/JACE/Connection/ActivateStrategy.java40
-rw-r--r--java/JACE/Connection/Blob.java114
-rw-r--r--java/JACE/Connection/BlobHandler.java35
-rw-r--r--java/JACE/Connection/BlobReader.java108
-rw-r--r--java/JACE/Connection/BlobWriter.java224
-rw-r--r--java/JACE/Connection/Connector.java148
-rw-r--r--java/JACE/Connection/CreationStrategy.java57
-rw-r--r--java/JACE/Connection/HTTPHelper.java182
-rw-r--r--java/JACE/Connection/StrategyAcceptor.java174
-rw-r--r--java/JACE/Connection/SvcHandler.java101
-rw-r--r--java/JACE/Connection/package.html7
13 files changed, 1492 insertions, 0 deletions
diff --git a/java/JACE/Connection/AcceptStrategy.java b/java/JACE/Connection/AcceptStrategy.java
new file mode 100644
index 00000000000..3af87865c79
--- /dev/null
+++ b/java/JACE/Connection/AcceptStrategy.java
@@ -0,0 +1,87 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * AcceptStrategy.java
+ *
+ *@author Prashant Jain
+ *@author Everett Anderson
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+
+/**
+ * Interface for specifying a passive connection
+ * acceptance strategy for a
+ * <a href="ACE.Connection.SvcHandler.html"><tt>SvcHandler</tt></a>
+ * .
+ * <P>
+ * This class provides a strategy that manages passive
+ * connection setup for an application, and can be extended
+ * to define new strategies.
+ * <P>
+ *
+ * The default implementation delegates to a generic Acceptor.
+ *
+ *@see SvcHandler
+ *@see Acceptor
+ */
+public class AcceptStrategy
+{
+ /**
+ * Create an instance of AcceptStrategy that delegates to the given
+ * Acceptor.
+ *@param port port number where the server will listen for connections
+ *@param peer Acceptor instance to delegate to
+ */
+ AcceptStrategy (int port, Acceptor peer) throws IOException
+ {
+ this.acceptor_ = peer;
+ this.open (port);
+ }
+
+ /**
+ * Create an instance of Accept Strategy that delegates to Acceptor.
+ *@param port port number where the server will listen for connections
+ *@exception IOException couldn't open port
+ */
+ AcceptStrategy (int port) throws IOException
+ {
+ this.acceptor_ = new Acceptor ();
+ this.open (port);
+ }
+
+ /**
+ * Initialize AcceptStrategy.
+ *@param port port number where the server will listen for connections
+ *@exception IOException couldn't open port
+ */
+ public void open (int port) throws IOException
+ {
+ this.acceptor_.open (port);
+ }
+
+ /**
+ * Accept connections into the SvcHandler. Note that subclasses
+ * should overwrite this method to provide a different accept
+ * strategy.
+ *@param sh Svc Handler in which to accept the connection
+ *@exception SocketException Socket error
+ *@exception IOException Socket error
+ *@return 0
+ */
+ public int acceptSvcHandler (SvcHandler sh) throws
+ SocketException, IOException
+ {
+ return this.acceptor_.acceptSvcHandler (sh);
+ }
+
+ // The Acceptor we delegate to (if any)
+ private Acceptor acceptor_;
+}
diff --git a/java/JACE/Connection/Acceptor.java b/java/JACE/Connection/Acceptor.java
new file mode 100644
index 00000000000..00dbed4c056
--- /dev/null
+++ b/java/JACE/Connection/Acceptor.java
@@ -0,0 +1,215 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * Acceptor.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.OS.*;
+import JACE.SOCK_SAP.*;
+import JACE.ServiceConfigurator.*;
+
+/**
+ * Abstract factory for creating a service handler
+ * (<a href="ACE.Connection.SvcHandler.html"><tt>SvcHandler</tt></a>),
+ * accepting into the
+ * <a href="ACE.Connection.SvcHandler.html"><tt>SvcHandler</tt></a>, and activating the
+ * <a href="ACE.Connection.SvcHandler.html"><tt>SvcHandler</tt></a>.
+ * <P>
+ *
+ * Implements the basic strategy for passively establishing
+ * connections with applications. The <tt>Acceptor</tt>
+ * is a factory for <tt>SvcHandler</tt> instances, and, by default
+ * generates a new <tt>SvcHandler</tt> instance for each connection
+ * esablished.
+ *
+ * <p>
+ *
+ * The user of this class <em>must</em> provide a
+ * reference to a handler factory prior to calling <a
+ * href="#accept()"><tt>accept</tt></a>, or an exception will be
+ * thrown. The handler factory is identified by the meta-class for
+ * the <tt>SvcHandler</tt>, and is typically obtained by calling <a
+ * href="java.lang.Class#classForName(java.lang.String)"><tt>Class.classForName("SvcHandler")</tt></a>.
+ *
+ * <p>
+ *
+ * TCP is the transport mechanism used, via
+ * <a href="ACE.SOCK_SAP.SOCKAcceptor.html#_top_"><tt>SOCKAcceptor</tt></a>,
+ * <em>et.al.</em> The SvcHandler is instantiated with a concrete type
+ * that performs the application-specific service.
+ *
+ * <P>
+ *
+ * This class is not directly related to the
+ * <tt>AcceptorStrategy</tt> class.
+ *
+ *
+ * @see java.lang.Class
+ * @see JACE.Connection.SvcHandler
+ * @see JACE.SOCK_SAP.SOCKAcceptor
+ */
+public class Acceptor extends ServiceObject
+{
+ /**
+ * Create an instance of Acceptor. Default constructor. Note that if
+ * an instance is created via this method, <tt>setHandlerFactory</tt>
+ * must be called prior to using <tt>accept</tt>.
+ *
+ * @see JACE.Connection.Acceptor#setHandlerFactory
+ */
+ public Acceptor ()
+ {
+ }
+
+ /**
+ * Create an instance of Acceptor.
+ *@param handlerFactory meta-class reference used to create
+ * an instance of a SvcHandler when a connection is accepted
+ * (typically obtained by calling <tt>Class.classForName</tt>).
+ *
+ *@see java.lang.Class#forName
+ */
+ public Acceptor (Class handlerFactory)
+ {
+ this.handlerFactory_ = handlerFactory;
+ }
+
+ /**
+ * Set the handler factory. This is provided to aid the default
+ * no-arg constructor.
+ *@param handlerFactory meta-class reference used to create
+ * an instance of a SvcHandler when a connection is accepted
+ * (typically obtained by calling <tt>Class.forName</tt>).
+ *
+ *@see java.lang.Class#forName
+ */
+ public void setHandlerFactory (Class handlerFactory)
+ {
+ this.handlerFactory_ = handlerFactory;
+ }
+
+ /**
+ * Initialize the Acceptor.
+ *@param port TCP port number where the Acceptor will listen for connections
+ *@exception IOException socket level exception
+ */
+ public void open (int port) throws IOException
+ {
+ this.port_ = port;
+ this.sockAcceptor_ = new SOCKAcceptor (port);
+ }
+
+ /**
+ * Template method for accepting connections. Delegates operational
+ * activities to the following bridge methods:
+ * <ul>
+ * <li><tt>makeSvcHandler</tt></li>
+ * <li><tt>acceptSvcHandler</tt></li>
+ * <li><tt>activateSvcHandler</tt></li>
+ * </ul>
+ *
+ * <p>
+ *
+ * The method first obtains a <tt>SvcHandler</tt> via
+ * <tt>makeSvcHandler</tt>, accepts the connection <q>into</q> the
+ * handler using <tt>acceptSvcHandler</tt>, and finally turns over
+ * control to the handler with <tt>activateSvcHandler</tt>.
+ *
+ *@exception SocketException socket level error
+ *@exception InstantiationException <tt>makeSvcHandler</tt> failure
+ *@exception IllegalAccessException <tt>makeSvcHandler</tt> failure
+ *@exception IOException socket level error
+ */
+ public void accept () throws SocketException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException
+ {
+
+ // Create a Svc_Handler using the appropriate Creation_Strategy
+ SvcHandler sh = this.makeSvcHandler ();
+
+ // Accept a connection into the SvcHandler using the appropriate
+ // Accept_Strategy
+ this.acceptSvcHandler (sh);
+
+ // Activate the SvcHandler using the appropriate ActivationStrategy
+ this.activateSvcHandler (sh);
+ }
+
+ /**
+ * Bridge method for creating a <tt>SvcHandler</tt>. The default is to
+ * create a new <SvcHandler>. However, subclasses can override this
+ * policy to perform <SvcHandler> creation in any way that they like
+ * (such as creating subclass instances of <SvcHandler>, using a
+ * singleton, etc.)
+ *@return a new instance of the SvcHandler
+ *@exception InstantiationException could not create new SvcHandler
+ *@exception IllegalAccessException no SvcHandler factory provided
+ */
+ protected SvcHandler makeSvcHandler ()
+ throws InstantiationException, IllegalAccessException
+ {
+ // Create a new handler for the connection
+ return (SvcHandler) handlerFactory_.newInstance ();
+ }
+
+ /**
+ * Bridge method for accepting the new connection into the
+ * <tt>SvcHandler</tt>. The default behavior delegates the work to
+ * <tt>SOCKAcceptor.accept</tt>. However, subclasses can override this
+ * strategy.
+ *@param sh SvcHandler in which to accept the connection
+ *@return 0
+ *@exception SocketException socket level error
+ *@exception IOException socket level error
+ */
+ protected int acceptSvcHandler (SvcHandler sh)
+ throws SocketException, IOException
+ {
+ // Create a new stream
+ SOCKStream sockStream = new SOCKStream ();
+
+ // Block in accept. Returns when a connection shows up
+ this.sockAcceptor_.accept (sockStream);
+
+ // Set the streams for the new handler
+ sh.setHandle (sockStream);
+ return 0;
+ }
+
+ /**
+ * Bridge method for activating a <tt>SvcHandler</tt>. The default
+ * behavior of this method is to activate the <tt>SvcHandler</tt> by
+ * calling its open() method (which allows the <tt>SvcHandler</tt> to
+ * define its own concurrency strategy). However, subclasses can
+ * override this strategy to do more sophisticated concurrency
+ * activations.
+ *@param sh SvcHandler to activate
+ *@return 0
+ */
+ protected int activateSvcHandler (SvcHandler sh)
+ {
+ sh.open (null);
+ return 0;
+ }
+
+ protected int port_ = ACE.DEFAULT_SERVER_PORT;
+
+ // Handler class that should be instantiated when a connection is
+ // made with a client
+ protected Class handlerFactory_;
+
+ // Our connection acceptance factory
+ protected SOCKAcceptor sockAcceptor_;
+}
+
diff --git a/java/JACE/Connection/ActivateStrategy.java b/java/JACE/Connection/ActivateStrategy.java
new file mode 100644
index 00000000000..91072a6c823
--- /dev/null
+++ b/java/JACE/Connection/ActivateStrategy.java
@@ -0,0 +1,40 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * ActivateStrategy.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+
+/**
+ * Bridge supporting activation strategy used by
+ * <a href="ACE.Connection.StrategyAcceptor.html#_top_"><tt>StrategyAcceptor</tt></a>
+ * <P>
+ * Subclass and overload
+ * <a href="#activateSvcHandler(ACE.Connection.SvcHandler)"><tt>activateSvcHandler</tt></a>
+ * in order change the activation strategy. Then, submit this subclass to
+ * <a href="ACE.Connection.StrategyAcceptor.html#_top_"><tt>StrategyAcceptor</tt></a>
+ * as the activation strategy.
+ *
+ *@see StrategyAcceptor
+ */
+public class ActivateStrategy
+{
+ /**
+ * Activate the Svc Handler. Note that subclasses should overwrite
+ * this method to provide a different Activate strategy.
+ *@param sh Svc Handler to activate
+ *@return zero if success, non-zero for failure
+ */
+ public int activateSvcHandler (SvcHandler sh)
+ {
+ sh.open (null);
+ return 0;
+ }
+}
diff --git a/java/JACE/Connection/Blob.java b/java/JACE/Connection/Blob.java
new file mode 100644
index 00000000000..d3102c81aa2
--- /dev/null
+++ b/java/JACE/Connection/Blob.java
@@ -0,0 +1,114 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * Blob.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+import JACE.ASX.*;
+import JACE.OS.*;
+
+/**
+ * Provides a way of reading from or writing to a remote file
+ * using MessageBlocks.
+ */
+public class Blob
+{
+ /**
+ * Initialize the Blob.
+ *
+ *@param filename File to read or write
+ *@param hostname Host to contact for the file
+ *@param port Port on which to connect
+ */
+ public int open (String filename, String hostname , int port)
+ {
+ this.filename_ = filename;
+ this.hostname_ = hostname;
+ this.port_ = port;
+ return 0;
+ }
+
+ /**
+ * Read a certain amount from the file.
+ */
+ public MessageBlock read (int length, int offset)
+ {
+ // Check if we have a valid length and a valid offset
+ if (length < 0 || offset < 0)
+ {
+ ACE.ERROR ("Blob::read(): Negative length or offset");
+ return null;
+ }
+
+ // Create a Blob Reader
+ BlobReader blobReader = new BlobReader (length,
+ offset,
+ this.filename_,
+ this.hostname_, this.port_);
+
+ // Receive data
+ MessageBlock mb = blobReader.receiveData ();
+ if (blobReader.bytesRead () != length)
+ return null;
+ else
+ return mb;
+ }
+
+ /**
+ * Write a certain amount to the file.
+ */
+ public int write (MessageBlock mb, int length, int offset)
+ {
+ // Check if we have a valid length and a valid offset
+ if (length < 0 || offset < 0)
+ ACE.ERROR ("Blob::write(): Negative length or offset");
+
+ // Create a Blob Writer
+ BlobWriter blobWriter = new BlobWriter (mb, length, offset, this.filename_);
+
+ try
+ {
+ // Connect to the server
+ this.connector_.open (this.hostname_, this.port_);
+ this.connector_.connect (blobWriter);
+ }
+ catch (UnknownHostException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (InstantiationException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IllegalAccessException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+
+ return blobWriter.bytesWritten ();
+ }
+
+ public int close ()
+ {
+ return 0;
+ }
+
+ String filename_;
+ String hostname_;
+ int port_;
+ Connector connector_ = new Connector ();
+}
diff --git a/java/JACE/Connection/BlobHandler.java b/java/JACE/Connection/BlobHandler.java
new file mode 100644
index 00000000000..ec282bdeaa9
--- /dev/null
+++ b/java/JACE/Connection/BlobHandler.java
@@ -0,0 +1,35 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * BlobHandler.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+import JACE.ASX.*;
+import JACE.OS.*;
+
+public abstract class BlobHandler extends SvcHandler
+{
+ public BlobHandler (int length, int offset, String filename)
+ {
+ this.length_ = length;
+ this.offset_ = offset;
+ this.filename_ = filename;
+ }
+
+ public abstract int open (Object obj);
+
+ protected int length_ = 0;
+ protected int offset_ = 0;
+ protected String filename_ = null;
+}
+
diff --git a/java/JACE/Connection/BlobReader.java b/java/JACE/Connection/BlobReader.java
new file mode 100644
index 00000000000..4de6b65bedc
--- /dev/null
+++ b/java/JACE/Connection/BlobReader.java
@@ -0,0 +1,108 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * BlobReader.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+import JACE.ASX.*;
+import JACE.OS.*;
+
+/**
+ * Provides a way to read from a remote file using
+ * MessageBlocks (and HTTP). <P>
+ *
+ * Created by Blob during a call to read.
+ */
+public class BlobReader
+{
+ public BlobReader (int length,
+ int offset,
+ String filename,
+ String hostname,
+ int port)
+ {
+ this.length_ = length;
+ this.offset_= offset;
+ this.filename_ = filename;
+ this.hostname_ = hostname;
+ this.port_ = port;
+ }
+
+
+ public MessageBlock receiveData ()
+ {
+ String hostname = this.hostname_;
+ String filename = this.filename_;
+
+ // Check if the filename begins with a "/" and if so, remove it
+ // since we are concatenating a "/" to the hostname.
+ if (this.filename_.startsWith ("/"))
+ filename = this.filename_.substring (1);
+
+ hostname = hostname + ":" + this.port_ + "/";
+ // System.out.println (hostname + filename);
+
+ // Allocate a buffer to hold the offset worth of data
+ byte tempBuf [] = new byte [this.offset_];
+ // Allocate a buffer to hold the actual data
+ byte dataBuf [] = new byte [this.length_];
+
+ try
+ {
+ // Create a URL to fetch the file
+ URL url = new URL (this.protocol_ + hostname + filename);
+
+ // Get the input stream and pipe it to a DataInputStream
+ DataInputStream iStream = new DataInputStream (url.openStream ());
+
+ // Read the offset worth of bytes
+ iStream.readFully (tempBuf, 0, this.offset_);
+
+ // Read length worth of bytes
+ iStream.readFully (dataBuf, 0, this.length_);
+ }
+ catch (MalformedURLException e)
+ {
+ ACE.ERROR (e);
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+ // Cache number of bytes read
+ this.bytesRead_ = this.length_;
+ return new MessageBlock (new String (dataBuf, 0, this.length_));
+ }
+
+ public int close (long flags)
+ {
+ return 0;
+ }
+
+ public int bytesRead ()
+ {
+ return this.bytesRead_;
+ }
+
+ private String protocol_ = "http://";
+
+ int length_ = 0;
+ int offset_= 0;
+ String filename_ = null;
+ String hostname_ = "localhost";
+ int port_ = 80;
+
+ int bytesRead_ = 0;
+}
+
+
diff --git a/java/JACE/Connection/BlobWriter.java b/java/JACE/Connection/BlobWriter.java
new file mode 100644
index 00000000000..18c9b092964
--- /dev/null
+++ b/java/JACE/Connection/BlobWriter.java
@@ -0,0 +1,224 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * BlobWriter.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+import JACE.ASX.*;
+import JACE.OS.*;
+
+/**
+ * Provides a way to write to a remote file using MessageBlocks
+ * (and HTTP). <P>
+ *
+ * Created by Blob during a write.
+ */
+public class BlobWriter extends BlobHandler
+{
+ public BlobWriter (MessageBlock mb,
+ int length,
+ int offset,
+ String filename)
+ {
+ super (length, offset, filename);
+ this.mb_ = mb;
+ this.returnCode_ = -1;
+
+ }
+
+ /*******************************
+ * This constructor should be used when using the basic HTTP 1.1
+ * authentication scheme
+ *******************************/
+ public BlobWriter (MessageBlock mb,
+ int length,
+ int offset,
+ String filename,
+ String authentication)
+ {
+ super (length, offset, filename);
+ this.mb_ = mb;
+ this.returnCode_ = -1;
+ this.authentication_ = authentication;
+ }
+
+
+ public int open (Object obj)
+ {
+ if (this.sendRequest () != 0)
+ {
+ ACE.ERROR ("BlobWriter::open():sendRequest failed");
+ return -1;
+ }
+ else if (this.receiveReply () != 0)
+ {
+ ACE.ERROR ("BlobWriter::open():receiveReply failed");
+ return -1;
+ }
+ return 0;
+ }
+
+ public int close (long flags)
+ {
+ return 0;
+ }
+
+ public int bytesWritten ()
+ {
+ return this.bytesWritten_;;
+ }
+
+ protected int sendRequest ()
+ {
+ // Check for sanity -- check if we have any data to send.
+ if (this.offset_+ this.length_ > this.mb_.length ())
+ {
+ ACE.ERROR ("BlobWriter::sendRequest():Invalid offset/length");
+ return -1;
+ }
+
+ if (this.sendHeader () == -1)
+ {
+ ACE.ERROR ("BlobWriter::sendHeader failed.");
+ return -1;
+ }
+ else
+ if (this.sendData () == -1)
+ {
+ ACE.ERROR ("BlobWriter::sendData failed.");
+ return -1;
+ }
+ return 0;
+ }
+
+ // Send the header
+ protected int sendHeader ()
+ {
+ String filename = this.filename_;
+ // Check if the filename begins with a "/" and if it doesn't, add it
+ if (!this.filename_.startsWith ("/"))
+ filename = "/" + this.filename_;
+
+ // Create the header, store the actual length in mesglen
+ String mesg = this.requestPrefix_ + " " + filename + " " + this.requestSuffix_;
+
+ if (this.authentication_ != null)
+ mesg += "Authorization: Basic " + JACE.Connection.HTTPHelper.EncodeBase64(this.authentication_) + '\n';
+
+ mesg += "Content-length: " + this.length_ + "\n";
+
+ try
+ {
+ if (this.peer ().send (mesg) < 0)
+ {
+ ACE.ERROR ("Error sending request");
+ return -1;
+ }
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ return -1;
+ }
+ return 0;
+ }
+
+ // Send the data
+ protected int sendData ()
+ {
+ // Get the actual data to send
+ String data = this.mb_.base ().substring (this.offset_,
+ this.offset_ + this.length_);
+
+
+ try
+ {
+ // System.out.println (data);
+ // Now send the data
+ if (this.peer ().send (data) != this.length_)
+ {
+ ACE.ERROR ("Error sending file");
+ return -1;
+ }
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ return -1;
+ }
+ this.bytesWritten_ = this.length_;
+ return 0;
+ }
+
+
+ protected int receiveReply ()
+ {
+ System.out.println("Waiting for reply");
+
+ // Receive the reply from the server
+ StringBuffer reply = new StringBuffer (1024);
+
+ try
+ {
+ if (this.peer ().recv (reply) < 0)
+ {
+ ACE.ERROR ("Error receiving reply from server");
+ return -1;
+ }
+ }
+ catch (IOException e)
+ {
+ ACE.ERROR (e);
+ }
+
+ String s = reply.toString ();
+
+ int index = -1;
+ // Now parse the reply to see if it was a success or a failure
+ if ((index = s.indexOf (replyPrefix_)) == -1)
+ {
+ ACE.ERROR ("Error receiving reply from server");
+ return -1;
+ }
+
+ int codeIndex = index + replyPrefix_.length () + 1;
+
+ // Assume code is a 3 digit number
+ String codeString = s.substring (codeIndex, codeIndex + 3);
+
+ returnCode_ = (new Integer (codeString)).intValue ();
+ // System.out.println (code);
+
+ if (returnCode_ >= 200 && returnCode_ < 300) { // Check if everything went smoothly
+ System.out.println("We got the goodies!");
+ return 0;
+ } else
+ return -1;
+ }
+
+ public int returnCode ()
+ {
+ return this.returnCode_;
+ }
+
+ protected String authentication_ = null;
+ protected String protocol_ = "http://";
+ protected int bytesWritten_ = 0;
+ protected MessageBlock mb_ = null;
+ protected String requestPrefix_ = "PUT";
+ protected String requestSuffix_ = "HTTP/1.0\n";
+ protected String replyPrefix_ = "HTTP/1.0";
+ protected int returnCode_;
+}
+
+
diff --git a/java/JACE/Connection/Connector.java b/java/JACE/Connection/Connector.java
new file mode 100644
index 00000000000..dbe72b8c359
--- /dev/null
+++ b/java/JACE/Connection/Connector.java
@@ -0,0 +1,148 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * Connector.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.OS.*;
+import JACE.SOCK_SAP.*;
+import JACE.ServiceConfigurator.*;
+
+/**
+ * Abstract factory for connecting a
+ * (<a href="JACE.Connection.SvcHandler.html"><tt>SvcHandler</tt></a>),
+ * to an application.
+ * <P>
+ * Implements the basic strategy for actively establishing connections
+ * with applications. The <tt>Connector</tt> establishes the connection,
+ * passing it on to a <tt>SvcHandler</tt> instance, and handing over
+ * control to that instance.
+ *<p>
+ * TCP is the transport mechanism used, via
+ * <a href="JACE.SOCK_SAP.SOCKConnector.html#_top_"><tt>SOCKConnector</tt></a>.
+ *<P>
+ * This class, as currently implemented, does not work like its C++
+ * counterpart.
+ * Future versions are expected to rectify this discrepancy.
+ *
+ *@see SOCKConnector
+ *@see SvcHandler
+ */
+public class Connector extends ServiceObject
+{
+ /**
+ * Create a Connector. Do nothing constructor. Allows user to
+ * call <a href="#open(java.lang.String)">open</a>() later.
+ */
+ public Connector ()
+ {
+ }
+
+ /**
+ * Create a Connector passing in server hostname and port
+ * number, effectively shorthand for calling
+ * <a href="#open(java.lang.String)">open</a>().
+ *@param hostname server hostname
+ *@param port server port number
+ */
+ public Connector (String hostname, int port)
+ {
+ this.open (hostname, port);
+ }
+
+ /**
+ * Initialize the Connector passing in server hostname and port
+ * number. Note that no connection attempt is made.
+ *@param hostname server hostname
+ *@param port server port number
+ */
+ public void open (String hostname, int port)
+ {
+ this.hostname_ = hostname;
+ this.port_ = port;
+ }
+
+ /**
+ * Connect to the server.
+ *@param sh Svc Handler to use to handle the connection
+ *@exception UnknownHostException Bad host
+ *@exception SocketException Socket error
+ *@exception InstantiationException Couldn't create new SOCKConnector
+ *@exception IllegalAccessException No strategy available
+ *@exception IOException Socket error
+ */
+ public void connect (SvcHandler sh) throws UnknownHostException,
+ SocketException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException
+ {
+ // Make a connection using the appropriate Connection_Strategy
+ this.connectSvcHandler (sh);
+
+ // Activate the Svc_Handler using the appropriate Activation_Strategy
+ this.activateSvcHandler (sh);
+ }
+
+ /**
+ * Bridge method for making a new connection. The default behavior
+ * creates a new SOCKConnector and then calls setHandle() on the
+ * <SvcHandler> that was passed in. Subclasses can override this
+ * strategy, if needed.
+ *@param sh Svc Handler to use to handle the connection
+ *@return 0
+ *@exception SocketException Socket error
+ *@exception IOException Socket error
+ */
+ protected int connectSvcHandler (SvcHandler sh) throws
+ SocketException, IOException
+ {
+ // Create a new stream
+ SOCKStream sockStream = new SOCKStream ();
+
+ // Create a SOCK_Connector (note the constructor does the connect for us)
+ this.sockConnector_ = new SOCKConnector (sockStream,
+ this.hostname_,
+ this.port_);
+ ACE.DEBUG ("Connected to " +
+ sockStream.socket ().getInetAddress ());
+
+ // Set the streams for the new handler
+ sh.setHandle (sockStream);
+ return 0;
+ }
+
+ /**
+ * Bridge method for activating a <SvcHandler>. The default
+ * behavior of this method is to activate the <SvcHandler> by
+ * calling its open() method (which allows the SVC_HANDLER to define
+ * its own concurrency strategy). However, subclasses can override
+ * this strategy to do more sophisticated concurrency activations.
+ *@param sh Svc Handler to activate
+ *@return 0
+ */
+ protected int activateSvcHandler (SvcHandler sh)
+ {
+ sh.open (null);
+ return 0;
+ }
+
+
+ // Port server is listening on
+ private int port_;
+
+ // Server hostname
+ private String hostname_;
+
+ // Our connection factory
+ private SOCKConnector sockConnector_;
+}
diff --git a/java/JACE/Connection/CreationStrategy.java b/java/JACE/Connection/CreationStrategy.java
new file mode 100644
index 00000000000..f4828d5bff5
--- /dev/null
+++ b/java/JACE/Connection/CreationStrategy.java
@@ -0,0 +1,57 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * CreationStrategy.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+/**
+ * Defines the interface for specifying a creation strategy for a
+ * <a href="ACE.Connection.SvcHandler.html#_top_"><tt>SvcHandler</tt></a> to the
+ * <a href="ACE.Connection.StrategyAcceptor.html#_top_"><tt>StrategyAcceptor</tt></a>.
+ * <P>
+ * The default behavior is to make a new SvcHandler. However,
+ * subclasses can override this strategy to perform SvcHandler
+ * creation in any way that they like (such as creating subclass
+ * instances of SvcHandler, using a singleton, dynamically
+ * linking the handler, etc.).
+ *
+ *@see SvcHandler
+ *@see StrategyAcceptor
+ *@see AcceptStrategy
+ *@see ActivateStrategy
+ */
+public class CreationStrategy
+{
+ /**
+ * Create an instance of Creation Strategy.
+ *@param handlerFactory Svc Handler factory that is used to create
+ * an instance of a Svc Handler
+ */
+ public CreationStrategy (Class handlerFactory)
+ {
+ this.handlerFactory_ = handlerFactory;
+ }
+
+ /**
+ * Create a new SvcHandler. Note that subclasses should override
+ * this method to provide a new creation strategy.
+ *@return reference to a new instance of the SvcHandler (or subclass)
+ *@exception InstantiationException Unable to instantiate.
+ *@exception IllegalAccessException No handler factory available.
+ */
+ public SvcHandler makeSvcHandler () throws InstantiationException,
+ IllegalAccessException
+ {
+ // Create a new Svc_Handler
+ return (SvcHandler) handlerFactory_.newInstance ();
+ }
+
+ private Class handlerFactory_;
+}
diff --git a/java/JACE/Connection/HTTPHelper.java b/java/JACE/Connection/HTTPHelper.java
new file mode 100644
index 00000000000..2901d74a14a
--- /dev/null
+++ b/java/JACE/Connection/HTTPHelper.java
@@ -0,0 +1,182 @@
+package JACE.Connection;
+
+import JACE.OS.*;
+
+/**
+ * Collection of methods concerning HTTP.
+ */
+public class HTTPHelper
+{
+ /**
+ * Alphabet used in encoding and decoding basic base64 authentication.
+ * See the HTTP 1.1 RFC for details.
+ */
+ public static String Alphabet
+ = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ /**
+ * Decode a secret encrypted with the basic base64 HTTP 1.1 authentication
+ * scheme.
+ *
+ *@param secret Message to decode
+ *@return null on error, decoded String on success
+ */
+ public static String DecodeBase64 (String secret)
+ {
+ StringBuffer output = new StringBuffer ();
+ boolean inalphabet [] = new boolean[256];
+ char decoder [] = new char [256];
+
+ for (int i = 0; i < 256; i++) {
+ inalphabet [i] = false;
+ decoder [i] = 0;
+ }
+
+ for (int i = Alphabet.length () - 1;
+ i >= 0;
+ i--)
+ {
+ inalphabet [(int)Alphabet.charAt (i)] = true;
+ decoder [(int)Alphabet.charAt (i)] = (char)i;
+ }
+
+ int inidx = 0;
+ int c = 0;
+ int char_count = 0;
+ int bits = 0;
+ boolean error = false;
+
+ while (inidx < secret.length ())
+ {
+ c = secret.charAt (inidx++);
+
+ if (c == '=')
+ break;
+
+ if (c > 255 || !inalphabet[(int)c])
+ continue;
+
+ bits += decoder[c];
+ char_count++;
+ if (char_count == 4) {
+ output.append ((char) (bits >> 16));
+ output.append ((char) ((bits >> 8) & 0xff));
+ output.append ((char) (bits & 0xff));
+ bits = 0;
+ char_count = 0;
+ } else
+ bits <<= 6;
+ }
+
+ if (c == '\0') {
+ if (char_count != 0) {
+ ACE.DEBUG ("base64 encoding incomplete: at least "
+ + ((4 - char_count) * 6) + " bits truncated");
+ error = true;
+ }
+ } else {
+ // c == '='
+ switch (char_count)
+ {
+ case 1:
+ ACE.DEBUG ("output so far: " + output.toString ());
+ ACE.DEBUG ("base64 encoding incomplete: at least 2 bits missing");
+ error = true;
+ break;
+ case 2:
+ output.append ((char) (bits >> 10));
+ break;
+ case 3:
+ output.append ((char) (bits >> 16));
+ output.append ((char) ((bits >> 8) & 0xff));
+ break;
+ }
+ }
+
+ if (!error)
+ return output.toString ();
+ else
+ return null;
+ }
+
+ /**
+ * Encode a message with the basic base64 HTTP 1.1 authentication
+ * scheme. Adapted from James' JAWS HTTP_Helpers code.
+ *
+ *@param secret Message to encode
+ *@return null on error, an encoded String on success
+ */
+ public static String EncodeBase64 (String secret)
+ {
+ StringBuffer output = new StringBuffer ();
+
+ // Index of the input string
+ int inidx = 0;
+
+ // character value
+ int c;
+
+ int char_count = 0;
+ int bits = 0;
+ boolean error = false;
+
+ while (inidx < secret.length())
+ {
+ c = secret.charAt(inidx++);
+
+ // This will mess up internationalization. I wonder if it is really
+ // necessary for HTTP?
+ if (c > 255)
+ {
+ ACE.DEBUG ("encountered char > 255 (decimal %d): " + c);
+ error = true;
+ break;
+ }
+
+ bits += c;
+ char_count++;
+
+ if (char_count == 3)
+ {
+ output.append(HTTPHelper.Alphabet.charAt(bits >> 18));
+ output.append(HTTPHelper.Alphabet.charAt((bits >> 12) & 0x3f));
+ output.append(HTTPHelper.Alphabet.charAt((bits >> 6) & 0x3f));
+ output.append(HTTPHelper.Alphabet.charAt(bits & 0x3f));
+
+ bits = 0;
+ char_count = 0;
+ }
+ else
+ bits <<= 8;
+ }
+
+ if (!error)
+ {
+ if (char_count != 0)
+ {
+ bits <<= 16 - (8 * char_count);
+ output.append(HTTPHelper.Alphabet.charAt(bits >> 18));
+ output.append(HTTPHelper.Alphabet.charAt((bits >> 12) & 0x3f));
+
+ if (char_count == 1)
+ {
+ output.append("==");
+ }
+ else
+ {
+ output.append(HTTPHelper.Alphabet.charAt((bits >> 6) & 0x3f));
+ output.append('=');
+ }
+ }
+
+ return output.toString();
+ }
+
+ // Returns null on error
+ return null;
+ }
+
+ private HTTPHelper () {}
+}
+
+
diff --git a/java/JACE/Connection/StrategyAcceptor.java b/java/JACE/Connection/StrategyAcceptor.java
new file mode 100644
index 00000000000..743d384776f
--- /dev/null
+++ b/java/JACE/Connection/StrategyAcceptor.java
@@ -0,0 +1,174 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * StrategyAcceptor.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.OS.*;
+import JACE.SOCK_SAP.*;
+
+/**
+ * Abstract factory for creating, accepting into, and activating
+ * a service handler.
+ * <P>
+ * Uses instances of CreationStrategy, AcceptStrategy, and
+ * ActivateStrategy.
+ *
+ *@see SvcHandler
+ *@see CreationStrategy
+ *@see AcceptStrategy
+ *@see ActivateStrategy
+ */
+public class StrategyAcceptor extends Acceptor
+{
+ /**
+ * Create an instance of StrategyAcceptor. The caller must
+ * call setHandlerFactory before open!
+ */
+ public StrategyAcceptor ()
+ {
+ this (null, null, null, null);
+ }
+
+ /**
+ * Create an instance of StrategyAcceptor.
+ *@param handlerFactory Svc Handler factory that is used to create
+ * an instance of a Svc Handler when a connection is accepted.
+ */
+ public StrategyAcceptor (Class handlerFactory)
+ {
+ this (handlerFactory, null, null, null);
+ }
+
+ /**
+ * Create an instance of StrategyAcceptor. Use the creation
+ * strategy and the handlerFactory passed in to creae a new instance
+ * of the Svc Handler.
+ *@param handlerFactory Svc Handler factory that is used to create
+ * an instance of a Svc Handler when a connection is accepted.
+ *@param creStrategy Creation strategy to use to create a new
+ * instance of the Svc Handler.
+ *@param acceptStrategy Accept strategy to use to accept a new
+ * connection into the Svc Handler.
+ *@param activateStrategy Activate strategy to use to activate the
+ * instance of the Svc Handler.
+ */
+ public StrategyAcceptor (Class handlerFactory,
+ CreationStrategy creStrategy,
+ AcceptStrategy acceptStrategy,
+ ActivateStrategy activateStrategy)
+ {
+ // Cache everything
+ this.handlerFactory_ = handlerFactory;
+ this.creStrategy_ = creStrategy;
+ this.acceptStrategy_ = acceptStrategy;
+ this.activateStrategy_ = activateStrategy;
+ }
+
+ /**
+ * Initialize the Strategy Acceptor. The method creates the
+ * appropriate strategies as needed.
+ *@param port port number where the server will listen for connections
+ *@exception IOException Socket level error
+ */
+ public void open (int port) throws IOException
+ {
+ if (this.creStrategy_ == null)
+ this.creStrategy_ = new CreationStrategy (this.handlerFactory_);
+ if (this.acceptStrategy_ == null)
+ this.acceptStrategy_ = new AcceptStrategy (port);
+ else
+ this.acceptStrategy_.open (port);
+ if (this.activateStrategy_ == null)
+ this.activateStrategy_ = new ActivateStrategy ();
+ }
+
+ /**
+ * Accept a connection using the appropriate strategies.
+ *
+ *@exception SocketException Socket level error
+ *@exception InstantiationException Problem creating a handler
+ *@exception IllegalAccessException No strategy available
+ *@exception IOException Socket level error
+ */
+ public void accept () throws SocketException,
+ InstantiationException,
+ IllegalAccessException,
+ IOException
+ {
+ // Create a Svc_Handler using the appropriate Creation_Strategy
+ SvcHandler sh = this.makeSvcHandler ();
+
+ // Accept a connection into the Svc_Handler
+ this.acceptSvcHandler (sh);
+
+ // Activate the Svc_Handler
+ this.activateSvcHandler (sh);
+ }
+
+ /**
+ * Bridge method for creating a SvcHandler. The strategy for
+ * creating a SvcHandler is configured into the Acceptor via it's
+ * creStrategy_. If no strategy is passed in, the default behavior
+ * of this method is to use the default CreationStrategy.
+ *@return a new instance of the Svc Handler
+ *@exception InstantiationException Couldn't create SvcHandler
+ *@exception IllegalAccessException No strategy available
+ */
+ protected SvcHandler makeSvcHandler ()
+ throws InstantiationException, IllegalAccessException
+ {
+ // Create a new handler for the connection
+ return this.creStrategy_.makeSvcHandler ();
+ }
+
+
+ /**
+ * Bridge method for accepting the new connection into the
+ * <SvcHandler>. The strategy for accepting into a SvcHandler is
+ * configured into the Acceptor via it's acceptStrategy_. If no
+ * strategy is passed in, the default behavior of this method is to
+ * use the default AcceptStrategy.
+ *@param sh Svc Handler in which to accept the connection
+ *@return result of accepting a connection using the accept strategy
+ *@exception SocketException Socket level error
+ *@exception IOException Socket level error
+ */
+ protected int acceptSvcHandler (SvcHandler sh) throws SocketException, IOException
+ {
+ // Delegate responsibility to the appropriate strategy
+ return this.acceptStrategy_.acceptSvcHandler (sh);
+ }
+
+ /**
+ * Bridge method for activating a <SvcHandler>. The strategy for
+ * activating a SvcHandler is configured into the Acceptor via it's
+ * activateStrategy_. If no strategy is passed in, the default
+ * behavior of this method is to use the default ActivateStrategy.
+ *@param sh Svc Handler to activate
+ *@return result of activating the Svc Handler
+ */
+ protected int activateSvcHandler (SvcHandler sh)
+ {
+ // Delegate responsibility to the appropriate strategy
+ return this.activateStrategy_.activateSvcHandler (sh);
+ }
+
+ // Creation Strategy
+ private CreationStrategy creStrategy_;
+
+ // Accept Strategy
+ private AcceptStrategy acceptStrategy_;
+
+ // Activation Strategy
+ private ActivateStrategy activateStrategy_;
+}
diff --git a/java/JACE/Connection/SvcHandler.java b/java/JACE/Connection/SvcHandler.java
new file mode 100644
index 00000000000..1df62247baa
--- /dev/null
+++ b/java/JACE/Connection/SvcHandler.java
@@ -0,0 +1,101 @@
+/*************************************************
+ *
+ * = PACKAGE
+ * JACE.Connection
+ *
+ * = FILENAME
+ * SvcHandler.java
+ *
+ *@author Prashant Jain
+ *
+ *************************************************/
+package JACE.Connection;
+
+import java.io.*;
+import java.net.*;
+import JACE.SOCK_SAP.*;
+import JACE.ASX.*;
+import JACE.Reactor.*;
+
+/**
+ * Defines the interface for a service that exchanges data with its
+ * connected peer.
+ * <P>
+ * This class provides a well-defined interface that the Acceptor and
+ * Connector pattern factories use as their target. Typically, client
+ * applications will subclass SvcHandler and do all the interesting work
+ * in the subclass. One thing that the SvcHandler does contain is a
+ * peer SOCKStream endpoint that is initialized by Acceptor or Connector
+ * when a connection is established successfully. This endpoint is used
+ * to exchange data between a SvcHandler and the peer it is connected
+ * with.
+ */
+public abstract class SvcHandler extends Task
+{
+
+ /**
+ * Do nothing constructor.
+ */
+ public SvcHandler ()
+ {
+ }
+
+ /**
+ * Set the stream using the SOCKStream passed in. This sets the
+ * underlying peer
+ *@param s SOCK Stream to use for the connection
+ */
+ public void setHandle (SOCKStream s) throws IOException
+ {
+ this.stream_ = s;
+ }
+
+ /**
+ * Get the underlying peer
+ *@return the underlying peer
+ */
+ public SOCKStream peer ()
+ {
+ return this.stream_;
+ }
+
+ /**
+ * Abstract method that subclasses must define to allow
+ * initialization to take place.
+ */
+ public abstract int open (Object obj);
+
+ /**
+ * Provide a default implementation to simplify ancestors.
+ *@return 0
+ */
+ public int close (long flags)
+ {
+ return 0;
+ }
+
+ /**
+ * Provide a default implementation to simplify ancestors.
+ *@return -1
+ */
+ public int put (MessageBlock mb, TimeValue tv)
+ {
+ return -1;
+ }
+
+ /**
+ * Provide a default implementation to simplify ancestors.
+ *@param tv Time Value when the event occured
+ *@param obj An arbitrary object that was passed to the Timer Queue
+ * (Asynchronous Completion Token)
+ */
+ public int handleTimeout (TimeValue tv, Object obj)
+ {
+ return -1;
+ }
+
+ /**
+ * Underlying peer socket stream.
+ */
+ protected SOCKStream stream_;
+}
diff --git a/java/JACE/Connection/package.html b/java/JACE/Connection/package.html
new file mode 100644
index 00000000000..429904216d5
--- /dev/null
+++ b/java/JACE/Connection/package.html
@@ -0,0 +1,7 @@
+<!-- $Id$ -->
+<HTML>
+<BODY>
+Collection of factories for services.
+@see <a href="http://www.cs.wustl.edu/~schmidt/ACE-papers.html#initialize">Documents on ACE object and service initialization components</a>
+</BODY>
+</HTML>