Coverage Report - net.wotonomy.web.xml.XMLRPCServlet
 
Classes in this File Line Coverage Branch Coverage Complexity
XMLRPCServlet
0% 
0% 
2
 
 1  
 /*
 2  
 Wotonomy: OpenStep design patterns for pure Java applications.
 3  
 Copyright (C) 2001 Intersect Software Corporation
 4  
 
 5  
 This library is free software; you can redistribute it and/or
 6  
 modify it under the terms of the GNU Lesser General Public
 7  
 License as published by the Free Software Foundation; either
 8  
 version 2.1 of the License, or (at your option) any later version.
 9  
 
 10  
 This library is distributed in the hope that it will be useful,
 11  
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 12  
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 13  
 Lesser General Public License for more details.
 14  
 
 15  
 You should have received a copy of the GNU Lesser General Public
 16  
 License along with this library; if not, see http://www.gnu.org
 17  
 */
 18  
 
 19  
 package net.wotonomy.web.xml;
 20  
 
 21  
 import java.io.ByteArrayInputStream;
 22  
 import java.io.ByteArrayOutputStream;
 23  
 import java.io.IOException;
 24  
 import java.io.InputStream;
 25  
 import java.io.OutputStream;
 26  
 import java.util.Hashtable;
 27  
 
 28  
 import javax.servlet.ServletException;
 29  
 import javax.servlet.http.HttpServlet;
 30  
 import javax.servlet.http.HttpServletRequest;
 31  
 import javax.servlet.http.HttpServletResponse;
 32  
 
 33  
 import net.wotonomy.foundation.NSSelector;
 34  
 import net.wotonomy.foundation.internal.WotonomyException;
 35  
 
 36  
 /**
 37  
 * A servlet that can make any java object into an XML-RPC server.
 38  
 * Simply pass in the object to the constructor and XML-RPC requests
 39  
 * to this servlet will call the appropriate methods and convert
 40  
 * the results to an XML-RPC response. <br><br>
 41  
 *
 42  
 * Depending on your servlet container, it may be necessary to 
 43  
 * create a simple subclass that creates your handler object
 44  
 * in its constructor and then calls setHandler(). <br><br>
 45  
 *
 46  
 * Responses are in the specification's standard response format.<br><br>
 47  
 *
 48  
 * Faults are returned if any exception is thrown in the method,
 49  
 * or if the specified method is not found on the object.
 50  
 * The fault string is the toString value of the exception,
 51  
 * and the fault code is the hasCode value of the exception. <br><br>
 52  
 *
 53  
 * Remember that this servlet only responds to POSTs, 
 54  
 * per the XML-RPC spec.  
 55  
 */
 56  
 public class XMLRPCServlet extends HttpServlet 
 57  
 {
 58  
     protected Object handler;
 59  
     protected boolean synchronizing;
 60  0
     private Hashtable selectorCache = new Hashtable(); // thread safe
 61  0
     private boolean copyStream = false;
 62  
     
 63  
     /**
 64  
     * Default constructor initializes internal state.
 65  
     */
 66  0
     public XMLRPCServlet()
 67  0
     {
 68  0
         handler = null;
 69  0
         synchronizing = false;
 70  0
     }
 71  
     
 72  
     /**
 73  
     * Constructor takes any java object and allows its methods
 74  
     * to be invoked via XMLRPC requests to this servlet.
 75  
     * Simply calls setHandler().
 76  
     */
 77  
     public XMLRPCServlet( Object aHandler )
 78  
     {
 79  0
         this();
 80  0
         setHandler( aHandler );
 81  0
     }
 82  
     
 83  
     /**
 84  
     * Gets the object whose methods will be invoked to
 85  
     * handle incoming requests.
 86  
     */
 87  
     public Object getHandler()
 88  
     {
 89  0
         return handler;
 90  
     }
 91  
     
 92  
     /**
 93  
     * Sets the object whose methods will be invoked to
 94  
     * handle incoming requests.
 95  
     */
 96  
     public void setHandler( Object aHandler )
 97  
     {
 98  0
         handler = aHandler;
 99  0
     }
 100  
     
 101  
     /**
 102  
     * Gets whether the servlet should synchonize on the
 103  
     * object before invoking methods on it.
 104  
     * Defaults to false.
 105  
     */
 106  
     public boolean isSynchronizing()
 107  
     {
 108  0
         return synchronizing;
 109  
     }
 110  
     
 111  
     /**
 112  
     * Sets whether the servlet should synchonize on the
 113  
     * object before invoking methods on it.
 114  
     * Defaults to false.
 115  
     */
 116  
     public void setSynchronizing( boolean willSynchronize )
 117  
     {
 118  0
         synchronizing = willSynchronize;
 119  0
     }
 120  
     
 121  
     /**
 122  
     * Overridden to service the request.
 123  
     */
 124  
     protected void doPost(
 125  
         HttpServletRequest req, HttpServletResponse resp) 
 126  
     throws ServletException, IOException
 127  
     {
 128  0
         if ( getHandler() != null )
 129  
         {
 130  0
             InputStream input = req.getInputStream();
 131  0
             byte[] copyOfRequest = null;
 132  
 
 133  0
             if ( copyStream )
 134  
             {
 135  0
                 ByteArrayOutputStream byteArray =
 136  0
                     new ByteArrayOutputStream();
 137  
                 int b;
 138  0
                 while ( ( b = input.read() ) != -1 )
 139  
                 {
 140  0
                     byteArray.write( b );
 141  0
                 }
 142  0
                 copyOfRequest = byteArray.toByteArray();
 143  0
                 input = new ByteArrayInputStream( copyOfRequest );
 144  
             }
 145  
             
 146  
             try
 147  
             {
 148  0
                 new XMLRPCDecoder().decode( input, 
 149  0
                     new Receiver( this, resp ) );
 150  
             }
 151  0
             catch ( WotonomyException exc )
 152  
             {
 153  0
                 if ( copyOfRequest != null )
 154  
                 {
 155  0
                     System.out.println( new String( copyOfRequest ) );
 156  0
                     exc.printStackTrace();
 157  
                 }
 158  
                 // catches io exceptions thrown in handleRequest.
 159  0
                 Throwable t = exc.getWrappedThrowable();
 160  0
                 if ( t instanceof IOException )
 161  
                 {
 162  0
                     throw (IOException)t;
 163  
                 }
 164  0
                 throw exc;
 165  0
             }
 166  
         }
 167  0
     }
 168  
     
 169  
     /**
 170  
     * Called by doPost after parsing an incoming request,
 171  
     * and is responsible for invoking the specified method
 172  
     * with the specified parameters on the handler object.
 173  
     * (This implementation calls getOutputStream() on the response.)
 174  
     * Override to customize the handling of the request.
 175  
     */
 176  
     protected void handleRequest( String aMethodName, 
 177  
         Object[] aParameterArray, HttpServletResponse aResponse )
 178  
     {
 179  0
         OutputStream output = null;
 180  
         
 181  
         try 
 182  
         {
 183  0
             output = aResponse.getOutputStream();
 184  0
             aResponse.setStatus( HttpServletResponse.SC_OK ); // always 200
 185  0
             aResponse.setContentType( "text/xml" );
 186  
         }
 187  0
         catch ( IOException exc )
 188  
         {
 189  
             // caught in doPost
 190  0
             throw new WotonomyException( exc );   
 191  0
         }
 192  
         
 193  
         // get the array of types
 194  0
         XMLRPCEncoder encoder = new XMLRPCEncoder();
 195  0
         Class[] types = new Class[ aParameterArray.length ];
 196  0
         for ( int i = 0; i < aParameterArray.length; i++ )
 197  
         {
 198  0
             types[i] = aParameterArray[i].getClass();
 199  
         }
 200  
         
 201  
         //TODO: selectors should be cached if possible
 202  
         
 203  0
         Object handler = getHandler();
 204  0
         if ( isSynchronizing() )
 205  
         {
 206  0
             synchronized ( handler )
 207  
             {
 208  0
                 execute( encoder, handler, output,
 209  0
                     new NSSelector( aMethodName, types ), aParameterArray );
 210  0
             }
 211  0
         }
 212  
         else
 213  
         {
 214  0
             execute( encoder, handler, output,
 215  0
                 new NSSelector( aMethodName, types ), aParameterArray );
 216  
         }
 217  0
     }
 218  
     
 219  
     private void execute( XMLRPCEncoder anEncoder, Object aHandler, 
 220  
         OutputStream output, NSSelector aSelector, Object[] aParameterArray )
 221  
     {
 222  
         try 
 223  
         {
 224  0
             Object result = 
 225  0
                 aSelector.invoke( aHandler, aParameterArray );
 226  0
             anEncoder.encodeResponse( result, output );
 227  
         }
 228  0
         catch ( Exception exc )
 229  
         {
 230  0
             anEncoder.encodeFault( 
 231  0
                 exc.hashCode(), exc.toString(), output );
 232  0
         }
 233  0
     }
 234  
     
 235  
     private class Receiver implements XMLRPCReceiver
 236  
     {
 237  
         XMLRPCServlet controller;
 238  
         HttpServletResponse response;
 239  
         
 240  0
         public Receiver( 
 241  
             XMLRPCServlet aController,
 242  
             HttpServletResponse aResponse )
 243  0
         {
 244  0
             controller = aController;
 245  0
             response = aResponse;
 246  0
         }
 247  
         
 248  
         public void request( 
 249  
             String aMethodName, Object[] aParameterArray )
 250  
         {
 251  0
             controller.handleRequest( 
 252  0
                 aMethodName, aParameterArray, response );
 253  0
         }
 254  
         
 255  
         public void response( 
 256  
             Object aResult ) 
 257  
         {
 258  
             // does nothing
 259  0
         }
 260  
         
 261  
         public void fault( 
 262  
             int aFaultCode, String aFaultString)
 263  
         {
 264  
             // does nothing
 265  0
         }
 266  
     }
 267  
 }
 268  
 
 269  
 /*
 270  
  * $Log$
 271  
  * Revision 1.1  2006/02/19 01:44:02  cgruber
 272  
  * Add xmlrpc files
 273  
  * Remove jclark and replace with dom4j and javax.xml.sax stuff
 274  
  * Re-work dependencies and imports so it all compiles.
 275  
  *
 276  
  * Revision 1.1  2006/02/16 13:22:22  cgruber
 277  
  * Check in all sources in eclipse-friendly maven-enabled packages.
 278  
  *
 279  
  * Revision 1.1  2001/02/07 19:24:28  mpowers
 280  
  * Moved XML classes to separate package.
 281  
  *
 282  
  */
 283