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    }