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