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