/*
* Sun Public License
*
* The contents of this file are subject to the Sun Public License Version
* 1.0 (the "License"). You may not use this file except in compliance with
* the License. A copy of the License is available at http://www.sun.com/
*
* The Original Code is the SLAMD Distributed Load Generation Engine.
* The Initial Developer of the Original Code is Neil A. Wilson.
* Portions created by Neil A. Wilson are Copyright (C) 2004-2010.
* Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc.
* All Rights Reserved.
*
* Contributor(s): Neil A. Wilson
*/
package com.slamd.asn1;
/**
* This class defines an ASN.1 element that can hold an enumerated value. It
* behaves in all respects like an integer, with the exception that each value
* of an enumerated element has a particular meaning (application-specific or
* context-specific) associated with it.
*
*
* @author Neil A. Wilson
*/
public class ASN1Enumerated
extends ASN1Element
{
// The Java int value that corresponds to the value of this ASN.1 enumerated
// element
int intValue;
/**
* Creates a new ASN.1 enumerated element with the specified value.
*
* @param intValue The Java int value to use in creating the ASN.1
* enumerated element.
*/
public ASN1Enumerated(int intValue)
{
this(ASN1_ENUMERATED_TYPE, intValue);
}
/**
* Creates a new ASN.1 enumerated element with the specified type and value.
*
* @param type The type to use for this enumerated value.
* @param intValue The Java int value to use in creating the ASN.1
* enumerated value.
*/
public ASN1Enumerated(byte type, int intValue)
{
super(type);
setValue(encodeIntValue(intValue));
this.intValue = intValue;
}
/**
* Encodes the provided int value in the appropriate manner for an ASN.1
* enumerated value.
*
* @param intValue The Java int value to encode as an ASN.1 enumerated
* value.
*
* @return A byte array that contains the encoded int value.
*/
public static byte[] encodeIntValue(int intValue)
{
return ASN1Integer.encodeIntValue(intValue);
}
/**
* Retrieves the Java int value that corresponds to the value of this ASN.1
* enumerated element.
*
* @return The Java int value that corresponds to the value of this ASN.1
* enumerated element.
*/
public int getIntValue()
{
return intValue;
}
/**
* Decodes the provided byte array as an ASN.1 enumerated element.
*
* @param encodedValue The encoded ASN.1 element.
*
* @return The decoded ASN.1 enumerated element.
*
* @throws ASN1Exception If the provided byte array cannot be decoded as an
* ASN.1 enumerated element.
*/
public static ASN1Enumerated decodeAsEnumerated(byte[] encodedValue)
throws ASN1Exception
{
// First make sure that there actually was a value provided
if ((encodedValue == null) || (encodedValue.length == 0))
{
throw new ASN1Exception("No data to decode");
}
// Make sure that the encoded value is at least three bytes. Otherwise,
// there can't be a type, length, and value.
if (encodedValue.length < 3)
{
throw new ASN1Exception("Not enough data to make a valid ASN.1 element");
}
// First, see if the type is supposed to be a single byte or multiple bytes.
if ((encodedValue[0] & 0x1F) == 0x1F)
{
// This indicates that the type is supposed to consist of multiple bytes,
// which we do not support, so throw an exception
throw new ASN1Exception("Multibyte type detected (not supported in " +
"this package)");
}
byte type = encodedValue[0];
// Next, look at the second byte to see if there is a single byte or
// multibyte length.
int length = 0;
int valueStartPos = 2;
if ((encodedValue[1] & 0x7F) != encodedValue[1])
{
if ((encodedValue[1] & 0x7F) == 0x00)
{
length = 128;
}
else
{
int numLengthBytes = (encodedValue[1] & 0x7F);
if (encodedValue.length < (numLengthBytes + 2))
{
throw new ASN1Exception ("Determined the length is encoded in " +
numLengthBytes + " bytes, but not enough " +
"bytes exist in the encoded value");
}
else
{
byte[] lengthArray = new byte[numLengthBytes+1];
lengthArray[0] = encodedValue[1];
System.arraycopy(encodedValue, 2, lengthArray, 1, numLengthBytes);
length = decodeLength(lengthArray);
valueStartPos += numLengthBytes;
}
}
}
else
{
length = encodedValue[1];
}
// Make sure that there are the correct number of bytes in the value. If
// not, then throw an exception.
if ((encodedValue.length - valueStartPos) != length)
{
throw new ASN1Exception("Expected a value of " + length + " bytes, but " +
(encodedValue.length - valueStartPos) +
" bytes exist");
}
byte[] value = new byte[length];
System.arraycopy(encodedValue, valueStartPos, value, 0, length);
int intValue = ASN1Integer.decodeIntValue(value);
ASN1Enumerated enumeratedElement = new ASN1Enumerated(type);
enumeratedElement.intValue = intValue;
enumeratedElement.value = value;
return enumeratedElement;
}
}