You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xmlrpc-dev@ws.apache.org by jo...@apache.org on 2002/02/19 03:25:02 UTC

cvs commit: xml-rpc/src/java/org/apache/xmlrpc Base64.java ServerInputStream.java WebServer.java XmlRpc.java XmlRpcClient.java

jon         02/02/18 18:25:02

  Modified:    src/java/org/apache/xmlrpc Base64.java
                        ServerInputStream.java WebServer.java XmlRpc.java
                        XmlRpcClient.java
  Log:
  I did a bunch of code cleanup and minor
  optimizations, switched to the catalina Base64 (note the one FIXME, if
  someone has a suggestion for a better way, let me know).
  
  Found a couple optimizations (such as not calling System.currentTimeMillis()
  unless debug is on...
  
  Revision  Changes    Path
  1.2       +271 -275  xml-rpc/src/java/org/apache/xmlrpc/Base64.java
  
  Index: Base64.java
  ===================================================================
  RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- Base64.java	20 Jul 2001 19:38:16 -0000	1.1
  +++ Base64.java	19 Feb 2002 02:25:01 -0000	1.2
  @@ -1,326 +1,322 @@
   package org.apache.xmlrpc;
   
  -// We can replace this with some apache code I'm sure. jvz.
  -
  -//////////////////////license & copyright header/////////////////////////
  -//                                                                     //
  -//    Base64 - encode/decode data using the Base64 encoding scheme     //
  -//                                                                     //
  -//                Copyright (c) 1998 by Kevin Kelley                   //
  -//                                                                     //
  -// 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, write to the Free Software //
  -// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA           //
  -// 02111-1307, USA, or contact the author:                             //
  -//                                                                     //
  -// Kevin Kelley <ke...@ruralnet.net> - 30718 Rd. 28, La Junta, CO,    //
  -// 81050  USA.                                                         //
  -//                                                                     //
  -////////////////////end license & copyright header///////////////////////
  -
  -import java.io.*; // needed only for main() method.
  -
  +/*
  + * $Header: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
  + * $Revision: 1.2 $
  + * $Date: 2002/02/19 02:25:01 $
  + *
  + * ====================================================================
  + *
  + * The Apache Software License, Version 1.1
  + *
  + * Copyright (c) 1999 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 acknowlegement:
  + *       "This product includes software developed by the
  + *        Apache Software Foundation (http://www.apache.org/)."
  + *    Alternately, this acknowlegement may appear in the software itself,
  + *    if and wherever such third-party acknowlegements normally appear.
  + *
  + * 4. The names "The Jakarta Project", "Tomcat", 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 names without prior written
  + *    permission of the Apache Group.
  + *
  + * 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/>.
  + *
  + * [Additional notices, if required by prior licensing conditions]
  + *
  + */
   
   /**
  -*   Provides encoding of raw bytes to base64-encoded characters, and
  -*  decoding of base64 characters to raw bytes.
  -*
  -* @author Kevin Kelley (kelley@ruralnet.net)
  -* @version 1.3
  -* @date 06 August 1998
  -* @modified 14 February 2000
  -* @modified 22 September 2000
  -*/
  -public class Base64
  + * This class provides encode/decode for RFC 2045 Base64 as defined by
  + * RFC 2045, N. Freed and N. Borenstein.  <a
  + * href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>:
  + * Multipurpose Internet Mail Extensions (MIME) Part One: Format of
  + * Internet Message Bodies. Reference 1996
  + *
  + * @author Jeffrey Rodriguez
  + * @version $Id: Base64.java,v 1.2 2002/02/19 02:25:01 jon Exp $
  + */
  +public final class  Base64
   {
  +    static private final int  BASELENGTH         = 255;
  +    static private final int  LOOKUPLENGTH       = 64;
  +    static private final int  TWENTYFOURBITGROUP = 24;
  +    static private final int  EIGHTBIT           = 8;
  +    static private final int  SIXTEENBIT         = 16;
  +    static private final int  SIXBIT             = 6;
  +    static private final int  FOURBYTE           = 4;
  +    static private final int  SIGN               = -128;
  +    static private final byte PAD                = (byte) '=';
  +    static private byte [] base64Alphabet       = new byte[BASELENGTH];
  +    static private byte [] lookUpBase64Alphabet = new byte[LOOKUPLENGTH];
  +    //static private final Log log = LogSource.getInstance("org.apache.commons.util.Base64");
   
  -    /**
  -    * returns an array of base64-encoded characters to represent the
  -    * passed data array.
  -    *
  -    * @param data the array of bytes to encode
  -    * @return base64-coded character array.
  -    */
  -    static public char[] encode(byte[] data)
  +    static
       {
  -        char[] out = new char[((data.length + 2) / 3) * 4];
  -
  -        //
  -        // 3 bytes encode to 4 chars.  Output is always an even
  -        // multiple of 4 characters.
  -        //
  -        for (int i = 0, index = 0; i < data.length; i += 3, index += 4)
  -        {
  -            boolean quad = false;
  -            boolean trip = false;
  -
  -            int val = (0xFF & (int) data[i]);
  -            val <<= 8;
  -            if ((i + 1) < data.length)
  -            {
  -                val |= (0xFF & (int) data[i + 1]);
  -                trip = true;
  -            }
  -            val <<= 8;
  -            if ((i + 2) < data.length)
  -            {
  -                val |= (0xFF & (int) data[i + 2]);
  -                quad = true;
  -            }
  -            out[index + 3] = alphabet[(quad ? (val & 0x3F) : 64)];
  -            val >>= 6;
  -            out[index + 2] = alphabet[(trip ? (val & 0x3F) : 64)];
  -            val >>= 6;
  -            out[index + 1] = alphabet[val & 0x3F];
  -            val >>= 6;
  -            out[index + 0] = alphabet[val & 0x3F];
  +        for (int i = 0; i < BASELENGTH; i++ )
  +        {
  +            base64Alphabet[i] = -1;
           }
  -        return out;
  -    }
  -
  -    /**
  -      * Decodes a BASE-64 encoded stream to recover the original
  -      * data. White space before and after will be trimmed away,
  -      * but no other manipulation of the input will be performed.
  -      *
  -      * As of version 1.2 this method will properly handle input
  -      * containing junk characters (newlines and the like) rather
  -      * than throwing an error. It does this by pre-parsing the
  -      * input and generating from that a count of VALID input
  -      * characters.
  -      **/
  -    static public byte[] decode(char[] data)
  -    {
  -        // as our input could contain non-BASE64 data (newlines,
  -        // whitespace of any sort, whatever) we must first adjust
  -        // our count of USABLE data so that...
  -        // (a) we don't misallocate the output array, and
  -        // (b) think that we miscalculated our data length
  -        //     just because of extraneous throw-away junk
  -
  -        int tempLen = data.length;
  -        for (int ix = 0; ix < data.length; ix++)
  +        for (int i = 'Z'; i >= 'A'; i--)
           {
  -            if ((data[ix] > 255) || codes[data[ix]] < 0)
  -                --tempLen; // ignore non-valid chars and padding
  +            base64Alphabet[i] = (byte) (i - 'A');
           }
  -        // calculate required length:
  -        //  -- 3 bytes for every 4 valid base64 chars
  -        //  -- plus 2 bytes if there are 3 extra base64 chars,
  -        //     or plus 1 byte if there are 2 extra.
  -
  -        int len = (tempLen / 4) * 3;
  -        if ((tempLen % 4) == 3)
  -            len += 2;
  -        if ((tempLen % 4) == 2)
  -            len += 1;
  -
  -        byte[] out = new byte[len];
  -
  -
  -
  -        int shift = 0; // # of excess bits stored in accum
  -        int accum = 0; // excess bits
  -        int index = 0;
  -
  -        // we now go through the entire array (NOT using the 'tempLen' value)
  -        for (int ix = 0; ix < data.length; ix++)
  +        for (int i = 'z'; i>= 'a'; i--)
           {
  -            int value = (data[ix] > 255) ? -1 : codes[data[ix]];
  -
  -            if (value >= 0)// skip over non-code
  -
  -            {
  -                accum <<= 6; // bits shift up by 6 each time thru
  -                shift += 6; // loop, with new bits being put in
  -                accum |= value; // at the bottom.
  -                if (shift >= 8)// whenever there are 8 or more shifted in,
  -
  -                {
  -                    shift -= 8; // write them out (from the top, leaving any
  -                    out[index++] = // excess at the bottom for next iteration.
  -                            (byte)((accum >> shift) & 0xff);
  -                }
  -            }
  -            // we will also have skipped processing a padding null byte ('=') here;
  -            // these are used ONLY for padding to an even length and do not legally
  -            // occur as encoded data. for this reason we can ignore the fact that
  -            // no index++ operation occurs in that special case: the out[] array is
  -            // initialized to all-zero bytes to start with and that works to our
  -            // advantage in this combination.
  +            base64Alphabet[i] = (byte) (i - 'a' + 26);
           }
  -
  -        // if there is STILL something wrong we just have to throw up now!
  -        if (index != out.length)
  +        for (int i = '9'; i >= '0'; i--)
           {
  -            throw new Error("Miscalculated data length (wrote " +
  -                    index + " instead of " + out.length + ")");
  +            base64Alphabet[i] = (byte) (i - '0' + 52);
           }
   
  -        return out;
  -    }
  -
  +        base64Alphabet['+']  = 62;
  +        base64Alphabet['/']  = 63;
   
  -    //
  -    // code characters for values 0..63
  -    //
  -    static private char[] alphabet =
  -            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" .toCharArray();
  -
  -    //
  -    // lookup table for converting base64 characters to value in range 0..63
  -    //
  -    static private byte[] codes = new byte[256];
  -    static
  -    {
  -        for (int i = 0; i < 256; i++)
  -            codes[i] = -1;
  -        for (int i = 'A'; i <= 'Z'; i++)
  -            codes[i] = (byte)(i - 'A');
  -        for (int i = 'a'; i <= 'z'; i++)
  -            codes[i] = (byte)(26 + i - 'a');
  -        for (int i = '0'; i <= '9'; i++)
  -            codes[i] = (byte)(52 + i - '0');
  -        codes['+'] = 62;
  -        codes['/'] = 63;
  -    }
  +        for (int i = 0; i <= 25; i++ )
  +            lookUpBase64Alphabet[i] = (byte) ('A' + i);
   
  +        for (int i = 26,  j = 0; i <= 51; i++, j++ )
  +            lookUpBase64Alphabet[i] = (byte) ('a'+ j);
   
  +        for (int i = 52,  j = 0; i <= 61; i++, j++ )
  +            lookUpBase64Alphabet[i] = (byte) ('0' + j);
   
  +        lookUpBase64Alphabet[62] = (byte) '+';
  +        lookUpBase64Alphabet[63] = (byte) '/';
  +    }
   
  -    ///////////////////////////////////////////////////
  -    // remainder (main method and helper functions) is
  -    // for testing purposes only, feel free to clip it.
  -    ///////////////////////////////////////////////////
  +    public static boolean isBase64( String isValidString )
  +    {
  +        return isArrayByteBase64(isValidString.getBytes());
  +    }
   
  -    public static void main(String[] args)
  +    public static boolean isBase64( byte octect )
       {
  -        boolean decode = false;
  +        //shall we ignore white space? JEFF??
  +        return (octect == PAD || base64Alphabet[octect] != -1);
  +    }
   
  -        if (args.length == 0)
  +    public static boolean isArrayByteBase64( byte[] arrayOctect )
  +    {
  +        int length = arrayOctect.length;
  +        if (length == 0)
           {
  -            System.out.println("usage:  java Base64 [-d[ecode]] filename");
  -            System.exit(0);
  +            // shouldn't a 0 length array be valid base64 data?
  +            // return false;
  +            return true;
           }
  -        for (int i = 0; i < args.length; i++)
  +        for (int i=0; i < length; i++)
           {
  -            if ("-decode".equalsIgnoreCase(args[i]))
  -                decode = true;
  -            else if ("-d".equalsIgnoreCase(args[i]))
  -                decode = true;
  +            if ( !Base64.isBase64(arrayOctect[i]) )
  +                return false;
           }
  +        return true;
  +    }
   
  -        String filename = args[args.length - 1];
  -        File file = new File(filename);
  -        if (!file.exists())
  -        {
  -            System.out.println("Error:  file '" + filename + "' doesn't exist!");
  -            System.exit(0);
  -        }
  +    /**
  +     * Encodes hex octects into Base64.
  +     *
  +     * @param binaryData Array containing binary data to encode.
  +     * @return Base64-encoded data.
  +     */
  +    public static byte[] encode( byte[] binaryData )
  +    {
  +        int      lengthDataBits    = binaryData.length*EIGHTBIT;
  +        int      fewerThan24bits   = lengthDataBits%TWENTYFOURBITGROUP;
  +        int      numberTriplets    = lengthDataBits/TWENTYFOURBITGROUP;
  +        byte     encodedData[]     = null;
   
  -        if (decode)
  +
  +        if (fewerThan24bits != 0)
           {
  -            char[] encoded = readChars(file);
  -            byte[] decoded = decode(encoded);
  -            writeBytes(file, decoded);
  +            //data not divisible by 24 bit
  +            encodedData = new byte[ (numberTriplets + 1 ) * 4 ];
           }
           else
           {
  -            byte[] decoded = readBytes(file);
  -            char[] encoded = encode(decoded);
  -            writeChars(file, encoded);
  +            // 16 or 8 bit
  +            encodedData = new byte[ numberTriplets * 4 ];
           }
  -    }
   
  -    private static byte[] readBytes(File file)
  -    {
  -        ByteArrayOutputStream baos = new ByteArrayOutputStream();
  -        try
  -        {
  -            InputStream fis = new FileInputStream(file);
  -            InputStream is = new BufferedInputStream(fis);
  -            int count = 0;
  -            byte[] buf = new byte[16384];
  -            while ((count = is.read(buf)) != -1)
  -            {
  -                if (count > 0)
  -                    baos.write(buf, 0, count);
  -            }
  -            is.close();
  -        }
  -        catch (Exception e)
  -        {
  -            e.printStackTrace();
  +        byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
  +
  +        int encodedIndex = 0;
  +        int dataIndex   = 0;
  +        int i           = 0;
  +        //log.debug("number of triplets = " + numberTriplets);
  +        for ( i = 0; i<numberTriplets; i++ )
  +        {
  +            dataIndex = i*3;
  +            b1 = binaryData[dataIndex];
  +            b2 = binaryData[dataIndex + 1];
  +            b3 = binaryData[dataIndex + 2];
  +
  +            //log.debug("b1= " + b1 +", b2= " + b2 + ", b3= " + b3);
  +
  +            l  = (byte)(b2 & 0x0f);
  +            k  = (byte)(b1 & 0x03);
  +
  +            encodedIndex = i * 4;
  +            byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
  +            byte val2 = ((b2 & SIGN)==0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
  +            byte val3 = ((b3 & SIGN)==0)?(byte)(b3>>6):(byte)((b3)>>6^0xfc);
  +
  +            encodedData[encodedIndex]   = lookUpBase64Alphabet[ val1 ];
  +            //log.debug( "val2 = " + val2 );
  +            //log.debug( "k4   = " + (k<<4) );
  +            //log.debug(  "vak  = " + (val2 | (k<<4)) );
  +            encodedData[encodedIndex+1] =
  +                lookUpBase64Alphabet[ val2 | ( k<<4 )];
  +            encodedData[encodedIndex+2] =
  +                lookUpBase64Alphabet[ (l <<2 ) | val3 ];
  +            encodedData[encodedIndex+3] = lookUpBase64Alphabet[ b3 & 0x3f ];
  +        }
  +
  +        // form integral number of 6-bit groups
  +        dataIndex    = i*3;
  +        encodedIndex = i*4;
  +        if (fewerThan24bits == EIGHTBIT )
  +        {
  +            b1 = binaryData[dataIndex];
  +            k = (byte) ( b1 &0x03 );
  +            //log.debug("b1=" + b1);
  +            //log.debug("b1<<2 = " + (b1>>2) );
  +            byte val1 = ((b1 & SIGN)==0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
  +            encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
  +            encodedData[encodedIndex + 1] = lookUpBase64Alphabet[ k<<4 ];
  +            encodedData[encodedIndex + 2] = PAD;
  +            encodedData[encodedIndex + 3] = PAD;
  +        }
  +        else if (fewerThan24bits == SIXTEENBIT)
  +        {
  +
  +            b1 = binaryData[dataIndex];
  +            b2 = binaryData[dataIndex +1 ];
  +            l = (byte) (b2 & 0x0f);
  +            k = (byte) (b1 & 0x03);
  +
  +            byte val1 = ((b1 & SIGN) == 0)?(byte)(b1>>2):(byte)((b1)>>2^0xc0);
  +            byte val2 = ((b2 & SIGN) == 0)?(byte)(b2>>4):(byte)((b2)>>4^0xf0);
  +
  +            encodedData[encodedIndex]     = lookUpBase64Alphabet[ val1 ];
  +            encodedData[encodedIndex + 1] =
  +                lookUpBase64Alphabet[ val2 | ( k<<4 )];
  +            encodedData[encodedIndex + 2] = lookUpBase64Alphabet[ l<<2 ];
  +            encodedData[encodedIndex + 3] = PAD;
           }
   
  -        return baos.toByteArray();
  +        return encodedData;
       }
   
  -    private static char[] readChars(File file)
  +    /**
  +     * Decodes Base64 data into octects
  +     *
  +     * @param binaryData Byte array containing Base64 data
  +     * @return Array containing decoded data.
  +     */
  +    public static byte[] decode( byte[] base64Data )
       {
  -        CharArrayWriter caw = new CharArrayWriter();
  -        try
  -        {
  -            Reader fr = new FileReader(file);
  -            Reader in = new BufferedReader(fr);
  -            int count = 0;
  -            char[] buf = new char[16384];
  -            while ((count = in.read(buf)) != -1)
  +        // handle the edge case, so we don't have to worry about it later
  +        if(base64Data.length == 0) { return new byte[0]; }
  +
  +        int      numberQuadruple    = base64Data.length/FOURBYTE;
  +        byte     decodedData[]      = null;
  +        byte     b1=0,b2=0,b3=0, b4=0, marker0=0, marker1=0;
  +
  +        // Throw away anything not in base64Data
  +
  +        int encodedIndex = 0;
  +        int dataIndex    = 0;
  +        {
  +            // this sizes the output array properly - rlw
  +            int lastData = base64Data.length;
  +            // ignore the '=' padding
  +            while (base64Data[lastData-1] == PAD)
               {
  -                if (count > 0)
  -                    caw.write(buf, 0, count);
  +                if (--lastData == 0)
  +                {
  +                    return new byte[0];
  +                }
               }
  -            in.close();
  +            decodedData = new byte[ lastData - numberQuadruple ];
           }
  -        catch (Exception e)
  +
  +        for (int i = 0; i < numberQuadruple; i++)
           {
  -            e.printStackTrace();
  -        }
  +            dataIndex = i * 4;
  +            marker0   = base64Data[dataIndex + 2];
  +            marker1   = base64Data[dataIndex + 3];
   
  -        return caw.toCharArray();
  -    }
  +            b1 = base64Alphabet[base64Data[dataIndex]];
  +            b2 = base64Alphabet[base64Data[dataIndex +1]];
   
  -    private static void writeBytes(File file, byte[] data)
  -    {
  -        try
  -        {
  -            OutputStream fos = new FileOutputStream(file);
  -            OutputStream os = new BufferedOutputStream(fos);
  -            os.write(data);
  -            os.close();
  -        }
  -        catch (Exception e)
  -        {
  -            e.printStackTrace();
  -        }
  -    }
  +            if (marker0 != PAD && marker1 != PAD)
  +            {
  +                //No PAD e.g 3cQl
  +                b3 = base64Alphabet[ marker0 ];
  +                b4 = base64Alphabet[ marker1 ];
  +
  +                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ;
  +                decodedData[encodedIndex + 1] =
  +                    (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
  +                decodedData[encodedIndex + 2] = (byte)( b3<<6 | b4 );
  +            }
  +            else if (marker0 == PAD)
  +            {
  +                //Two PAD e.g. 3c[Pad][Pad]
  +                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 ) ;
  +            }
  +            else if (marker1 == PAD)
  +            {
  +                //One PAD e.g. 3cQ[Pad]
  +                b3 = base64Alphabet[ marker0 ];
   
  -    private static void writeChars(File file, char[] data)
  -    {
  -        try
  -        {
  -            Writer fos = new FileWriter(file);
  -            Writer os = new BufferedWriter(fos);
  -            os.write(data);
  -            os.close();
  -        }
  -        catch (Exception e)
  -        {
  -            e.printStackTrace();
  +                decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 );
  +                decodedData[encodedIndex + 1] =
  +                    (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
  +            }
  +            encodedIndex += 3;
           }
  +        return decodedData;
       }
  -    ///////////////////////////////////////////////////
  -    // end of test code.
  -    ///////////////////////////////////////////////////
  +
   
   }
  
  
  
  1.2       +12 -9     xml-rpc/src/java/org/apache/xmlrpc/ServerInputStream.java
  
  Index: ServerInputStream.java
  ===================================================================
  RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/ServerInputStream.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ServerInputStream.java	20 Jul 2001 19:38:16 -0000	1.1
  +++ ServerInputStream.java	19 Feb 2002 02:25:01 -0000	1.2
  @@ -69,8 +69,8 @@
       // This is used in order to correctly return a -1 when all the
       // data POSTed was read. If this is left to -1, content length is
       // assumed as unknown and the standard InputStream methods will be used
  -    long available = -1;
  -    long markedAvailable;
  +    private long available = -1;
  +    private long markedAvailable;
   
       private BufferedInputStream in;
   
  @@ -120,7 +120,9 @@
               return read;
           }
           else if (available == -1)
  -            return in.read (b, off, len);
  +        {
  +            return in.read(b, off, len);
  +        }
           return -1;
       }
   
  @@ -128,25 +130,26 @@
       {
           long skip = in.skip(n);
           if (available > 0)
  +        {
               available -= skip;
  +        }
           return skip;
       }
   
  -    public void mark (int readlimit)
  +    public void mark(int readlimit)
       {
  -        in.mark (readlimit);
  +        in.mark(readlimit);
           markedAvailable = available;
       }
   
  -    public void reset () throws IOException
  +    public void reset() throws IOException
       {
  -        in.reset ();
  +        in.reset();
           available = markedAvailable;
       }
   
  -    public boolean markSupported ()
  +    public boolean markSupported()
       {
           return true;
       }
  -
   }
  
  
  
  1.5       +166 -126  xml-rpc/src/java/org/apache/xmlrpc/WebServer.java
  
  Index: WebServer.java
  ===================================================================
  RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/WebServer.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- WebServer.java	13 Feb 2002 00:51:55 -0000	1.4
  +++ WebServer.java	19 Feb 2002 02:25:01 -0000	1.5
  @@ -87,6 +87,9 @@
       protected static final byte[] ok = " 200 OK\r\n".getBytes();
       protected static final byte[] server = "Server: Apache XML-RPC 1.0\r\n".getBytes();
   
  +    private static final String HTTP_11 = "HTTP/1.1";
  +    private static final String STAR = "*";
  +
       /**
        * This <em>can</em> be called from command line, but you'll have to edit and recompile
        * to change the server port or handler objects. By default, it sets up the following responders:
  @@ -113,44 +116,44 @@
           XmlRpc.setKeepAlive (true);
           try
           {
  -            WebServer webserver = new WebServer (p);
  +            WebServer webserver = new WebServer(p);
               // webserver.setParanoid (true);
               // webserver.acceptClient ("192.168.*.*");
  -            webserver.addHandler ("string", "Welcome to XML-RPC!");
  -            webserver.addHandler ("math", Math.class);
  -            webserver.addHandler ("auth", new AuthDemo());
  -            webserver.addHandler ("$default", new Echo());
  +            webserver.addHandler("string", "Welcome to XML-RPC!");
  +            webserver.addHandler("math", Math.class);
  +            webserver.addHandler("auth", new AuthDemo());
  +            webserver.addHandler("$default", new Echo());
               // XmlRpcClients can be used as Proxies in XmlRpcServers which is a cool feature for applets.
  -            webserver.addHandler ("mttf", new XmlRpcClient ("http://www.mailtothefuture.com:80/RPC2"));
  -            System.err.println ("started web server on port "+p);
  +            webserver.addHandler("mttf", new XmlRpcClient("http://www.mailtothefuture.com:80/RPC2"));
  +            System.err.println("started web server on port "+p);
           }
           catch (IOException x)
           {
  -            System.err.println ("Error creating web server: "+x);
  +            System.err.println("Error creating web server: "+x);
           }
       }
   
       /**
         * Creates a Web server at the specified port number.
         */
  -    public WebServer (int port) 
  +    public WebServer(int port) 
           throws IOException
       {
  -        this (port, null);
  +        this(port, null);
       }
   
       /**
         * Creates a Web server at the specified port number and IP address.
         */
  -    public WebServer (int port, InetAddress add) 
  +    public WebServer(int port, InetAddress add) 
           throws IOException
       {
           this.port = port;
  -        xmlrpc = new XmlRpcServer ();
  -        accept = new Vector ();
  -        deny = new Vector ();
  -        threadpool = new Stack ();
  -        runners = new ThreadGroup ("XML-RPC Runner");
  +        xmlrpc = new XmlRpcServer();
  +        accept = new Vector();
  +        deny = new Vector();
  +        threadpool = new Stack();
  +        runners = new ThreadGroup("XML-RPC Runner");
   
           try
           {
  @@ -193,7 +196,7 @@
   
       public void start()
       {
  -        listener = new Thread (this, "XML-RPC Weblistener");
  +        listener = new Thread(this, "XML-RPC Weblistener");
           listener.start();
       }
   
  @@ -201,17 +204,17 @@
         * Register a handler object with this name. Methods of this objects will be
         * callable over XML-RPC as "name.method".
         */
  -    public void addHandler (String name, Object target)
  +    public void addHandler(String name, Object target)
       {
  -        xmlrpc.addHandler (name, target);
  +        xmlrpc.addHandler(name, target);
       }
   
       /**
         * Remove a handler object that was previously registered with this server.
         */
  -    public void removeHandler (String name)
  +    public void removeHandler(String name)
       {
  -        xmlrpc.removeHandler (name);
  +        xmlrpc.removeHandler(name);
       }
   
       /**
  @@ -219,7 +222,7 @@
         * @see acceptClient(java.lang.String)
         * @see denyClient(java.lang.String)
         */
  -    public void setParanoid (boolean p)
  +    public void setParanoid(boolean p)
       {
           paranoid = p;
       }
  @@ -232,17 +235,19 @@
         * @see denyClient(java.lang.String)
         * @see setParanoid(boolean)
         */
  -    public void acceptClient (String address)
  -            throws IllegalArgumentException
  +    public void acceptClient(String address)
  +        throws IllegalArgumentException
       {
           try
           {
  -            AddressMatcher m = new AddressMatcher (address);
  -            accept.addElement (m);
  +            AddressMatcher m = new AddressMatcher(address);
  +            accept.addElement(m);
           }
           catch (Exception x)
           {
  -            throw new IllegalArgumentException ("\""+address + "\" does not represent a valid IP address");
  +            throw new IllegalArgumentException("\"" + 
  +                address + 
  +                "\" does not represent a valid IP address");
           }
       }
   
  @@ -254,35 +259,41 @@
         * @see acceptClient(java.lang.String)
         * @see setParanoid(boolean)
         */
  -    public void denyClient (String address) throws IllegalArgumentException
  +    public void denyClient(String address) throws IllegalArgumentException
       {
           try
           {
  -            AddressMatcher m = new AddressMatcher (address);
  -            deny.addElement (m);
  +            AddressMatcher m = new AddressMatcher(address);
  +            deny.addElement(m);
           }
           catch (Exception x)
           {
  -            throw new IllegalArgumentException ("\""+address + "\" does not represent a valid IP address");
  +            throw new IllegalArgumentException("\"" + 
  +                address + 
  +                "\" does not represent a valid IP address");
           }
       }
   
  -    protected boolean checkSocket (Socket s)
  +    protected boolean checkSocket(Socket s)
       {
  -        int l = deny.size ();
  -        byte address[] = s.getInetAddress ().getAddress ();
  +        int l = deny.size();
  +        byte address[] = s.getInetAddress().getAddress();
           for (int i = 0; i < l; i++)
           {
  -            AddressMatcher match = (AddressMatcher) deny.elementAt (i);
  -            if (match.matches (address))
  +            AddressMatcher match = (AddressMatcher)deny.elementAt(i);
  +            if (match.matches(address))
  +            {
                   return false;
  +            }
           }
  -        l = accept.size ();
  +        l = accept.size();
           for (int i = 0; i < l; i++)
           {
  -            AddressMatcher match = (AddressMatcher) accept.elementAt (i);
  -            if (match.matches (address))
  +            AddressMatcher match = (AddressMatcher)accept.elementAt(i);
  +            if (match.matches(address))
  +            {
                   return true;
  +            }
           }
           return false;
       }
  @@ -299,14 +310,15 @@
                   try
                   {
                       Socket socket = serverSocket.accept();
  -                    if (!paranoid || checkSocket (socket))
  +                    if (!paranoid || checkSocket(socket))
                       {
  -                        Runner runner = getRunner ();
  +                        Runner runner = getRunner();
                           runner.handle (socket);
  -                        // new Connection (socket);
                       }
                       else
  -                        socket.close ();
  +                    {
  +                        socket.close();
  +                    }
                   }
                   catch (InterruptedIOException checkState)
                   {
  @@ -341,14 +353,15 @@
                   serverSocket = null;
               }
               catch (IOException ignore)
  -                {}
  +            {
  +            }
           }
       }
   
       /**
         * Stop listening on the server port.
         */
  -    public void shutdown ()
  +    public void shutdown()
       {
           if (listener != null)
           {
  @@ -358,19 +371,19 @@
           }
       }
   
  -
  -
  -    protected Runner getRunner ()
  +    protected Runner getRunner()
       {
           try
           {
  -            return (Runner) threadpool.pop ();
  +            return (Runner)threadpool.pop();
           }
           catch (EmptyStackException empty)
           {
               if (runners.activeCount () > 255)
  +            {
                   throw new RuntimeException ("System overload");
  -            return new Runner ();
  +            }
  +            return new Runner();
           }
       }
   
  @@ -381,28 +394,27 @@
   
       class Runner implements Runnable
       {
  -
           Thread thread;
           Connection con;
           int count;
   
  -        public synchronized void handle (Socket socket)
  +        public synchronized void handle(Socket socket)
               throws IOException
           {
  -            con = new Connection (socket);
  +            con = new Connection(socket);
               count = 0;
               if (thread == null || !thread.isAlive())
               {
  -                thread = new Thread (runners, this);
  -                thread.start ();
  +                thread = new Thread(runners, this);
  +                thread.start();
               }
               else
               {
  -                this.notify ();
  +                this.notify();
               }
           }
   
  -        public void run ()
  +        public void run()
           {
               while (Thread.currentThread () == thread)
               {
  @@ -411,14 +423,15 @@
                   con = null;
   
                   if (count > 200 || threadpool.size() > 20)
  +                {
                       return;
  -
  -                synchronized (this)
  +                }
  +                synchronized(this)
                   {
  -                    releaseRunner (this);
  +                    releaseRunner(this);
                       try
                       {
  -                        this.wait ();
  +                        this.wait();
                       }
                       catch (InterruptedException ir)
                       {
  @@ -427,19 +440,15 @@
                   }
               }
           }
  -
  -    } // end class Runner
  -
  +    }
   
       class Connection implements Runnable
       {
  -
           private Socket socket;
           private BufferedInputStream input;
           private BufferedOutputStream output;
  -        // private Thread responder;
  -        private long lastRequest;
           private String user, password;
  +        byte[] buffer;
   
           public Connection (Socket socket) throws IOException
           {
  @@ -447,13 +456,11 @@
               socket.setSoTimeout (30000);
   
               this.socket = socket;
  -            input = new BufferedInputStream (socket.getInputStream());
  -            output = new BufferedOutputStream (socket.getOutputStream());
  -            // responder = new Thread (this, "xmlrpc-worker");
  -            // responder.start();
  +            input = new BufferedInputStream(socket.getInputStream());
  +            output = new BufferedOutputStream(socket.getOutputStream());
           }
   
  -        public void run ()
  +        public void run()
           {
               try
               {
  @@ -463,43 +470,52 @@
                   {
                       // reset user authentication
                       user = password = null;
  -                    String line = readLine ();
  +                    String line = readLine();
                       // Netscape sends an extra \n\r after bodypart, swallow it
  -                    if ("".equals (line))
  +                    if (line != null && line.length() == 0)
  +                    {
                           line = readLine();
  +                    }
                       if (XmlRpc.debug)
  +                    {
                           System.err.println (line);
  -                    // get time of last request
  -                    lastRequest = System.currentTimeMillis ();
  +                    }
                       int contentLength = -1;
   
                       // tokenize first line of HTTP request
                       StringTokenizer tokens = new StringTokenizer(line);
                       String method = tokens.nextToken();
  -                    String uri = tokens.nextToken ();
  -                    String httpversion = tokens.nextToken ();
  -                    keepalive = XmlRpc.getKeepAlive() && "HTTP/1.1".equals (httpversion);
  +                    String uri = tokens.nextToken();
  +                    String httpversion = tokens.nextToken();
  +                    keepalive = XmlRpc.getKeepAlive() && HTTP_11.equals(httpversion);
                       do
                       {
                           line = readLine();
                           if (line != null)
                           {
                               if (XmlRpc.debug)
  -                                System.err.println (line);
  -                            String lineLower = line.toLowerCase ();
  -                            if (lineLower.startsWith ("content-length:"))
  -                                contentLength = Integer.parseInt (
  -                                        line.substring (15).trim ());
  -                            if (lineLower.startsWith ("connection:"))
  +                            {
  +                                System.err.println(line);
  +                            }
  +                            String lineLower = line.toLowerCase();
  +                            if (lineLower.startsWith("content-length:"))
  +                            {
  +                                contentLength = Integer.parseInt(
  +                                        line.substring(15).trim());
  +                            }
  +                            if (lineLower.startsWith("connection:"))
  +                            {
                                   keepalive = XmlRpc.getKeepAlive() &&
                                           lineLower.indexOf ("keep-alive")
                                           > -1;
  -                            if (lineLower.startsWith ("authorization: basic "))
  +                            }
  +                            if (lineLower.startsWith("authorization: basic "))
  +                            {
                                   parseAuth (line);
  +                            }
                           }
                       }
  -                    while (line != null && ! line.equals(""))
  -                        ;
  +                    while (line != null && line.length() != 0);
   
                       if ("POST".equalsIgnoreCase (method))
                       {
  @@ -508,35 +524,38 @@
                                   contentLength);
                           byte result[] =
                                   xmlrpc.execute (sin, user, password);
  -                        output.write (httpversion.getBytes());
  -                        output.write (ok);
  -                        output.write (server);
  +                        output.write(httpversion.getBytes());
  +                        output.write(ok);
  +                        output.write(server);
                           if (keepalive)
  -                            output.write (conkeep);
  +                        {
  +                            output.write(conkeep);
  +                        }
                           else
  +                        {
                               output.write (conclose);
  -                        output.write (ctype);
  -                        output.write (clength);
  -                        output.write ( Integer.toString (
  +                        }
  +                        output.write(ctype);
  +                        output.write(clength);
  +                        output.write(Integer.toString(
                                   result.length).getBytes());
  -                        output.write (doubleNewline);
  -                        output.write (result);
  -                        output.flush ();
  +                        output.write(doubleNewline);
  +                        output.write(result);
  +                        output.flush();
                       }
                       else
                       {
  -                        output.write (httpversion.getBytes());
  -                        output.write (" 400 Bad Request\r\n".getBytes());
  -                        output.write (server);
  -                        output.write ("\r\n".getBytes());
  -                        output.write ( ("Method "+method +
  -                                " not implemented (try POST)"). getBytes());
  -                        output.flush ();
  +                        output.write(httpversion.getBytes());
  +                        output.write(" 400 Bad Request\r\n".getBytes());
  +                        output.write(server);
  +                        output.write("\r\n".getBytes());
  +                        output.write(("Method "+method +
  +                                " not implemented (try POST)").getBytes());
  +                        output.flush();
                           keepalive = false;
                       }
                   }
  -                while (keepalive)
  -                    ;
  +                while (keepalive);
               }
               catch (Exception exception)
               {
  @@ -546,16 +565,22 @@
                       exception.printStackTrace ();
                   }
               }
  -            finally { try
  +            finally
  +            {
  +                try
                   {
  -                    socket.close();
  +                    if (socket != null)
  +                    {
  +                        socket.close();
  +                    }
                   }
                   catch (IOException ignore)
  -                    {}
  -            } }
  +                {
  +                }
  +            }
  +        }
   
  -        byte[] buffer;
  -        private String readLine () throws IOException
  +        private String readLine() throws IOException
           {
               if (buffer == null)
               {
  @@ -567,51 +592,63 @@
               {
                   next = input.read();
                   if (next < 0 || next == '\n')
  +                {
                       break;
  +                }
                   if (next != '\r')
                   {
                       buffer[count++] = (byte) next;
                   }
                   if (count >= 512)
  +                {
                       throw new IOException ("HTTP Header too long");
  +                }
               }
               return new String (buffer, 0, count);
           }
   
  -        private void parseAuth (String line)
  +        private void parseAuth(String line)
           {
               try
               {
                   byte[] c =
  -                        Base64.decode (line.substring (21).toCharArray());
  +                        Base64.decode (line.substring(21).getBytes());
                   String str = new String (c);
  -                int col = str.indexOf (":");
  +                int col = str.indexOf (':');
                   user = str.substring (0, col);
                   password = str.substring (col + 1);
               }
               catch (Throwable ignore)
  -                {}
  +            {
  +            }
           }
  -
       }
   
       class AddressMatcher
       {
           int pattern[];
  -
  +        
           public AddressMatcher (String address) throws Exception
           {
               pattern = new int[4];
  -            StringTokenizer st = new StringTokenizer (address, ".");
  -            if (st.countTokens () != 4)
  -                throw new Exception ("\""+address + "\" does not represent a valid IP address");
  +            StringTokenizer st = new StringTokenizer(address, ".");
  +            if (st.countTokens() != 4)
  +            {
  +                throw new Exception ("\"" + 
  +                    address + 
  +                    "\" does not represent a valid IP address");
  +            }
               for (int i = 0; i < 4; i++)
               {
  -                String next = st.nextToken ();
  -                if ("*".equals (next))
  +                String next = st.nextToken();
  +                if (STAR.equals(next))
  +                {
                       pattern[i] = 256;
  +                }
                   else
  -                    pattern[i] = (byte) Integer.parseInt (next);
  +                {
  +                    pattern[i] = (byte) Integer.parseInt(next);
  +                }
               }
           }
   
  @@ -620,10 +657,13 @@
               for (int i = 0; i < 4; i++)
               {
                   if (pattern[i] > 255)// wildcard
  -
  +                {
                       continue;
  +                }
                   if (pattern[i] != address[i])
  +                {
                       return false;
  +                }
               }
               return true;
           }
  
  
  
  1.18      +3 -2      xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java
  
  Index: XmlRpc.java
  ===================================================================
  RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpc.java,v
  retrieving revision 1.17
  retrieving revision 1.18
  diff -u -r1.17 -r1.18
  --- XmlRpc.java	18 Feb 2002 23:22:29 -0000	1.17
  +++ XmlRpc.java	19 Feb 2002 02:25:01 -0000	1.18
  @@ -587,7 +587,7 @@
                       }
                       break;
                   case BASE64:
  -                    value = Base64.decode (cdata.toCharArray());
  +                    value = Base64.decode (cdata.getBytes());
                       break;
                   case STRING:
                       value = cdata;
  @@ -700,7 +700,8 @@
               else if (obj instanceof byte[])
               {
                   startElement("base64");
  -                write(Base64.encode((byte[]) obj));
  +                // FIXME: Yucky! Find a better way!
  +                write(new String(Base64.encode((byte[]) obj)).toCharArray());
                   endElement("base64");
               }
               else if (obj instanceof Vector)
  
  
  
  1.7       +172 -144  xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClient.java
  
  Index: XmlRpcClient.java
  ===================================================================
  RCS file: /home/cvs/xml-rpc/src/java/org/apache/xmlrpc/XmlRpcClient.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- XmlRpcClient.java	18 Feb 2002 23:22:29 -0000	1.6
  +++ XmlRpcClient.java	19 Feb 2002 02:25:01 -0000	1.7
  @@ -4,7 +4,7 @@
    * The Apache Software License, Version 1.1
    *
    *
  - * Copyright (c) 2001 The Apache Software Foundation.  All rights
  + * Copyright(c) 2001 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -22,7 +22,7 @@
    * 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/)."
  + *        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.
    *
  @@ -40,11 +40,11 @@
    * 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
  + * 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
  + * 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.
    * ====================================================================
  @@ -62,7 +62,7 @@
   
   /**
    * A multithreaded, reusable XML-RPC client object. Use this if you need a full-grown
  - * HTTP client (e.g. for Proxy and Cookies support). If you don't need that, <code>XmlRpcClientLite</code>
  + * HTTP client(e.g. for Proxy and Cookies support). If you don't need that, <code>XmlRpcClientLite</code>
    * may work better for you.
    * 
    * @author <a href="mailto:hannes@apache.org">Hannes Wallnoefer</a>
  @@ -70,21 +70,21 @@
   public class XmlRpcClient 
       implements XmlRpcHandler
   {
  -    URL url;
  -    String auth;
  +    protected URL url;
  +    private String auth;
   
       // pool of worker instances
  -    Stack pool = new Stack ();
  -    int workers = 0;
  -    int asyncWorkers = 0;
  +    protected Stack pool = new Stack();
  +    protected int workers = 0;
  +    protected int asyncWorkers = 0;
   
       // a queue of calls to be handled asynchronously
  -    CallData first, last;
  +    private CallData first, last;
   
       /**
        * Construct a XML-RPC client with this URL.
        */
  -    public XmlRpcClient (URL url)
  +    public XmlRpcClient(URL url)
       {
           this.url = url;
       }
  @@ -92,24 +92,24 @@
       /**
         * Construct a XML-RPC client for the URL represented by this String.
         */
  -    public XmlRpcClient (String url) throws MalformedURLException
  +    public XmlRpcClient(String url) throws MalformedURLException
       {
  -        this.url = new URL (url);
  +        this.url = new URL(url);
       }
   
       /**
         * Construct a XML-RPC client for the specified hostname and port.
         */
  -    public XmlRpcClient (String hostname,
  +    public XmlRpcClient(String hostname,
               int port) throws MalformedURLException
       {
  -        this.url = new URL ("http://" + hostname + ':' + port + "/RPC2");
  +        this.url = new URL("http://" + hostname + ':' + port + "/RPC2");
       }
   
       /**
         * Return the URL for this XML-RPC client.
         */
  -    public URL getURL ()
  +    public URL getURL()
       {
           return url;
       }
  @@ -118,15 +118,17 @@
         * Sets Authentication for this client. This will be sent as Basic Authentication header
         * to the server as described in <a href="http://www.ietf.org/rfc/rfc2617.txt">http://www.ietf.org/rfc/rfc2617.txt</a>.
         */
  -    public void setBasicAuthentication (String user, String password)
  +    public void setBasicAuthentication(String user, String password)
       {
           if (user == null || password == null)
  +        {
               auth = null;
  +        }
           else
           {
  -            char[] basicAuth =
  -                    Base64.encode ((user + ":"+password).getBytes());
  -            auth = new String (basicAuth).trim();
  +            auth = new String(
  +                Base64.encode((user + ':' + password)
  +                .getBytes())).trim();
           }
       }
   
  @@ -138,18 +140,18 @@
         * @exception XmlRpcException: If the remote host returned a fault message.
         * @exception IOException: If the call could not be made because of lower level problems.
         */
  -    public Object execute (String method,
  +    public Object execute(String method,
               Vector params) throws XmlRpcException, IOException
       {
  -        Worker worker = getWorker (false);
  +        Worker worker = getWorker(false);
           try
           {
  -            Object retval = worker.execute (method, params);
  +            Object retval = worker.execute(method, params);
               return retval;
           }
           finally
           {
  -            releaseWorker (worker, false);
  +            releaseWorker(worker, false);
           }
       }
   
  @@ -159,78 +161,93 @@
         * If the callback parameter is not null, it will be called later to handle the result or error when the call is finished.
         *
         */
  -    public void executeAsync (String method, Vector params,
  -            AsyncCallback callback)
  +    public void executeAsync(String method, Vector params,
  +                             AsyncCallback callback)
       {
           // if at least 4 threads are running, don't create any new ones,
  -	// just enqueue the request.
  +        // just enqueue the request.
           if (asyncWorkers >= 4)
           {
  -            enqueue (method, params, callback);
  +            enqueue(method, params, callback);
               return;
           }
           Worker worker = null;
           try
           {
  -            worker = getWorker (true);
  -            worker.start (method, params, callback);
  +            worker = getWorker(true);
  +            worker.start(method, params, callback);
           }
  -        catch (IOException iox)
  +        catch(IOException iox)
           {
               // make a queued worker that doesn't run immediately
  -            enqueue (method, params, callback);
  +            enqueue(method, params, callback);
           }
       }
   
  -
  -    synchronized Worker getWorker (boolean async)
  +    synchronized Worker getWorker(boolean async)
           throws IOException
       {
           try
           {
  -            Worker w = (Worker) pool.pop ();
  +            Worker w =(Worker) pool.pop();
               if (async)
  +            {
                   asyncWorkers += 1;
  +            }
               else
  +            {
                   workers += 1;
  +            }
               return w;
           }
  -        catch (EmptyStackException x)
  +        catch(EmptyStackException x)
           {
               if (workers < XmlRpc.getMaxThreads())
               {
                   if (async)
  +                {
                       asyncWorkers += 1;
  +                }
                   else
  +                {
                       workers += 1;
  -                return new Worker ();
  +                }
  +                return new Worker();
               }
  -            throw new IOException ("XML-RPC System overload");
  +            throw new IOException("XML-RPC System overload");
           }
       }
   
       /**
          * Release possibly big per-call object references to allow them to be garbage collected
          */
  -    synchronized void releaseWorker (Worker w, boolean async)
  +    synchronized void releaseWorker(Worker w, boolean async)
       {
           w.result = null;
           w.call = null;
           if (pool.size() < 20 && !w.fault)
  -            pool.push (w);
  +        {
  +            pool.push(w);
  +        }
           if (async)
  +        {
               asyncWorkers -= 1;
  +        }
           else
  +        {
               workers -= 1;
  +        }
       }
   
   
  -    synchronized void enqueue (String method, Vector params,
  +    synchronized void enqueue(String method, Vector params,
               AsyncCallback callback)
       {
  -        CallData call = new CallData (method, params, callback);
  +        CallData call = new CallData(method, params, callback);
           if (last == null)
  +        {
               first = last = call;
  +        }
           else
           {
               last.next = call;
  @@ -238,15 +255,21 @@
           }
       }
   
  -    synchronized CallData dequeue ()
  +    synchronized CallData dequeue()
       {
           if (first == null)
  +        {
               return null;
  +        }
           CallData call = first;
           if (first == last)
  +        {
               first = last = null;
  +        }
           else
  +        {
               first = first.next;
  +        }
           return call;
       }
   
  @@ -262,52 +285,53 @@
   
           CallData call;
   
  -        public Worker ()
  +        public Worker()
           {
  -            super ();
  +            super();
           }
   
  -        public void start (String method, Vector params,
  +        public void start(String method, Vector params,
                   AsyncCallback callback)
           {
  -            this.call = new CallData (method, params, callback);
  -            Thread t = new Thread (this);
  -            t.start ();
  +            this.call = new CallData(method, params, callback);
  +            Thread t = new Thread(this);
  +            t.start();
           }
   
  -        public void run ()
  +        public void run()
           {
               while (call != null)
               {
  -                executeAsync (call.method, call.params, call.callback);
  -                call = dequeue ();
  +                executeAsync(call.method, call.params, call.callback);
  +                call = dequeue();
               }
  -            releaseWorker (this, true);
  +            releaseWorker(this, true);
           }
   
  -
           /**
            * Execute an XML-RPC call and handle asyncronous callback.
            */
  -        void executeAsync (String method, Vector params, AsyncCallback callback)
  +        void executeAsync(String method, Vector params, AsyncCallback callback)
           {
               Object res = null;
               try
               {
  -                res = execute (method, params);
  +                res = execute(method, params);
                   // notify callback object
                   if (callback != null)
  -                    callback.handleResult (res, url, method);
  +                {
  +                    callback.handleResult(res, url, method);
  +                }
               }
  -            catch (Exception x)
  +            catch(Exception x)
               {
                   if (callback != null)
                   {
                       try
                       {
  -                        callback.handleError (x, url, method);
  +                        callback.handleError(x, url, method);
                       }
  -                    catch (Exception ignore)
  +                    catch(Exception ignore)
                       {
                       }
                   }
  @@ -317,18 +341,23 @@
           /**
            * Execute an XML-RPC call.
            */
  -        Object execute (String method,
  +        Object execute(String method,
                   Vector params) throws XmlRpcException, IOException
           {
  -            if (debug)
  +            fault = false;
  +            long now = 0;
  +
  +            if (XmlRpc.debug)
  +            {
                   System.err.println("Client calling procedure '" + method +
                                      "' with parameters " + params);
   
  -            fault = false;
  -            long now = System.currentTimeMillis ();
  +                now = System.currentTimeMillis();
  +            }
  +            
               try
               {
  -                ByteArrayOutputStream bout = new ByteArrayOutputStream ();
  +                ByteArrayOutputStream bout = new ByteArrayOutputStream();
   
                   if (buffer == null)
                   {
  @@ -339,33 +368,36 @@
                       buffer.reset();
                   }
   
  -                XmlWriter writer = new XmlWriter (buffer);
  -                writeRequest (writer, method, params);
  +                XmlWriter writer = new XmlWriter(buffer);
  +                writeRequest(writer, method, params);
                   writer.flush();
                   byte[] request = buffer.toByteArray();
   
  -                URLConnection con = url.openConnection ();
  -                con.setDoInput (true);
  -                con.setDoOutput (true);
  -                con.setUseCaches (false);
  +                URLConnection con = url.openConnection();
  +                con.setDoInput(true);
  +                con.setDoOutput(true);
  +                con.setUseCaches(false);
                   con.setAllowUserInteraction(false);
  -                con.setRequestProperty ("Content-Length",
  -                        Integer.toString (request.length));
  -                con.setRequestProperty ("Content-Type", "text/xml");
  +                con.setRequestProperty("Content-Length",
  +                        Integer.toString(request.length));
  +                con.setRequestProperty("Content-Type", "text/xml");
                   if (auth != null)
  -                    con.setRequestProperty ("Authorization", "Basic "+auth);
  -                // con.connect ();
  -                OutputStream out = con.getOutputStream ();
  -                out.write (request);
  -                out.flush ();
  -                InputStream in = con.getInputStream ();
  -                parse (in);
  -            }
  -            catch (Exception x)
  -            {
  -                if (debug)
  -                    x.printStackTrace ();
  -                throw new IOException (x.getMessage ());
  +                {
  +                    con.setRequestProperty("Authorization", "Basic " + auth);
  +                }
  +                OutputStream out = con.getOutputStream();
  +                out.write(request);
  +                out.flush();
  +                InputStream in = con.getInputStream();
  +                parse(in);
  +            }
  +            catch(Exception x)
  +            {
  +                if (XmlRpc.debug)
  +                {
  +                    x.printStackTrace();
  +                }
  +                throw new IOException(x.getMessage());
               }
               if (fault)
               {
  @@ -373,78 +405,76 @@
                   XmlRpcException exception = null;
                   try
                   {
  -                    Hashtable f = (Hashtable) result;
  -                    String faultString = (String) f.get ("faultString");
  -                    int faultCode = Integer.parseInt (
  -                            f.get ("faultCode").toString ());
  -                    exception = new XmlRpcException (faultCode,
  -                            faultString.trim ());
  +                    Hashtable f =(Hashtable) result;
  +                    String faultString =(String) f.get("faultString");
  +                    int faultCode = Integer.parseInt(
  +                            f.get("faultCode").toString());
  +                    exception = new XmlRpcException(faultCode,
  +                            faultString.trim());
                   }
  -                catch (Exception x)
  +                catch(Exception x)
                   {
  -                    throw new XmlRpcException (0, "Invalid fault response");
  +                    throw new XmlRpcException(0, "Invalid fault response");
                   }
                   throw exception;
               }
  -            if (debug)
  -                System.err.println ("Spent "+
  -                        (System.currentTimeMillis () - now) + " in request");
  +            if (XmlRpc.debug)
  +            {
  +                System.err.println("Spent "+
  +                       (System.currentTimeMillis() - now) + " in request");
  +            }
               return result;
           }
   
  -
           /**
             * Called when the return value has been parsed.
             */
  -        void objectParsed (Object what)
  +        void objectParsed(Object what)
           {
               result = what;
           }
   
  -
           /**
             * Generate an XML-RPC request from a method name and a parameter vector.
             */
  -        void writeRequest (XmlWriter writer, String method,
  +        void writeRequest(XmlWriter writer, String method,
                   Vector params) throws IOException, XmlRpcException
           {
  -            writer.startElement ("methodCall");
  -
  -            writer.startElement ("methodName");
  -            writer.write (method);
  -            writer.endElement ("methodName");
  -
  -            writer.startElement ("params");
  -            int l = params.size ();
  +            writer.startElement("methodCall");
  +            writer.startElement("methodName");
  +            writer.write(method);
  +            writer.endElement("methodName");
  +            writer.startElement("params");
  +            int l = params.size();
               for (int i = 0; i < l; i++)
               {
  -                writer.startElement ("param");
  -                writer.writeObject (params.elementAt (i));
  -                writer.endElement ("param");
  +                writer.startElement("param");
  +                writer.writeObject(params.elementAt(i));
  +                writer.endElement("param");
               }
  -            writer.endElement ("params");
  -            writer.endElement ("methodCall");
  +            writer.endElement("params");
  +            writer.endElement("methodCall");
           }
   
           /**
             * Overrides method in XmlRpc to handle fault repsonses.
             */
  -        public void startElement (String name,
  +        public void startElement(String name,
                   AttributeList atts) throws SAXException
           {
  -            if ("fault".equals (name))
  +            if ("fault".equals(name))
  +            {
                   fault = true;
  +            }
               else
  -                super.startElement (name, atts);
  +            {
  +                super.startElement(name, atts);
  +            }
           }
  -
  -
       } // end of inner class Worker
   
  -
       class CallData
       {
  -
           String method;
           Vector params;
           AsyncCallback callback;
  @@ -453,7 +483,7 @@
           /**
            * Make a call to be queued and then executed by the next free async thread
            */
  -        public CallData (String method, Vector params,
  +        public CallData(String method, Vector params,
                   AsyncCallback callback)
           {
               this.method = method;
  @@ -461,49 +491,47 @@
               this.callback = callback;
               this.next = null;
           }
  -
       }
   
  -
       /**
         * Just for testing.
         */
  -    public static void main (String args[]) throws Exception
  +    public static void main(String args[]) throws Exception
       {
  -        // XmlRpc.setDebug (true);
  -        // XmlRpc.setKeepAlive (true);
  +        // XmlRpc.setDebug(true);
  +        // XmlRpc.setKeepAlive(true);
           try
           {
               String url = args[0];
               String method = args[1];
  -            Vector v = new Vector ();
  +            Vector v = new Vector();
               for (int i = 2; i < args.length; i++)
  +            {
                   try
                   {
  -                    v.addElement (
  -                            new Integer (Integer.parseInt (args[i])));
  +                    v.addElement(
  +                            new Integer(Integer.parseInt(args[i])));
                   }
  -                catch (NumberFormatException nfx)
  +                catch(NumberFormatException nfx)
                   {
  -                    v.addElement (args[i]);
  +                    v.addElement(args[i]);
                   }
  -            XmlRpcClient client = new XmlRpcClientLite (url);
  +            }
  +            XmlRpcClient client = new XmlRpcClientLite(url);
               try
               {
  -                System.err.println (client.execute (method, v));
  +                System.err.println(client.execute(method, v));
               }
  -            catch (Exception ex)
  +            catch(Exception ex)
               {
  -                System.err.println ("Error: "+ex.getMessage());
  +                System.err.println("Error: " + ex.getMessage());
               }
           }
  -        catch (Exception x)
  +        catch(Exception x)
           {
  -            System.err.println (x);
  -            System.err.println ("Usage: java org.apache.xmlrpc.XmlRpcClient <url> <method> <arg> ....");
  -            System.err.println ("Arguments are sent as integers or strings.");
  +            System.err.println(x);
  +            System.err.println("Usage: java org.apache.xmlrpc.XmlRpcClient <url> <method> <arg> ....");
  +            System.err.println("Arguments are sent as integers or strings.");
           }
       }
   }
  -
  -
  
  
  

Re: cvs commit: xml-rpc/src/java/org/apache/xmlrpc Base64.java ServerInputStream.java WebServer.java XmlRpc.java XmlRpcClient.java

Posted by Daniel Rall <dl...@finemaltcoding.com>.
jon@apache.org writes:

> jon         02/02/18 18:25:02
>
>   Modified:    src/java/org/apache/xmlrpc Base64.java
>                         ServerInputStream.java WebServer.java XmlRpc.java
>                         XmlRpcClient.java
>   Log:
>   I did a bunch of code cleanup and minor
>   optimizations, switched to the catalina Base64 (note the one FIXME, if
>   someone has a suggestion for a better way, let me know).
>   
>   Found a couple optimizations (such as not calling System.currentTimeMillis()
>   unless debug is on...

Ugh, you mixed'em...

Re: cvs commit: xml-rpc/src/java/org/apache/xmlrpc Base64.java ServerInputStream.java WebServer.java XmlRpc.java XmlRpcClient.java

Posted by Daniel Rall <dl...@finemaltcoding.com>.
jon@apache.org writes:

> jon         02/02/18 18:25:02
>
>   Modified:    src/java/org/apache/xmlrpc Base64.java
>                         ServerInputStream.java WebServer.java XmlRpc.java
>                         XmlRpcClient.java
>   Log:
>   I did a bunch of code cleanup and minor
>   optimizations, switched to the catalina Base64 (note the one FIXME, if
>   someone has a suggestion for a better way, let me know).
>   
>   Found a couple optimizations (such as not calling System.currentTimeMillis()
>   unless debug is on...

Ugh, you mixed'em...