| /* |
| * 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$ |
| */ |
| |
| package org.apache.harmony.security.asn1; |
| |
| import java.util.Arrays; |
| |
| import org.apache.harmony.security.internal.nls.Messages; |
| |
| /** |
| * 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 <a href="http://asn1.elibel.tm.fr/en/standards/index.htm">ASN.1</a> |
| */ |
| |
| 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(Messages.getString("security.98")); |
| } |
| |
| if (oid.length < 2) { |
| throw new IllegalArgumentException( |
| Messages.getString("security.99")); |
| } |
| |
| if (oid[0] > 2) { |
| throw new IllegalArgumentException( |
| Messages.getString("security.9A")); |
| } else if (oid[0] != 2 && oid[1] > 39) { |
| throw new IllegalArgumentException( |
| Messages.getString("security.9B")); |
| } |
| |
| for (int i = 0; i < oid.length; i++) { |
| if (oid[i] < 0) { |
| throw new IllegalArgumentException( |
| Messages.getString("security.9C")); |
| } |
| } |
| } |
| |
| // 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) { |
| StringBuilder sb = new StringBuilder(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(); |
| } |
| |
| // BEGIN android-changed |
| /** |
| * 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) { |
| return toIntArray(str, true); |
| } |
| |
| /** |
| * Returns whether the given string is a valid ObjectIdentifier |
| * (OID) representation. |
| * |
| * String representation is defined as for {@link #toIntArray}. |
| * |
| * @param oidString - string representation of OID |
| * @return true if oidString has valid syntax or false if not |
| */ |
| public static boolean isOID(String str) { |
| return toIntArray(str, false) != null; |
| } |
| |
| /** |
| * 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 or null if the oid string is |
| * invalid or null and shouldThrow is false |
| * @throws IllegalArgumentException - if oid string is invalid or null and |
| * shouldThrow is true |
| */ |
| private static int[] toIntArray(String str, boolean shouldThrow) { |
| if (str == null) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException( |
| Messages.getString("security.9D")); |
| } |
| |
| int length = str.length(); |
| if (length == 0) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException(Messages.getString("security.9E")); |
| } |
| |
| 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) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException(Messages.getString("security.9E")); |
| } |
| wasDot = true; |
| count++; |
| } else if (c >= '0' && c <= '9') { |
| wasDot = false; |
| } else { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException(Messages.getString("security.9E")); |
| } |
| } |
| |
| if (wasDot) { |
| // the last char is dot |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException(Messages.getString("security.9E")); |
| } |
| |
| if (count < 2) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException( |
| Messages.getString("security.99")); |
| } |
| |
| 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) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException( |
| Messages.getString("security.9A")); |
| } else if (oid[0] != 2 && oid[1] > 39) { |
| if (! shouldThrow) { |
| return null; |
| } |
| throw new IllegalArgumentException( |
| Messages.getString("security.9B")); |
| } |
| |
| return oid; |
| } |
| // END android-changed |
| } |