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