1    package org.bouncycastle.asn1;
2    
3    import java.io.*;
4    
5    public class DERObjectIdentifier
6        extends DERObject
7    {
8        String      identifier;
9    
10       /**
11        * return an OID from the passed in object
12        *
13        * @exception IllegalArgumentException if the object cannot be converted.
14        */
15       public static DERObjectIdentifier getInstance(
16           Object  obj)
17       {
18           if (obj == null || obj instanceof DERObjectIdentifier)
19           {
20               return (DERObjectIdentifier)obj;
21           }
22   
23           if (obj instanceof ASN1OctetString)
24           {
25               return new DERObjectIdentifier(((ASN1OctetString)obj).getOctets());
26           }
27   
28           if (obj instanceof ASN1TaggedObject)
29           {
30               return getInstance(((ASN1TaggedObject)obj).getObject());
31           }
32   
33           throw new IllegalArgumentException("illegal object in getInstance: " + obj.getClass().getName());
34       }
35   
36       /**
37        * return an Object Identifier from a tagged object.
38        *
39        * @param obj the tagged object holding the object we want
40        * @param explicit true if the object is meant to be explicitly
41        *              tagged false otherwise.
42        * @exception IllegalArgumentException if the tagged object cannot
43        *               be converted.
44        */
45       public static DERObjectIdentifier getInstance(
46           ASN1TaggedObject obj,
47           boolean          explicit)
48       {
49           return getInstance(obj.getObject());
50       }
51       
52   
53       DERObjectIdentifier(
54           byte[]  bytes)
55       {
56           int             head = bytes[0] & 0xff;
57           StringBuffer    objId = new StringBuffer();
58           int             value = 0;
59           boolean         first = true;
60   
61           for (int i = 0; i != bytes.length; i++)
62           {
63               int b = bytes[i] & 0xff;
64   
65               value = value * 128 + (b & 0x7f);
66               if ((b & 0x80) == 0)             // end of number reached
67               {
68                   if (first)
69                   {
70                       switch (value / 40)
71                       {
72                       case 0:
73                           objId.append('0');
74                           break;
75                       case 1:
76                           objId.append('1');
77                           value -= 40;
78                           break;
79                       default:
80                           objId.append('2');
81                           value -= 80;
82                       }
83                       first = false;
84                   }
85   
86                   objId.append('.');
87                   objId.append(Integer.toString(value));
88                   value = 0;
89               }
90           }
91   
92           this.identifier = objId.toString();
93       }
94   
95       public DERObjectIdentifier(
96           String  identifier)
97       {
98           this.identifier = identifier;
99       }
100  
101      public String getId()
102      {
103          return identifier;
104      }
105  
106      private void writeField(
107          OutputStream    out,
108          int             fieldValue)
109          throws IOException
110      {
111          if (fieldValue >= (1 << 7))
112          {
113              if (fieldValue >= (1 << 14))
114              {
115                  if (fieldValue >= (1 << 21))
116                  {
117                      if (fieldValue >= (1 << 28))
118                      {
119                          out.write((fieldValue >> 28) | 0x80);
120                      }
121                      out.write((fieldValue >> 21) | 0x80);
122                  }
123                  out.write((fieldValue >> 14) | 0x80);
124              }
125              out.write((fieldValue >> 7) | 0x80);
126          }
127          out.write(fieldValue & 0x7f);
128      }
129  
130      void encode(
131          DEROutputStream out)
132          throws IOException
133      {
134          OIDTokenizer            tok = new OIDTokenizer(identifier);
135          ByteArrayOutputStream   bOut = new ByteArrayOutputStream();
136          DEROutputStream         dOut = new DEROutputStream(bOut);
137  
138          writeField(bOut, 
139                      Integer.parseInt(tok.nextToken()) * 40
140                      + Integer.parseInt(tok.nextToken()));
141  
142          while (tok.hasMoreTokens())
143          {
144              writeField(bOut, Integer.parseInt(tok.nextToken()));
145          }
146  
147          dOut.close();
148  
149          byte[]  bytes = bOut.toByteArray();
150  
151          out.writeEncoded(OBJECT_IDENTIFIER, bytes);
152      }
153  
154      public int hashCode()
155      {
156          return identifier.hashCode();
157      }
158  
159      public boolean equals(
160          Object  o)
161      {
162          if ((o == null) || !(o instanceof DERObjectIdentifier))
163          {
164              return false;
165          }
166  
167          return identifier.equals(((DERObjectIdentifier)o).identifier);
168      }
169  }
170