1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
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
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
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
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
120
121 if ( tag.isUniversal() )
122 {
123 throw new DecoderException( "Universal tag 31 is reserved" );
124 }
125
126
127
128
129
130 container.setState( TLVStateEnum.TAG_STATE_PENDING );
131 tag.setId( 0 );
132 tag.addByte( octet );
133 }
134 else
135 {
136
137
138
139
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
153 container.setState( TLVStateEnum.TAG_STATE_END );
154 }
155
156
157 container.setCurrentTLV( tlv );
158
159 return MORE;
160 }
161 else
162 {
163
164
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
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
304 container.getCurrentTLV().setParent(container.getParentTLV());
305
306
307
308 container.getGrammar().executeAction( container );
309
310
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
342
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
477
478
479 TLV parentTLV = container.getParentTLV();
480
481 if ( DEBUG )
482 {
483 log.debug(getParentLength(parentTLV));
484 }
485
486 if (parentTLV == null)
487 {
488
489
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
501
502 int expectedLength = parentTLV.getExpectedLength();
503 int currentLength = tlv.getSize();
504
505 if (expectedLength < currentLength)
506 {
507
508
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
518
519
520
521
522
523
524 if ( tlv.getTag().isConstructed() )
525 {
526
527
528
529 if ( tlv.getLength().getLength() == 0 )
530 {
531
532
533 while ( parentTLV != null )
534 {
535 if ( parentTLV.getExpectedLength() != 0 )
536 {
537
538
539 break;
540 }
541 else
542 {
543 parentTLV = parentTLV.getParent();
544 }
545 }
546
547 container.setParentTLV(parentTLV);
548 }
549 else
550 {
551
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
562
563
564 while (parentTLV != null)
565 {
566 if ( parentTLV.getExpectedLength() != 0 )
567 {
568
569
570 break;
571 }
572 else
573 {
574 parentTLV = parentTLV.getParent();
575 }
576 }
577
578 container.setParentTLV(parentTLV);
579 }
580 }
581 else
582 {
583
584 parentTLV.setExpectedLength(expectedLength - currentLength);
585 tlv.setExpectedLength(tlv.getLength().getLength());
586
587 if (tlv.getTag().isConstructed())
588 {
589
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
606 container.setState( TLVStateEnum.TLV_STATE_DONE );
607 }
608 else
609 {
610
611
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
732 container.getGrammar().executeAction( container );
733
734
735 if ( isTLVDecoded(container) )
736 {
737
738 container.setState( TLVStateEnum.PDU_DECODED );
739
740 }
741 else
742 {
743
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
815
816
817
818
819
820
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
902 break;
903
904 case TLVStateEnum.TLV_STATE_DONE :
905 hasRemaining = treatTLVDoneState( stream, container );
906
907 break;
908
909 case TLVStateEnum.PDU_DECODED :
910
911
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 }
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 }