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: /**
019: * @author Stepan M. Mishura
020: * @version $Revision$
021: */package org.apache.harmony.security.asn1;
022:
023: import java.util.Arrays;
024:
025: import org.apache.harmony.security.internal.nls.Messages;
026:
027: /**
028: * Instance of this class represents ObjectIdentifier (OID).
029: *
030: * According to X.690:
031: * OID is represented as a sequence of subidentifier.
032: * Each subidentifier is represented as non negative integer value.
033: * There are at least 2 subidentifiers in the sequence.
034: *
035: * Valid values for first subidentifier are 0, 1 and 2.
036: * If the first subidentifier has 0 or 1 value the second
037: * subidentifier must be less then 40.
038: *
039: * @see http://asn1.elibel.tm.fr/en/standards/index.htm
040: */
041:
042: public final class ObjectIdentifier {
043:
044: // OID as array of integers
045: private final int[] oid;
046:
047: // OID as string
048: private String soid;
049:
050: /**
051: * Creates ObjectIdentifier(OID) from array of integers.
052: *
053: * @param oid - array of integers
054: * @throws IllegalArgumentException - if oid is invalid or null
055: */
056: public ObjectIdentifier(int[] oid) {
057: validate(oid);
058: this .oid = oid;
059: }
060:
061: /**
062: * Creates ObjectIdentifier(OID) from string representation.
063: *
064: * @param strOid - oid string
065: * @throws IllegalArgumentException - if oid string is invalid or null
066: */
067: public ObjectIdentifier(String strOid) {
068: this .oid = toIntArray(strOid);
069: this .soid = strOid;
070: }
071:
072: /**
073: * Returns array of integers.
074: *
075: * @return array of integers
076: */
077: public int[] getOid() {
078: return oid;
079: }
080:
081: /**
082: * Compares object with OID for equality.
083: *
084: * @return true if object is ObjectIdentifier and it has the same
085: * representation as array of integers, otherwise false
086: */
087: public boolean equals(Object o) {
088: if (this == o) {
089: return true;
090: }
091: if (o == null || this .getClass() != o.getClass()) {
092: return false;
093: }
094: return Arrays.equals(oid, ((ObjectIdentifier) o).oid);
095: }
096:
097: /**
098: * @see java.lang.Object#toString()
099: */
100: public String toString() {
101: if (soid == null) {
102: soid = toString(oid);
103: }
104: return soid;
105: }
106:
107: /**
108: * @see java.lang.Object#hashCode()
109: */
110: public int hashCode() {
111: // FIXME change me to Arrays.hashCode(int[])
112: int intHash = 0;
113: for (int i = 0; i < oid.length && i < 4; i++) {
114: intHash += oid[i] << (8 * i); //TODO what about to find better one?
115: }
116: return intHash & 0x7FFFFFFF; // only positive
117: }
118:
119: /**
120: * Validates ObjectIdentifier (OID).
121: *
122: * @param oid - oid as array of integers
123: * @throws IllegalArgumentException - if oid is invalid or null
124: */
125: public static void validate(int[] oid) {
126:
127: if (oid == null) {
128: throw new IllegalArgumentException(Messages
129: .getString("security.98")); //$NON-NLS-1$
130: }
131:
132: if (oid.length < 2) {
133: throw new IllegalArgumentException(Messages
134: .getString("security.99")); //$NON-NLS-1$
135: }
136:
137: if (oid[0] > 2) {
138: throw new IllegalArgumentException(Messages
139: .getString("security.9A")); //$NON-NLS-1$
140: } else if (oid[0] != 2 && oid[1] > 39) {
141: throw new IllegalArgumentException(Messages
142: .getString("security.9B")); //$NON-NLS-1$
143: }
144:
145: for (int i = 0; i < oid.length; i++) {
146: if (oid[i] < 0) {
147: throw new IllegalArgumentException(Messages
148: .getString("security.9C")); //$NON-NLS-1$
149: }
150: }
151: }
152:
153: // FIXME: implement me
154: // /**
155: // * Validates ObjectIdentifier (OID).
156: // *
157: // * @param oid - oid as string
158: // * @throws IllegalArgumentException - if oid string is invalid or null
159: // */
160: // public static void validate(String oid) {
161: //
162: // if (oid == null) {
163: // throw new NullPointerException();
164: // }
165: //
166: // int length = oid.length();
167: // if (length < 3 || oid.charAt(1) != '.') {
168: // throw new IllegalArgumentException("Invalid oid string");
169: // }
170: //
171: // int pos = 2;
172: // int subidentifier = 0;
173: // switch (oid.charAt(0)) {
174: // case '0':
175: // case '1':
176: // for (char c = oid.charAt(pos);;) {
177: // if (c < '0' || c > '9') {
178: // throw new IllegalArgumentException("Invalid oid string");
179: // } else {
180: // subidentifier = subidentifier * 10 + c - '0';
181: // }
182: //
183: // pos++;
184: // if (pos == length) {
185: // break;
186: // }
187: //
188: // c = oid.charAt(pos);
189: // if (c == '.') {
190: // pos++;
191: // if (pos == length) {
192: // throw new IllegalArgumentException("Invalid oid string");
193: // }
194: // break;
195: // }
196: // }
197: //
198: // if (subidentifier > 39) {
199: // throw new IllegalArgumentException(
200: // "If the first subidentifier has 0 or 1 value the second "
201: // + "subidentifier value MUST be less then 40.");
202: // }
203: // break;
204: // case '2':
205: // break;
206: // default:
207: // throw new IllegalArgumentException(
208: // "Valid values for first subidentifier are 0, 1 and 2");
209: // }
210: //
211: // if (pos == length) {
212: // return;
213: // }
214: //
215: // for (char c = oid.charAt(pos);;) {
216: // if (c < '0' || c > '9') {
217: // throw new IllegalArgumentException("Invalid oid string");
218: // }
219: //
220: // pos++;
221: // if (pos == length) {
222: // return;
223: // }
224: //
225: // c = oid.charAt(pos);
226: // if (c == '.') {
227: // pos++;
228: // if (pos == length) {
229: // throw new IllegalArgumentException("Invalid oid string");
230: // }
231: // }
232: // }
233: // }
234:
235: /**
236: * Returns string representation of OID.
237: *
238: * Note: it is supposed that passed array of integers
239: * contains valid OID value, so no checks are performed.
240: *
241: * @param oid - oid as array of integers
242: * @return oid string representation
243: */
244: public static String toString(int[] oid) {
245: StringBuffer sb = new StringBuffer(3 * oid.length);
246:
247: for (int i = 0; i < oid.length - 1; ++i) {
248: sb.append(oid[i]);
249: sb.append('.');
250: }
251: sb.append(oid[oid.length - 1]);
252: return sb.toString();
253: }
254:
255: /**
256: * Gets ObjectIdentifier (OID) from string representation.
257: *
258: * String representation is defined by the following syntax:
259: * OID = subidentifier 1*("." subidentifier)
260: * subidentifier = 1*(digit)
261: *
262: * @param oidString - string representation of OID
263: * @return - oid as array of integers
264: * @throws IllegalArgumentException - if oid string is invalid or null
265: */
266: public static int[] toIntArray(String str) {
267:
268: if (str == null) {
269: throw new IllegalArgumentException(Messages
270: .getString("security.9D")); //$NON-NLS-1$
271: }
272:
273: int length = str.length();
274: if (length == 0) {
275: throw new IllegalArgumentException(Messages
276: .getString("security.9E")); //$NON-NLS-1$
277: }
278:
279: int count = 1; // number of subidentifiers
280: boolean wasDot = true; // indicates whether char before was dot or not.
281: char c; // current char
282: for (int i = 0; i < length; i++) {
283: c = str.charAt(i);
284: if (c == '.') {
285: if (wasDot) {
286: throw new IllegalArgumentException(Messages
287: .getString("security.9E")); //$NON-NLS-1$
288: }
289: wasDot = true;
290: count++;
291: } else if (c >= '0' && c <= '9') {
292: wasDot = false;
293: } else {
294: throw new IllegalArgumentException(Messages
295: .getString("security.9E")); //$NON-NLS-1$
296: }
297: }
298:
299: if (wasDot) {
300: // the last char is dot
301: throw new IllegalArgumentException(Messages
302: .getString("security.9E")); //$NON-NLS-1$
303: }
304:
305: if (count < 2) {
306: throw new IllegalArgumentException(Messages
307: .getString("security.99")); //$NON-NLS-1$
308: }
309:
310: int[] oid = new int[count];
311: for (int i = 0, j = 0; i < length; i++) {
312: c = str.charAt(i);
313: if (c == '.') {
314: j++;
315: } else {
316: oid[j] = oid[j] * 10 + c - 48; // '0' = 48
317: }
318: }
319:
320: if (oid[0] > 2) {
321: throw new IllegalArgumentException(Messages
322: .getString("security.9A")); //$NON-NLS-1$
323: } else if (oid[0] != 2 && oid[1] > 39) {
324: throw new IllegalArgumentException(Messages
325: .getString("security.9B")); //$NON-NLS-1$
326: }
327:
328: return oid;
329: }
330: }
|