001 /*
002 * Copyright 2007-2016 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2016 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 import com.unboundid.util.NotMutable;
028 import com.unboundid.util.ThreadSafety;
029 import com.unboundid.util.ThreadSafetyLevel;
030
031 import static com.unboundid.asn1.ASN1Constants.*;
032 import static com.unboundid.asn1.ASN1Messages.*;
033 import static com.unboundid.util.Debug.*;
034 import static com.unboundid.util.StaticUtils.*;
035 import 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)
046 public 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 }