CheckSignatureAdapter.java revision 674060f01e9090cd21b3c5656cc3204912ad17a6
1/***
2 * ASM: a very small and fast Java bytecode manipulation framework
3 * Copyright (c) 2000-2007 INRIA, France Telecom
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of the copyright holders nor the names of its
15 *    contributors may be used to endorse or promote products derived from
16 *    this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
29 */
30package org.mockito.asm.util;
31
32import org.mockito.asm.signature.SignatureVisitor;
33
34/**
35 * A {@link SignatureVisitor} that checks that its methods are properly used.
36 *
37 * @author Eric Bruneton
38 */
39public class CheckSignatureAdapter implements SignatureVisitor {
40
41    /**
42     * Type to be used to check class signatures. See
43     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
44     */
45    public static final int CLASS_SIGNATURE = 0;
46
47    /**
48     * Type to be used to check method signatures. See
49     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
50     */
51    public static final int METHOD_SIGNATURE = 1;
52
53    /**
54     * Type to be used to check type signatures.See
55     * {@link #CheckSignatureAdapter(int, SignatureVisitor) CheckSignatureAdapter}.
56     */
57    public static final int TYPE_SIGNATURE = 2;
58
59    private static final int EMPTY = 1;
60
61    private static final int FORMAL = 2;
62
63    private static final int BOUND = 4;
64
65    private static final int SUPER = 8;
66
67    private static final int PARAM = 16;
68
69    private static final int RETURN = 32;
70
71    private static final int SIMPLE_TYPE = 64;
72
73    private static final int CLASS_TYPE = 128;
74
75    private static final int END = 256;
76
77    /**
78     * Type of the signature to be checked.
79     */
80    private final int type;
81
82    /**
83     * State of the automaton used to check the order of method calls.
84     */
85    private int state;
86
87    /**
88     * <tt>true</tt> if the checked type signature can be 'V'.
89     */
90    private boolean canBeVoid;
91
92    /**
93     * The visitor to which this adapter must delegate calls. May be
94     * <tt>null</tt>.
95     */
96    private final SignatureVisitor sv;
97
98    /**
99     * Creates a new {@link CheckSignatureAdapter} object.
100     *
101     * @param type the type of signature to be checked. See
102     *        {@link #CLASS_SIGNATURE}, {@link #METHOD_SIGNATURE} and
103     *        {@link #TYPE_SIGNATURE}.
104     * @param sv the visitor to which this adapter must delegate calls. May be
105     *        <tt>null</tt>.
106     */
107    public CheckSignatureAdapter(final int type, final SignatureVisitor sv) {
108        this.type = type;
109        this.state = EMPTY;
110        this.sv = sv;
111    }
112
113    // class and method signatures
114
115    public void visitFormalTypeParameter(final String name) {
116        if (type == TYPE_SIGNATURE
117                || (state != EMPTY && state != FORMAL && state != BOUND))
118        {
119            throw new IllegalStateException();
120        }
121        CheckMethodAdapter.checkIdentifier(name, "formal type parameter");
122        state = FORMAL;
123        if (sv != null) {
124            sv.visitFormalTypeParameter(name);
125        }
126    }
127
128    public SignatureVisitor visitClassBound() {
129        if (state != FORMAL) {
130            throw new IllegalStateException();
131        }
132        state = BOUND;
133        SignatureVisitor v = sv == null ? null : sv.visitClassBound();
134        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
135    }
136
137    public SignatureVisitor visitInterfaceBound() {
138        if (state != FORMAL && state != BOUND) {
139            throw new IllegalArgumentException();
140        }
141        SignatureVisitor v = sv == null ? null : sv.visitInterfaceBound();
142        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
143    }
144
145    // class signatures
146
147    public SignatureVisitor visitSuperclass() {
148        if (type != CLASS_SIGNATURE || (state & (EMPTY | FORMAL | BOUND)) == 0)
149        {
150            throw new IllegalArgumentException();
151        }
152        state = SUPER;
153        SignatureVisitor v = sv == null ? null : sv.visitSuperclass();
154        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
155    }
156
157    public SignatureVisitor visitInterface() {
158        if (state != SUPER) {
159            throw new IllegalStateException();
160        }
161        SignatureVisitor v = sv == null ? null : sv.visitInterface();
162        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
163    }
164
165    // method signatures
166
167    public SignatureVisitor visitParameterType() {
168        if (type != METHOD_SIGNATURE
169                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
170        {
171            throw new IllegalArgumentException();
172        }
173        state = PARAM;
174        SignatureVisitor v = sv == null ? null : sv.visitParameterType();
175        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
176    }
177
178    public SignatureVisitor visitReturnType() {
179        if (type != METHOD_SIGNATURE
180                || (state & (EMPTY | FORMAL | BOUND | PARAM)) == 0)
181        {
182            throw new IllegalArgumentException();
183        }
184        state = RETURN;
185        SignatureVisitor v = sv == null ? null : sv.visitReturnType();
186        CheckSignatureAdapter cv = new CheckSignatureAdapter(TYPE_SIGNATURE, v);
187        cv.canBeVoid = true;
188        return cv;
189    }
190
191    public SignatureVisitor visitExceptionType() {
192        if (state != RETURN) {
193            throw new IllegalStateException();
194        }
195        SignatureVisitor v = sv == null ? null : sv.visitExceptionType();
196        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
197    }
198
199    // type signatures
200
201    public void visitBaseType(final char descriptor) {
202        if (type != TYPE_SIGNATURE || state != EMPTY) {
203            throw new IllegalStateException();
204        }
205        if (descriptor == 'V') {
206            if (!canBeVoid) {
207                throw new IllegalArgumentException();
208            }
209        } else {
210            if ("ZCBSIFJD".indexOf(descriptor) == -1) {
211                throw new IllegalArgumentException();
212            }
213        }
214        state = SIMPLE_TYPE;
215        if (sv != null) {
216            sv.visitBaseType(descriptor);
217        }
218    }
219
220    public void visitTypeVariable(final String name) {
221        if (type != TYPE_SIGNATURE || state != EMPTY) {
222            throw new IllegalStateException();
223        }
224        CheckMethodAdapter.checkIdentifier(name, "type variable");
225        state = SIMPLE_TYPE;
226        if (sv != null) {
227            sv.visitTypeVariable(name);
228        }
229    }
230
231    public SignatureVisitor visitArrayType() {
232        if (type != TYPE_SIGNATURE || state != EMPTY) {
233            throw new IllegalStateException();
234        }
235        state = SIMPLE_TYPE;
236        SignatureVisitor v = sv == null ? null : sv.visitArrayType();
237        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
238    }
239
240    public void visitClassType(final String name) {
241        if (type != TYPE_SIGNATURE || state != EMPTY) {
242            throw new IllegalStateException();
243        }
244        CheckMethodAdapter.checkInternalName(name, "class name");
245        state = CLASS_TYPE;
246        if (sv != null) {
247            sv.visitClassType(name);
248        }
249    }
250
251    public void visitInnerClassType(final String name) {
252        if (state != CLASS_TYPE) {
253            throw new IllegalStateException();
254        }
255        CheckMethodAdapter.checkIdentifier(name, "inner class name");
256        if (sv != null) {
257            sv.visitInnerClassType(name);
258        }
259    }
260
261    public void visitTypeArgument() {
262        if (state != CLASS_TYPE) {
263            throw new IllegalStateException();
264        }
265        if (sv != null) {
266            sv.visitTypeArgument();
267        }
268    }
269
270    public SignatureVisitor visitTypeArgument(final char wildcard) {
271        if (state != CLASS_TYPE) {
272            throw new IllegalStateException();
273        }
274        if ("+-=".indexOf(wildcard) == -1) {
275            throw new IllegalArgumentException();
276        }
277        SignatureVisitor v = sv == null ? null : sv.visitTypeArgument(wildcard);
278        return new CheckSignatureAdapter(TYPE_SIGNATURE, v);
279    }
280
281    public void visitEnd() {
282        if (state != CLASS_TYPE) {
283            throw new IllegalStateException();
284        }
285        state = END;
286        if (sv != null) {
287            sv.visitEnd();
288        }
289    }
290}
291