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 }