xml-rpc-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Daniel Rall <...@finemaltcoding.com>
Subject Re: system.multicall()
Date Wed, 14 Aug 2002 17:44:21 GMT
Adam, I added your handler and associated to XmlRpcServer refactoring
to CVS HEAD (thanks).  I haven't yet looked at the auth changes.

I explicitly didn't add the automatic addition of the system.multicall
handler to the XmlRpcServer class, as I don't think it currently adds
any handler by default and am hoping to keep it that way.  The
multicall handler needs a reference to the XmlRpcServer to perform the
multiple RPC calls; I assume this is why you set things up this way.
Any ideas on avoiding this issue?

- Dan


Adam Megacz <adam@megacz.com> writes:

> Here's the patch for system.multicall(), plus a new file it adds
> (SystemMethods.java). This patch also includes my last patch for HTTP
> Basic authentication.
> 
>   - a
> 
> ______________________________________________________________________________
> org/apache/xmlrpc/SystemMethods.java
> 
> package org.apache.xmlrpc;
> 
> /*
>  * The Apache Software License, Version 1.1
>  *
>  *
>  * Copyright(c) 2001 The Apache Software Foundation.  All rights
>  * reserved.
>  *
>  * Redistribution and use in source and binary forms, with or without
>  * modification, are permitted provided that the following conditions
>  * are met:
>  *
>  * 1. Redistributions of source code must retain the above copyright
>  *    notice, this list of conditions and the following disclaimer.
>  *
>  * 2. Redistributions in binary form must reproduce the above copyright
>  *    notice, this list of conditions and the following disclaimer in
>  *    the documentation and/or other materials provided with the
>  *    distribution.
>  *
>  * 3. The end-user documentation included with the redistribution,
>  *    if any, must include the following acknowledgment:
>  *       "This product includes software developed by the
>  *        Apache Software Foundation(http://www.apache.org/)."
>  *    Alternately, this acknowledgment may appear in the software itself,
>  *    if and wherever such third-party acknowledgments normally appear.
>  *
>  * 4. The names "XML-RPC" and "Apache Software Foundation" must
>  *    not be used to endorse or promote products derived from this
>  *    software without prior written permission. For written
>  *    permission, please contact apache@apache.org.
>  *
>  * 5. Products derived from this software may not be called "Apache",
>  *    nor may "Apache" appear in their name, without prior written
>  *    permission of the Apache Software Foundation.
>  *
>  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
>  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
>  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
>  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
>  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
>  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT
>  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
>  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
>  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
>  * OR TORT(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
>  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>  * SUCH DAMAGE.
>  * ====================================================================
>  *
>  * This software consists of voluntary contributions made by many
>  * individuals on behalf of the Apache Software Foundation.  For more
>  * information on the Apache Software Foundation, please see
>  * <http://www.apache.org/>.
>  */
> 
> import org.apache.xmlrpc.*;
> import java.util.*;
> 
> /** Implements the XML-RPC standard system.* methods */
> public class SystemMethods {
> 
>     XmlRpcServer serv = null;
> 
>     SystemMethods(XmlRpcServer serv) { this.serv = serv; }
> 
>     public Vector multicall(Vector in) {
>         Vector ret = new Vector();
>         for(int i=0; i<in.size(); i++) {
>             try {
>                 Hashtable call = (Hashtable)in.elementAt(i);
>                 String methodName = (String)call.get("methodName");
>                 Vector params = (Vector)call.get("params");
>                 Object handler = serv.getHandler(methodName);
>                 Vector v = new Vector();
>                 v.addElement(serv.invokeHandler(handler, methodName, params, null, null));
>                 ret.addElement(v);
>             } catch (Exception x) {
>                 String message = x.toString();
>                 int code = x instanceof XmlRpcException ? ((XmlRpcException) x).code
: 0;
>                 Hashtable h = new Hashtable();
>                 h.put("faultString", message);
>                 h.put("faultCode", new Integer(code));
>                 ret.addElement(h);
>             }
>         }
>         return ret;
>     }
>     
> }
> 
> 
> 
> 
> ______________________________________________________________________________
> patch
> 
> Index: src/java/org/apache/xmlrpc/WebServer.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
> retrieving revision 1.13
> diff -u -r1.13 WebServer.java
> --- src/java/org/apache/xmlrpc/WebServer.java	13 Aug 2002 22:27:16 -0000	1.13
> +++ src/java/org/apache/xmlrpc/WebServer.java	14 Aug 2002 04:24:39 -0000
> @@ -94,6 +94,7 @@
>      protected static final byte[] conclose = "Connection: close\r\n".getBytes();
>      protected static final byte[] ok = " 200 OK\r\n".getBytes();
>      protected static final byte[] server = "Server: Apache XML-RPC 1.0\r\n".getBytes();
> +    protected static final byte[] www_authenticate = "WWW-Authenticate: Basic realm=XMLRPC\r\n".getBytes();
>  
>      private static final String HTTP_11 = "HTTP/1.1";
>      private static final String STAR = "*";
> @@ -584,29 +585,40 @@
>                      {
>                          ServerInputStream sin = new ServerInputStream(input,
>                                  contentLength);
> -                        byte result[] = xmlrpc.execute(sin, user, password);
> -                        output.write(httpversion.getBytes());
> -                        output.write(ok);
> -                        output.write(server);
> -                        if (keepalive)
> -                        {
> -                            output.write(conkeep);
> -                        }
> -                        else
> -                        {
> -                            output.write (conclose);
> +                        try {
> +                            byte result[] = xmlrpc.execute(sin, user, password);
> +                            output.write(httpversion.getBytes());
> +                            output.write(ok);
> +                            output.write(server);
> +                            if (keepalive)
> +                                {
> +                                    output.write(conkeep);
> +                                }
> +                            else
> +                                {
> +                                    output.write (conclose);
> +                                }
> +                            output.write(ctype);
> +                            output.write(clength);
> +                            output.write(Integer.toString(result.length)
> +                                         .getBytes());
> +                            output.write(doubleNewline);
> +                            output.write(result);
> +                        } catch (XmlRpcServer.AuthenticationRequiredException are) {
> +                            output.write("HTTP/1.0".getBytes());
> +                            output.write(" 401 Unauthorized\r\n".getBytes());
> +                            output.write(server);
> +                            output.write(www_authenticate);
> +                            output.write("\r\n".getBytes());
> +                            output.write(("Method " + method
> +                                          + " requires a username and password").getBytes());
> +                            keepalive = false;
>                          }
> -                        output.write(ctype);
> -                        output.write(clength);
> -                        output.write(Integer.toString(result.length)
> -                                .getBytes());
> -                        output.write(doubleNewline);
> -                        output.write(result);
>                          output.flush();
>                      }
>                      else
>                      {
> -                        output.write(httpversion.getBytes());
> +                        output.write("HTTP/1.0".getBytes());
>                          output.write(" 400 Bad Request\r\n".getBytes());
>                          output.write(server);
>                          output.write("\r\n".getBytes());
> Index: src/java/org/apache/xmlrpc/XmlRpcServer.java
> ===================================================================
> RCS file: /home/cvspublic/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcServer.java,v
> retrieving revision 1.28
> diff -u -r1.28 XmlRpcServer.java
> --- src/java/org/apache/xmlrpc/XmlRpcServer.java	9 Aug 2002 09:14:24 -0000	1.28
> +++ src/java/org/apache/xmlrpc/XmlRpcServer.java	14 Aug 2002 04:24:41 -0000
> @@ -93,6 +93,7 @@
>          handlers = new Hashtable();
>          pool = new Stack();
>          workers = 0;
> +        addHandler("system", new SystemMethods(this));
>      }
>  
>      /**
> @@ -136,6 +137,7 @@
>       * since this is all packed into the response.
>       */
>      public byte[] execute(InputStream is)
> +        throws AuthenticationRequiredException
>      {
>          return execute(is, null, null);
>      }
> @@ -146,6 +148,7 @@
>       * use the credentials to authenticate the user.
>       */
>      public byte[] execute(InputStream is, String user, String password)
> +        throws AuthenticationRequiredException
>      {
>          Worker worker = getWorker();
>          byte[] retval = worker.execute(is, user, password);
> @@ -179,6 +182,61 @@
>          }
>      }
>  
> +    /** find the handler for a given method */
> +    Object getHandler(String methodName) throws Exception {
> +        Object handler = null;
> +        String handlerName = null;
> +        int dot = methodName.lastIndexOf('.');
> +        if (dot > -1)
> +            {
> +                handlerName = methodName.substring(0, dot);
> +                handler = handlers.get(handlerName);
> +                if (handler != null)
> +                    {
> +                        methodName = methodName.substring(dot + 1);
> +                    }
> +            }
> +        
> +        if (handler == null)
> +            {
> +                handler = handlers.get("$default");
> +            }
> +        
> +        if (handler == null)
> +            {
> +                if (dot > -1)
> +                    {
> +                        throw new Exception("RPC handler object \""
> +                                            + handlerName + "\" not found and no default
"
> +                                            + "handler registered.");
> +                    }
> +                else
> +                    {
> +                        throw new Exception("RPC handler object not found for \""
> +                                            + methodName
> +                                            + "\": no default handler registered.");
> +                    }
> +            }
> +        
> +        return handler;
> +    }
> +    
> +    Object invokeHandler(Object handler, String methodName,
> +                         Vector inParams, String user, String password)
> +        throws Exception {
> +        if (handler instanceof AuthenticatedXmlRpcHandler)
> +            {
> +                if (user == null) throw new XmlRpcServer.AuthenticationRequiredException();
> +                return ((AuthenticatedXmlRpcHandler) handler)
> +                    .execute(methodName, inParams, user, password);
> +            }
> +        else
> +            {
> +                return ((XmlRpcHandler) handler).execute(methodName, inParams);
> +            }
> +    }
> +
> +
>      /**
>       * Performs streaming, parsing, and handler execution.
>       * Implementation is not thread-safe.
> @@ -202,6 +260,7 @@
>           * Given a request for the server, generates a response.
>           */
>          public byte[] execute(InputStream is, String user, String password)
> +            throws AuthenticationRequiredException
>          {
>              try
>              {
> @@ -223,10 +282,10 @@
>           * @param password
>           * @return
>           */
> -        private byte[] executeInternal(InputStream is, String user,
> -                String password)
> +        byte[] executeInternal(InputStream is, String user,
> +                String password) throws AuthenticationRequiredException
>          {
> -            byte[] result;
> +            byte[] result = null;
>              long now = 0;
>  
>              if (XmlRpc.debug)
> @@ -246,63 +305,20 @@
>                  {
>                      throw new Exception(errorMsg);
>                  }
> -                Object handler = null;
> -
> -                String handlerName = null;
> -                int dot = methodName.lastIndexOf('.');
> -                if (dot > -1)
> -                {
> -                    handlerName = methodName.substring(0, dot);
> -                    handler = handlers.get(handlerName);
> -                    if (handler != null)
> -                    {
> -                        methodName = methodName.substring(dot + 1);
> -                    }
> -                }
> -
> -                if (handler == null)
> -                {
> -                    handler = handlers.get("$default");
> -                }
>  
> -                if (handler == null)
> -                {
> -                    if (dot > -1)
> -                    {
> -                        throw new Exception("RPC handler object \""
> -                                + handlerName + "\" not found and no default "
> -                                + "handler registered.");
> -                    }
> -                    else
> -                    {
> -                        throw new Exception("RPC handler object not found for \""
> -                                + methodName
> -                                + "\": no default handler registered.");
> -                    }
> -                }
> +                Object handler = getHandler(methodName);
> +                Object outParam = invokeHandler(handler, methodName, inParams, user,
password);
>  
> -                Object outParam;
> -                if (handler instanceof AuthenticatedXmlRpcHandler)
> -                {
> -                    outParam =((AuthenticatedXmlRpcHandler) handler)
> -                            .execute(methodName, inParams, user, password);
> -                }
> -                else
> -                {
> -                    outParam =((XmlRpcHandler) handler)
> -                            .execute(methodName, inParams);
> -                }
>                  if (XmlRpc.debug)
>                  {
>                      System.out.println("outparam = " + outParam);
>                  }
> -                writer = new XmlWriter(buffer, encoding);
> -                writeResponse(outParam, writer);
> -                writer.flush();
> -                result = buffer.toByteArray();
>              }
>              catch(Exception x)
>              {
> +                if (x instanceof XmlRpcServer.AuthenticationRequiredException)
> +                    throw (XmlRpcServer.AuthenticationRequiredException)x;
> +
>                  if (XmlRpc.debug)
>                  {
>                      x.printStackTrace();
> @@ -427,6 +443,11 @@
>              writer.endElement("methodResponse");
>          }
>      } // end of inner class Worker
> +
> +    public static class AuthenticationRequiredException extends IOException {
> +        AuthenticationRequiredException() { }
> +    }
> +
>  } // XmlRpcServer
>  
>  /**
> @@ -555,4 +576,6 @@
>          }
>          return returnValue;
>      }
> +
>  }
> +
> 

-- 

Daniel Rall <dlr@finemaltcoding.com>

Mime
View raw message