001 /* 002 * Copyright 2007-2015 UnboundID Corp. 003 * All Rights Reserved. 004 */ 005 /* 006 * Copyright (C) 2008-2015 UnboundID Corp. 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 */ 021 package com.unboundid.asn1; 022 023 024 025 import com.unboundid.util.ByteString; 026 import com.unboundid.util.ByteStringBuffer; 027 028 import static com.unboundid.asn1.ASN1Constants.*; 029 import static com.unboundid.asn1.ASN1Messages.*; 030 import static com.unboundid.util.Debug.*; 031 import static com.unboundid.util.StaticUtils.*; 032 import static com.unboundid.util.Validator.*; 033 034 035 036 /** 037 * This class provides an ASN.1 octet string element, whose value is simply 038 * comprised of zero or more bytes. Octet string elements are frequently used 039 * to represent string values as well. 040 */ 041 public final class ASN1OctetString 042 extends ASN1Element 043 implements ByteString 044 { 045 /** 046 * The serial version UID for this serializable class. 047 */ 048 private static final long serialVersionUID = -7857753188341295516L; 049 050 051 052 /* 053 * NOTE: This class uses lazy initialization for the value. The value may 054 * be initially specified as either a string or a byte array, and if the value 055 * is provided as a string, then the byte array version of that value will be 056 * computed on-demand later. Even though this class is externally immutable, 057 * that does not by itself make it completely threadsafe, because weirdness in 058 * the Java memory model could allow the assignment to be performed out of 059 * order. By passing the value through a volatile variable any time the value 060 * is set other than in the constructor (which will always be safe) we ensure 061 * that this reordering cannot happen. This is only needed for the valueBytes 062 * array because it is not required for primitives (like length and offset) or 063 * for objects with only final fields (like stringValue). 064 * 065 * In the majority of cases, passing the value through a volatile variable is 066 * much faster than declaring valueBytes itself to be volatile because a 067 * volatile variable cannot be held in CPU caches or registers and must only 068 * be accessed from memory visible to all threads. Since the value may be 069 * read much more often than it is written, passing it through a volatile 070 * variable rather than making it volatile directly can help avoid that 071 * penalty when possible. 072 */ 073 074 075 076 // The binary representation of the value for this element. 077 private byte[] valueBytes; 078 079 // A volatile variable used to guard publishing the valueBytes array. See the 080 // note above to explain why this is needed. 081 private volatile byte[] valueBytesGuard; 082 083 // The length of the value in the byte array, if applicable. 084 private int length; 085 086 // The offset in the byte array at which the value begins, if applicable. 087 private int offset; 088 089 // The string representation of the value for this element. 090 private String stringValue; 091 092 093 094 /** 095 * Creates a new ASN.1 octet string element with the default BER type and 096 * no value. 097 */ 098 public ASN1OctetString() 099 { 100 super(UNIVERSAL_OCTET_STRING_TYPE); 101 102 valueBytes = NO_BYTES; 103 stringValue = ""; 104 offset = 0; 105 length = 0; 106 } 107 108 109 110 /** 111 * Creates a new ASN.1 octet string element with the specified type and no 112 * value. 113 * 114 * @param type The BER type to use for this element. 115 */ 116 public ASN1OctetString(final byte type) 117 { 118 super(type); 119 120 valueBytes = NO_BYTES; 121 stringValue = ""; 122 offset = 0; 123 length = 0; 124 } 125 126 127 128 /** 129 * Creates a new ASN.1 octet string element with the default BER type and the 130 * provided value. 131 * 132 * @param value The value to use for this element. 133 */ 134 public ASN1OctetString(final byte[] value) 135 { 136 super(UNIVERSAL_OCTET_STRING_TYPE); 137 138 if (value == null) 139 { 140 valueBytes = NO_BYTES; 141 stringValue = ""; 142 offset = 0; 143 length = 0; 144 } 145 else 146 { 147 valueBytes = value; 148 stringValue = null; 149 offset = 0; 150 length = value.length; 151 } 152 } 153 154 155 156 /** 157 * Creates a new ASN.1 octet string element with the default BER type and the 158 * provided value. 159 * 160 * @param value The byte array containing the value to use for this 161 * element It must not be {@code null}. 162 * @param offset The offset within the array at which the value begins. It 163 * must be greater than or equal to zero and less than or 164 * equal to the length of the array. 165 * @param length The length in bytes of the value. It must be greater than 166 * or equal to zero, and it must not extend beyond the end of 167 * the array. 168 */ 169 public ASN1OctetString(final byte[] value, final int offset, final int length) 170 { 171 super(UNIVERSAL_OCTET_STRING_TYPE); 172 173 ensureNotNull(value); 174 ensureTrue((offset >= 0) && (length >= 0) && 175 (offset+length <= value.length)); 176 177 valueBytes = value; 178 stringValue = null; 179 this.offset = offset; 180 this.length = length; 181 } 182 183 184 185 /** 186 * Creates a new ASN.1 octet string element with the specified type and the 187 * provided value. 188 * 189 * @param type The BER type to use for this element. 190 * @param value The value to use for this element. 191 */ 192 public ASN1OctetString(final byte type, final byte[] value) 193 { 194 super(type); 195 196 if (value == null) 197 { 198 valueBytes = NO_BYTES; 199 stringValue = ""; 200 offset = 0; 201 length = 0; 202 } 203 else 204 { 205 valueBytes = value; 206 stringValue = null; 207 offset = 0; 208 length = value.length; 209 } 210 } 211 212 213 214 /** 215 * Creates a new ASN.1 octet string element with the specified type and the 216 * provided value. 217 * 218 * @param type The BER type to use for this element. 219 * @param value The byte array containing the value to use for this 220 * element. It must not be {@code null}. 221 * @param offset The offset within the array at which the value begins. It 222 * must be greater than or equal to zero and less than or 223 * equal to the length of the array.. 224 * @param length The length in bytes of the value. It must be greater than 225 * or equal to zero, and it must not extend beyond the end of 226 * the array. 227 */ 228 public ASN1OctetString(final byte type, final byte[] value, final int offset, 229 final int length) 230 { 231 super(type); 232 233 ensureTrue((offset >= 0) && (length >= 0) && 234 (offset+length <= value.length)); 235 236 valueBytes = value; 237 stringValue = null; 238 this.offset = offset; 239 this.length = length; 240 } 241 242 243 244 /** 245 * Creates a new ASN.1 octet string element with the default BER type and the 246 * provided value. 247 * 248 * @param value The value to use for this element. 249 */ 250 public ASN1OctetString(final String value) 251 { 252 super(UNIVERSAL_OCTET_STRING_TYPE); 253 254 if (value == null) 255 { 256 valueBytes = NO_BYTES; 257 stringValue = ""; 258 offset = 0; 259 length = 0; 260 } 261 else 262 { 263 valueBytes = null; 264 stringValue = value; 265 offset = -1; 266 length = -1; 267 } 268 } 269 270 271 272 /** 273 * Creates a new ASN.1 octet string element with the specified type and the 274 * provided value. 275 * 276 * @param type The BER type to use for this element. 277 * @param value The value to use for this element. 278 */ 279 public ASN1OctetString(final byte type, final String value) 280 { 281 super(type); 282 283 if (value == null) 284 { 285 valueBytes = NO_BYTES; 286 stringValue = ""; 287 offset = 0; 288 length = 0; 289 } 290 else 291 { 292 valueBytes = null; 293 stringValue = value; 294 offset = -1; 295 length = -1; 296 } 297 } 298 299 300 301 /** 302 * {@inheritDoc} 303 */ 304 @Override() 305 byte[] getValueArray() 306 { 307 return getValue(); 308 } 309 310 311 312 /** 313 * {@inheritDoc} 314 */ 315 @Override() 316 int getValueOffset() 317 { 318 return 0; 319 } 320 321 322 323 /** 324 * {@inheritDoc} 325 */ 326 @Override() 327 public int getValueLength() 328 { 329 return getValue().length; 330 } 331 332 333 334 /** 335 * {@inheritDoc} 336 */ 337 @Override() 338 public byte[] getValue() 339 { 340 if (valueBytes == null) 341 { 342 valueBytesGuard = getBytes(stringValue); 343 offset = 0; 344 length = valueBytesGuard.length; 345 valueBytes = valueBytesGuard; 346 } 347 else if ((offset != 0) || (length != valueBytes.length)) 348 { 349 final byte[] newArray = new byte[length]; 350 System.arraycopy(valueBytes, offset, newArray, 0, length); 351 offset = 0; 352 valueBytesGuard = newArray; 353 valueBytes = valueBytesGuard; 354 } 355 356 return valueBytes; 357 } 358 359 360 361 /** 362 * {@inheritDoc} 363 */ 364 @Override() 365 public void encodeTo(final ByteStringBuffer buffer) 366 { 367 buffer.append(getType()); 368 369 if (valueBytes == null) 370 { 371 // Assume that the string contains only ASCII characters. That will be 372 // true most of the time and we can optimize for it. If it's not true, 373 // then we'll fix it later. 374 final int stringLength = stringValue.length(); 375 final int lengthStartPos = buffer.length(); 376 encodeLengthTo(stringLength, buffer); 377 final int valueStartPos = buffer.length(); 378 buffer.append(stringValue); 379 final int stringBytesLength = buffer.length() - valueStartPos; 380 if (stringBytesLength != stringLength) 381 { 382 // This must mean that the string had non-ASCII characters in it, so 383 // fix the encoded representation. 384 final byte[] newLengthBytes = encodeLength(stringBytesLength); 385 if (newLengthBytes.length == (valueStartPos - lengthStartPos)) 386 { 387 // It takes the same number of bytes to encode the new length as 388 // the length we previously expected, so we can just overwrite the 389 // length bytes in the backing array. 390 System.arraycopy(newLengthBytes, 0, buffer.getBackingArray(), 391 lengthStartPos, newLengthBytes.length); 392 } 393 else 394 { 395 buffer.setLength(lengthStartPos); 396 buffer.append(newLengthBytes); 397 buffer.append(stringValue); 398 } 399 } 400 } 401 else 402 { 403 encodeLengthTo(length, buffer); 404 buffer.append(valueBytes, offset, length); 405 } 406 } 407 408 409 410 /** 411 * Retrieves the string value for this element. 412 * 413 * @return The String value for this element. 414 */ 415 public String stringValue() 416 { 417 if (stringValue == null) 418 { 419 if (length == 0) 420 { 421 stringValue = ""; 422 } 423 else 424 { 425 stringValue = toUTF8String(valueBytes, offset, length); 426 } 427 } 428 429 return stringValue; 430 } 431 432 433 434 /** 435 * Decodes the contents of the provided byte array as an octet string element. 436 * 437 * @param elementBytes The byte array to decode as an ASN.1 octet string 438 * element. 439 * 440 * @return The decoded ASN.1 octet string element. 441 * 442 * @throws ASN1Exception If the provided array cannot be decoded as an 443 * octet string element. 444 */ 445 public static ASN1OctetString decodeAsOctetString(final byte[] elementBytes) 446 throws ASN1Exception 447 { 448 try 449 { 450 int valueStartPos = 2; 451 int length = (elementBytes[1] & 0x7F); 452 if (length != elementBytes[1]) 453 { 454 final int numLengthBytes = length; 455 456 length = 0; 457 for (int i=0; i < numLengthBytes; i++) 458 { 459 length <<= 8; 460 length |= (elementBytes[valueStartPos++] & 0xFF); 461 } 462 } 463 464 if ((elementBytes.length - valueStartPos) != length) 465 { 466 throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length, 467 (elementBytes.length - valueStartPos))); 468 } 469 470 return new ASN1OctetString(elementBytes[0], elementBytes, valueStartPos, 471 length); 472 } 473 catch (final ASN1Exception ae) 474 { 475 debugException(ae); 476 throw ae; 477 } 478 catch (final Exception e) 479 { 480 debugException(e); 481 throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e); 482 } 483 } 484 485 486 487 /** 488 * Decodes the provided ASN.1 element as an octet string element. 489 * 490 * @param element The ASN.1 element to be decoded. 491 * 492 * @return The decoded ASN.1 octet string element. 493 */ 494 public static ASN1OctetString decodeAsOctetString(final ASN1Element element) 495 { 496 return new ASN1OctetString(element.getType(), element.getValue()); 497 } 498 499 500 501 /** 502 * Appends the value of this ASN.1 octet string to the provided buffer. 503 * 504 * @param buffer The buffer to which the value is to be appended. 505 */ 506 public void appendValueTo(final ByteStringBuffer buffer) 507 { 508 if (valueBytes == null) 509 { 510 buffer.append(stringValue); 511 } 512 else 513 { 514 buffer.append(valueBytes, offset, length); 515 } 516 } 517 518 519 520 /** 521 * Converts this byte string to an ASN.1 octet string. 522 * 523 * @return An ASN.1 octet string with the value of this byte string. 524 */ 525 public ASN1OctetString toASN1OctetString() 526 { 527 return this; 528 } 529 530 531 532 /** 533 * Appends a string representation of this ASN.1 element to the provided 534 * buffer. 535 * 536 * @param buffer The buffer to which to append the information. 537 */ 538 @Override() 539 public void toString(final StringBuilder buffer) 540 { 541 buffer.append(stringValue()); 542 } 543 }