001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 package org.apache.directory.shared.asn1.ber.tlv; 021 022 023 import org.apache.directory.shared.asn1.util.Asn1StringUtils; 024 025 026 /** 027 * This class is used to store Tag, Length and Value decoded from a PDU. 028 * 029 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 030 * @version $Rev: 664290 $, $Date: 2008-06-07 08:28:06 +0200 (Sat, 07 Jun 2008) $ 031 */ 032 public class TLV 033 { 034 // ~ Static fields/initializers 035 // ----------------------------------------------------------------- 036 037 // ~ Instance fields 038 // ---------------------------------------------------------------------------- 039 040 /** The current Tag being processed */ 041 private byte tag; 042 043 /** The current Length being processed */ 044 private int length; 045 046 /** The number of byte to store the Length being processed */ 047 private int lengthNbBytes; 048 049 /** The number of length's bytes currently read */ 050 private int lengthBytesRead; 051 052 /** The current Value being processed */ 053 private Value value; 054 055 /** An identity for the TLV. It store the TLV hashCode */ 056 private int id; 057 058 /** 059 * Reference the TLV which contains the current TLV, if any. As the 060 * enclosing TLV of a PDU does not have parent, it can be null in this case. 061 * Otherwise, it must point to a constructed TLV 062 */ 063 private TLV parent; 064 065 /** 066 * The expected length of the TLV's elements, if the current TLV is a 067 * constructed TLV. 068 */ 069 private int expectedLength; 070 071 /** tag flag for the primitive/constructed bit - 0010 0000 - 0x20 */ 072 public static final byte CONSTRUCTED_FLAG = 0x20; 073 074 /** mask to get the type class value */ 075 public static final byte TYPE_CLASS_MASK = (byte)0xC0; 076 077 /** value for the universal type class */ 078 public static final byte TYPE_CLASS_UNIVERSAL = 0x00; 079 080 /** tag mask for the short tag format - 0001 1111 - 0x1F */ 081 public static final int SHORT_MASK = 0x1F; 082 083 /** A mask to get the Length form */ 084 public static final int LENGTH_LONG_FORM = 0x0080; 085 086 /** Value of the reserved extension */ 087 public static final int LENGTH_EXTENSION_RESERVED = 0x7F; 088 089 /** A mask to get the long form value */ 090 public static final int LENGTH_SHORT_MASK = 0x007F; 091 092 /** A speedup for single bytes length */ 093 static byte[][] ONE_BYTE = new byte[256][]; 094 095 static 096 { 097 for ( int i = 0; i < 256; i++ ) 098 { 099 ONE_BYTE[i] = new byte[1]; 100 ONE_BYTE[i][0] = (byte)i; 101 } 102 } 103 104 105 /** 106 * Creates a new TLV object. 107 * 108 * @param id the TLV's id 109 */ 110 public TLV( int id ) 111 { 112 tag = 0; 113 length = 0; 114 lengthNbBytes = 0; 115 value = new Value(); 116 this.id = id; 117 118 expectedLength = 0; 119 } 120 121 122 // ~ Methods 123 // ------------------------------------------------------------------------------------ 124 125 /** 126 * Checks to see if the tag is constructed. 127 * 128 * @param tag the TLV's tag 129 * @return true if constructed, false if primitive 130 */ 131 public static boolean isConstructed( byte tag ) 132 { 133 return ( tag & CONSTRUCTED_FLAG ) != 0; 134 } 135 136 /** 137 * Checks to see if the current tlv's tag is constructed. 138 * 139 * @return true if constructed, false if primitive 140 */ 141 public boolean isConstructed() 142 { 143 return ( tag & CONSTRUCTED_FLAG ) != 0; 144 } 145 146 147 /** 148 * Checks to see if the tag represented by this Tag is primitive or 149 * constructed. 150 * 151 * @param tag the tag to be checked 152 * @return true if it is primitive, false if it is constructed 153 */ 154 public static boolean isPrimitive( byte tag ) 155 { 156 return ( tag & CONSTRUCTED_FLAG ) == 0; 157 } 158 159 /** 160 * Tells if the tag is Universal or not 161 * 162 * @param tag the tag to be checked 163 * @return true if it is primitive, false if it is constructed 164 */ 165 public static boolean isUniversal( byte tag ) 166 { 167 return ( tag & TYPE_CLASS_MASK ) == TYPE_CLASS_UNIVERSAL; 168 } 169 170 /** 171 * Reset the TLV, so it can be reused for the next PDU decoding. 172 */ 173 public void reset() 174 { 175 tag = 0; 176 length = 0; 177 lengthNbBytes = 0; 178 value.reset(); 179 180 expectedLength = 0; 181 } 182 183 /** 184 * @return Returns the tag. 185 */ 186 public byte getTag() 187 { 188 return tag; 189 } 190 191 /** 192 * Set a tag value for this TLV. 193 * 194 * @param tag the tag field for this TLV. 195 */ 196 public void setTag( byte tag ) 197 { 198 this.tag = tag; 199 } 200 201 /** 202 * @return Returns the value. 203 */ 204 public Value getValue() 205 { 206 return value; 207 } 208 209 /** 210 * Get a String representation of the TLV 211 * 212 * @return A String 213 */ 214 public String toString() 215 { 216 217 StringBuffer sb = new StringBuffer(); 218 219 sb.append( "TLV[ " ); 220 sb.append( Asn1StringUtils.dumpByte( tag ) ).append( ", " ); 221 sb.append( length ).append( ", " ); 222 sb.append( value.toString() ); 223 sb.append( "]" ); 224 225 return sb.toString(); 226 } 227 228 229 /** 230 * The TLV size is calculated by adding the Tag's size, the Length's size 231 * and the Value's length, if any. 232 * 233 * @return Returns the size of the TLV. 234 */ 235 public int getSize() 236 { 237 return 1 + lengthNbBytes + length; 238 } 239 240 /** 241 * Utility function that return the number of bytes necessary to store the 242 * length 243 * 244 * @param length The length to store in a byte array 245 * @return The number of bytes necessary to store the length. 246 */ 247 public static int getNbBytes( int length ) 248 { 249 250 if ( length >= 0 ) 251 { 252 253 if ( length < 128 ) 254 { 255 return 1; 256 } 257 else if ( length < 256 ) 258 { 259 return 2; 260 } 261 else if ( length < 65536 ) 262 { 263 return 3; 264 } 265 else if ( length < 16777216 ) 266 { 267 return 4; 268 } 269 else 270 { 271 return 5; 272 } 273 } 274 else 275 { 276 return 5; 277 } 278 } 279 280 /** 281 * Utility function that return a byte array representing the length 282 * 283 * @param length The length to store in a byte array 284 * @return The byte array representing the length. 285 */ 286 public static byte[] getBytes( int length ) 287 { 288 if ( length >= 0 ) 289 { 290 if ( length < 128 ) 291 { 292 return ONE_BYTE[length]; 293 } 294 else 295 { 296 byte[] bytes = new byte[getNbBytes( length )]; 297 298 if ( length < 256 ) 299 { 300 bytes[0] = ( byte ) 0x81; 301 bytes[1] = ( byte ) length; 302 } 303 else if ( length < 65536 ) 304 { 305 bytes[0] = ( byte ) 0x82; 306 bytes[1] = ( byte ) ( length >> 8 ); 307 bytes[2] = ( byte ) ( length & 0x00FF ); 308 } 309 else if ( length < 16777216 ) 310 { 311 bytes[0] = ( byte ) 0x83; 312 bytes[1] = ( byte ) ( length >> 16 ); 313 bytes[2] = ( byte ) ( ( length >> 8 ) & 0x00FF ); 314 bytes[3] = ( byte ) ( length & 0x00FF ); 315 } 316 else 317 { 318 bytes[0] = ( byte ) 0x84; 319 bytes[1] = ( byte ) ( length >> 24 ); 320 bytes[2] = ( byte ) ( ( length >> 16 ) & 0x00FF ); 321 bytes[3] = ( byte ) ( ( length >> 8 ) & 0x00FF ); 322 bytes[4] = ( byte ) ( length & 0x00FF ); 323 } 324 325 return bytes; 326 } 327 } 328 else 329 { 330 byte[] bytes = new byte[getNbBytes( length )]; 331 332 bytes[0] = ( byte ) 0x84; 333 bytes[1] = ( byte ) ( length >> 24 ); 334 bytes[2] = ( byte ) ( ( length >> 16 ) & 0x00FF ); 335 bytes[3] = ( byte ) ( ( length >> 8 ) & 0x00FF ); 336 bytes[4] = ( byte ) ( length & 0x00FF ); 337 338 return bytes; 339 } 340 } 341 342 343 /** 344 * @return Returns the parent. 345 */ 346 public TLV getParent() 347 { 348 return parent; 349 } 350 351 352 /** 353 * @param parent The parent to set. 354 */ 355 public void setParent( TLV parent ) 356 { 357 this.parent = parent; 358 } 359 360 361 /** 362 * Get the TLV expected length. 363 * 364 * @return Returns the expectedLength. 365 */ 366 public int getExpectedLength() 367 { 368 return expectedLength; 369 } 370 371 372 /** 373 * Set the new expected length of the current TLV. 374 * 375 * @param expectedLength The expectedLength to set. 376 */ 377 public void setExpectedLength( int expectedLength ) 378 { 379 this.expectedLength = expectedLength; 380 } 381 382 383 /** 384 * @return the number of bytes necessary to store the TLV's length 385 */ 386 public int getLengthNbBytes() 387 { 388 return lengthNbBytes; 389 } 390 391 392 /** 393 * Set the number of bytes we should use to store the TLV's length 394 * @param lengthNbBytes the number of bytes necessary to store the TLV's length 395 */ 396 public void setLengthNbBytes( int lengthNbBytes ) 397 { 398 this.lengthNbBytes = lengthNbBytes; 399 } 400 401 402 /** 403 * @return the tLV's length 404 */ 405 public int getLength() 406 { 407 return length; 408 } 409 410 411 /** 412 * Set the TLV's length 413 * 414 * @param length the TLV's length 415 */ 416 public void setLength( int length ) 417 { 418 this.length = length; 419 } 420 421 422 /** 423 * @return the currently read TLV's length bytes 424 */ 425 public int getLengthBytesRead() 426 { 427 return lengthBytesRead; 428 } 429 430 431 /** 432 * Set the currently read TLV's length bytes. 433 * 434 * @param lengthBytesRead the currently read TLV's length bytes 435 */ 436 public void setLengthBytesRead( int lengthBytesRead ) 437 { 438 this.lengthBytesRead = lengthBytesRead; 439 } 440 441 442 /** 443 * Increment the number of bytes read for this TLV 444 * 445 */ 446 public void incLengthBytesRead() 447 { 448 lengthBytesRead++; 449 } 450 451 452 /** 453 * @return the TLV's ID 454 */ 455 public int getId() 456 { 457 return id; 458 } 459 } 460