directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From elecha...@apache.org
Subject svn commit: r1710496 - in /directory/shared/trunk/asn1/api/src: main/java/org/apache/directory/api/asn1/util/Oid.java test/java/org/apache/directory/api/asn1/util/OidTest.java
Date Sun, 25 Oct 2015 23:19:26 GMT
Author: elecharny
Date: Sun Oct 25 23:19:25 2015
New Revision: 1710496

URL: http://svn.apache.org/viewvc?rev=1710496&view=rev
Log:
Fix for DIRAPI-261. There is still more fixes to push

Modified:
    directory/shared/trunk/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java
    directory/shared/trunk/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java

Modified: directory/shared/trunk/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java?rev=1710496&r1=1710495&r2=1710496&view=diff
==============================================================================
--- directory/shared/trunk/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java (original)
+++ directory/shared/trunk/asn1/api/src/main/java/org/apache/directory/api/asn1/util/Oid.java Sun Oct 25 23:19:25 2015
@@ -23,9 +23,8 @@ package org.apache.directory.api.asn1.ut
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
+import java.math.BigInteger;
 import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.Queue;
 
 import org.apache.directory.api.asn1.DecoderException;
 import org.apache.directory.api.i18n.I18n;
@@ -66,11 +65,11 @@ import org.apache.directory.api.i18n.I18
  * are allocated from the root node, and at most 39 subsequent values from nodes 
  * reached by X = 0 and X = 1.</i></p>
  * 
- * <p>For example, the OID "2.123456.7" would be turned into a list of 2 values:
- * <code>[((2*80)+123456), 7]</code>.  The first of which, 
- * <code>123536</code>, would be encoded as the bytes 
- * <code>[0x87, 0xC5, 0x10]</code>, the second would be <code>[0x07]</code>,
- * giving the final encoding <code>[0x87, 0xC5, 0x10, 0x07]</code>.</p>
+ * <p>For example, the OID "2.12.3456.7" would be turned into a list of 3 values:
+ * <code>[((2*40)+12), 3456, 7]</code>. The first of which, 
+ * <code>92</code>, would be encoded as the bytes <code>0x5C</code>, the second 
+ * would be <code>[0x9B, 0x00]</code>, and the third as <code>0x07</code>
+ * giving the final encoding <code>[0x5C, 0x9B, 0x00, 0x07]</code>.</p>
  * 
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
@@ -81,6 +80,76 @@ public final class Oid
     
     /** The OID as a String */
     private String oidString;
+    
+    private static final BigInteger JOINT_ISO_ITU_T = new BigInteger( "80" );
+    
+    /**
+     * The OID FSA states. We have the following Finite State Automaton :
+     * 
+     * <pre>
+     * (Start) --['0','1']--> (A)
+     * (start) --['2']--> (F)
+     * 
+     * (A) --['.']--> (B)
+     * 
+     * (B) --['0']--> (D)
+     * (B) --['1'..'3']--> (C)
+     * (B) --['4'..'9']--> (E)
+     * 
+     * (C) --[]--> (End)
+     * (C) --['.']--> (K)
+     * (C) --['0'..'9']--> (E)
+     * 
+     * (D) --[]--> (End)
+     * (D) --['.']--> (K)
+     * 
+     * (E) --[]--> (End)
+     * (E) --['.']--> (K)
+     * 
+     * (F) --['.']--> (G)
+     * 
+     * (G) --['0']--> (I)
+     * (G) --['1'..'9']--> (H)
+     *
+     * (H) --[]--> (End)
+     * (H) --['.']--> (K)
+     * (H) --['0'..'9']--> (J)
+     * 
+     * (I) --[]--> (End)
+     * (I) --['.']--> (K)
+     *
+     * (J) --[]--> (End)
+     * (J) --['.']--> (K)
+     * (J) --['0'..'9']--> (J)
+     * 
+     * (K) --['0']--> (M) 
+     * (K) --['1'..'9']--> (L)
+     * 
+     * (L) --[]--> (End)
+     * (L) --['.']--> (K)
+     * (L) --['0'..'9']--> (L)
+     * 
+     * (M) --[]--> (End)
+     * (M) --['.']--> (K)
+     * </pre>
+     */
+    private enum OidFSAState 
+    {
+        START,
+        STATE_A,
+        STATE_B,
+        STATE_C,
+        STATE_D,
+        STATE_E,
+        STATE_F,
+        STATE_G,
+        STATE_H,
+        STATE_I,
+        STATE_J,
+        STATE_K,
+        STATE_L,
+        STATE_M,
+    }
 
 
     /**
@@ -117,7 +186,7 @@ public final class Oid
      */
     public static Oid fromBytes( byte[] oidBytes ) throws DecoderException
     {
-        if ( oidBytes == null || oidBytes.length < 1 )
+        if ( ( oidBytes == null ) || ( oidBytes.length < 1 ) )
         {
             throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, Arrays.toString( oidBytes ) ) );
         }
@@ -189,8 +258,8 @@ public final class Oid
      * @param oidString The string representation of the OID
      * @return A new Oid
      * @throws DecoderException  When the OID is not valid
-     */
-    public static Oid fromString( String oidString ) throws DecoderException
+     *
+    public static Oid fromStringLong( String oidString ) throws DecoderException
     {
         if ( ( oidString == null ) || oidString.isEmpty() )
         {
@@ -239,8 +308,1008 @@ public final class Oid
         return new Oid( oidString, buffer.toByteArray() );
     }
 
+    
+    /**
+     * Process state A
+     * <pre>
+     * (Start) --['0','1']--> (A)
+     * (start) --['2']--> (F)
+     * </pre>
+     */
+    private static OidFSAState processStateStart( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+                buffer[0] = ( byte ) ( ( c - '0' ) * 40 );
+                return OidFSAState.STATE_A;
+                
+            case '2' :
+                return OidFSAState.STATE_F;
+                
+            default :
+                // This is an error
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Should start with 0, 1 or 2" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state B
+     * <pre>
+     * (A) --['.']--> (B)
+     * </pre>
+     */
+    private static OidFSAState processStateA( String oid, int pos ) throws DecoderException
+    {
+        if ( oid.charAt( pos ) != '.' )
+        {
+            // Expecting a Dot here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+        
+        return OidFSAState.STATE_B;
+    }
+    
+    
+    /**
+     * Process state B
+     * <pre>
+     * (B) --['0']--> (D)
+     * (B) --['1'..'3']--> (C)
+     * (B) --['4'..'9']--> (E)
+     * </pre>
+     */
+    private static OidFSAState processStateB( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                return OidFSAState.STATE_D;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+                // We may have a second digit. Atm, store the current one in the second psotion
+                buffer[1] = ( byte ) ( c - '0' );
+                
+                return  OidFSAState.STATE_C;
+                
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                buffer[0] += ( byte ) ( c - '0' );
+                return OidFSAState.STATE_E;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state C
+     * <pre>
+     * (C) --['.']--> (K)
+     * (C) --['0'..'9']--> (E)
+     * </pre>
+     */
+    private static OidFSAState processStateC( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                buffer[0] += ( byte ) ( buffer[1] * 10 + ( c - '0' ) );
+                buffer[1] = 0;
+                return OidFSAState.STATE_E;
+
+            case '.' :
+                buffer[0] += buffer[1];
+                buffer[1] = 0;
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state D and E
+     * <pre>
+     * (D) --['.']--> (K)
+     * (E) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateDE( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        if ( c != '.' )
+        {
+            // Expecting a '.' here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a dot is expected" ) );
+        }
+        
+        // Store the first byte into it
+        buffer[0] = ( byte ) ( buffer[0] | buffer[1] );
+        buffer[1] = 0;
+        
+        return OidFSAState.STATE_K;
+    }
+    
+    
+    /**
+     * Process state F
+     * <pre>
+     * (F) --['.']--> (G)
+     * </pre>
+     */
+    private static OidFSAState processStateF( String oid, int pos ) throws DecoderException
+    {
+        if ( oid.charAt( pos ) != '.' )
+        {
+            // Expecting a Dot here
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+        
+        return OidFSAState.STATE_G;
+    }
+    
+    
+    /**
+     * Process state G
+     * <pre>
+     * (G) --['0']--> (I)
+     * (G) --['1'..'9']--> (H)
+     * </pre>
+     */
+    private static OidFSAState processStateG( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                buffer[0] = ( byte ) 80;
+                return OidFSAState.STATE_I;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the read digit in the second position in the buffer
+                buffer[0] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_H;
+
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state H
+     * <pre>
+     * (H) --['.']--> (K)
+     * (H) --['0'..'9']--> (J)
+     * </pre>
+     */
+    private static OidFSAState processStateH( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the read digit in the first position in the buffer
+                buffer[1] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_J;
+
+            case '.' :
+                // The first 2 arcs are single digit, we can collapse them in one byte.
+                buffer[0] = ( byte ) ( 80 + buffer[0] );
+                
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state I
+     * <pre>
+     * (I) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateI( String oid, byte[] buffer, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                // The first 2 arcs are single digit, we can collapse them in one byte.
+                buffer[0] = ( byte ) ( 80 + buffer[1] );
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (J) --['.']--> (K)
+     * (J) --['0'..'9']--> (J)
+     * </pre>
+     */
+    private static OidFSAState processStateJ( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                buffer[bufferPos] = ( byte ) ( c - '0' );
+                return OidFSAState.STATE_J;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (K) --['0']--> (M)
+     * (K) --['1'..'9']--> (L)
+     * </pre>
+     */
+    private static OidFSAState processStateK( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '0' :
+                buffer[bufferPos] = 0x00;
+                return OidFSAState.STATE_M;
+                
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                return OidFSAState.STATE_L;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit is expected" ) );
+        }
+    }
+    
+    
+    /**
+     * Process state J
+     * <pre>
+     * (L) --['.']--> (K)
+     * (L) --['0'..'9']--> (L)
+     * </pre>
+     */
+    private static OidFSAState processStateL( String oid, byte[] buffer, int bufferPos, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            case '0' :
+            case '1' :
+            case '2' :
+            case '3' :
+            case '4' :
+            case '5' :
+            case '6' :
+            case '7' :
+            case '8' :
+            case '9' :
+                // Store the new digit at the right position in the buffer
+                buffer[bufferPos] = ( byte ) ( c - '0' );
+                
+                return OidFSAState.STATE_L;
+                
+            default :
+                // Expecting a digit here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a digit or a dot is expected" ) );
+        }
+    }
+
+    
+    /**
+     * Process state J
+     * <pre>
+     * (M) --['.']--> (K)
+     * </pre>
+     */
+    private static OidFSAState processStateM( String oid, int pos ) throws DecoderException
+    {
+        char c = oid.charAt( pos );
+        
+        switch ( c )
+        {
+            case '.' :
+                return OidFSAState.STATE_K;
+                
+            default :
+                // Expecting a '.' here
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "a '.' is expected" ) );
+        }
+    }
+
+    
+    /**
+     * Compute the number of bytes necessary to store a long
+     */
+    private int getNbBytes( long value )
+    {
+        if ( value > 0x00000000FFFFFFFFL )
+        {
+            if ( value > 0x0000FFFFFFFFFFFFL )
+            {
+                if ( value > 0x00FFFFFFFFFFFFFFL )
+                {
+                    return 8;
+                }
+                else
+                {
+                    return 7;
+                }
+            }
+            else
+            {
+                if ( value > 0x000000FFFFFFFFFFL )
+                {
+                    return 6;
+                }
+                else
+                {
+                    return 5;
+                }
+            }
+                
+        }
+        else
+        {
+            if ( value > 0x00000000000000FFFFL )
+            {
+                if ( value > 0x0000000000FFFFFFL )
+                {
+                    return 4;
+                }
+                else
+                {
+                    return 3;
+                }
+            }
+            else
+            {
+                if ( value > 0x00000000000000FFL )
+                {
+                    return 2;
+                }
+                else
+                {
+                    return 1;
+                }
+                
+            }
+        }
+    }
+    
+    
+    /**
+     * Get a bte[] that will hold the 
+     * TODO getBytes.
+     *
+     * @param value
+     * @return
+     */
+    private byte[] getBytes( long value )
+    {
+        int nbBytes = getNbBytes( value );
+        
+        return new byte[nbBytes];
+
+    }
 
     /**
+     * Convert a list of digits to a list of 7 bits bytes. We must start by the end, and we don't
+     * know how many bytes we will need, except when we will be done with the conversion.
+     */
+    private static int convert( String oid, byte[] buffer, int start, int nbDigits, int posBuffer, boolean isJointIsoItuT )
+    {
+        if ( nbDigits < 3 )
+        {
+            // Speedup when we have a number in [0..99] : it's guaranteed to be hold
+            // by a single byte.
+            if ( isJointIsoItuT )
+            {
+                // Another special case : this is an OID that starts with '2.'
+                buffer[0] =  ( byte ) ( 80 + ( oid.charAt( 2 ) - '0' ) * 10 + ( oid.charAt( 3 ) - '0' ) );
+                
+                if ( buffer[0] < 0 )
+                {
+                    // Here, we need 2 bytes
+                    buffer[1] = ( byte ) ( buffer[0] & 0x007F );
+                    buffer[0] = ( byte ) 0x81;
+                    
+                    return 2;
+                }
+                else
+                {
+                    return 1;
+                }
+            }
+            else
+            {
+                if ( nbDigits == 1 )
+                {
+                    buffer[posBuffer] = ( byte ) ( oid.charAt( start ) - '0' );
+                }
+                else
+                {
+                    buffer[posBuffer] = ( byte ) ( ( oid.charAt( start ) - '0' ) * 10 + ( oid.charAt( start + 1 ) - '0' ) );
+                    
+                }
+                return 1;
+            }
+
+        }
+        else if ( nbDigits < 19 )
+        {
+            // The value can be hold in a Long if it's up to 999999999999999999 
+            // Convert the String to a long :
+            String number = oid.substring( start, start + nbDigits );
+
+            long value = Long.parseLong( number );
+
+            if ( isJointIsoItuT )
+            {
+                value += 80L;
+            }
+            
+            // Convert the long to a byte array
+            if ( ( value & 0xFFFFFFFFFFFFFF80L ) == 0 )
+            {
+                // The value will be hold in one byte
+                buffer[posBuffer] = ( byte ) ( value );
+                
+                return 1;
+            }
+            
+            if ( ( value & 0xFFFFFFFFFFFFC000L ) == 0 )
+            {
+                // The value is between 0x80 and 0x3FFF : it will be hold in 2 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 2;
+            }
+            
+            if ( ( value & 0xFFFFFFFFFFE00000L ) == 0 )
+            {
+                // The value is between 0x4000 and 0x1FFFFF : it will be hold in 3 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 3;
+            }
+            
+            if ( ( value & 0xFFFFFFFFF0000000L ) == 0 )
+            {
+                // The value is between 0x200000 and 0xFFFFFFF : it will be hold in 4 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 4;
+            }
+
+            if ( ( value & 0xFFFFFFF800000000L ) == 0 )
+            {
+                // The value is between 0x10000000 and 0x7FFFFFFFF : it will be hold in 5 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 5;
+            }
+
+            if ( ( value & 0xFFFFFC0000000000L ) == 0 )
+            {
+                // The value is between 0x800000000 and 0x3FFFFFFFFFF : it will be hold in 6 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 6;
+            }
+
+            if ( ( value & 0xFFFE000000000000L ) == 0 )
+            {
+                // The value is between 0x40000000000 and 0x1FFFFFFFFFFFF : it will be hold in 7 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 7;
+            }
+
+            if ( ( value & 0xFF00000000000000L ) == 0 )
+            {
+                // The value is between 0x2000000000000 and 0xFF000000000000 : it will be hold in 8 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 7] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 8;
+            }
+            else
+            {
+                // The value is between 0x100000000000000 and 0x7F00000000000000 : it will be hold in 9 bytes
+                buffer[posBuffer] = ( byte ) ( ( byte ) ( ( value & 0x7F00000000000000L ) >> 56 ) | 0x80 );
+                buffer[posBuffer + 1] = ( byte ) ( ( byte ) ( ( value & 0x00FE000000000000L ) >> 49 ) | 0x80 );
+                buffer[posBuffer + 2] = ( byte ) ( ( byte ) ( ( value & 0x0001FC0000000000L ) >> 42 ) | 0x80 );
+                buffer[posBuffer + 3] = ( byte ) ( ( byte ) ( ( value & 0x000003F800000000L ) >> 35 ) | 0x80 );
+                buffer[posBuffer + 4] = ( byte ) ( ( byte ) ( ( value & 0x00000007F0000000L ) >> 28 ) | 0x80 );
+                buffer[posBuffer + 5] = ( byte ) ( ( byte ) ( ( value & 0x000000000FE00000L ) >> 21 ) | 0x80 );
+                buffer[posBuffer + 6] = ( byte ) ( ( byte ) ( ( value & 0x00000000001FC000L ) >> 14 ) | 0x80 );
+                buffer[posBuffer + 7] = ( byte ) ( ( byte ) ( ( value & 0x0000000000003F80L ) >> 7 ) | 0x80 );
+                buffer[posBuffer + 8] = ( byte ) ( value & 0x000000000000007FL );
+                
+                return 9;
+            }
+        }
+        else
+        {
+            // The value is bigger than 9999999999999999999, we need to use a BigInteger
+            // First, get the number of bytes we need to store the value in base 16
+            String number = oid.substring( start, start + nbDigits );
+            BigInteger bigInteger = new BigInteger( number );
+            
+            if ( isJointIsoItuT )
+            {
+                bigInteger = bigInteger.add( JOINT_ISO_ITU_T );
+                posBuffer = 0;
+            }
+            
+            byte[] bytes = bigInteger.toByteArray();
+            
+            // Now, convert this value to the ASN.1 OID format : we store the value
+            // as 7 bits bytes 
+            int nbNeededBytes = ( bytes.length * 8 ) / 7;
+            
+            switch ( ( bytes.length - 1 ) % 7 )
+            {
+                case 0 :
+                    if ( ( bytes[0] & 0x0080 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 1 :
+                    if ( ( bytes[0] & 0x00C0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 2 :
+                    if ( ( bytes[0] & 0x00E0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 3 : 
+                    if ( ( bytes[0] & 0x00F0 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 4 :
+                    if ( ( bytes[0] & 0x00F8 ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 5 :
+                    if ( ( bytes[0] & 0x00FC ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                case 6 : 
+                    if ( ( bytes[0] & 0x00FE ) != 0 )
+                    {
+                        nbNeededBytes++;
+                    }
+                    
+                    break;
+                    
+                default :
+                    // Exist to please checkstyle...
+                    break;
+            }
+            
+            byte[] converted = new byte[nbNeededBytes];
+            
+            int posConverted = nbNeededBytes - 1;
+            int posBytes = bytes.length - 1;
+            int counter = 0;
+            byte reminder = 0;
+            
+            while ( posBytes >= 0 )
+            {
+                byte newByte = ( byte ) ( ( bytes[posBytes] & 0x00FF ) << counter );
+                converted[posConverted] = ( byte ) ( reminder | newByte | 0x0080 );
+                reminder = ( byte ) ( ( bytes[posBytes] & 0x00FF ) >> ( 7 - counter ) );
+                counter =  ( counter + 1 ) % 8; 
+                posConverted--;
+                
+                if ( counter != 0 )
+                {
+                    posBytes--;
+                }
+                else
+                {
+                    reminder = 0;
+                }
+            }
+            
+            converted[nbNeededBytes - 1] &= 0x7F;
+            
+            // Copy the converted bytes in the buffer
+            System.arraycopy( converted, 0, buffer, posBuffer, nbNeededBytes );
+            
+            return nbNeededBytes;
+        }
+    }
+    
+    
+    /**
+     * Returns an OID object representing <code>oidString</code>.  
+     *  
+     * @param oidString The string representation of the OID
+     * @return A new Oid
+     * @throws DecoderException  When the OID is not valid
+     */
+    public static Oid fromString( String oidString ) throws DecoderException
+    {
+        if ( ( oidString == null ) || oidString.isEmpty() )
+        {
+            throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "empty" ) );
+        }
+
+        // Create a buffer that is wide enough to contain all the values
+        byte[] buffer = new byte[oidString.length()];
+
+        OidFSAState state = OidFSAState.START;
+        
+        // A counter of chars used for an arc. In 1.2.45345, this counter will be 5 for the '45345' arc.
+        int arcNbChars = 0;
+        
+        // The position in the buffer where we accumulate the result. 
+        int bufPos = 0;
+        
+        // The position in the OID string where we started to read an arc
+        int startArc = 0;
+        
+        // The number of bytes in the resulting OID byte[]
+        int nbBytes = 0;
+        
+        boolean isJointIsoItuT = false;
+        
+        for ( int i = 0; i < oidString.length(); i++ )
+        {
+            switch ( state )
+            {
+                case START :
+                    // (Start) --['0'..'1']--> (A)
+                    // (start) --['2']--> (F)
+                    state = processStateStart( oidString, buffer, i );
+                    break;
+                    
+                case STATE_A :
+                    // (A) --['.']--> (B)
+                    state = processStateA( oidString, i );
+
+                    
+                    break;
+                    
+                case STATE_B :
+                    // (B) --['0']--> (D)
+                    // (B) --['1'..'3']--> (C)
+                    // (B) --['4'..'9']--> (E)
+                    state = processStateB( oidString, buffer, i );
+                    
+                    break;
+                    
+                case STATE_C :
+                    // (C) --['.']--> (K)
+                    // (C) --['0'..'9']--> (E)
+                    state = processStateC( oidString, buffer, i );
+
+                    // the next arc will be store at position 1 in the buffer
+                    bufPos = 1;
+
+                    break;
+                    
+                case STATE_D :
+                    // (D) --['.']--> (K)
+                    // Fallthrough
+                    
+                case STATE_E :
+                    // (E) --['.']--> (K)
+                    state = processStateDE( oidString, buffer, i );
+                    
+                    // the next arc will be store at position 1 in teh buffer
+                    bufPos = 1;
+
+                    break;
+                    
+                case STATE_F :
+                    isJointIsoItuT = true;
+                    // (F) --['.']--> (G)
+                    state = processStateF( oidString, i );
+                    
+                    break;
+                    
+                case STATE_G :
+                    // (G) --['0']--> (I)
+                    // (G) --['1'..'9']--> (H)
+                    state = processStateG( oidString, buffer, i );
+                    arcNbChars = 1;
+                    startArc = i;
+
+                    break;
+
+                case STATE_H :
+                    // (H) --['.']--> (K)
+                    // (H) --['0'..'9']--> (J)
+                    state = processStateH( oidString, buffer, i );
+                    
+                    if ( state == OidFSAState.STATE_J )
+                    {
+                        // We have already two digits
+                        arcNbChars = 2;
+                        bufPos = 0;
+                    }
+                    
+                    break;
+
+                case STATE_I :
+                    // (I) --['.']--> (K)
+                    state = processStateI( oidString, buffer, i );
+                    
+                    // Set the arc position to buffer[1], we haven't yet accumulated digits.
+                    bufPos = 1;
+                    
+                    break;
+
+                case STATE_J :
+                    // (J) --['.']--> (K)
+                    // (J) --['0'..'9']--> (J)
+                    state = processStateJ( oidString, buffer, arcNbChars + bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_J )
+                    {
+                        // We can increment the number of digit for this arc
+                        arcNbChars++;
+                    }
+                    else
+                    {
+                        // We are done with the first arc : convert it
+                        bufPos += convert( oidString, buffer, bufPos, arcNbChars, 0, true );
+                    }
+                    
+                    break;
+
+                case STATE_K :
+                    startArc = i;
+                    state = processStateK( oidString, buffer, bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_M )
+                    { 
+                        bufPos++;
+                    }
+                    else
+                    {
+                        arcNbChars = 1;
+                    }
+                    
+                    break;
+
+                case STATE_L :
+                    state = processStateL( oidString, buffer, arcNbChars + bufPos, i );
+                    
+                    if ( state == OidFSAState.STATE_L )
+                    {
+                        arcNbChars++;
+                        break;
+                    }
+                    else
+                    {
+                        // We are done with the arc : convert it
+                        bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
+                    }
+
+                    break;
+                    
+                case STATE_M :
+                    state = processStateM( oidString, i );
+                    break;
+                    
+                default :
+                    // Exist to please checkstyle...
+                    break;
+            }
+        }
+        
+        // End of the string : check that we are in a correct state for a completion
+        // The only valid exit states are :
+        // (C) --[]--> (End)
+        // (D) --[]--> (End)
+        // (E) --[]--> (End)
+        // (H) --[]--> (End)
+        // (I) --[]--> (End)
+        // (J) --[]--> (End)
+        // (L) --[]--> (End)
+        // (M) --[]--> (End)
+        switch ( state )
+        {
+            case STATE_C :
+                // (C) --[]--> (End)
+                // fallthrough
+                
+            case STATE_D :
+                // (D) --[]--> (End)
+                // fallthrough
+                
+            case STATE_E :
+                // (E) --[]--> (End)
+                // fallthrough
+
+            case STATE_H :
+                // (H) --[]--> (End)
+                // fallthrough
+                
+            case STATE_I :
+                // (I) --[]--> (End)
+                byte[] bytes = new byte[1];
+                bytes[0] = ( byte ) ( buffer[0] | buffer[1] );
+
+                return new Oid( oidString, bytes );
+                
+            case STATE_J :
+                // (J) --[]--> (End)
+                nbBytes = convert( oidString, buffer, 2, arcNbChars, 0, true );
+                bytes = new byte[nbBytes];
+                System.arraycopy( buffer, 0, bytes, 0, nbBytes );
+                
+                return new Oid( oidString, bytes );
+
+            case STATE_L :
+                bufPos += convert( oidString, buffer, startArc, arcNbChars, bufPos, false );
+                bytes = new byte[bufPos];
+                System.arraycopy( buffer, 0, bytes, 0, bufPos );
+                
+                return new Oid( oidString, bytes );
+                
+            case STATE_M :
+                bytes = new byte[bufPos];
+                System.arraycopy( buffer, 0, bytes, 0, bufPos );
+                
+                return new Oid( oidString, bytes );
+            default :
+                // This should never happen...
+                throw new DecoderException( I18n.err( I18n.ERR_00033_INVALID_OID, "Wrong OID" ) );
+        }
+    }
+
+    
+    /**
      * Returns the length of the encoded <code>byte[]</code> representation.
      * 
      * @return The length of the byte[]

Modified: directory/shared/trunk/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java
URL: http://svn.apache.org/viewvc/directory/shared/trunk/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java?rev=1710496&r1=1710495&r2=1710496&view=diff
==============================================================================
--- directory/shared/trunk/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java (original)
+++ directory/shared/trunk/asn1/api/src/test/java/org/apache/directory/api/asn1/util/OidTest.java Sun Oct 25 23:19:25 2015
@@ -109,6 +109,35 @@ public class OidTest
         assertEquals( expectedString, Oid.fromString( expectedString ).toString() );
     }
 
+    
+    /** Hex chars */
+    private static final byte[] HEX_CHAR = new byte[]
+        { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+
+    /**
+     * Helper function that dump an array of bytes in hex form
+     *
+     * @param buffer The bytes array to dump
+     * @return A string representation of the array of bytes
+     */
+    public static String dumpBytes( byte[] buffer )
+    {
+        if ( buffer == null )
+        {
+            return "";
+        }
+
+        StringBuffer sb = new StringBuffer();
+
+        for ( int i = 0; i < buffer.length; i++ )
+        {
+            sb.append( "0x" ).append( ( char ) ( HEX_CHAR[( buffer[i] & 0x00F0 ) >> 4] ) ).append(
+                ( char ) ( HEX_CHAR[buffer[i] & 0x000F] ) ).append( " " );
+        }
+
+        return sb.toString();
+    }
+
 
     @Test
     public void fromString() throws DecoderException
@@ -118,9 +147,10 @@ public class OidTest
         { // [0..2]
             for ( int j = 0; j < 40; j++ )
             { // [0..39]
-                assertTrue( Arrays.equals( new byte[]
-                    { ( byte ) ( i * 40 + j ) },
-                    Oid.fromString( i + "." + j ).toBytes() ) );
+                String oidStr = i + "." + j;
+                byte[] expected = new byte[]{ ( byte ) ( i * 40 + j ) };
+                byte[] oidBytes = Oid.fromString( oidStr ).toBytes();
+                assertTrue( Arrays.equals( expected, oidBytes ) );
             }
         }
 
@@ -350,13 +380,20 @@ public class OidTest
     public void testNewOidStringBad()
     {
         assertFalse( Oid.isOid( "0" ) );
+        assertFalse( Oid.isOid( "1" ) );
         assertFalse( Oid.isOid( "0." ) );
+        assertFalse( Oid.isOid( "1." ) );
+        assertFalse( Oid.isOid( "2." ) );
+        assertFalse( Oid.isOid( "2." ) );
         assertFalse( Oid.isOid( "." ) );
         assertFalse( Oid.isOid( "0.1.2." ) );
         assertFalse( Oid.isOid( "3.1" ) );
         assertFalse( Oid.isOid( "0..1" ) );
         assertFalse( Oid.isOid( "0..12" ) );
         assertFalse( Oid.isOid( "0.a.2" ) );
+        assertFalse( Oid.isOid( "0.40" ) );
+        assertFalse( Oid.isOid( "0.51" ) );
+        assertFalse( Oid.isOid( "0.01" ) );
         assertFalse( Oid.isOid( "0.123456" ) );
         assertFalse( Oid.isOid( "1.123456" ) );
     }
@@ -384,6 +421,252 @@ public class OidTest
 
 
     /**
+     * Test an OID with a node which does not fit in a long
+     * @throws DecoderException 
+     */
+    @Test
+    public void testOidLongValue() throws DecoderException
+    {
+        // 2.0 -> expected 0x02
+        Oid oid = Oid.fromString( "2.0" );
+        byte[] oidBytes = oid.toBytes();
+        assertEquals( 1, oidBytes.length );
+        assertEquals( 80, oidBytes[0] );
+        
+        // 2.40 -> expected 0x78
+        oid = Oid.fromString( "2.40" );
+        oidBytes = oid.toBytes();
+        assertEquals( 1, oidBytes.length );
+        assertEquals( 0x78, oidBytes[0] );
+        
+        // 2.48 -> expected 0x80
+        oid = Oid.fromString( "2.48" );
+        oidBytes = oid.toBytes();
+        assertEquals( 2, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( 0x00, oidBytes[1] );
+        
+        // The second arc is below and equal to 16304 : 0x4000 - 0x50
+        oid = Oid.fromString( "2.16303" );
+        oidBytes = oid.toBytes();
+        assertEquals( 2, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( 0x7F, oidBytes[1] );
+
+        oid = Oid.fromString( "2.16304" );
+        oidBytes = oid.toBytes();
+        assertEquals( 3, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( 0x00, oidBytes[2] );
+        
+        // The second arc is below and equal to 2097072 : 0x200000 - 0x50
+        oid = Oid.fromString( "2.2097071" );
+        oidBytes = oid.toBytes();
+        assertEquals( 3, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( 0x7F, oidBytes[2] );
+
+        oid = Oid.fromString( "2.2097072" );
+        oidBytes = oid.toBytes();
+        assertEquals( 4, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( 0x00, oidBytes[3] );
+        
+        // The second arc is below and equal to 268435376 : 0x10000000 - 0x50
+        oid = Oid.fromString( "2.268435375" );
+        oidBytes = oid.toBytes();
+        assertEquals( 4, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( 0x7F, oidBytes[3] );
+
+        oid = Oid.fromString( "2.268435376" );
+        oidBytes = oid.toBytes();
+        assertEquals( 5, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( 0x00, oidBytes[4] );
+        
+        // The second arc is below and equal to 34359738288 : 0x800000000 - 0x50
+        oid = Oid.fromString( "2.34359738287" );
+        oidBytes = oid.toBytes();
+        assertEquals( 5, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( 0x7F, oidBytes[4] );
+
+        oid = Oid.fromString( "2.34359738288" );
+        oidBytes = oid.toBytes();
+        assertEquals( 6, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( 0x00, oidBytes[5] );
+
+        // The second arc is below and equal to 4398046511024 : 0x40000000000 - 0x50
+        oid = Oid.fromString( "2.4398046511023" );
+        oidBytes = oid.toBytes();
+        assertEquals( 6, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( 0x7F, oidBytes[5] );
+
+        oid = Oid.fromString( "2.4398046511024" );
+        oidBytes = oid.toBytes();
+        assertEquals( 7, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( 0x00, oidBytes[6] );
+
+        // The second arc is below and equal to 562949953421232 : 0x2000000000000 - 0x50
+        oid = Oid.fromString( "2.562949953421231" );
+        oidBytes = oid.toBytes();
+        assertEquals( 7, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( 0x7F, oidBytes[6] );
+
+        oid = Oid.fromString( "2.562949953421232" );
+        oidBytes = oid.toBytes();
+        assertEquals( 8, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( 0x00, oidBytes[7] );
+
+        // The second arc is below and equal to 72057594037927856 : 0x100000000000000 - 0x50
+        oid = Oid.fromString( "2.72057594037927855" );
+        oidBytes = oid.toBytes();
+        assertEquals( 8, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( 0x7F, oidBytes[7] );
+
+        oid = Oid.fromString( "2.72057594037927856" );
+        oidBytes = oid.toBytes();
+        assertEquals( 9, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( (byte)0x80, oidBytes[7] );
+        assertEquals( 0x00, oidBytes[8] );
+
+        // The second arc is below and equal to 9223372036854775728 : 0x8000000000000000 - 0x50
+        oid = Oid.fromString( "2.9223372036854775727" );
+        oidBytes = oid.toBytes();
+        assertEquals( 9, oidBytes.length );
+        assertEquals( (byte)0xFF, oidBytes[0] );
+        assertEquals( (byte)0xFF, oidBytes[1] );
+        assertEquals( (byte)0xFF, oidBytes[2] );
+        assertEquals( (byte)0xFF, oidBytes[3] );
+        assertEquals( (byte)0xFF, oidBytes[4] );
+        assertEquals( (byte)0xFF, oidBytes[5] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( (byte)0xFF, oidBytes[6] );
+        assertEquals( (byte)0xFF, oidBytes[7] );
+        assertEquals( 0x7F, oidBytes[8] );
+
+        oid = Oid.fromString( "2.9223372036854775728" );
+        oidBytes = oid.toBytes();
+        assertEquals( 10, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x80, oidBytes[1] );
+        assertEquals( (byte)0x80, oidBytes[2] );
+        assertEquals( (byte)0x80, oidBytes[3] );
+        assertEquals( (byte)0x80, oidBytes[4] );
+        assertEquals( (byte)0x80, oidBytes[5] );
+        assertEquals( (byte)0x80, oidBytes[6] );
+        assertEquals( (byte)0x80, oidBytes[7] );
+        assertEquals( (byte)0x80, oidBytes[8] );
+        assertEquals( 0x00, oidBytes[9] );
+
+        // Check for 9999999999999999999 which is higher than Long.MAX_VALUE
+        oid = Oid.fromString( "2.9999999999999999999" );
+        oidBytes = oid.toBytes();
+        assertEquals( 10, oidBytes.length );
+        assertEquals( (byte)0x81, oidBytes[0] );
+        assertEquals( (byte)0x8A, oidBytes[1] );
+        assertEquals( (byte)0xE3, oidBytes[2] );
+        assertEquals( (byte)0xC8, oidBytes[3] );
+        assertEquals( (byte)0xE0, oidBytes[4] );
+        assertEquals( (byte)0xC8, oidBytes[5] );
+        assertEquals( (byte)0xCF, oidBytes[6] );
+        assertEquals( (byte)0xA0, oidBytes[7] );
+        assertEquals( (byte)0x80, oidBytes[8] );
+        assertEquals( (byte)0x4F, oidBytes[9] );
+
+        // A bigger one
+        oid = Oid.fromString( "2.81407072025111374527560065493494091452" );
+        oidBytes = oid.toBytes();
+        assertEquals( 18, oidBytes.length );
+        assertEquals( (byte)0xFA, oidBytes[0] );
+        assertEquals( (byte)0xBE, oidBytes[1] );
+        assertEquals( (byte)0xB7, oidBytes[2] );
+        assertEquals( (byte)0xA2, oidBytes[3] );
+        assertEquals( (byte)0x8E, oidBytes[4] );
+        assertEquals( (byte)0xF4, oidBytes[5] );
+        assertEquals( (byte)0xC0, oidBytes[6] );
+        assertEquals( (byte)0xC7, oidBytes[7] );
+        assertEquals( (byte)0xCB, oidBytes[8] );
+        assertEquals( (byte)0x9F, oidBytes[9] );
+        assertEquals( (byte)0xA0, oidBytes[10] );
+        assertEquals( (byte)0xC5, oidBytes[11] );
+        assertEquals( (byte)0xEA, oidBytes[12] );
+        assertEquals( (byte)0xDA, oidBytes[13] );
+        assertEquals( (byte)0x92, oidBytes[14] );
+        assertEquals( (byte)0x9D, oidBytes[15] );
+        assertEquals( (byte)0x9E, oidBytes[16] );
+        assertEquals( (byte)0x0C, oidBytes[17] );
+    }
+
+
+    /**
+     * Test an OID with 2 at the first position and a second node > 39
+     * @throws DecoderException 
+     */
+    @Test
+    public void testOidNode2() throws DecoderException
+    {
+        Oid oid = Oid.fromString( "2.12345" );
+    }
+
+
+    /**
      * Test Kerberos V5 NewOid
      */
     @Test
@@ -419,7 +702,7 @@ public class OidTest
             oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 
-            oid = Oid.fromString( "0.0.0.0.0" );
+            oid = Oid.fromString( "1.2.3.4.5" );
             oid2 = Oid.fromBytes( oid.toBytes() );
             assertEquals( oid.toString(), oid2.toString() );
 



Mime
View raw message