001/* 002 * Copyright 2017-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2017-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.asn1; 022 023 024 025import com.unboundid.util.Debug; 026import com.unboundid.util.NotMutable; 027import com.unboundid.util.StaticUtils; 028import com.unboundid.util.ThreadSafety; 029import com.unboundid.util.ThreadSafetyLevel; 030 031import static com.unboundid.asn1.ASN1Messages.*; 032 033 034 035/** 036 * This class provides an ASN.1 IA5 string element that can hold any empty or 037 * non-empty string comprised only of the ASCII characters (including ASCII 038 * control characters). 039 */ 040@NotMutable() 041@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 042public final class ASN1IA5String 043 extends ASN1Element 044{ 045 /** 046 * The serial version UID for this serializable class. 047 */ 048 private static final long serialVersionUID = -9112411497688179053L; 049 050 051 052 // The string value for this element. 053 private final String stringValue; 054 055 056 057 /** 058 * Creates a new ASN.1 IA5 string element with the default BER type and the 059 * provided value. 060 * 061 * @param stringValue The string value to use for this element. It may be 062 * {@code null} or empty if the value should be empty. 063 * It must only contain characters from the ASCII 064 * character set (including control characters). 065 * 066 * @throws ASN1Exception If the provided string does not represent a valid 067 * IA5 string. 068 */ 069 public ASN1IA5String(final String stringValue) 070 throws ASN1Exception 071 { 072 this(ASN1Constants.UNIVERSAL_IA5_STRING_TYPE, stringValue); 073 } 074 075 076 077 /** 078 * Creates a new ASN.1 IA5 string element with the specified BER type and the 079 * provided value. 080 * 081 * @param type The BER type for this element. 082 * @param stringValue The string value to use for this element. It may be 083 * {@code null} or empty if the value should be empty. 084 * It must only contain characters from the ASCII 085 * character set (including control characters). 086 * 087 * @throws ASN1Exception If the provided string does not represent a valid 088 * IA5 string. 089 */ 090 public ASN1IA5String(final byte type, final String stringValue) 091 throws ASN1Exception 092 { 093 this(type, stringValue, StaticUtils.getBytes(stringValue)); 094 } 095 096 097 098 /** 099 * Creates a new ASN.1 IA5 string element with the specified BER type and the 100 * provided value. 101 * 102 * @param type The BER type for this element. 103 * @param stringValue The string value to use for this element. It may be 104 * {@code null} or empty if the value should be empty. 105 * It must only contain characters from the ASCII 106 * character set (including control characters). 107 * @param encodedValue The bytes that comprise the encoded element value. 108 * 109 * @throws ASN1Exception If the provided string does not represent a valid 110 * IA5 string. 111 */ 112 private ASN1IA5String(final byte type, final String stringValue, 113 final byte[] encodedValue) 114 throws ASN1Exception 115 { 116 super(type, encodedValue); 117 118 if (stringValue == null) 119 { 120 this.stringValue = ""; 121 } 122 else 123 { 124 this.stringValue = stringValue; 125 126 for (final byte b : encodedValue) 127 { 128 if ((b & 0x7F) != (b & 0xFF)) 129 { 130 throw new ASN1Exception(ERR_IA5_STRING_DECODE_VALUE_NOT_IA5.get()); 131 } 132 } 133 } 134 } 135 136 137 138 /** 139 * Retrieves the string value for this element. 140 * 141 * @return The string value for this element. 142 */ 143 public String stringValue() 144 { 145 return stringValue; 146 } 147 148 149 150 /** 151 * Decodes the contents of the provided byte array as an IA5 string element. 152 * 153 * @param elementBytes The byte array to decode as an ASN.1 IA5 string 154 * element. 155 * 156 * @return The decoded ASN.1 IA5 string element. 157 * 158 * @throws ASN1Exception If the provided array cannot be decoded as an 159 * IA5 string element. 160 */ 161 public static ASN1IA5String decodeAsIA5String(final byte[] elementBytes) 162 throws ASN1Exception 163 { 164 try 165 { 166 int valueStartPos = 2; 167 int length = (elementBytes[1] & 0x7F); 168 if (length != elementBytes[1]) 169 { 170 final int numLengthBytes = length; 171 172 length = 0; 173 for (int i=0; i < numLengthBytes; i++) 174 { 175 length <<= 8; 176 length |= (elementBytes[valueStartPos++] & 0xFF); 177 } 178 } 179 180 if ((elementBytes.length - valueStartPos) != length) 181 { 182 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 183 (elementBytes.length - valueStartPos))); 184 } 185 186 final byte[] elementValue = new byte[length]; 187 System.arraycopy(elementBytes, valueStartPos, elementValue, 0, length); 188 189 return new ASN1IA5String(elementBytes[0], 190 StaticUtils.toUTF8String(elementValue), elementValue); 191 } 192 catch (final ASN1Exception ae) 193 { 194 Debug.debugException(ae); 195 throw ae; 196 } 197 catch (final Exception e) 198 { 199 Debug.debugException(e); 200 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 201 } 202 } 203 204 205 206 /** 207 * Decodes the provided ASN.1 element as an IA5 string element. 208 * 209 * @param element The ASN.1 element to be decoded. 210 * 211 * @return The decoded ASN.1 IA5 string element. 212 * 213 * @throws ASN1Exception If the provided element cannot be decoded as an 214 * IA5 string element. 215 */ 216 public static ASN1IA5String decodeAsIA5String(final ASN1Element element) 217 throws ASN1Exception 218 { 219 final byte[] elementValue = element.getValue(); 220 return new ASN1IA5String(element.getType(), 221 StaticUtils.toUTF8String(elementValue), elementValue); 222 } 223 224 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override() 230 public void toString(final StringBuilder buffer) 231 { 232 buffer.append(stringValue); 233 } 234}