001    /*
002     * Copyright (c) 2000 - 2006 The Legion Of The Bouncy Castle (http://www.bouncycastle.org)
003     * 
004     * Permission is hereby granted, free of charge, to any person obtaining a copy of this
005     * software and associated documentation files (the "Software"), to deal in the Software
006     * without restriction, including without limitation the rights to use, copy, modify,
007     * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
008     * permit persons to whom the Software is furnished to do so, subject to the following
009     * conditions:
010     * 
011     * The above copyright notice and this permission notice shall be included in all copies
012     * or substantial portions of the Software.
013     * 
014     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
015     * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
016     * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
017     * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
018     * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
019     * DEALINGS IN THE SOFTWARE.
020     * 
021     */
022    
023    package org.apache.directory.shared.asn1.der;
024    
025    
026    import java.io.ByteArrayOutputStream;
027    import java.io.IOException;
028    import java.io.OutputStream;
029    
030    
031    public class DERObjectIdentifier extends DERObject
032    {
033        String identifier;
034    
035    
036        DERObjectIdentifier(byte[] bytes)
037        {
038            super( OBJECT_IDENTIFIER, bytes );
039    
040            StringBuffer objId = new StringBuffer();
041            long value = 0;
042            boolean first = true;
043    
044            for ( int i = 0; i != bytes.length; i++ )
045            {
046                int b = bytes[i] & 0xff;
047    
048                value = value * 128 + ( b & 0x7f );
049                if ( ( b & 0x80 ) == 0 ) // end of number reached
050                {
051                    if ( first )
052                    {
053                        switch ( ( int ) value / 40 )
054                        {
055                            case 0:
056                                objId.append( '0' );
057                                break;
058                            case 1:
059                                objId.append( '1' );
060                                value -= 40;
061                                break;
062                            default:
063                                objId.append( '2' );
064                                value -= 80;
065                                break;
066                        }
067                        first = false;
068                    }
069    
070                    objId.append( '.' );
071                    objId.append( Long.toString( value ) );
072                    value = 0;
073                }
074            }
075    
076            this.identifier = objId.toString();
077        }
078    
079    
080        private void writeField( OutputStream out, long fieldValue ) throws IOException
081        {
082            if ( fieldValue >= ( 1 << 7 ) )
083            {
084                if ( fieldValue >= ( 1 << 14 ) )
085                {
086                    if ( fieldValue >= ( 1 << 21 ) )
087                    {
088                        if ( fieldValue >= ( 1 << 28 ) )
089                        {
090                            if ( fieldValue >= ( 1 << 35 ) )
091                            {
092                                if ( fieldValue >= ( 1 << 42 ) )
093                                {
094                                    if ( fieldValue >= ( 1 << 49 ) )
095                                    {
096                                        if ( fieldValue >= ( 1 << 56 ) )
097                                        {
098                                            out.write( ( int ) ( fieldValue >> 56 ) | 0x80 );
099                                        }
100                                        out.write( ( int ) ( fieldValue >> 49 ) | 0x80 );
101                                    }
102                                    out.write( ( int ) ( fieldValue >> 42 ) | 0x80 );
103                                }
104                                out.write( ( int ) ( fieldValue >> 35 ) | 0x80 );
105                            }
106                            out.write( ( int ) ( fieldValue >> 28 ) | 0x80 );
107                        }
108                        out.write( ( int ) ( fieldValue >> 21 ) | 0x80 );
109                    }
110                    out.write( ( int ) ( fieldValue >> 14 ) | 0x80 );
111                }
112                out.write( ( int ) ( fieldValue >> 7 ) | 0x80 );
113            }
114            out.write( ( int ) fieldValue & 0x7f );
115        }
116    
117    
118        public void encode( ASN1OutputStream out ) throws IOException
119        {
120            OIDTokenizer tok = new OIDTokenizer( identifier );
121            ByteArrayOutputStream baos = new ByteArrayOutputStream();
122            ASN1OutputStream aos = new ASN1OutputStream( baos );
123    
124            writeField( baos, Integer.parseInt( tok.nextToken() ) * 40 + Integer.parseInt( tok.nextToken() ) );
125    
126            while ( tok.hasMoreTokens() )
127            {
128                writeField( baos, Long.parseLong( tok.nextToken() ) );
129            }
130    
131            aos.close();
132    
133            byte[] bytes = baos.toByteArray();
134    
135            out.writeEncoded( OBJECT_IDENTIFIER, bytes );
136        }
137    }