You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by to...@apache.org on 2003/02/04 06:50:00 UTC

cvs commit: jakarta-commons-sandbox/codec/src/test/org/apache/commons/codec/binary TestBase64.java

tobrien     2003/02/03 21:50:00

  Modified:    codec    TODO
               codec/src/java/org/apache/commons/codec/base64 Base64.java
               codec/src/test/org/apache/commons/codec TestAll.java
  Added:       codec/src/java/org/apache/commons/codec/binary Base64.java
               codec/src/test/org/apache/commons/codec/binary
                        TestBase64.java
  Log:
  Added Base64 impl from xml-rpc courtesy of M. Redington
  
  Revision  Changes    Path
  1.6       +10 -6     jakarta-commons-sandbox/codec/TODO
  
  Index: TODO
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/codec/TODO,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- TODO	4 Feb 2003 04:49:00 -0000	1.5
  +++ TODO	4 Feb 2003 05:50:00 -0000	1.6
  @@ -15,19 +15,23 @@
   
   * Delete language encoders in codec package by 2/10
   
  -* Add a ship encode and decode
  +* move additional string encoding/decoding method from deprecated Base64 to improved Base64
   
  -* Add a btoa encode and decode
  +* add flags to new Base64 for the enforcement of different levels of RFC compliance.
  +
  +* Add a ship encode and decode to binary package
  +
  +* Add a btoa encode and decode to binary package
   
   * Move Base64 from HttpClient to Codec
   
  -* Add a BinHex endode and decode
  +* Add a BinHex endode and decode to binary package
   
  -* Add a uu encode and decode
  +* Add a uu encode and decode to binary package
   
  -* Add a Hex implementation 
  +* Add a Hex implementation to binary package
   
  -* Add a Rot13 implementation 
  +* Add a Rot13 implementation to text package 
   
   * Add a Decoder interface 
   
  
  
  
  1.5       +6 -4      jakarta-commons-sandbox/codec/src/java/org/apache/commons/codec/base64/Base64.java
  
  Index: Base64.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/codec/src/java/org/apache/commons/codec/base64/Base64.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- Base64.java	30 May 2002 16:14:30 -0000	1.4
  +++ Base64.java	4 Feb 2003 05:50:00 -0000	1.5
  @@ -77,6 +77,8 @@
    * </p>
    * @author Jeffrey Rodriguez
    * @version $Revision$ $Date$
  + *
  + * @deprecated This class has been replaced by {@link org.apache.commons.codec.binary.Base64}
    */
   public final class Base64 {
   
  
  
  
  1.1                  jakarta-commons-sandbox/codec/src/java/org/apache/commons/codec/binary/Base64.java
  
  Index: Base64.java
  ===================================================================
  package org.apache.commons.codec.binary;
  
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/codec/src/java/org/apache/commons/codec/binary/Base64.java,v 1.1 2003/02/04 05:50:00 tobrien Exp $
   * $Revision: 1.1 $
   * $Date: 2003/02/04 05:50:00 $
    *
    * ====================================================================
    *
    * 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]
    *
    */
  
  import java.util.Enumeration;
  import java.util.Vector;
  
  /**
    * 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
    * @author Daniel Rall
    * @author <a href="m.redington@ucl.ac.uk">Martin Redington</a>
    * @since 1.2
    */
  public final class Base64
  {
       static final int CHUNK_SIZE = 76;
       static final byte[] CHUNK_SEPARATOR = "\n".getBytes();
  
       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");
  
       static
       {
           for (int i = 0; i < BASELENGTH; i++ )
           {
               base64Alphabet[i] = -1;
           }
           for (int i = 'Z'; i >= 'A'; i--)
           {
               base64Alphabet[i] = (byte) (i - 'A');
           }
           for (int i = 'z'; i>= 'a'; i--)
           {
               base64Alphabet[i] = (byte) (i - 'a' + 26);
           }
           for (int i = '9'; i >= '0'; i--)
           {
               base64Alphabet[i] = (byte) (i - '0' + 52);
           }
  
           base64Alphabet['+']  = 62;
           base64Alphabet['/']  = 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) '/';
       }
  
       public static boolean isBase64( String isValidString )
       {
           return isArrayByteBase64(isValidString.getBytes());
       }
  
       public static boolean isBase64( byte octect )
       {
           //shall we ignore white space? JEFF??
           return (octect == PAD || base64Alphabet[octect] != -1);
       }
  
       public static boolean isArrayByteBase64( byte[] arrayOctect )
       {
  	 arrayOctect = discardWhitespace( arrayOctect );
  
           int length = arrayOctect.length;
           if (length == 0)
           {
               // shouldn't a 0 length array be valid base64 data?
               // return false;
               return true;
           }
           for (int i=0; i < length; i++)
           {
               if ( !Base64.isBase64(arrayOctect[i]) )
                   return false;
           }
           return true;
       }
  
       /**
        * 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;
           int      encodedDataLength = 0;
  
           if (fewerThan24bits != 0)
           {
               //data not divisible by 24 bit
               encodedDataLength = (numberTriplets + 1 ) * 4;
           }
           else
           {
               // 16 or 8 bit
               encodedDataLength = numberTriplets * 4;
           }
  
           // allow extra length for the separator
           int nbrChunks = (CHUNK_SEPARATOR.length == 0 ? 0 :
                            (int) Math.ceil((float) encodedDataLength / CHUNK_SIZE));
  
           encodedDataLength += nbrChunks * CHUNK_SEPARATOR.length;
           encodedData = new byte[encodedDataLength];
  
           byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
  
           int encodedIndex = 0;
           int dataIndex   = 0;
           int i           = 0;
           int nextSeparatorIndex = CHUNK_SIZE;
           int chunksSoFar = 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);
  
               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 ];
  
               encodedIndex += 4;
  
               // this assumes that CHUNK_SIZE % 4 == 0
               if(encodedIndex == nextSeparatorIndex){
                   System.arraycopy(CHUNK_SEPARATOR, 0, encodedData,
                                    encodedIndex, CHUNK_SEPARATOR.length);
                   chunksSoFar++;
                   nextSeparatorIndex = (CHUNK_SIZE * (chunksSoFar + 1)) +
                                        (chunksSoFar * CHUNK_SEPARATOR.length);
                   encodedIndex += CHUNK_SEPARATOR.length;
               }
           }
  
           // form integral number of 6-bit groups
           dataIndex    = i*3;
  
           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;
           }
  
           // we also add a separator to the end of the final chunk.
           if(chunksSoFar < nbrChunks)
               System.arraycopy(CHUNK_SEPARATOR, 0, encodedData,
                                encodedDataLength - 
  			      CHUNK_SEPARATOR.length, CHUNK_SEPARATOR.length);
  
           return encodedData;
       }
  
       /**
        * Decodes Base64 data into octects
        *
        * @param binaryData Byte array containing Base64 data
        * @return Array containing decoded data.
        */
       public static byte[] decode( byte[] base64Data )
       {
           // RFC 2045 suggests line wrapping at (no more than) 76
           // characters -- we may have embedded whitespace.
           base64Data = discardWhitespace(base64Data);
  
           // 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 (--lastData == 0)
                   {
                       return new byte[0];
                   }
               }
               decodedData = new byte[ lastData - numberQuadruple ];
           }
  
           for (int i = 0; i < numberQuadruple; i++)
           {
               dataIndex = i * 4;
               marker0   = base64Data[dataIndex + 2];
               marker1   = base64Data[dataIndex + 3];
  
               b1 = base64Alphabet[base64Data[dataIndex]];
               b2 = base64Alphabet[base64Data[dataIndex +1]];
  
               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 ];
  
                   decodedData[encodedIndex]   = (byte)(  b1 <<2 | b2>>4 );
                   decodedData[encodedIndex + 1] =
                       (byte)(((b2 & 0xf)<<4 ) |( (b3>>2) & 0xf) );
               }
               encodedIndex += 3;
           }
           return decodedData;
       }
  
       /**
        * Discards any whitespace from a base-64 encoded block.
        *
        * Any other non-base-64 characters will be silently
        * discarded. This complies with the RFC, although a warning or
        * exception would also be RFC compliant (and is actually
        * recommended).
        *
        * @param data The base-64 encoded data to discard the whitespace
        * from.
        * @return The data, less whitespace (see RFC 2045).
        */
       static byte[] discardWhitespace(byte[] data)
       {
           byte groomedData[] = new byte[data.length];
           int bytesCopied = 0;
  
           for (int i = 0; i < data.length; i++)
           {
               switch (data[i])
               {
               case (byte) ' ':
               case (byte) '\n':
               case (byte) '\r':
               case (byte) '\t':
                   break;
               default:
                   if(isBase64(data[i])){
                      groomedData[bytesCopied++] = data[i];
                   }
                   else{
                       // according to the RFC, we could raise a warning
                       // or exception here
                   }
               }
           }
  
           byte packedData[] = new byte[bytesCopied];
  
           System.arraycopy(groomedData, 0, packedData,
                                0, bytesCopied);
  
           return packedData;
       }
  }
  
  
  
  
  
  
  
  
  
  
  
  1.6       +7 -4      jakarta-commons-sandbox/codec/src/test/org/apache/commons/codec/TestAll.java
  
  Index: TestAll.java
  ===================================================================
  RCS file: /home/cvs/jakarta-commons-sandbox/codec/src/test/org/apache/commons/codec/TestAll.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- TestAll.java	4 Feb 2003 04:46:01 -0000	1.5
  +++ TestAll.java	4 Feb 2003 05:50:00 -0000	1.6
  @@ -62,11 +62,13 @@
   package org.apache.commons.codec;
   
   import org.apache.commons.codec.language.*;
  +import org.apache.commons.codec.binary.*;
   
   import junit.framework.Test;
   import junit.framework.TestCase;
   import junit.framework.TestSuite;
   
  +
   /**
    * Entry point for all Codec tests.
    * @version $Revision$ $Date$
  @@ -85,6 +87,7 @@
           suite.addTest(TestRefinedSoundex.suite());
   	suite.addTest(TestDoubleMetaphone.suite());
   	suite.addTest(TestNysiis.suite());
  +	suite.addTest(TestBase64.suite());
           return suite;
       }
           
  
  
  
  1.1                  jakarta-commons-sandbox/codec/src/test/org/apache/commons/codec/binary/TestBase64.java
  
  Index: TestBase64.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-commons-sandbox/codec/src/test/org/apache/commons/codec/binary/TestBase64.java,v 1.1 2003/02/04 05:50:00 tobrien Exp $
   * $Revision: 1.1 $
   * $Date: 2003/02/04 05:50:00 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2002 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", "Commons", 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/>.
   *
   */
  package org.apache.commons.codec.binary;
  
  
  import junit.framework.Test;
  import junit.framework.TestCase;
  import junit.framework.TestSuite;
  import java.util.Arrays;
  import java.util.Random;
  
  /**
   * @version $Revision: 1.1 $ $Date: 2003/02/04 05:50:00 $
   * @author Scott Sanders
   * @author Rodney Waldhoff
   */
  public class TestBase64 extends TestCase {
  
      /**
       * Construct a new instance of this test case.
       *
       * @param name Name of the test case
       */
      public TestBase64(String name) {
          super(name);
      }
  
  
      /**
       * Set up instance variables required by this test case.
       */
      public void setUp() {
      }
  
  
      /**
       * Return the tests included in this test suite.
       */
      public static Test suite() {
          return (new TestSuite(TestBase64.class));
      }
  
      /**
       * Tear down instance variables required by this test case.
       */
      public void tearDown() {
      }
  
  
      /**
       *  Test the Base64 implementation
       */
      public void testBase64() {
          String content = "Hello World";
          String encodedContent;
          encodedContent = new String(Base64.encode(content.getBytes()));
          assertTrue("encoding hello world", encodedContent.equals("SGVsbG8gV29ybGQ=\n"));
      }
  
      // encode/decode random arrays from size 0 to size 11
      public void testEncodeDecodeSmall() {
          for(int i=0;i<12;i++) {
              byte[] data = new byte[i];
              _random.nextBytes(data);
              byte[] enc =  Base64.encode(data);
              assertTrue("\"" + (new String(enc)) + "\" is Base64 data.",Base64.isBase64((new String(enc))));
              byte[] data2 = Base64.decode(enc);
              assertTrue(toString(data) + " equals " + toString(data2),Arrays.equals(data,data2));
          }
      }
  
      // encode/decode a large random array
      public void testEncodeDecodeRandom() {
          for(int i=1;i<5;i++) {
              byte[] data = new byte[_random.nextInt(10000)+1];
              _random.nextBytes(data);
              byte[] enc =  Base64.encode(data);
              assertTrue(Base64.isBase64(new String(enc)));
              byte[] data2 = Base64.decode(enc);
              assertTrue(Arrays.equals(data,data2));
          }
      }
  
      public void testSingletons() {
          assertEquals("AA==\n",new String(Base64.encode(new byte[] { (byte)0 })));
          assertEquals("AQ==\n",new String(Base64.encode(new byte[] { (byte)1 })));
          assertEquals("Ag==\n",new String(Base64.encode(new byte[] { (byte)2 })));
          assertEquals("Aw==\n",new String(Base64.encode(new byte[] { (byte)3 })));
          assertEquals("BA==\n",new String(Base64.encode(new byte[] { (byte)4 })));
          assertEquals("BQ==\n",new String(Base64.encode(new byte[] { (byte)5 })));
          assertEquals("Bg==\n",new String(Base64.encode(new byte[] { (byte)6 })));
          assertEquals("Bw==\n",new String(Base64.encode(new byte[] { (byte)7 })));
          assertEquals("CA==\n",new String(Base64.encode(new byte[] { (byte)8 })));
          assertEquals("CQ==\n",new String(Base64.encode(new byte[] { (byte)9 })));
          assertEquals("Cg==\n",new String(Base64.encode(new byte[] { (byte)10 })));
          assertEquals("Cw==\n",new String(Base64.encode(new byte[] { (byte)11 })));
          assertEquals("DA==\n",new String(Base64.encode(new byte[] { (byte)12 })));
          assertEquals("DQ==\n",new String(Base64.encode(new byte[] { (byte)13 })));
          assertEquals("Dg==\n",new String(Base64.encode(new byte[] { (byte)14 })));
          assertEquals("Dw==\n",new String(Base64.encode(new byte[] { (byte)15 })));
          assertEquals("EA==\n",new String(Base64.encode(new byte[] { (byte)16 })));
          assertEquals("EQ==\n",new String(Base64.encode(new byte[] { (byte)17 })));
          assertEquals("Eg==\n",new String(Base64.encode(new byte[] { (byte)18 })));
          assertEquals("Ew==\n",new String(Base64.encode(new byte[] { (byte)19 })));
          assertEquals("FA==\n",new String(Base64.encode(new byte[] { (byte)20 })));
          assertEquals("FQ==\n",new String(Base64.encode(new byte[] { (byte)21 })));
          assertEquals("Fg==\n",new String(Base64.encode(new byte[] { (byte)22 })));
          assertEquals("Fw==\n",new String(Base64.encode(new byte[] { (byte)23 })));
          assertEquals("GA==\n",new String(Base64.encode(new byte[] { (byte)24 })));
          assertEquals("GQ==\n",new String(Base64.encode(new byte[] { (byte)25 })));
          assertEquals("Gg==\n",new String(Base64.encode(new byte[] { (byte)26 })));
          assertEquals("Gw==\n",new String(Base64.encode(new byte[] { (byte)27 })));
          assertEquals("HA==\n",new String(Base64.encode(new byte[] { (byte)28 })));
          assertEquals("HQ==\n",new String(Base64.encode(new byte[] { (byte)29 })));
          assertEquals("Hg==\n",new String(Base64.encode(new byte[] { (byte)30 })));
          assertEquals("Hw==\n",new String(Base64.encode(new byte[] { (byte)31 })));
          assertEquals("IA==\n",new String(Base64.encode(new byte[] { (byte)32 })));
          assertEquals("IQ==\n",new String(Base64.encode(new byte[] { (byte)33 })));
          assertEquals("Ig==\n",new String(Base64.encode(new byte[] { (byte)34 })));
          assertEquals("Iw==\n",new String(Base64.encode(new byte[] { (byte)35 })));
          assertEquals("JA==\n",new String(Base64.encode(new byte[] { (byte)36 })));
          assertEquals("JQ==\n",new String(Base64.encode(new byte[] { (byte)37 })));
          assertEquals("Jg==\n",new String(Base64.encode(new byte[] { (byte)38 })));
          assertEquals("Jw==\n",new String(Base64.encode(new byte[] { (byte)39 })));
          assertEquals("KA==\n",new String(Base64.encode(new byte[] { (byte)40 })));
          assertEquals("KQ==\n",new String(Base64.encode(new byte[] { (byte)41 })));
          assertEquals("Kg==\n",new String(Base64.encode(new byte[] { (byte)42 })));
          assertEquals("Kw==\n",new String(Base64.encode(new byte[] { (byte)43 })));
          assertEquals("LA==\n",new String(Base64.encode(new byte[] { (byte)44 })));
          assertEquals("LQ==\n",new String(Base64.encode(new byte[] { (byte)45 })));
          assertEquals("Lg==\n",new String(Base64.encode(new byte[] { (byte)46 })));
          assertEquals("Lw==\n",new String(Base64.encode(new byte[] { (byte)47 })));
          assertEquals("MA==\n",new String(Base64.encode(new byte[] { (byte)48 })));
          assertEquals("MQ==\n",new String(Base64.encode(new byte[] { (byte)49 })));
          assertEquals("Mg==\n",new String(Base64.encode(new byte[] { (byte)50 })));
          assertEquals("Mw==\n",new String(Base64.encode(new byte[] { (byte)51 })));
          assertEquals("NA==\n",new String(Base64.encode(new byte[] { (byte)52 })));
          assertEquals("NQ==\n",new String(Base64.encode(new byte[] { (byte)53 })));
          assertEquals("Ng==\n",new String(Base64.encode(new byte[] { (byte)54 })));
          assertEquals("Nw==\n",new String(Base64.encode(new byte[] { (byte)55 })));
          assertEquals("OA==\n",new String(Base64.encode(new byte[] { (byte)56 })));
          assertEquals("OQ==\n",new String(Base64.encode(new byte[] { (byte)57 })));
          assertEquals("Og==\n",new String(Base64.encode(new byte[] { (byte)58 })));
          assertEquals("Ow==\n",new String(Base64.encode(new byte[] { (byte)59 })));
          assertEquals("PA==\n",new String(Base64.encode(new byte[] { (byte)60 })));
          assertEquals("PQ==\n",new String(Base64.encode(new byte[] { (byte)61 })));
          assertEquals("Pg==\n",new String(Base64.encode(new byte[] { (byte)62 })));
          assertEquals("Pw==\n",new String(Base64.encode(new byte[] { (byte)63 })));
          assertEquals("QA==\n",new String(Base64.encode(new byte[] { (byte)64 })));
          assertEquals("QQ==\n",new String(Base64.encode(new byte[] { (byte)65 })));
          assertEquals("Qg==\n",new String(Base64.encode(new byte[] { (byte)66 })));
          assertEquals("Qw==\n",new String(Base64.encode(new byte[] { (byte)67 })));
          assertEquals("RA==\n",new String(Base64.encode(new byte[] { (byte)68 })));
          assertEquals("RQ==\n",new String(Base64.encode(new byte[] { (byte)69 })));
          assertEquals("Rg==\n",new String(Base64.encode(new byte[] { (byte)70 })));
          assertEquals("Rw==\n",new String(Base64.encode(new byte[] { (byte)71 })));
          assertEquals("SA==\n",new String(Base64.encode(new byte[] { (byte)72 })));
          assertEquals("SQ==\n",new String(Base64.encode(new byte[] { (byte)73 })));
          assertEquals("Sg==\n",new String(Base64.encode(new byte[] { (byte)74 })));
          assertEquals("Sw==\n",new String(Base64.encode(new byte[] { (byte)75 })));
          assertEquals("TA==\n",new String(Base64.encode(new byte[] { (byte)76 })));
          assertEquals("TQ==\n",new String(Base64.encode(new byte[] { (byte)77 })));
          assertEquals("Tg==\n",new String(Base64.encode(new byte[] { (byte)78 })));
          assertEquals("Tw==\n",new String(Base64.encode(new byte[] { (byte)79 })));
          assertEquals("UA==\n",new String(Base64.encode(new byte[] { (byte)80 })));
          assertEquals("UQ==\n",new String(Base64.encode(new byte[] { (byte)81 })));
          assertEquals("Ug==\n",new String(Base64.encode(new byte[] { (byte)82 })));
          assertEquals("Uw==\n",new String(Base64.encode(new byte[] { (byte)83 })));
          assertEquals("VA==\n",new String(Base64.encode(new byte[] { (byte)84 })));
          assertEquals("VQ==\n",new String(Base64.encode(new byte[] { (byte)85 })));
          assertEquals("Vg==\n",new String(Base64.encode(new byte[] { (byte)86 })));
          assertEquals("Vw==\n",new String(Base64.encode(new byte[] { (byte)87 })));
          assertEquals("WA==\n",new String(Base64.encode(new byte[] { (byte)88 })));
          assertEquals("WQ==\n",new String(Base64.encode(new byte[] { (byte)89 })));
          assertEquals("Wg==\n",new String(Base64.encode(new byte[] { (byte)90 })));
          assertEquals("Ww==\n",new String(Base64.encode(new byte[] { (byte)91 })));
          assertEquals("XA==\n",new String(Base64.encode(new byte[] { (byte)92 })));
          assertEquals("XQ==\n",new String(Base64.encode(new byte[] { (byte)93 })));
          assertEquals("Xg==\n",new String(Base64.encode(new byte[] { (byte)94 })));
          assertEquals("Xw==\n",new String(Base64.encode(new byte[] { (byte)95 })));
          assertEquals("YA==\n",new String(Base64.encode(new byte[] { (byte)96 })));
          assertEquals("YQ==\n",new String(Base64.encode(new byte[] { (byte)97 })));
          assertEquals("Yg==\n",new String(Base64.encode(new byte[] { (byte)98 })));
          assertEquals("Yw==\n",new String(Base64.encode(new byte[] { (byte)99 })));
          assertEquals("ZA==\n",new String(Base64.encode(new byte[] { (byte)100 })));
          assertEquals("ZQ==\n",new String(Base64.encode(new byte[] { (byte)101 })));
          assertEquals("Zg==\n",new String(Base64.encode(new byte[] { (byte)102 })));
          assertEquals("Zw==\n",new String(Base64.encode(new byte[] { (byte)103 })));
          assertEquals("aA==\n",new String(Base64.encode(new byte[] { (byte)104 })));
      }
  
      public void testTriplets() {
          assertEquals("AAAA\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)0 })));
          assertEquals("AAAB\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)1 })));
          assertEquals("AAAC\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)2 })));
          assertEquals("AAAD\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)3 })));
          assertEquals("AAAE\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)4 })));
          assertEquals("AAAF\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)5 })));
          assertEquals("AAAG\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)6 })));
          assertEquals("AAAH\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)7 })));
          assertEquals("AAAI\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)8 })));
          assertEquals("AAAJ\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)9 })));
          assertEquals("AAAK\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)10 })));
          assertEquals("AAAL\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)11 })));
          assertEquals("AAAM\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)12 })));
          assertEquals("AAAN\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)13 })));
          assertEquals("AAAO\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)14 })));
          assertEquals("AAAP\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)15 })));
          assertEquals("AAAQ\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)16 })));
          assertEquals("AAAR\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)17 })));
          assertEquals("AAAS\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)18 })));
          assertEquals("AAAT\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)19 })));
          assertEquals("AAAU\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)20 })));
          assertEquals("AAAV\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)21 })));
          assertEquals("AAAW\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)22 })));
          assertEquals("AAAX\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)23 })));
          assertEquals("AAAY\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)24 })));
          assertEquals("AAAZ\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)25 })));
          assertEquals("AAAa\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)26 })));
          assertEquals("AAAb\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)27 })));
          assertEquals("AAAc\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)28 })));
          assertEquals("AAAd\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)29 })));
          assertEquals("AAAe\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)30 })));
          assertEquals("AAAf\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)31 })));
          assertEquals("AAAg\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)32 })));
          assertEquals("AAAh\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)33 })));
          assertEquals("AAAi\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)34 })));
          assertEquals("AAAj\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)35 })));
          assertEquals("AAAk\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)36 })));
          assertEquals("AAAl\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)37 })));
          assertEquals("AAAm\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)38 })));
          assertEquals("AAAn\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)39 })));
          assertEquals("AAAo\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)40 })));
          assertEquals("AAAp\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)41 })));
          assertEquals("AAAq\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)42 })));
          assertEquals("AAAr\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)43 })));
          assertEquals("AAAs\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)44 })));
          assertEquals("AAAt\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)45 })));
          assertEquals("AAAu\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)46 })));
          assertEquals("AAAv\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)47 })));
          assertEquals("AAAw\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)48 })));
          assertEquals("AAAx\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)49 })));
          assertEquals("AAAy\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)50 })));
          assertEquals("AAAz\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)51 })));
          assertEquals("AAA0\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)52 })));
          assertEquals("AAA1\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)53 })));
          assertEquals("AAA2\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)54 })));
          assertEquals("AAA3\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)55 })));
          assertEquals("AAA4\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)56 })));
          assertEquals("AAA5\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)57 })));
          assertEquals("AAA6\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)58 })));
          assertEquals("AAA7\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)59 })));
          assertEquals("AAA8\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)60 })));
          assertEquals("AAA9\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)61 })));
          assertEquals("AAA+\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)62 })));
          assertEquals("AAA/\n",new String(Base64.encode(new byte[] { (byte)0, (byte)0, (byte)63 })));
      }
  
      public void testKnownEncodings() {
          assertEquals("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg==\n",new String(Base64.encode("The quick brown fox jumped over the lazy dogs.".getBytes())));
          assertEquals("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg==\n",new String(Base64.encode("It was the best of times, it was the worst of times.".getBytes())));
          assertEquals("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw==\n",new String(Base64.encode("http://jakarta.apache.org/commmons".getBytes())));
          assertEquals("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg==\n",new String(Base64.encode("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz".getBytes())));
          assertEquals("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0=\n",new String(Base64.encode("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }".getBytes())));
          assertEquals("eHl6enkh\n",new String(Base64.encode("xyzzy!".getBytes())));
      }
  
      public void testKnownDecodings() {
          assertEquals("The quick brown fox jumped over the lazy dogs.",new String(Base64.decode("VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wZWQgb3ZlciB0aGUgbGF6eSBkb2dzLg==".getBytes())));
          assertEquals("It was the best of times, it was the worst of times.",new String(Base64.decode("SXQgd2FzIHRoZSBiZXN0IG9mIHRpbWVzLCBpdCB3YXMgdGhlIHdvcnN0IG9mIHRpbWVzLg==".getBytes())));
          assertEquals("http://jakarta.apache.org/commmons",new String(Base64.decode("aHR0cDovL2pha2FydGEuYXBhY2hlLm9yZy9jb21tbW9ucw==".getBytes())));
          assertEquals("AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz",new String(Base64.decode("QWFCYkNjRGRFZUZmR2dIaElpSmpLa0xsTW1Obk9vUHBRcVJyU3NUdFV1VnZXd1h4WXlaeg==".getBytes())));
          assertEquals("{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }",new String(Base64.decode("eyAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5IH0=".getBytes())));
          assertEquals("xyzzy!",new String(Base64.decode("eHl6enkh".getBytes())));
      }
  
      // -------------------------------------------------------- Private Methods
  
      private String toString(byte[] data) {
          StringBuffer buf = new StringBuffer();
          for(int i=0;i<data.length;i++) {
              buf.append(data[i]);
              if(i != data.length-1) {
                  buf.append(",");
              }
          }
          return buf.toString();
      }
  
      // ------------------------------------------------------------------------
  
      private Random _random = new Random();
  
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org