summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java
diff options
context:
space:
mode:
Diffstat (limited to 'projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java')
-rw-r--r--projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java283
1 files changed, 283 insertions, 0 deletions
diff --git a/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java
new file mode 100644
index 0000000..a9981a4
--- /dev/null
+++ b/projects/net.wotonomy.web/src/main/java/net/wotonomy/web/xml/XMLRPCServlet.java
@@ -0,0 +1,283 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2001 Intersect Software Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+
+package net.wotonomy.web.xml;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Hashtable;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import net.wotonomy.foundation.NSSelector;
+import net.wotonomy.foundation.internal.WotonomyException;
+
+/**
+* A servlet that can make any java object into an XML-RPC server.
+* Simply pass in the object to the constructor and XML-RPC requests
+* to this servlet will call the appropriate methods and convert
+* the results to an XML-RPC response. <br><br>
+*
+* Depending on your servlet container, it may be necessary to
+* create a simple subclass that creates your handler object
+* in its constructor and then calls setHandler(). <br><br>
+*
+* Responses are in the specification's standard response format.<br><br>
+*
+* Faults are returned if any exception is thrown in the method,
+* or if the specified method is not found on the object.
+* The fault string is the toString value of the exception,
+* and the fault code is the hasCode value of the exception. <br><br>
+*
+* Remember that this servlet only responds to POSTs,
+* per the XML-RPC spec.
+*/
+public class XMLRPCServlet extends HttpServlet
+{
+ protected Object handler;
+ protected boolean synchronizing;
+ private Hashtable selectorCache = new Hashtable(); // thread safe
+ private boolean copyStream = false;
+
+ /**
+ * Default constructor initializes internal state.
+ */
+ public XMLRPCServlet()
+ {
+ handler = null;
+ synchronizing = false;
+ }
+
+ /**
+ * Constructor takes any java object and allows its methods
+ * to be invoked via XMLRPC requests to this servlet.
+ * Simply calls setHandler().
+ */
+ public XMLRPCServlet( Object aHandler )
+ {
+ this();
+ setHandler( aHandler );
+ }
+
+ /**
+ * Gets the object whose methods will be invoked to
+ * handle incoming requests.
+ */
+ public Object getHandler()
+ {
+ return handler;
+ }
+
+ /**
+ * Sets the object whose methods will be invoked to
+ * handle incoming requests.
+ */
+ public void setHandler( Object aHandler )
+ {
+ handler = aHandler;
+ }
+
+ /**
+ * Gets whether the servlet should synchonize on the
+ * object before invoking methods on it.
+ * Defaults to false.
+ */
+ public boolean isSynchronizing()
+ {
+ return synchronizing;
+ }
+
+ /**
+ * Sets whether the servlet should synchonize on the
+ * object before invoking methods on it.
+ * Defaults to false.
+ */
+ public void setSynchronizing( boolean willSynchronize )
+ {
+ synchronizing = willSynchronize;
+ }
+
+ /**
+ * Overridden to service the request.
+ */
+ protected void doPost(
+ HttpServletRequest req, HttpServletResponse resp)
+ throws ServletException, IOException
+ {
+ if ( getHandler() != null )
+ {
+ InputStream input = req.getInputStream();
+ byte[] copyOfRequest = null;
+
+ if ( copyStream )
+ {
+ ByteArrayOutputStream byteArray =
+ new ByteArrayOutputStream();
+ int b;
+ while ( ( b = input.read() ) != -1 )
+ {
+ byteArray.write( b );
+ }
+ copyOfRequest = byteArray.toByteArray();
+ input = new ByteArrayInputStream( copyOfRequest );
+ }
+
+ try
+ {
+ new XMLRPCDecoder().decode( input,
+ new Receiver( this, resp ) );
+ }
+ catch ( WotonomyException exc )
+ {
+ if ( copyOfRequest != null )
+ {
+ System.out.println( new String( copyOfRequest ) );
+ exc.printStackTrace();
+ }
+ // catches io exceptions thrown in handleRequest.
+ Throwable t = exc.getWrappedThrowable();
+ if ( t instanceof IOException )
+ {
+ throw (IOException)t;
+ }
+ throw exc;
+ }
+ }
+ }
+
+ /**
+ * Called by doPost after parsing an incoming request,
+ * and is responsible for invoking the specified method
+ * with the specified parameters on the handler object.
+ * (This implementation calls getOutputStream() on the response.)
+ * Override to customize the handling of the request.
+ */
+ protected void handleRequest( String aMethodName,
+ Object[] aParameterArray, HttpServletResponse aResponse )
+ {
+ OutputStream output = null;
+
+ try
+ {
+ output = aResponse.getOutputStream();
+ aResponse.setStatus( HttpServletResponse.SC_OK ); // always 200
+ aResponse.setContentType( "text/xml" );
+ }
+ catch ( IOException exc )
+ {
+ // caught in doPost
+ throw new WotonomyException( exc );
+ }
+
+ // get the array of types
+ XMLRPCEncoder encoder = new XMLRPCEncoder();
+ Class[] types = new Class[ aParameterArray.length ];
+ for ( int i = 0; i < aParameterArray.length; i++ )
+ {
+ types[i] = aParameterArray[i].getClass();
+ }
+
+ //TODO: selectors should be cached if possible
+
+ Object handler = getHandler();
+ if ( isSynchronizing() )
+ {
+ synchronized ( handler )
+ {
+ execute( encoder, handler, output,
+ new NSSelector( aMethodName, types ), aParameterArray );
+ }
+ }
+ else
+ {
+ execute( encoder, handler, output,
+ new NSSelector( aMethodName, types ), aParameterArray );
+ }
+ }
+
+ private void execute( XMLRPCEncoder anEncoder, Object aHandler,
+ OutputStream output, NSSelector aSelector, Object[] aParameterArray )
+ {
+ try
+ {
+ Object result =
+ aSelector.invoke( aHandler, aParameterArray );
+ anEncoder.encodeResponse( result, output );
+ }
+ catch ( Exception exc )
+ {
+ anEncoder.encodeFault(
+ exc.hashCode(), exc.toString(), output );
+ }
+ }
+
+ private class Receiver implements XMLRPCReceiver
+ {
+ XMLRPCServlet controller;
+ HttpServletResponse response;
+
+ public Receiver(
+ XMLRPCServlet aController,
+ HttpServletResponse aResponse )
+ {
+ controller = aController;
+ response = aResponse;
+ }
+
+ public void request(
+ String aMethodName, Object[] aParameterArray )
+ {
+ controller.handleRequest(
+ aMethodName, aParameterArray, response );
+ }
+
+ public void response(
+ Object aResult )
+ {
+ // does nothing
+ }
+
+ public void fault(
+ int aFaultCode, String aFaultString)
+ {
+ // does nothing
+ }
+ }
+}
+
+/*
+ * $Log$
+ * Revision 1.1 2006/02/19 01:44:02 cgruber
+ * Add xmlrpc files
+ * Remove jclark and replace with dom4j and javax.xml.sax stuff
+ * Re-work dependencies and imports so it all compiles.
+ *
+ * Revision 1.1 2006/02/16 13:22:22 cgruber
+ * Check in all sources in eclipse-friendly maven-enabled packages.
+ *
+ * Revision 1.1 2001/02/07 19:24:28 mpowers
+ * Moved XML classes to separate package.
+ *
+ */
+