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