gecko-dev/directory/java-sdk/ldapjdk/netscape/ldap/ber/stream/BERElement.java

323 строки
12 KiB
Java

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public
* License Version 1.1 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.mozilla.org/NPL/
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* The Original Code is mozilla.org code.
*
* The Initial Developer of the Original Code is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1999 Netscape Communications Corporation. All
* Rights Reserved.
*
* Contributor(s):
*/
package netscape.ldap.ber.stream;
import java.util.*;
import java.io.*;
/**
* This class is for the tagged object type. A nested tag is
* allowed. A tagged element contains another BER element.
*
* @version 1.0
* @seeAlso CCITT X.209
*/
public abstract class BERElement implements Serializable {
/**
* Possible element types.
*/
public final static int BOOLEAN = 0x01;
public final static int INTEGER = 0x02;
public final static int BITSTRING = 0x03;
public final static int OCTETSTRING = 0x04;
public final static int NULL = 0x05;
public final static int OBJECTID = 0x06;
public final static int REAL = 0x09;
public final static int ENUMERATED = 0x0a;
public final static int SET = 0x31; /* always constructed */
public final static int SEQUENCE = 0x30; /* always constructed */
public final static int NUMERICSTRING = 0x12;
public final static int PRINTABLESTRING = 0x13;
public final static int TELETEXSTRING = 0x14;
public final static int VIDEOTEXSTRING = 0x15;
public final static int IA5STRING = 0x16;
public final static int UTCTIME = 0x17;
public final static int GRAPHICSTRING = 0x19;
public final static int VISIBLESTRING = 0x1A;
public final static int GENERALSTRING = 0x1B;
/**
* Internal (non-transmitted) tags.
*/
public final static int TAG = -1;
public final static int CHOICE = -2;
public final static int ANY = -3;
/**
* Possible tags.
*/
public final static int EOC = 0x00; /* End Of Construction */
public final static int UNIVERSAL = 0x00;
public final static int APPLICATION = 0x40;
public final static int CONTEXT = 0x80;
public final static int SASLCONTEXT = 0xa0;
public final static int PRIVATE = 0xC0;
public final static int PRIMITIVE = 0x00;
public final static int CONSTRUCTED = 0x20;
public final static int MRA_OID = 0x01;
public final static int MRA_TYPE = 0x02;
public final static int MRA_VALUE = 0x03;
public final static int MRA_DNATTRS = 0x04;
public final static int EXOP_REQ_OID = 0x00;
public final static int EXOP_REQ_VALUE = 0x01;
public final static int EXOP_RES_OID = 0x0a;
public final static int EXOP_RES_VALUE = 0x0b;
public final static int SK_MATCHRULE = 0x00;
public final static int SK_REVERSE = 0x01;
public final static int SR_ATTRTYPE = 0x00;
/**
* Gets a ber element from the input stream.
* @param decoder decoder for application specific BER
* @param stream source of ber encoding
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @exception IOException failed to decode an element.
*/
public static BERElement getElement(BERTagDecoder decoder,
InputStream stream, int[] bytes_read) throws IOException {
BERElement element = null;
int tag = stream.read();
bytes_read[0] = 1;
if (tag == EOC) {
stream.read(); /* length octet (always zero) */
bytes_read[0] = 1;
element = null;
} else if (tag == BOOLEAN) {
element = new BERBoolean(stream, bytes_read);
} else if (tag == INTEGER) {
element = new BERInteger(stream, bytes_read);
} else if (tag == BITSTRING) {
element = new BERBitString(stream, bytes_read);
} else if (tag == (BITSTRING | CONSTRUCTED)) {
element = new BERBitString(decoder, stream, bytes_read);
} else if (tag == OCTETSTRING) {
element = new BEROctetString(stream, bytes_read);
} else if (tag == (OCTETSTRING | CONSTRUCTED)) {
element = new BEROctetString(decoder, stream, bytes_read);
} else if (tag == NULL) {
element = new BERNull(stream, bytes_read);
} else if (tag == OBJECTID) {
element = new BERObjectId(stream, bytes_read);
} else if (tag == REAL) {
element = new BERReal(stream, bytes_read);
} else if (tag == ENUMERATED) {
element = new BEREnumerated(stream, bytes_read);
} else if (tag == SEQUENCE) {
element = new BERSequence(decoder, stream, bytes_read);
} else if (tag == SET) {
element = new BERSet(decoder, stream, bytes_read);
} else if (tag == NUMERICSTRING) {
element = new BERNumericString(stream, bytes_read);
} else if (tag == (NUMERICSTRING | CONSTRUCTED)) {
element = new BERNumericString(decoder, stream, bytes_read);
} else if (tag == PRINTABLESTRING) {
element = new BERPrintableString(stream, bytes_read);
} else if (tag == (PRINTABLESTRING | CONSTRUCTED)) {
element = new BERPrintableString(decoder, stream, bytes_read);
} else if (tag == UTCTIME) {
element = new BERUTCTime(stream, bytes_read);
} else if (tag == (UTCTIME | CONSTRUCTED)) {
element = new BERUTCTime(decoder, stream, bytes_read);
} else if (tag == VISIBLESTRING) {
element = new BERVisibleString(stream, bytes_read);
} else if (tag == (VISIBLESTRING | CONSTRUCTED)) {
element = new BERVisibleString(decoder, stream, bytes_read);
} else if ((tag & (APPLICATION | PRIVATE | CONTEXT)) > 0) {
element = new BERTag(decoder, tag, stream, bytes_read);
} else
throw new IOException("invalid tag " + tag);
return element;
}
/**
* Reads and decodes a length byte and then that many octets
* from the input stream.
* @param stream input stream from which to read
* @param bytes_read array of 1 int; value incremented by
* number of bytes read from stream
* @return length of contents or -1 if indefinite length.
* @exception IOException failed to read octets
*/
public static int readLengthOctets(InputStream stream, int[] bytes_read)
throws IOException {
int contents_length = 0;
int octet = stream.read();
bytes_read[0]++;
if (octet == 0x80)
/* Indefinite length */
contents_length = -1;
else if ((octet & 0x80) > 0) {
/* Definite (long form) - num octets encoded in 7 rightmost bits */
int num_length_octets = (octet & 0x7F);
for (int i = 0; i < num_length_octets; i++) {
octet = stream.read();
bytes_read[0]++;
contents_length = (contents_length<<8) + octet;
}
} else {
/* Definite (short form) - one length octet. Value encoded in */
/* 7 rightmost bits. */
contents_length = octet;
}
return contents_length;
}
/**
* Writes length octets (definite length only) to stream.
* Uses shortform whenever possible.
* @param stream output stream to write to
* @param num_content_octets value to be encode into length octets
* @return number of bytes sent to stream.
* @exception IOException failed to read octets
*/
public static void sendDefiniteLength(OutputStream stream,
int num_content_octets) throws IOException {
int bytes_written = 0;
if (num_content_octets <= 127) {
/* Use short form */
stream.write(num_content_octets);
} else {
/* Using long form:
* Need to determine how many octets are required to
* encode the length.
*/
int num_length_octets = 0;
int num = num_content_octets;
while (num >= 0) {
num_length_octets++;
num = (num>>8);
if (num <= 0)
break;
}
byte[] buffer = new byte[num_length_octets+1];
buffer[0] = (byte)(0x80 | num_length_octets);
num = num_content_octets;
for (int i = num_length_octets; i > 0; i--) {
buffer[i] = (byte)(num & 0xFF);
num = (num>>8);
}
stream.write(buffer);
}
}
/**
* Reads a number of bytes from an input stream and form
* an integer..
* @param stream source of data
* @param bytes_read number of bytes read
* @param length number of bytes to be read (1 to 4)
* @return the value of the data as two's complement.
* @exception IOException failed to read octets
*/
protected int readUnsignedBinary(InputStream stream,
int[] bytes_read, int length) throws IOException {
int value = 0;
int octet;
for (int i = 0; i < length; i++) {
octet = stream.read();
bytes_read[0]++;
value = (value<<8) + octet;
}
return value;
}
/**
* Reads the two's complement representation of an integer from
* an input stream.
* @param stream source of data
* @param bytes_read number of bytes read
* @param length number of bytes to be read
* @return the integer value as two's complement.
* @exception IOException failed to read octets
*/
protected int readTwosComplement(InputStream stream,
int[] bytes_read, int length) throws IOException {
int value = 0;
if (length > 0) {
boolean negative = false;
int octet = stream.read();
bytes_read[0]++;
if ((octet & 0x80) > 0) /* left-most bit is 1. */
negative = true;
for (int i = 0; i < length; i++) {
if (i > 0) {
octet = stream.read();
bytes_read[0]++;
}
if (negative)
value = (value<<8) + (int)(octet^0xFF)&0xFF;
else
value = (value<<8) + (int)(octet&0xFF);
}
if (negative) /* convert to 2's complement */
value = (value + 1) * -1;
}
return value;
}
/**
* Converts byte to hex string.
* @param value byte value
* @return string representation of Hex String
*/
public String byteToHexString(byte value) {
if (value < 0)
return Integer.toHexString((value & 0x7F) + 128);
else
return Integer.toHexString(value);
}
/**
* Sends the BER encoding directly to a stream.
* @param stream output stream
* @return bytes written to stream.
*/
public abstract void write(OutputStream stream) throws IOException;
/**
* Gets the element type.
* @return element type.
*/
public abstract int getType();
/**
* Gets the string representation.
* @return string representation of an element.
*/
public abstract String toString();
}