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.digester.rules ;
18  
19  
20  import java.nio.ByteBuffer;
21  
22  import org.apache.asn1.ber.TagEnum;
23  import org.apache.asn1.ber.TypeClass;
24  import org.apache.asn1.ber.digester.AbstractRule;
25  import org.apache.asn1.ber.primitives.PrimitiveUtils;
26  import org.apache.asn1.ber.primitives.UniversalTag;
27  
28  
29  /***
30   * A rule to Decode a BER encoded ASN.1 INTEGER into a Java primitive int.
31   * <p>
32   * The bytes to form the integer are extracted from the BER value which may
33   * arrive in multiple chunks.  The individual bytes are temporarily stored
34   * within a 4 byte array while incrementing a counter to track the capture.
35   * Once gathered the bytes are decoded into a int in the finish
36   * </p>
37   * <p>
38   * As a side effect once the decode is complete, the primitive value is pushed
39   * onto the primitive int stack to be utilized by other rules later.  If there
40   * is a loss of precision where the ASN.1 INTEGER is larger or smaller than
41   * the maximum or minimum value of a Java primitive integer an exception is
42   * thrown.
43   * </p>
44   *
45   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
46   * @version $Rev: 157644 $
47   */
48  public class PrimitiveIntDecodeRule extends AbstractRule
49  {
50      /*** the bytes used to form the Java primitive integer */
51      private final byte[] value = new byte[4] ;
52      /*** the current 8 bit position to fill in the integer */
53      private int pos ;
54      /*** the number of bytes we must read */
55      private int length ;
56      /*** the tag this rule accepts */
57      private final TagEnum tag ;
58  
59  
60      // -----------------------------------------------------------------------
61      // C O N S T R U C T O R S
62      // -----------------------------------------------------------------------
63  
64  
65      /***
66       * Creates a default primitive integer decoding rule that only accepts
67       * tags of UniversalTag.INTEGER.
68       */
69      public PrimitiveIntDecodeRule()
70      {
71          tag = UniversalTag.INTEGER ;
72      }
73  
74  
75      /***
76       * Creates a default primitive integer decoding rule that only accepts
77       * tags of UniversalTag.INTEGER.
78       */
79      public PrimitiveIntDecodeRule( TagEnum tag )
80      {
81          this.tag = tag ;
82      }
83  
84  
85      // -----------------------------------------------------------------------
86      // Rule Implementation
87      // -----------------------------------------------------------------------
88  
89  
90      /* (non-Javadoc)
91       * @see org.apache.asn1.ber.digester.Rule#tag(int, boolean,
92       * org.apache.asn1.ber.TypeClass)
93       */
94      public void tag( int id, boolean isPrimitive, TypeClass typeClass )
95      {
96          if ( id != tag.getTagId() )
97          {
98              throw new IllegalArgumentException(
99                      "Expecting " + tag.getName()
100                     + " with an id of " + tag.getTagId()
101                     + " but instead got a tag id of " + id ) ;
102         }
103     }
104 
105 
106     /* (non-Javadoc)
107      * @see org.apache.asn1.ber.digester.Rule#length(int)
108      */
109     public void length( int length )
110     {
111         if ( length > 4 || length < 0 )
112         {
113             throw new IllegalArgumentException( "The target primitive for this "
114                 + "rule can only hold integers of 32 bits or 4 bytes.  "
115                 + "The length of the field however is " + length ) ;
116         }
117 
118         this.length = length ;
119     }
120 
121 
122     /* (non-Javadoc)
123      * @see org.apache.asn1.ber.digester.Rule#value(java.nio.ByteBuffer)
124      */
125     public void value( ByteBuffer buf )
126     {
127         if ( buf == null )
128         {
129             return ;
130         }
131 
132         while ( buf.hasRemaining() && ( pos + 1 ) <= length )
133         {
134             value[pos] = buf.get() ;
135             pos++ ;
136         }
137     }
138 
139 
140     /* (non-Javadoc)
141      * @see org.apache.asn1.ber.digester.Rule#finish()
142      */
143     public void finish()
144     {
145         // decode and push primitive integer onto stack
146         int numba = PrimitiveUtils.decodeInt( this.value, 0, this.length ) ;
147 
148         if ( getDigester() != null )
149         {
150             getDigester().pushInt( numba ) ;
151         }
152 
153         // cleanup
154         this.pos = 0 ;
155         this.length = 0 ;
156     }
157 
158 
159     /***
160      * Used for testing to check and see if a value of the byte buffer has
161      * been set after a value event.
162      *
163      * @param bite the byte value to check
164      * @param ii the index to check the byte for in the values array
165      * @return true if the byte value matches the byte value in the array
166      */
167     boolean equals( byte bite, int ii )
168     {
169         return value[ii] == bite ;
170     }
171 }