View Javadoc

1   /*
2    *   Copyright 2005 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.asn1new.ber;
18  
19  
20  import org.apache.asn1.codec.DecoderException;
21  import org.apache.asn1new.ber.containers.IAsn1Container;
22  import org.apache.asn1new.ber.tlv.Length;
23  import org.apache.asn1new.ber.tlv.TLV;
24  import org.apache.asn1new.ber.tlv.ITLVBerDecoderMBean;
25  import org.apache.asn1new.ber.tlv.TLVStateEnum;
26  import org.apache.asn1new.ber.tlv.Tag;
27  import org.apache.asn1new.ber.tlv.UniversalTag;
28  import org.apache.asn1new.ber.tlv.Value;
29  import org.apache.asn1new.util.StringUtils;
30  
31  import org.apache.log4j.Logger;
32  
33  import java.nio.ByteBuffer;
34  
35  
36  /***
37   * A BER TLV Tag component decoder.  This decoder instanciate a Tag. The tag
38   * won't be implementations should not copy the handle to the Tag object
39   * delivered but should copy the data if they need it over the long term.
40   *
41   * @author   <a href="mailto:dev@directory.apache.org">Apache
42   *           Directory Project</a>
43   */
44  public class Asn1Decoder implements ITLVBerDecoderMBean
45  {
46      //~ Static fields/initializers -----------------------------------------------------------------
47  
48      /*** The logger */
49      private static final Logger log = Logger.getLogger( Asn1Decoder.class );
50      
51      /*** A speedup for logs */
52      private static boolean DEBUG;
53  
54      /*** This flag is used to indicate that there are more bytes in the stream */
55      private static final boolean MORE = true;
56  
57      /*** This flag is used to indicate that there are no more bytes in the stream */
58      private static final boolean END = false;
59  
60      //~ Instance fields ----------------------------------------------------------------------------
61  
62      /*** Flag that is used to allow/disallow the indefinite form of Length */
63      private boolean indefiniteLengthAllowed;
64  
65      /*** The maximum number of bytes that could be used to encode the Length */
66      private int maxLengthLength;
67  
68      /*** The maximum number of bytes that could be used to encode the Tag */
69      private int maxTagLength;
70  
71      //~ Constructors -------------------------------------------------------------------------------
72  
73      /***
74       * A public constructor of an Asn1 Decoder.
75       */
76      public Asn1Decoder()
77      {
78          indefiniteLengthAllowed = false;
79          maxLengthLength         = 1;
80          maxTagLength            = 1;
81          DEBUG = log.isDebugEnabled();
82      }
83  
84      //~ Methods ------------------------------------------------------------------------------------
85  
86      /***
87       * Treat the start of a TLV. It reads the tag and get its value.
88       *
89       * @param stream The ByteBuffer containing the PDU to decode
90       * @param container The container that stores the current state,
91       * the result and other informations.
92       * 
93       * @return <code>true</code> if there are more bytes to read, <code>false 
94       * </code> otherwise
95       * 
96       * @throws DecoderException If something went wrong.
97       */
98      private boolean treatTagStartState( ByteBuffer stream, IAsn1Container container )
99          throws DecoderException
100     {
101 
102         if ( stream.hasRemaining() )
103         {
104 
105             byte octet = stream.get();
106 
107             TLV tlv = new TLV();
108             Tag tag = tlv.getTag();
109 
110             tag.setSize( 1 );
111             tag.setPrimitive( ( octet & Tag.CONSTRUCTED_FLAG ) == 0 );
112             tag.setTypeClass( Tag.TYPE_CLASS[( octet & Tag.TYPE_CLASS_MASK ) >>> 6] );
113 
114             int value = octet & Tag.SHORT_MASK;
115 
116             if ( value == Tag.SHORT_MASK )
117             {
118 
119                 // we have to check the typeClass. UNIVERSAL class is not
120                 // allowed with this value.
121                 if ( tag.isUniversal() )
122                 {
123                     throw new DecoderException( "Universal tag 31 is reserved" );
124                 }
125 
126                 // we will have more than one byte to encode the value
127                 // The tag is encoded on [2 - 6 bytes], its value
128                 // is container in the 7 lower bits of the bytes following
129                 // the first byte.
130                 container.setState( TLVStateEnum.TAG_STATE_PENDING );
131                 tag.setId( 0 );
132                 tag.addByte( octet );
133             }
134             else
135             {
136                 // It's a tag wich value is below 30 (31 is not allowed
137                 // as it signals a multi-bytes value. Everything is done.
138 
139                 // We have to check for reserved tags if typeClass is UNIVERSAL
140                 if ( tag.isUniversal() )
141                 {
142 
143                     if ( ( value == UniversalTag.RESERVED_14 ) || ( value == UniversalTag.RESERVED_15 ) )
144                     {
145                         throw new DecoderException( "Universal tag " + value + " is reserved" );
146                     }
147                 }
148 
149                 tag.setId( value );
150                 tag.addByte( octet );
151 
152                 // The tag has been completed, we have to decode the Length
153                 container.setState( TLVStateEnum.TAG_STATE_END );
154             }
155 
156             // Store the current TLV in the container.
157             container.setCurrentTLV( tlv );
158 
159             return MORE;
160         }
161         else
162         {
163 
164             // The stream has been exhausted
165             return END;
166         }
167     }
168 
169     /***
170      * Treat a tag that is more than one byte long if the stream was cut in pieces. This
171      * function is called when some new bytes where got from the stream.
172      * 
173      * @param stream The ByteBuffer containing the PDU to decode
174      * @param container The container that stores the current state,
175      * the result and other informations.
176      * 
177      * @return <code>true</code> if there are more bytes to read, <code>false 
178      * </code> otherwise
179      * 
180      * @throws DecoderException Thrown if anything went wrong
181      */
182     private boolean treatTagPendingState( ByteBuffer stream, IAsn1Container container )
183         throws DecoderException
184     {
185 
186         if ( stream.hasRemaining() )
187         {
188 
189             Tag  tag    = container.getCurrentTLV().getTag();
190             byte octet = stream.get();
191 
192             if ( tag.getSize() >= Tag.MAX_TAG_BYTES )
193             {
194                 container.setState( TLVStateEnum.TAG_STATE_OVERFLOW );
195                 log.error( "Tag label Overflow" );
196                 throw new DecoderException( "Tag label overflow" );
197             }
198 
199             byte val = ( byte ) ( octet & Tag.LONG_MASK );
200 
201             tag.setId( ( tag.getId() << 7 ) | val );
202             tag.incTagSize();
203 
204             if ( val == octet )
205             {
206 
207                 // The Tag is completed, so let's decode the Length
208                 container.setState( TLVStateEnum.LENGTH_STATE_START );
209             }
210 
211             return MORE;
212         }
213         else
214         {
215 
216             return END;
217         }
218 
219     }
220 
221     /***
222      * Dump the current TLV tree
223      * @param container The container
224      */
225     private void dumpTLVTree( IAsn1Container container )
226     {
227         StringBuffer sb = new StringBuffer();
228         TLV current = container.getCurrentTLV();
229         
230         sb.append("TLV").
231         	append(StringUtils.dumpByte(current.getTag().getTagBytes()[0])).
232         	append("(").
233         	append(current.getExpectedLength()).
234         	append(")");
235         
236         current = current.getParent();
237         
238         while (current != null)
239         {
240             sb.append("-TLV").
241         		append(StringUtils.dumpByte(current.getTag().getTagBytes()[0])).
242         		append("(").
243         		append(current.getExpectedLength()).
244         		append(")");
245             current = current.getParent();
246         }
247         
248         log.debug("TLV Tree : " + sb.toString());
249     }
250     
251     /***
252      * Check if the TLV tree is fully decoded
253      * @param container The container
254      */
255     private boolean isTLVDecoded( IAsn1Container container )
256     {
257         TLV current = container.getCurrentTLV();
258         
259         TLV parent = current.getParent();
260         
261         while (parent != null)
262         {
263         	if (parent.getExpectedLength() != 0)
264         	{
265         	    return false;
266         	}
267         	
268         	parent = parent.getParent();
269         }
270         
271         Value value = current.getValue();
272         
273         if ( (value != null) && (value.getData() != null) )
274         {
275             return (current.getExpectedLength() == value.getData().length);
276         } 
277         else
278         {
279             return current.getExpectedLength() == 0;
280         }
281     }
282     
283     /***
284      * Action to be executed when the Tag has been decoded. Basically, this
285      * is a debug action. We will log the information that the Tag has been
286      * decoded.
287      *  
288      * @param container The container that stores the current state,
289      * the result and other informations.
290      * 
291      * @throws DecoderException Thrown if anything went wrong
292      */
293     private void treatTagEndState( IAsn1Container container )
294         throws DecoderException
295     {
296 
297         if ( DEBUG )
298         {
299             Tag tag = container.getCurrentTLV().getTag();
300             log.debug( tag.toString() + " has been decoded" );
301         }
302         
303         // Create a link between the current TLV with its parent
304         container.getCurrentTLV().setParent(container.getParentTLV());
305         
306         // After having decoded a tag, we have to execute the action
307         // which controls if this tag is allowed and well formed.
308         container.getGrammar().executeAction( container );
309 
310         // Switch to the next state, which is the Length decoding
311         container.setState( TLVStateEnum.LENGTH_STATE_START );
312     }
313 
314     /***
315      * Treat the Length start. The tag has been decoded, so we have to deal
316      * with the LENGTH, which can be multi-bytes.
317      *
318      * @param stream The ByteBuffer containing the PDU to decode
319      * @param container The container that stores the current state,
320      * the result and other informations.
321      * 
322      * @return <code>true</code> if there are more bytes to read, <code>false 
323      * </code> otherwise
324      * 
325      * @throws DecoderException Thrown if anything went wrong
326      */
327     private boolean treatLengthStartState( ByteBuffer stream, IAsn1Container container )
328         throws DecoderException
329     {
330 
331         if ( stream.hasRemaining() )
332         {
333 
334             byte octet = stream.get();
335 
336             Length length = container.getCurrentTLV().getLength();
337 
338             if ( ( octet & Length.LENGTH_LONG_FORM ) == 0 )
339             {
340 
341                 // We don't have a long form. The Length of the Value part is
342                 // given by this byte.
343                 length.setLength( octet );
344                 length.setExpectedLength( 0 );
345                 length.setCurrentLength( 0 );
346                 length.setSize( 1 );
347 
348                 container.setState( TLVStateEnum.LENGTH_STATE_END );
349             }
350             else if ( ( octet & Length.LENGTH_EXTENSION_RESERVED ) !=
351                     Length.LENGTH_EXTENSION_RESERVED )
352             {
353 
354                 int expectedLength = octet & Length.SHORT_MASK;
355 
356                 if ( expectedLength > 4 )
357                 {
358                     log.error( "Overflow : can't have more than 4 bytes long length" );
359                     throw new DecoderException(
360                         "Overflow : can't have more than 4 bytes long length" );
361                 }
362 
363                 length.setExpectedLength( expectedLength );
364                 length.setCurrentLength( 0 );
365                 length.setLength( 0 );
366                 length.setSize( 1 );
367                 container.setState( TLVStateEnum.LENGTH_STATE_PENDING );
368             }
369             else
370             {
371                 log.error( "Length reserved extension used" );
372                 throw new DecoderException( "Length reserved extension used" );
373             }
374 
375             return MORE;
376         }
377         else
378         {
379 
380             return END;
381         }
382     }
383 
384     /***
385      * This function is called when a Length is in the process of being 
386      * decoded, but the lack of bytes in the buffer stopped the process. 
387      *
388      * @param stream The ByteBuffer containing the PDU to decode
389      * @param container The container that stores the current state,
390      * the result and other informations.
391      * 
392      * @return <code>true</code> if there are more bytes to read, <code>false 
393      * </code> otherwise
394      * 
395      * @throws DecoderException Thrown if anything went wrong
396      */
397     private boolean treatLengthPendingState( ByteBuffer stream, IAsn1Container container )
398         throws DecoderException
399     {
400 
401         if ( stream.hasRemaining() )
402         {
403 
404             Length length = container.getCurrentTLV().getLength();
405 
406             while ( length.getCurrentLength() < length.getExpectedLength() )
407             {
408 
409                 byte octet = stream.get();
410 
411                 if ( DEBUG )
412                 {
413                     log.debug( "  current byte : " + StringUtils.dumpByte( octet ) );
414                 }
415 
416                 length.incCurrentLength();
417                 length.incSize();
418                 length.setLength( ( length.getLength() << 8 ) | (octet & 0x00FF));
419             }
420 
421             container.setState( TLVStateEnum.LENGTH_STATE_END );
422 
423             return MORE;
424         }
425         else
426         {
427 
428             return END;
429         }
430     }
431     
432     /***
433      * A debug function used to dump the expected length stack.
434      * @param tlv The current TLV.
435      * @return A string which represent the expected length stack.
436      */
437     private String getParentLength(TLV tlv)
438     {
439         StringBuffer buffer = new StringBuffer();
440         
441         buffer.append("TLV expected length stack : ");
442         
443         while (true)
444         {
445             if ( tlv == null )
446             {
447                 buffer.append(" - null");
448                 break;
449             }
450             else
451             {
452                 buffer.append(" - ").append(tlv.getExpectedLength());
453             }
454             
455             tlv = tlv.getParent();
456         }
457         
458         return buffer.toString();
459     }
460 
461     /***
462      * The Length is fully decoded. We have to call an action to check the
463      * size.
464      *
465      * @param container The container that stores the current state,
466      * the result and other informations.
467      * 
468      * @throws DecoderException Thrown if anything went wrong
469      */
470     private void treatLengthEndState( IAsn1Container container )
471         throws DecoderException
472     {
473         TLV tlv = container.getCurrentTLV();
474         Length length = tlv.getLength();
475 
476         // We will check the length here. What we must control is
477         // that the enclosing constructed TLV expected length is not
478         // exceeded by the current TLV.
479         TLV parentTLV = container.getParentTLV();
480         
481         if ( DEBUG )
482         {
483             log.debug(getParentLength(parentTLV));
484         }
485         
486         if (parentTLV == null) 
487         {
488             // This is the first TLV, so we can't check anything. We will
489             // just store this TLV as the root of the PDU
490             tlv.setExpectedLength(length.getLength());
491             container.setParentTLV(tlv);
492             
493             if ( DEBUG )
494             {
495                 log.debug("Root TLV[" + tlv.getLength().getLength() + "]");
496             }
497         }
498         else
499         {
500             // We have a parent, so we will check that its expected length is
501             // not exceeded. 
502             int expectedLength = parentTLV.getExpectedLength();
503             int currentLength = tlv.getSize();
504             
505             if (expectedLength < currentLength)
506             {
507                 // The expected length is lower than the Value length of the
508                 // current TLV. This is an error...
509                 log.error("tlv[" + expectedLength + ", " + currentLength + "]");
510                 throw new DecoderException("The current Value length is above the expected length");
511             }
512             
513             if (expectedLength == currentLength)
514             {
515                 parentTLV.setExpectedLength(0);
516 
517                 // deal with the particular case where expected length equal
518                 // the current length, which means that the parentTLV has been
519                 // completed. 
520                 // We also have to check that the current TLV is a constructed
521                 // one. 
522                 // In this case, we have to switch from this parent TLV
523                 // to the parent's parent TLV.
524                 if ( tlv.getTag().isConstructed() )
525                 {
526                     // here, we also have another special case : a 
527                     // zero length TLV. We must then unstack all 
528                     // the parents which length is null.
529                     if ( tlv.getLength().getLength() == 0 )
530                     {
531                         // We will set the parent to the first parentTLV which expectedLength 
532                         // is not null, and it will become the new parent TLV
533                         while ( parentTLV != null )
534                         {
535                             if ( parentTLV.getExpectedLength() != 0 )
536                             {
537                                 // ok, we have an incomplete parent. we will
538                                 // stop the recursion right here
539                                 break;
540                             }
541                             else
542                             {
543                                 parentTLV = parentTLV.getParent();
544                             }
545                         }
546 
547                         container.setParentTLV(parentTLV);
548                     }
549                     else
550                     {
551                         // The new Parent TLV is this Constructed TLV
552                         container.setParentTLV( tlv );
553                     }
554 
555                     tlv.setParent( parentTLV );
556                     tlv.setExpectedLength( tlv.getLength().getLength() );
557                 }
558                 else
559                 {
560                     tlv.setExpectedLength(tlv.getLength().getLength());
561                     // It's over, the parent TLV has been completed.
562                     // Go back to the parent's parent TLV until we find
563                     // a tlv which is not complete.
564                     while (parentTLV != null)
565                     {
566                         if ( parentTLV.getExpectedLength() != 0 )
567                         {
568                             // ok, we have an incomplete parent. we will
569                             // stop the recursion right here
570                             break;
571                         }
572                         else
573                         {
574                             parentTLV = parentTLV.getParent();
575                         }
576                     }
577                     
578                     container.setParentTLV(parentTLV);
579                 }
580             }
581             else
582             {
583 	            // Renew the expected Length.
584 	            parentTLV.setExpectedLength(expectedLength - currentLength);
585                 tlv.setExpectedLength(tlv.getLength().getLength());
586 	            
587 	            if (tlv.getTag().isConstructed())
588 	            {
589 	                // We have a constructed tag, so we must switch the parentTLV
590                     tlv.setParent(parentTLV);
591                     container.setParentTLV(tlv);
592 	            }
593             }
594             
595         }
596 
597         if ( DEBUG )
598         {
599             log.debug( length.toString() + " has been decoded" );
600         }
601 
602         if ( length.getLength() == 0 )
603         {
604 
605             // The length is 0, so we can't expect a value.
606             container.setState( TLVStateEnum.TLV_STATE_DONE );
607         }
608         else
609         {
610 
611             // Go ahead and decode the value part
612             container.setState( TLVStateEnum.VALUE_STATE_START );
613         }
614     }
615 
616     /***
617      * Treat the Value part. We will distinguish two cases : 
618      *  - if the Tag is a Primitive one, we will get the value.
619      *  - if the Tag is a Constructed one, nothing will be done.
620      * 
621      * @param stream The ByteBuffer containing the PDU to decode
622      * @param container The container that stores the current state,
623      * the result and other informations.
624      * 
625      * @return <code>true</code> if there are more bytes to read, <code>false 
626      * </code> otherwise
627      * 
628      * @throws DecoderException Thrown if anything went wrong
629      */
630     private boolean treatValueStartState( ByteBuffer stream, IAsn1Container container )
631         throws DecoderException
632     {
633 
634         TLV currentTlv = container.getCurrentTLV();
635 
636         if ( currentTlv.getTag().isConstructed() )
637         {
638             container.setState( TLVStateEnum.TLV_STATE_DONE );
639 
640             return MORE;
641         }
642         else
643         {
644 
645             int length  = currentTlv.getLength().getLength();
646             int nbBytes = stream.remaining();
647 
648             if ( nbBytes < length )
649             {
650                 currentTlv.getValue().init( length );
651                 currentTlv.getValue().setData( stream );
652                 container.setState( TLVStateEnum.VALUE_STATE_PENDING );
653 
654                 return END;
655             }
656             else
657             {
658                 currentTlv.getValue().init( length );
659                 stream.get( currentTlv.getValue().getData(), 0, length );
660                 container.setState( TLVStateEnum.TLV_STATE_DONE );
661 
662                 return MORE;
663             }
664         }
665     }
666 
667     /***
668      * Treat a pending Value when we get more bytes in the buffer.
669      *
670      * @param stream The ByteBuffer containing the PDU to decode
671      * @param container The container that stores the current state,
672      * the result and other informations.
673      * 
674      * @return <code>MORE</code> if some bytes remain in the buffer when 
675      * the value has been decoded, <code>END</code> if whe still need to get 
676      * some more bytes.
677      * 
678      * @throws DecoderException Thrown if anything went wrong
679      */
680     private boolean treatValuePendingState( ByteBuffer stream, IAsn1Container container )
681         throws DecoderException
682     {
683 
684         TLV currentTlv    = container.getCurrentTLV();
685 
686         int length        = currentTlv.getLength().getLength();
687         int currentLength = currentTlv.getValue().getCurrentLength();
688         int nbBytes       = stream.remaining();
689 
690         if ( ( currentLength + nbBytes ) < length )
691         {
692             currentTlv.getValue().addData( stream );
693             container.setState( TLVStateEnum.VALUE_STATE_PENDING );
694 
695             return END;
696         }
697         else
698         {
699 
700             int    remaining = length - currentLength;
701             byte[] data      = new byte[remaining];
702             stream.get( data, 0, remaining );
703             currentTlv.getValue().addData( data );
704             container.setState( TLVStateEnum.TLV_STATE_DONE );
705 
706             return MORE;
707         }
708     }
709 
710     /***
711      * When the TLV has been fully decoded, we have to execute the associated
712      * action and switch to the next TLV, which will start with a Tag.
713      * 
714      * @param stream The ByteBuffer containing the PDU to decode
715      * @param container The container that stores the current state,
716      * the result and other informations.
717      * 
718      * @return <code>true</code> if there are more bytes to read, <code>false 
719      * </code> otherwise
720      * 
721      * @throws DecoderException Thrown if anything went wrong
722      */
723     private boolean treatTLVDoneState( ByteBuffer stream, IAsn1Container container )
724         throws DecoderException
725     {
726         if ( DEBUG )
727         {
728             dumpTLVTree(container);
729         }
730         
731         // First, we have to execute the associated action
732         container.getGrammar().executeAction( container );
733 
734         // Check if the PDU has been fully decoded.
735         if ( isTLVDecoded(container) )
736         {
737             // Change the state to DECODED
738             container.setState( TLVStateEnum.PDU_DECODED );
739             
740         }
741         else
742         {
743             // Then we switch to the Start tag state and free the current TLV
744             container.setState( TLVStateEnum.TAG_STATE_START );
745         }
746 
747         return stream.hasRemaining();
748     }
749 
750     /***
751      * An helper function that return a string representing the current state
752      * for debuging purpose.
753      * 
754      * @param state The state
755      * 
756      * @return A string representation of the state
757     */
758     private String stateToString( int state )
759     {
760 
761         switch ( state )
762         {
763 
764             case TLVStateEnum.TAG_STATE_START :
765                 return "TAG_STATE_START";
766 
767             case TLVStateEnum.TAG_STATE_PENDING :
768                 return "TAG_STATE_PENDING";
769 
770             case TLVStateEnum.TAG_STATE_END :
771                 return "TAG_STATE_END";
772 
773             case TLVStateEnum.TAG_STATE_OVERFLOW :
774                 return "TAG_STATE_OVERFLOW";
775 
776             case TLVStateEnum.LENGTH_STATE_START :
777                 return "LENGTH_STATE_START";
778 
779             case TLVStateEnum.LENGTH_STATE_PENDING :
780                 return "LENGTH_STATE_PENDING";
781 
782             case TLVStateEnum.LENGTH_STATE_END :
783                 return "LENGTH_STATE_END";
784 
785             case TLVStateEnum.VALUE_STATE_START :
786                 return "VALUE_STATE_START";
787 
788             case TLVStateEnum.VALUE_STATE_PENDING :
789                 return "VALUE_STATE_PENDING";
790 
791             case TLVStateEnum.TLV_STATE_DONE :
792                 return "TLV_STATE_DONE";
793 
794             default :
795                 return "UNKNOWN_STATE";
796         }
797     }
798 
799     /***
800      * The decoder main function. This is where we read bytes from the stream
801      * and go through the automaton. It's an inifnite loop which stop when no
802      * more bytes are to be read. It can occurs if the ByteBuffer is exhausted 
803      * or if the PDU has been fully decoded. 
804      *
805      * @param stream The ByteBuffer containing the PDU to decode
806      * @param container The container that store the state, the result and
807      * other elements.
808      * 
809      * @throws DecoderException Thrown if anything went wrong!
810      */
811     public void decode( ByteBuffer stream, IAsn1Container container ) throws org.apache.asn1.codec.DecoderException
812     {
813 
814         /* We have to deal with the current state. This is an
815          * infinite loop, which will stop for any of these reasons :
816          * - STATE_END has been reached (hopefully, the most frequent case)
817          * - buffer is empty (it could happen)
818          * - STATE_OVERFLOW : bad situation ! The PDU may be a malevolous hand
819          * crafted ones, that try to "kill" our decoder. Whe must log it with
820          * all information to track back this case, and punish the guilty !
821          */
822 
823         boolean hasRemaining = stream.hasRemaining();
824 
825         if ( DEBUG )
826         {
827             log.debug( ">>>==========================================" );
828             log.debug( "--> Decoding a PDU" );
829             log.debug( ">>>------------------------------------------" );
830         }
831 
832         while ( hasRemaining )
833         {
834 
835             if ( DEBUG )
836             {
837                 log.debug( "--- State = " + stateToString( container.getState() ) + " ---" );
838 
839                 if (stream.hasRemaining())
840                 {
841                     byte octet = stream.get(stream.position());
842 
843                     log.debug( "  current byte : " + StringUtils.dumpByte( octet ) );
844                 }
845                 else
846                 {
847                     log.debug( "  no more byte to decode in the stream");
848                 }
849             }
850 
851             switch ( container.getState() )
852             {
853 
854                 case TLVStateEnum.TAG_STATE_START :
855                     hasRemaining = treatTagStartState( stream, container );
856 
857                     break;
858 
859                 case TLVStateEnum.TAG_STATE_PENDING :
860                     hasRemaining = treatTagPendingState( stream, container );
861 
862                     break;
863 
864                 case TLVStateEnum.TAG_STATE_END :
865                     treatTagEndState( container );
866 
867                     break;
868 
869                 case TLVStateEnum.TAG_STATE_OVERFLOW :
870                     log.error( "Incompatible state : OVERFLOW" );
871                     throw new DecoderException( "Incompatible state occured" );
872 
873                 case TLVStateEnum.LENGTH_STATE_START :
874                     hasRemaining = treatLengthStartState( stream, container );
875 
876                     break;
877 
878                 case TLVStateEnum.LENGTH_STATE_PENDING :
879                     hasRemaining = treatLengthPendingState( stream, container );
880 
881                     break;
882 
883                 case TLVStateEnum.LENGTH_STATE_END :
884                     treatLengthEndState( container );
885 
886                     break;
887 
888                 case TLVStateEnum.VALUE_STATE_START :
889                     hasRemaining = treatValueStartState( stream, container );
890 
891                     break;
892 
893                 case TLVStateEnum.VALUE_STATE_PENDING :
894                     hasRemaining = treatValuePendingState( stream, container );
895 
896                     break;
897 
898                 case TLVStateEnum.VALUE_STATE_END :
899                 	hasRemaining = stream.hasRemaining();
900 
901                     // Nothing to do. We will never reach this state
902                     break;
903 
904                 case TLVStateEnum.TLV_STATE_DONE :
905                     hasRemaining = treatTLVDoneState( stream, container );
906                     
907                     break;
908 
909                 case TLVStateEnum.PDU_DECODED :
910                     // We have to deal with the case where there are
911                     // more bytes in the buffer, but the PDU has been decoded.
912                     if ( log.isWarnEnabled() )
913                     {
914                         log.warn("The PDU has been fully decoded but there are still bytes in the buffer.");
915                     }
916                     
917                     hasRemaining = false;
918                     
919                     break;
920             }
921         }
922 
923         if ( DEBUG )
924         {
925             log.debug( "<<<------------------------------------------" );
926             
927             if ( container.getState() == TLVStateEnum.PDU_DECODED )
928             {
929                 log.debug( "<-- Stop decoding : " + container.getCurrentTLV().toString() );
930             }
931             else
932             {
933                 log.debug( "<-- End decoding : " + container.getCurrentTLV().toString() );
934             }
935             
936             log.debug( "<<<==========================================" );
937         }
938         
939         return;
940     } // end method decode
941 
942     /***
943      * Get the length's Length.
944      *
945      * @return  Returns the length's Length.
946      */
947     public int getMaxLengthLength()
948     {
949 
950         return maxLengthLength;
951     }
952 
953     /***
954      * Get the maximum Tag's length
955      *
956      * @return  Returns the maximum tag Length.
957      */
958     public int getMaxTagLength()
959     {
960 
961         return maxTagLength;
962     }
963 
964     /***
965      * Disallow indefinite length.
966      */
967     public void disallowIndefiniteLength()
968     {
969         this.indefiniteLengthAllowed = false;
970     }
971 
972     /***
973      * Allow indefinite length.
974      */
975     public void allowIndefiniteLength()
976     {
977         this.indefiniteLengthAllowed = true;
978     }
979 
980     /***
981      * Tells if indefinite length form could be used for Length
982      *
983      * @return  Returns <code>true</code> if the current decoder support
984      *          indefinite length
985      */
986     public boolean isIndefiniteLengthAllowed()
987     {
988 
989         return indefiniteLengthAllowed;
990     }
991 
992     /***
993      * Set the maximul length for a Length
994      *
995      * @param maxLengthLength  The lengthLength to set.
996      *
997      * @throws  DecoderException Thrown if the indefinite length is allowed
998      * or if the length's Length is above 126 bytes
999      */
1000     public void setMaxLengthLength( int maxLengthLength ) throws DecoderException
1001     {
1002 
1003         if ( ( this.indefiniteLengthAllowed ) && ( maxLengthLength > 126 ) )
1004         {
1005             throw new DecoderException(
1006                 "Length above 126 bytes are not allowed for a definite form Length" );
1007         }
1008 
1009         this.maxLengthLength = maxLengthLength;
1010     }
1011 
1012     /***
1013      * Set the maximum Tag length
1014      *
1015      * @param maxTagLength  The tagLength to set.
1016      */
1017     public void setMaxTagLength( int maxTagLength )
1018     {
1019         this.maxTagLength = maxTagLength;
1020     }
1021 
1022 } // end class TLVTagDecoder