View Javadoc

1   /*
2    *   Copyright 2004 The Apache Software Foundation
3    *
4    *   Licensed under the Apache License, Version 2.0 (the "License");
5    *   you may not use this file except in compliance with the License.
6    *   You may obtain a copy of the License at
7    *
8    *       http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *   Unless required by applicable law or agreed to in writing, software
11   *   distributed under the License is distributed on an "AS IS" BASIS,
12   *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *   See the License for the specific language governing permissions and
14   *   limitations under the License.
15   *
16   */
17  package org.apache.asn1.ber ;
18  
19  
20  import java.nio.ByteBuffer;
21  import java.util.List;
22  
23  import org.apache.commons.lang.ArrayUtils;
24  
25  
26  /***
27   * TLV Tuple used by the value chunking decoder.  Because the length field is
28   * a primitive int it's maximum value is 2,147,483,647 a single TLV's tuple
29   * cannot have a length over this amount or a value size over 2 GB.
30   *
31   * @author <a href="mailto:dev@directory.apache.org">
32   * Apache Directory Project</a>
33   * @version $Rev: 157644 $
34   */
35  public class Tuple
36  {
37      /*** empty buffer reused for handling null */
38      private static final ByteBuffer EMPTY_BUFFER =
39          ByteBuffer.wrap( ArrayUtils.EMPTY_BYTE_ARRAY ) ;
40  
41      /*** mask for bit 5 with 0-based index */
42      private static final int BIT_5 = 0x20 ;
43      /*** mask for bit 6 with 0-based index */
44      private static final int BIT_6 = 0x40 ;
45      /*** mask for bit 7 with 0-based index */
46      private static final int BIT_7 = 0x80 ;
47  
48      /*** precalculated left shift of 1 by 14 places */
49      private static final int BIT_13 = 1 << 14 ;
50      /*** precalculated left shift of 1 by 16 places */
51      private static final int BIT_15 = 1 << 16 ;
52      /*** precalculated left shift of 1 by 21 places */
53      private static final int BIT_20 = 1 << 21 ;
54      /*** precalculated left shift of 1 by 24 places */
55      private static final int BIT_23 = 1 << 24 ;
56      /*** precalculated left shift of 1 by 28 places */
57      private static final int BIT_27 = 1 << 28 ;
58  
59      /*** the raw tag data */
60      int rawTag = 0 ;
61      /*** the tag id for this TLV tuple */
62      int id = 0 ;
63      /*** the flag for whether or not this TLV is constructed or primitive */
64      boolean isPrimitive = true ;
65      /*** the type class for this TLV */
66      TypeClass typeClass = TypeClass.APPLICATION ;
67      /*** the length for this TLV tuple's value field */
68      int length = 0 ;
69      /*** the present value chunk buffer read for this TLV tuple */
70      ByteBuffer valueChunk = EMPTY_BUFFER ;
71  
72      /*** tlv byte index */
73      int index = Length.UNDEFINED ;
74      /*** tlv value index for how far into the value we have read */
75      int valueIndex = Length.UNDEFINED ;
76  
77  
78      // ------------------------------------------------------------------------
79      // C O N S T R U C T O R S
80      // ------------------------------------------------------------------------
81  
82  
83      /***
84       * Empty do nothing tuple.
85       */
86      public Tuple()
87      {
88      }
89  
90  
91      /***
92       * Creates constructed application type tlv tuples.  Constructed TLV's with
93       * a definate length will use this constructor predominantly.  The TypeClass
94       * defualts to APPLICATION.
95       *
96       * @param id the tag id of the tlv
97       * @param length the length of the value which is the length of all the
98       *      nested tuples.
99       */
100     public Tuple( int id, int length )
101     {
102         this( id, length, TypeClass.APPLICATION ) ;
103     }
104 
105 
106     /***
107      * Creates constructed application type tlv tuples.  Constructed TLV's with
108      * a definate length will use this constructor predominantly.
109      *
110      * @param id the tag id of the tlv
111      * @param length the length of the value which is the length of all the
112      *      nested tuples.
113      * @param typeClass the type class of this tlv tuple
114      */
115     public Tuple( int id, int length, TypeClass typeClass )
116     {
117         this.id = id ;
118         this.length = length ;
119         valueChunk = EMPTY_BUFFER ;
120         isPrimitive = false ;
121 
122         if ( typeClass != null )
123         {
124             this.typeClass = typeClass ;
125         }
126     }
127 
128 
129     /***
130      * Creates constructed application type tlv tuples.  Constructed TLV's with
131      * a definate length will use this constructor predominantly.
132      *
133      * @param id the tag id of the tlv
134      * @param length the length of the value which is the length of all the
135      *      nested tuples.
136      * @param isPrimitive whether or not this Tuple is primitive or constructed
137      * @param typeClass the type class of this tlv tuple
138      */
139     public Tuple( int id, int length, boolean isPrimitive, TypeClass typeClass )
140     {
141         this.id = id ;
142         this.length = length ;
143         valueChunk = EMPTY_BUFFER ;
144         isPrimitive = false ;
145 
146         if ( typeClass != null )
147         {
148             this.typeClass = typeClass ;
149         }
150     }
151 
152 
153     /***
154      * Creates a tuple where the length is indefinite.  The tuple according to
155      * the BER encoding must be of the constructed type.
156      *
157      * @param id the tag id of the tlv
158      * @param typeClass the type class for the tlv
159      */
160     public Tuple( int id, TypeClass typeClass )
161     {
162         this.id = id ;
163         this.isPrimitive = false ;
164         valueChunk = EMPTY_BUFFER ;
165         length = Length.INDEFINITE ;
166 
167         if ( typeClass != null )
168         {
169             this.typeClass = typeClass ;
170         }
171     }
172 
173 
174     // ------------------------------------------------------------------------
175     // Public Accessors and Mutators
176     // ------------------------------------------------------------------------
177 
178 
179     /***
180      * Gets the tag id for this TLV Tuple.
181      *
182      * @return the tag id
183      */
184     public int getId()
185     {
186         return id ;
187     }
188 
189 
190     /***
191      * Sets the id of this Tuple and as a side effect the rawTag.
192      *
193      * @param id the new tag id to set
194      */
195     public void setId( int id )
196     {
197         this.id = id ;
198         rawTag = Tag.setIntEncodedId( rawTag, id );
199     }
200 
201 
202     /***
203      * Gets the raw tag as it is stuffed into a primitive int.
204      *
205      * @return a primitive int stuffed with the first four octets of the tag
206      */
207     public int getRawTag()
208     {
209         return rawTag ;
210     }
211 
212 
213     /***
214      * Sets the raw tag encoded as a primitive int and as a side effect this
215      * call also sets the id, primitive flag, and typeClass of this TLV tuple.
216      *
217      * @param rawTag the raw primitive int encoded tag.
218      */
219     public void setRawTag( int rawTag )
220     {
221         this.rawTag = rawTag;
222         this.id = Tag.getTagId( rawTag );
223         this.isPrimitive = ! Tag.isRawTagConstructed( rawTag );
224         this.typeClass = TypeClass.getTypeClass( rawTag >> 24 );
225     }
226 
227 
228     /***
229      * Sets the tag parameters using a tag enumeration type.  This operation
230      * sets the id, isPrimitive, typeClass, and rawTag fields at the same time.
231      *
232      * @param tag the tag enumeration constant
233      */
234     public void setTag( TagEnum tag )
235     {
236         this.rawTag = tag.getValue();
237         this.id = tag.getTagId();
238         this.isPrimitive = ! Tag.isRawTagConstructed( tag.getValue() ) ;
239         this.typeClass = tag.getTypeClass();
240     }
241 
242 
243     /***
244      * Sets the tag parameters using a tag enumeration type explicitly setting
245      * the primitive/constructed bit.  This operation sets the id, isPrimitive,
246      * typeClass, and rawTag fields at the same time.
247      *
248      * @param tag the tag enumeration constant
249      * @param isPrimitive primitive/constructed bit override
250      */
251     public void setTag( TagEnum tag, boolean isPrimitive )
252     {
253         this.rawTag = tag.getValue();
254         this.id = tag.getTagId();
255         this.isPrimitive = isPrimitive;
256         this.typeClass = tag.getTypeClass();
257     }
258 
259 
260     /***
261      * Gets the raw tag with the primitive/constructed flag dubbed out.
262      * Effectively this makes every tag appear primitive and is done
263      * to remove encoding ambiguities that could interfere with pattern
264      * matching.
265      *
266      * @return the raw tag with the primitive/constructed flag dubbed out
267      */
268     public int getRawPrimitiveTag()
269     {
270         return rawTag & 0xDFFFFFFF ;
271     }
272 
273 
274     /***
275      * Get's whether or not this tuples's length is indefinite.
276      *
277      * @return whether or not this tuple's length is indefinite
278      */
279     public boolean isIndefinite()
280     {
281         return length == Length.INDEFINITE ;
282     }
283 
284 
285     /***
286      * Get's whether or not this tuple terminates an indefinite constructed
287      * tuple.  This means that length == 0 && isPrimitive = true && id == 0
288      * and the type class is universal.
289      *
290      * @return whether or not this node's length is indefinite
291      */
292     public boolean isIndefiniteTerminator()
293     {
294         return isPrimitive && id == 0 && length <= 0 &&
295             typeClass.equals( TypeClass.UNIVERSAL ) ;
296     }
297 
298 
299     /***
300      * Gets whether or not this TLV tuple is primitive or constructed.
301      *
302      * @return true if it is primitive, false if it is constructed
303      */
304     public boolean isPrimitive()
305     {
306         return isPrimitive ;
307     }
308 
309 
310     /***
311      * Gets the value length for this TLV Tuple.
312      *
313      * @return the length in bytes of the value field for this TLV tuple
314      */
315     public int getLength()
316     {
317         return length ;
318     }
319 
320 
321 
322     public void setLength( int length )
323     {
324         this.length = length;
325     }
326 
327 
328     /***
329      * Gets the BER TLV TypeClass for this TLV Tuple.
330      *
331      * @return the BER TLV TypeClass for this TLV Tuple
332      */
333     public TypeClass getTypeClass()
334     {
335         return typeClass ;
336     }
337 
338 
339     /***
340      * Gets the last chunk read for the value field (V-part) for this TLV Tuple.
341      *
342      * @return the last valueChunk field for this TLV Tuple
343      */
344     public ByteBuffer getLastValueChunk()
345     {
346         return valueChunk ;
347     }
348 
349 
350     /***
351      * Sets the value representing the last chunk read or the last chunch to
352      * write.
353      *
354      * @param buf the last chunk as a buffer
355      */
356     public void setLastValueChunk( ByteBuffer buf )
357     {
358         this.valueChunk = buf;
359     }
360 
361 
362     /***
363      * Gets the total size of this TLV tuple in bytes.  This includes the
364      * length of the tag field, the length of the length field and the length
365      * of the value feild.
366      *
367      * @return the total TLV size in bytes
368      */
369     public int size()
370     {
371         if ( this.length == Length.INDEFINITE )
372         {
373             return getTagLength() + getLengthLength() ;
374         }
375         else
376         {
377             return getTagLength() + getLengthLength() + length ;
378         }
379     }
380 
381 
382     // ------------------------------------------------------------------------
383     // Utility methods and java.lang.Object overrides
384     // ------------------------------------------------------------------------
385 
386 
387     /***
388      * Clears the values of this tuple.
389      */
390     public void clear()
391     {
392         this.id = 0 ;
393         this.index = 0 ;
394         this.rawTag = 0 ;
395         this.isPrimitive = true ;
396         this.length = Length.UNDEFINED ;
397         this.typeClass = TypeClass.APPLICATION ;
398         this.valueChunk = EMPTY_BUFFER ;
399         this.valueIndex = Length.UNDEFINED ;
400     }
401 
402 
403     /***
404      * Does not take into account the value, index or the valueIndex values when
405      * checking for equality.  Technically if both are being constructed by
406      * the decoder then they should only be equal when these values are equal
407      * because the tag, length or value would not be correct.  Plus since this
408      * is a chunking tuple the valueChunk means nothing with respect to the
409      * final value.
410      *
411      * @see java.lang.Object#equals(java.lang.Object)
412      */
413     public boolean equals( Object o )
414     {
415         if ( o == this )
416         {
417             return true ;
418         }
419 
420         if ( o instanceof Tuple )
421         {
422             Tuple t = ( Tuple ) o ;
423 
424             if ( t.id != id )
425             {
426                 return false ;
427             }
428 
429             if ( t.isPrimitive != isPrimitive )
430             {
431                 return false ;
432             }
433 
434             if ( t.length != length )
435             {
436                 return false ;
437             }
438 
439             if ( t.typeClass != typeClass )
440             {
441                 return false ;
442             }
443 
444             return true ;
445         }
446 
447         return false ;
448     }
449 
450 
451     /*
452      * (non-Javadoc)
453      * @see java.lang.Object#clone()
454      */
455     public Object clone()
456     {
457         Tuple t = new Tuple() ;
458         t.id = id ;
459         t.rawTag = rawTag ;
460         t.isPrimitive = isPrimitive ;
461         t.typeClass = typeClass ;
462         t.length = length ;
463 
464         /* ------------------------------------------------------------------ +/
465          * @todo figure out if we should remove this section
466          *
467          * Do think we need this anymore since the last valueChunk does not
468          * factor into the result returned by the equals(Object) method?
469          * ------------------------------------------------------------------ */
470         ByteBuffer bb = valueChunk ;
471         ByteBuffer cloned = ByteBuffer.allocate( bb.capacity() ) ;
472         int oldPos = bb.position() ;
473         bb.rewind() ;
474         cloned.put( bb ) ;
475         cloned.limit( bb.limit() ) ;
476         bb.position( oldPos ) ;
477         cloned.rewind() ;
478         t.valueChunk = cloned ;
479         /* ------------------------------------------------------------------ */
480 
481         t.index = index ;
482         t.valueIndex = valueIndex ;
483 
484         return t ;
485     }
486 
487 
488     // ------------------------------------------------------------------------
489     // Tuple encoding operations
490     // ------------------------------------------------------------------------
491 
492 
493     /***
494      * If this is a primitive TLV then the valueBytes argument is used to
495      * produce an encoded image of this TLV.  If it is constructed then
496      * only the TL part of the tuple is encoded leaving the value to be encoded
497      * by the set of child TLVs.
498      *
499      * @todo this should produce chunking output and needs to be removed from
500      * here actually and made into a standalone encoder.  You give it a buffer
501      * and it fills it as much as it can remembering where the encode stopped.
502      * Hence it is stateful as expected from the statemachine.
503      *
504      * @return partial encoded image if constructed or complete TLV if primitive
505      */
506     public ByteBuffer toEncodedBuffer( List valueChunks )
507     {
508         ByteBuffer octets = null ;
509         int tagLength = getTagLength() ;
510         int lengthLength = getLengthLength() ;
511         int total = tagLength + lengthLength ;
512 
513         if ( isPrimitive )
514         {
515             total += length ;
516         }
517 
518         octets = ByteBuffer.allocate( total ) ;
519         setTag( octets, tagLength ) ;
520         setLength( octets, lengthLength ) ;
521 
522         if ( isPrimitive )
523         {
524             for ( int ii = 0; ii < valueChunks.size(); ii++ )
525             {
526                 octets.put( ( ByteBuffer ) valueChunks.get(ii) ) ;
527             }
528         }
529 
530         return ( ByteBuffer ) octets.flip() ;
531     }
532 
533 
534     /***
535      * Sets the tag section within the buffer.
536      *
537      * @param octets the buffer to set the tag in
538      * @param tagLength the length of the tag section
539      */
540     public void setTag( ByteBuffer octets, int tagLength )
541     {
542         if ( tagLength >= 6 )
543         {
544             throw new IllegalArgumentException( "cannot support id's as large "
545                     + "as " + id + " unless we start using longs for the id" ) ;
546         }
547 
548         byte octet = ( byte ) typeClass.getValue() ;
549         int i = octets.position();
550 
551         if ( ! isPrimitive )
552         {
553             octet |= BIT_5;
554         }
555 
556 		if ( id < 31 )
557 		{
558             octets.put( ( byte ) ( octet | (id & Tag.SHORT_MASK ) ) ) ;
559             return;
560 
561 		}
562 		else
563 		{
564             octets.put( ( byte ) ( octet | Tag.SHORT_MASK ) ) ;
565             i++;
566 		}
567 
568 		switch ( tagLength - 1) {
569         	case 5 :
570                 octets.put( ( byte ) ( ( ( id >> 21 ) & Tag.LONG_MASK ) | BIT_7 ) ) ;
571                 i++;
572                 // fallthrough
573 
574         	case 4:
575                 octets.put( ( byte ) ( ( ( id >> 21 ) & Tag.LONG_MASK ) | BIT_7 ) ) ;
576                 i++;
577                 // fallthrough
578 
579         	case 3 :
580                 octets.put( ( byte ) ( ( ( id >> 14 ) & Tag.LONG_MASK ) | BIT_7 ) ) ;
581                 i++;
582                 // fallthrough
583 
584         	case 2 :
585                 octets.put( ( byte ) ( ( ( id >> 7 ) & Tag.LONG_MASK ) | BIT_7 ) ) ;
586                 i++;
587                 // fallthrough
588 
589         	case 1 :
590                 octets.put( ( byte ) ( id  & Tag.LONG_MASK ) ) ;
591                 break;
592         }
593 
594 		//octets.f
595         return ;
596     }
597 
598 
599     /***
600      * Sets the value length of this Tuple.
601      *
602      * @param length the length of this tuple's value.
603      * @see Tuple#size() to get the entire determinate length of tuple
604      */
605     public void setValueLength( int length )
606     {
607         this.length = length;
608     }
609 
610 
611     /***
612      * Sets the length bytes.
613      *
614      * @param octets the byte [] to set length in
615      * @param lengthBytes the number bytes for the length section
616      */
617     public void setLength( ByteBuffer octets, int lengthBytes )
618     {
619         if ( lengthBytes >= 6 )
620         {
621             throw new IllegalArgumentException( "cannot support lengths larger "
622                     + "than a max integer using " + lengthBytes
623                     + " bytes unless we start using longs or BigIntegers for "
624                     + "the length" ) ;
625         }
626 
627         if ( length == Length.INDEFINITE )
628         {
629             octets.put( ( byte ) BIT_7 ) ;
630             return ;
631         }
632         else if ( lengthBytes == 1 )
633         {
634             octets.put( ( byte ) length ) ;
635             return ;
636         }
637         else
638         {
639             /*
640              * Here we basically set the first byte of the length field which
641              * is in the long form.  In this case the first byte's 7 least
642              * significant bits hold the length of the length field or the
643              * number of bytes used to hold the size of the value.  BTW the
644              * first most significant bit is set to 1 to mark the long form and
645              * hence why we bitwise or it with 0x80 which is BIT_7.
646              */
647 
648             /*
649              * the lengthBytes argument is the number of octets for the L field
650              * total which for the long form includes the first octet for the
651              * length of length (N) value where N < 127.  Technically with the
652              * 7 bits we can specify an N of up to 127 but this value of N is
653              * reserved.  Anyway below we subtract one from lengthBytes to get
654              * N which is set as the last 7 bits of the first octet of the L
655              * field.
656              */
657             octets.put( ( byte ) ( BIT_7 | ( lengthBytes - 1 ) ) ) ;
658         }
659 
660 
661         // using the long form so we calculate the length from all octets
662         for ( int ii = 0, shift = (lengthBytes-2)<<3; ii <= lengthBytes-2; ii++, shift -= 8 )
663         {
664             octets.put( octets.position() + ii, ( byte ) ( ( ( 0xff << shift ) & length ) >> shift ) );
665         }
666 
667         octets.position( octets.position() + lengthBytes - 1 );
668 
669 //        if ( lengthBytes >= 2 )
670 //        {
671 //            octets.put( ( byte ) ( 0xff & length ) ) ;
672 //        }
673 //        else
674 //        {
675 //            return ;
676 //        }
677 //
678 //        if ( lengthBytes >= 3 )
679 //        {
680 //            octets.put( ( byte ) ( ( 0xff00 & length ) >> 8 ) ) ;
681 //        }
682 //        else
683 //        {
684 //            return ;
685 //        }
686 //
687 //        if ( lengthBytes >= 4 )
688 //        {
689 //            octets.put( ( byte ) ( ( 0xff0000 & length ) >> 16 ) ) ;
690 //        }
691 //        else
692 //        {
693 //            return ;
694 //        }
695 //
696 //        if ( lengthBytes >= 5 )
697 //        {
698 //            octets.put( ( byte ) ( ( 0xff000000 & length ) >> 24 ) ) ;
699 //        }
700 //        else
701 //        {
702 //            return ;
703 //        }
704 
705     }
706 
707 
708     /***
709      * Gets the length in bytes of the tag section for this TLV tuple.
710      *
711      * @return the length in bytes of the tag section for this TLV tuple
712      */
713     public int getTagLength()
714     {
715         if ( id < 31 )
716         {
717             return 1 ;
718         }
719         else if ( id < BIT_6 )
720         {
721             return 2 ;
722         }
723 
724         else if ( id < BIT_13 )
725         {
726             return 3 ;
727         }
728         else if ( id < BIT_20 )
729         {
730             return 4 ;
731         }
732         else if ( id < BIT_27 )
733         {
734             return 5 ;
735         }
736 
737         throw new IllegalArgumentException( "cannot support id's larger than "
738                 + id + " unless we start using longs for the id" ) ;
739     }
740 
741 
742     /***
743      * Gets the length in bytes of the length section of this TLV Tuple.
744      *
745      * @return the length in bytes of the length section
746      */
747     public int getLengthLength()
748     {
749         if ( length == Length.INDEFINITE )
750         {
751             return 1 ;
752         }
753 
754         if ( length < 0 )
755         {
756             throw new IllegalArgumentException( "integer overflow makes id "
757                     + "negative with a value of " + id
758                     + " - unless we start using longs for"
759                     + " the id there you've hit a limitation" ) ;
760         }
761         else if ( length < BIT_7 )
762         {
763             return 1 ;
764         }
765         else if ( length < 256 )
766         {
767             return 2 ;
768         }
769         else if ( length < BIT_15 )
770         {
771             return 3 ;
772         }
773         else if ( length < BIT_23 )
774         {
775             return 4 ;
776         }
777         else
778         {
779             return 5 ;
780         }
781     }
782 }