001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.protocols.asn1;
028 import org.opends.messages.Message;
029
030
031
032 import static org.opends.messages.ProtocolMessages.*;
033 import static org.opends.server.protocols.asn1.ASN1Constants.*;
034 import static org.opends.server.util.ServerConstants.*;
035 import static org.opends.server.util.StaticUtils.*;
036
037
038
039 /**
040 * This class defines the data structures and methods to use when interacting
041 * with ASN.1 null elements.
042 */
043 @org.opends.server.types.PublicAPI(
044 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED,
045 mayInstantiate=true,
046 mayExtend=false,
047 mayInvoke=true)
048 public final class ASN1Null
049 extends ASN1Element
050 {
051 /**
052 * The serial version identifier required to satisfy the compiler because this
053 * class implements the <CODE>java.io.Serializable</CODE> interface. This
054 * value was generated using the <CODE>serialver</CODE> command-line utility
055 * included with the Java SDK.
056 */
057 private static final long serialVersionUID = 8921787912269145125L;
058
059
060
061 /**
062 * Creates a new ASN.1 null element with the default type.
063 */
064 public ASN1Null()
065 {
066 super(UNIVERSAL_NULL_TYPE);
067
068 }
069
070
071
072 /**
073 * Creates a new ASN.1 null element with the specified type.
074 *
075 * @param type The BER type to use for this ASN.1 null element.
076 */
077 public ASN1Null(byte type)
078 {
079 super(type);
080
081 }
082
083
084
085 /**
086 * Specifies the value for this ASN.1 null element.
087 *
088 * @param value The encoded value for this ASN.1 null element.
089 *
090 * @throws ASN1Exception If the provided array is not empty.
091 */
092 public void setValue(byte[] value)
093 throws ASN1Exception
094 {
095 if ((value != null) && (value.length != 0))
096 {
097 Message message =
098 ERR_ASN1_NULL_SET_VALUE_INVALID_LENGTH.get(value.length);
099 throw new ASN1Exception(message);
100 }
101 }
102
103
104
105 /**
106 * Decodes the provided ASN.1 element as a null element.
107 *
108 * @param element The ASN.1 element to decode as a null element.
109 *
110 * @return The decoded ASN.1 null element.
111 *
112 * @throws ASN1Exception If the provided ASN.1 element cannot be decoded as
113 * a null element.
114 */
115 public static ASN1Null decodeAsNull(ASN1Element element)
116 throws ASN1Exception
117 {
118 if (element == null)
119 {
120 Message message = ERR_ASN1_NULL_DECODE_ELEMENT_NULL.get();
121 throw new ASN1Exception(message);
122 }
123
124 byte[] value = element.value();
125 if (value.length != 0)
126 {
127 Message message =
128 ERR_ASN1_NULL_DECODE_ELEMENT_INVALID_LENGTH.get(value.length);
129 throw new ASN1Exception(message);
130 }
131
132 return new ASN1Null(element.getType());
133 }
134
135
136
137 /**
138 * Decodes the provided byte array as an ASN.1 null element.
139 *
140 * @param encodedElement The byte array to decode as an ASN.1 null element.
141 *
142 * @return The decoded ASN.1 null element.
143 *
144 * @throws ASN1Exception If the provided byte array cannot be decoded as an
145 * ASN.1 null element.
146 */
147 public static ASN1Null decodeAsNull(byte[] encodedElement)
148 throws ASN1Exception
149 {
150 // First make sure that the array is not null and long enough to contain
151 // a valid ASN.1 null element.
152 if (encodedElement == null)
153 {
154 Message message = ERR_ASN1_NULL_DECODE_ARRAY_NULL.get();
155 throw new ASN1Exception(message);
156 }
157
158 if (encodedElement.length < 2)
159 {
160 Message message = ERR_ASN1_SHORT_ELEMENT.get(encodedElement.length);
161 throw new ASN1Exception(message);
162 }
163
164
165 // Next, decode the length. This allows multi-byte lengths with up to four
166 // bytes used to indicate how many bytes are in the length.
167 byte type = encodedElement[0];
168 int length = (encodedElement[1] & 0x7F);
169 int valueStartPos = 2;
170 if (length != encodedElement[1])
171 {
172 int numLengthBytes = length;
173 if (numLengthBytes > 4)
174 {
175 Message message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES.get(numLengthBytes);
176 throw new ASN1Exception(message);
177 }
178 else if (encodedElement.length < (2 + numLengthBytes))
179 {
180 Message message = ERR_ASN1_TRUNCATED_LENGTH.get(numLengthBytes);
181 throw new ASN1Exception(message);
182 }
183
184 length = 0x00;
185 valueStartPos = 2 + numLengthBytes;
186 for (int i=0; i < numLengthBytes; i++)
187 {
188 length = (length << 8) | (encodedElement[i+2] & 0xFF);
189 }
190 }
191
192
193 // Make sure that the number of bytes left is equal to the number of bytes
194 // in the value.
195 if ((encodedElement.length - valueStartPos) != length)
196 {
197 Message message = ERR_ASN1_LENGTH_MISMATCH.get(
198 length, (encodedElement.length - valueStartPos));
199 throw new ASN1Exception(message);
200 }
201
202
203 // Make sure that the decoded length is exactly zero byte.
204 if (length != 0)
205 {
206 Message message = ERR_ASN1_NULL_DECODE_ARRAY_INVALID_LENGTH.get(length);
207 throw new ASN1Exception(message);
208 }
209
210
211 // Copy the value and construct the element to return.
212 return new ASN1Null(type);
213 }
214
215
216
217 /**
218 * Appends a string representation of this ASN.1 null element to the provided
219 * buffer.
220 *
221 * @param buffer The buffer to which the information should be appended.
222 */
223 public void toString(StringBuilder buffer)
224 {
225 buffer.append("ASN1Null(type=");
226 buffer.append(byteToHex(getType()));
227 buffer.append(")");
228 }
229
230
231
232 /**
233 * Appends a string representation of this protocol element to the provided
234 * buffer.
235 *
236 * @param buffer The buffer into which the string representation should be
237 * written.
238 * @param indent The number of spaces that should be used to indent the
239 * resulting string representation.
240 */
241 public void toString(StringBuilder buffer, int indent)
242 {
243 StringBuilder indentBuf = new StringBuilder(indent);
244 for (int i=0 ; i < indent; i++)
245 {
246 indentBuf.append(' ');
247 }
248
249 buffer.append(indentBuf);
250 buffer.append("ASN.1 Null");
251 buffer.append(EOL);
252
253 buffer.append(indentBuf);
254 buffer.append(" BER Type: ");
255 buffer.append(byteToHex(getType()));
256 buffer.append(EOL);
257 }
258 }
259