001    /**
002     *
003     *  Licensed to the Apache Software Foundation (ASF) under one or more
004     *  contributor license agreements.  See the NOTICE file distributed with
005     *  this work for additional information regarding copyright ownership.
006     *  The ASF licenses this file to You under the Apache License, Version 2.0
007     *  (the "License"); you may not use this file except in compliance with
008     *  the License.  You may obtain a copy of the License at
009     *
010     *     http://www.apache.org/licenses/LICENSE-2.0
011     *
012     *  Unless required by applicable law or agreed to in writing, software
013     *  distributed under the License is distributed on an "AS IS" BASIS,
014     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015     *  See the License for the specific language governing permissions and
016     *  limitations under the License.
017     */
018    
019    package org.apache.geronimo.util.asn1;
020    
021    import java.io.ByteArrayOutputStream;
022    import java.io.IOException;
023    import java.io.OutputStream;
024    
025    public class DERObjectIdentifier
026        extends DERObject
027    {
028        String      identifier;
029    
030        /**
031         * return an OID from the passed in object
032         *
033         * @exception IllegalArgumentException if the object cannot be converted.
034         */
035        public static DERObjectIdentifier getInstance(
036            Object  obj)
037        {
038            if (obj == null || obj instanceof DERObjectIdentifier)
039            {
040                return (DERObjectIdentifier)obj;
041            }
042    
043            if (obj instanceof ASN1OctetString)
044            {
045                return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
046            }
047    
048            if (obj instanceof ASN1TaggedObject)
049            {
050                return getInstance(((ASN1TaggedObject)obj).getObject());
051            }
052    
053            throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
054        }
055    
056        /**
057         * return an Object Identifier from a tagged object.
058         *
059         * @param obj the tagged object holding the object we want
060         * @param explicit true if the object is meant to be explicitly
061         *              tagged false otherwise.
062         * @exception IllegalArgumentException if the tagged object cannot
063         *               be converted.
064         */
065        public static DERObjectIdentifier getInstance(
066            ASN1TaggedObject obj,
067            boolean          explicit)
068        {
069            return getInstance(obj.getObject());
070        }
071    
072    
073        DERObjectIdentifier(
074            byte[]  bytes)
075        {
076            StringBuffer    objId = new StringBuffer();
077            long            value = 0;
078            boolean         first = true;
079    
080            for (int i = 0; i != bytes.length; i++)
081            {
082                int b = bytes[i] & 0xff;
083    
084                value = value * 128 + (b & 0x7f);
085                if ((b & 0x80) == 0)             // end of number reached
086                {
087                    if (first)
088                    {
089                        switch ((int)value / 40)
090                        {
091                        case 0:
092                            objId.append('0');
093                            break;
094                        case 1:
095                            objId.append('1');
096                            value -= 40;
097                            break;
098                        default:
099                            objId.append('2');
100                            value -= 80;
101                        }
102                        first = false;
103                    }
104    
105                    objId.append('.');
106                    objId.append(Long.toString(value));
107                    value = 0;
108                }
109            }
110    
111            this.identifier = objId.toString();
112        }
113    
114        public DERObjectIdentifier(
115            String  identifier)
116        {
117            for (int i = identifier.length() - 1; i >= 0; i--)
118            {
119                char ch = identifier.charAt(i);
120    
121                if ('0' <= ch && ch <= '9')
122                {
123                    continue;
124                }
125    
126                if (ch == '.')
127                {
128                    continue;
129                }
130    
131                throw new IllegalArgumentException("string " + identifier + " not an OID");
132            }
133    
134            this.identifier = identifier;
135        }
136    
137        public String getId()
138        {
139            return identifier;
140        }
141    
142        private void writeField(
143            OutputStream    out,
144            long            fieldValue)
145            throws IOException
146        {
147            if (fieldValue >= (1 << 7))
148            {
149                if (fieldValue >= (1 << 14))
150                {
151                    if (fieldValue >= (1 << 21))
152                    {
153                        if (fieldValue >= (1 << 28))
154                        {
155                            if (fieldValue >= (1 << 35))
156                            {
157                                if (fieldValue >= (1 << 42))
158                                {
159                                    if (fieldValue >= (1 << 49))
160                                    {
161                                        if (fieldValue >= (1 << 56))
162                                        {
163                                            out.write((int)(fieldValue >> 56) | 0x80);
164                                        }
165                                        out.write((int)(fieldValue >> 49) | 0x80);
166                                    }
167                                    out.write((int)(fieldValue >> 42) | 0x80);
168                                }
169                                out.write((int)(fieldValue >> 35) | 0x80);
170                            }
171                            out.write((int)(fieldValue >> 28) | 0x80);
172                        }
173                        out.write((int)(fieldValue >> 21) | 0x80);
174                    }
175                    out.write((int)(fieldValue >> 14) | 0x80);
176                }
177                out.write((int)(fieldValue >> 7) | 0x80);
178            }
179            out.write((int)fieldValue & 0x7f);
180        }
181    
182        void encode(
183            DEROutputStream out)
184            throws IOException
185        {
186            OIDTokenizer            tok = new OIDTokenizer(identifier);
187            ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
188            DEROutputStream         dOut = new DEROutputStream(bOut);
189    
190            writeField(bOut,
191                        Integer.parseInt(tok.nextToken()) * 40
192                        + Integer.parseInt(tok.nextToken()));
193    
194            while (tok.hasMoreTokens())
195            {
196                writeField(bOut, Long.parseLong(tok.nextToken()));
197            }
198    
199            dOut.close();
200    
201            byte[]  bytes = bOut.toByteArray();
202    
203            out.writeEncoded(OBJECT_IDENTIFIER, bytes);
204        }
205    
206        public int hashCode()
207        {
208            return identifier.hashCode();
209        }
210    
211        public boolean equals(
212            Object  o)
213        {
214            if ((o == null) || !(o instanceof DERObjectIdentifier))
215            {
216                return false;
217            }
218    
219            return identifier.equals(((DERObjectIdentifier)o).identifier);
220        }
221    
222        public String toString()
223        {
224            return getId();
225        }
226    }