/*
* 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 octet string value. An
* octet string is simply a set of bytes, and therefore any value can be encoded
* as an octet string, although other types may be more appropriate.
*
*
* @author Neil A. Wilson
*/
public class ASN1OctetString
extends ASN1Element
{
/**
* Creates a new ASN.1 octet string with no value.
*/
public ASN1OctetString()
{
this(ASN1_OCTET_STRING_TYPE, EMPTY_BYTES);
}
/**
* Creates a new ASN.1 octet string with the specified type and no value.
*
* @param type The type to use for this octet string element.
*/
public ASN1OctetString(byte type)
{
this(type, EMPTY_BYTES);
}
/**
* Creates a new ASN.1 octet string with the specified value.
*
* @param value The Java string value to encode into this octet string.
*/
public ASN1OctetString(String value)
{
this(ASN1_OCTET_STRING_TYPE, getBytes(value));
}
/**
* Creates a new ASN.1 octet string with the specified value.
*
* @param value The byte array to use as the value for this octet string.
*/
public ASN1OctetString(byte[] value)
{
this(ASN1_OCTET_STRING_TYPE, value);
}
/**
* Creates a new ASN.1 octet string with the specified type and value.
*
* @param type The type to use for this octet string element.
* @param value The Java string value to encode into this octet string.
*/
public ASN1OctetString(byte type, String value)
{
this(type, getBytes(value));
}
/**
* Creates a new ASN.1 octet string with the specified type and value.
*
* @param type The type to use for this octet string element.
* @param value The byte array to use as the value for this octet string.
*/
public ASN1OctetString(byte type, byte[] value)
{
super(type, value);
}
/**
* Retrieves the value of this ASN.1 element as a Java string.
*
* @return The value of this ASN.1 element as a Java string.
*/
public String getStringValue()
{
return new String(value);
}
/**
* Decodes the provided byte array as an ASN.1 octet string element.
*
* @param encodedValue The encoded ASN.1 element.
*
* @return The decoded ASN.1 octet string element.
*
* @throws ASN1Exception If the provided byte array cannot be decoded as an
* ASN.1 octet string element.
*/
public static ASN1OctetString decodeAsOctetString(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 two bytes. Otherwise, there
// can't be both a type and a length
if (encodedValue.length < 2)
{
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);
return new ASN1OctetString(type, value);
}
}