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}