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