/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @author Stepan M. Mishura * @version $Revision$ */ /* * Imported by CG 20090319 based on Apache Harmony ("enhanced") revision 490473. */ package org.apache.harmony.security.asn1; import java.util.Arrays; /** * Instance of this class represents ObjectIdentifier (OID). * * According to X.690: * OID is represented as a sequence of subidentifier. * Each subidentifier is represented as non negative integer value. * There are at least 2 subidentifiers in the sequence. * * Valid values for first subidentifier are 0, 1 and 2. * If the first subidentifier has 0 or 1 value the second * subidentifier must be less then 40. * * @see http://asn1.elibel.tm.fr/en/standards/index.htm */ public final class ObjectIdentifier { // OID as array of integers private final int[] oid; // OID as string private String soid; /** * Creates ObjectIdentifier(OID) from array of integers. * * @param oid - array of integers * @throws IllegalArgumentException - if oid is invalid or null */ public ObjectIdentifier(int[] oid) { validate(oid); this.oid = oid; } /** * Creates ObjectIdentifier(OID) from string representation. * * @param strOid - oid string * @throws IllegalArgumentException - if oid string is invalid or null */ public ObjectIdentifier(String strOid) { this.oid = toIntArray(strOid); this.soid = strOid; } /** * Returns array of integers. * * @return array of integers */ public int[] getOid() { return oid; } /** * Compares object with OID for equality. * * @return true if object is ObjectIdentifier and it has the same * representation as array of integers, otherwise false */ public boolean equals(Object o) { if (this == o) { return true; } if (o == null || this.getClass() != o.getClass()) { return false; } return Arrays.equals(oid, ((ObjectIdentifier) o).oid); } /** * @see java.lang.Object#toString() */ public String toString() { if (soid == null) { soid = toString(oid); } return soid; } /** * @see java.lang.Object#hashCode() */ public int hashCode() { // FIXME change me to Arrays.hashCode(int[]) int intHash = 0; for (int i = 0; i < oid.length && i < 4; i++) { intHash += oid[i] << (8 * i); //TODO what about to find better one? } return intHash & 0x7FFFFFFF; // only positive } /** * Validates ObjectIdentifier (OID). * * @param oid - oid as array of integers * @throws IllegalArgumentException - if oid is invalid or null */ public static void validate(int[] oid) { if (oid == null) { throw new IllegalArgumentException("OID's array is null"); } if (oid.length < 2) { throw new IllegalArgumentException("OID MUST have at least 2 subidentifiers"); } if (oid[0] > 2) { throw new IllegalArgumentException("Valid values for first subidentifier are 0, 1 and 2"); } else if (oid[0] != 2 && oid[1] > 39) { throw new IllegalArgumentException("If the first subidentifier has 0 or 1 value the second subidentifier value MUST be less then 40."); } for (int i = 0; i < oid.length; i++) { if (oid[i] < 0) { throw new IllegalArgumentException("Subidentifier MUST have positive value."); } } } // FIXME: implement me // /** // * Validates ObjectIdentifier (OID). // * // * @param oid - oid as string // * @throws IllegalArgumentException - if oid string is invalid or null // */ // public static void validate(String oid) { // // if (oid == null) { // throw new NullPointerException(); // } // // int length = oid.length(); // if (length < 3 || oid.charAt(1) != '.') { // throw new IllegalArgumentException("Invalid oid string"); // } // // int pos = 2; // int subidentifier = 0; // switch (oid.charAt(0)) { // case '0': // case '1': // for (char c = oid.charAt(pos);;) { // if (c < '0' || c > '9') { // throw new IllegalArgumentException("Invalid oid string"); // } else { // subidentifier = subidentifier * 10 + c - '0'; // } // // pos++; // if (pos == length) { // break; // } // // c = oid.charAt(pos); // if (c == '.') { // pos++; // if (pos == length) { // throw new IllegalArgumentException("Invalid oid string"); // } // break; // } // } // // if (subidentifier > 39) { // throw new IllegalArgumentException( // "If the first subidentifier has 0 or 1 value the second " // + "subidentifier value MUST be less then 40."); // } // break; // case '2': // break; // default: // throw new IllegalArgumentException( // "Valid values for first subidentifier are 0, 1 and 2"); // } // // if (pos == length) { // return; // } // // for (char c = oid.charAt(pos);;) { // if (c < '0' || c > '9') { // throw new IllegalArgumentException("Invalid oid string"); // } // // pos++; // if (pos == length) { // return; // } // // c = oid.charAt(pos); // if (c == '.') { // pos++; // if (pos == length) { // throw new IllegalArgumentException("Invalid oid string"); // } // } // } // } /** * Returns string representation of OID. * * Note: it is supposed that passed array of integers * contains valid OID value, so no checks are performed. * * @param oid - oid as array of integers * @return oid string representation */ public static String toString(int[] oid) { StringBuffer sb = new StringBuffer(3 * oid.length); for (int i = 0; i < oid.length - 1; ++i) { sb.append(oid[i]); sb.append('.'); } sb.append(oid[oid.length - 1]); return sb.toString(); } /** * Gets ObjectIdentifier (OID) from string representation. * * String representation is defined by the following syntax: * OID = subidentifier 1*("." subidentifier) * subidentifier = 1*(digit) * * @param oidString - string representation of OID * @return - oid as array of integers * @throws IllegalArgumentException - if oid string is invalid or null */ public static int[] toIntArray(String str) { if (str == null) { throw new IllegalArgumentException("ObjectIdentifier string is null"); } int length = str.length(); if (length == 0) { throw new IllegalArgumentException("Incorrect syntax"); } int count = 1; // number of subidentifiers boolean wasDot = true; // indicates whether char before was dot or not. char c; // current char for (int i = 0; i < length; i++) { c = str.charAt(i); if (c == '.') { if (wasDot) { throw new IllegalArgumentException("Incorrect syntax"); } wasDot = true; count++; } else if (c >= '0' && c <= '9') { wasDot = false; } else { throw new IllegalArgumentException("Incorrect syntax"); } } if (wasDot) { // the last char is dot throw new IllegalArgumentException("Incorrect syntax"); } if (count < 2) { throw new IllegalArgumentException("OID MUST have at least 2 subidentifiers"); } int[] oid = new int[count]; for (int i = 0, j = 0; i < length; i++) { c = str.charAt(i); if (c == '.') { j++; } else { oid[j] = oid[j] * 10 + c - 48; // '0' = 48 } } if (oid[0] > 2) { throw new IllegalArgumentException("Valid values for first subidentifier are 0, 1 and 2"); } else if (oid[0] != 2 && oid[1] > 39) { throw new IllegalArgumentException("If the first subidentifier has 0 or 1 value the second subidentifier value MUST be less then 40."); } return oid; } }