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.NotMutable;
026    import com.unboundid.util.ThreadSafety;
027    import com.unboundid.util.ThreadSafetyLevel;
028    
029    import static com.unboundid.asn1.ASN1Constants.*;
030    import static com.unboundid.asn1.ASN1Messages.*;
031    import static com.unboundid.util.Debug.*;
032    
033    
034    
035    /**
036     * This class provides an ASN.1 Boolean element, whose value is a single byte
037     * and represents either "TRUE" or "FALSE".  A value whose only byte is 0x00 is
038     * considered "false", while any other single-byte value is considered "true".
039     */
040    @NotMutable()
041    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
042    public final class ASN1Boolean
043           extends ASN1Element
044    {
045      /**
046       * A pre-allocated ASN.1 Boolean element with the universal Boolean BER type
047       * and a value of "FALSE".
048       */
049      public static final ASN1Boolean UNIVERSAL_BOOLEAN_FALSE_ELEMENT =
050             new ASN1Boolean(false);
051    
052    
053    
054      /**
055       * A pre-allocated ASN.1 Boolean element with the universal Boolean BER type
056       * and a value of "TRUE".
057       */
058      public static final ASN1Boolean UNIVERSAL_BOOLEAN_TRUE_ELEMENT =
059             new ASN1Boolean(true);
060    
061    
062    
063      /**
064       * The serial version UID for this serializable class.
065       */
066      private static final long serialVersionUID = 7131700816847855524L;
067    
068    
069    
070      // The boolean value for this element.
071      private final boolean booleanValue;
072    
073    
074    
075      /**
076       * Creates a new ASN.1 Boolean element with the default BER type and the
077       * provided boolean value.
078       *
079       * @param  booleanValue  The boolean value to use for this element.
080       */
081      public ASN1Boolean(final boolean booleanValue)
082      {
083        super(UNIVERSAL_BOOLEAN_TYPE,
084              (booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE));
085    
086        this.booleanValue = booleanValue;
087      }
088    
089    
090    
091      /**
092       * Creates a new ASN.1 Boolean element with the specified BER type and the
093       * provided boolean value.
094       *
095       * @param  type          The BER type to use for this element.
096       * @param  booleanValue  The boolean value to use for this element.
097       */
098      public ASN1Boolean(final byte type, final boolean booleanValue)
099      {
100        super(type, (booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE));
101    
102        this.booleanValue = booleanValue;
103      }
104    
105    
106    
107      /**
108       * Creates a new ASN.1 Boolean element with the provided information.
109       *
110       * @param  type          The BER type to use for this element.
111       * @param  booleanValue  The boolean value to use for this element.
112       * @param  value         The pre-encoded value to use for this element.
113       */
114      private ASN1Boolean(final byte type, final boolean booleanValue,
115                          final byte[] value)
116      {
117        super(type, value);
118    
119        this.booleanValue = booleanValue;
120      }
121    
122    
123    
124      /**
125       * Retrieves the boolean value for this element.
126       *
127       * @return  {@code true} if this element has a value of "TRUE", or
128       *          {@code false} if it has a value of "FALSE".
129       */
130      public boolean booleanValue()
131      {
132        return booleanValue;
133      }
134    
135    
136    
137      /**
138       * Decodes the contents of the provided byte array as a Boolean element.
139       *
140       * @param  elementBytes  The byte array to decode as an ASN.1 Boolean element.
141       *
142       * @return  The decoded ASN.1 Boolean element.
143       *
144       * @throws  ASN1Exception  If the provided array cannot be decoded as a
145       *                         Boolean element.
146       */
147      public static ASN1Boolean decodeAsBoolean(final byte[] elementBytes)
148             throws ASN1Exception
149      {
150        try
151        {
152          int valueStartPos = 2;
153          int length = (elementBytes[1] & 0x7F);
154          if (length != elementBytes[1])
155          {
156            final int numLengthBytes = length;
157    
158            length = 0;
159            for (int i=0; i < numLengthBytes; i++)
160            {
161              length <<= 8;
162              length |= (elementBytes[valueStartPos++] & 0xFF);
163            }
164          }
165    
166          if ((elementBytes.length - valueStartPos) != length)
167          {
168            throw new ASN1Exception(ERR_ELEMENT_LENGTH_MISMATCH.get(length,
169                                         (elementBytes.length - valueStartPos)));
170          }
171    
172          if (length != 1)
173          {
174            throw new ASN1Exception(ERR_BOOLEAN_INVALID_LENGTH.get());
175          }
176    
177          final byte[] value = { elementBytes[valueStartPos] };
178          final boolean booleanValue = (value[0] != 0x00);
179          return new ASN1Boolean(elementBytes[0], booleanValue, value);
180        }
181        catch (final ASN1Exception ae)
182        {
183          debugException(ae);
184          throw ae;
185        }
186        catch (final Exception e)
187        {
188          debugException(e);
189          throw new ASN1Exception(ERR_ELEMENT_DECODE_EXCEPTION.get(e), e);
190        }
191      }
192    
193    
194    
195      /**
196       * Decodes the provided ASN.1 element as a Boolean element.
197       *
198       * @param  element  The ASN.1 element to be decoded.
199       *
200       * @return  The decoded ASN.1 Boolean element.
201       *
202       * @throws  ASN1Exception  If the provided element cannot be decoded as a
203       *                         Boolean element.
204       */
205      public static ASN1Boolean decodeAsBoolean(final ASN1Element element)
206             throws ASN1Exception
207      {
208        final byte[] value = element.getValue();
209        if (value.length != 1)
210        {
211          throw new ASN1Exception(ERR_BOOLEAN_INVALID_LENGTH.get());
212        }
213    
214        if (value[0] == 0x00)
215        {
216          return new ASN1Boolean(element.getType(), false, value);
217        }
218        else
219        {
220          return new ASN1Boolean(element.getType(), true, value);
221        }
222      }
223    
224    
225    
226      /**
227       * Appends a string representation of this ASN.1 element to the provided
228       * buffer.
229       *
230       * @param  buffer  The buffer to which to append the information.
231       */
232      @Override
233      public void toString(final StringBuilder buffer)
234      {
235        buffer.append(booleanValue);
236      }
237    }