KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > logicalcobwebs > asm > util > CheckClassAdapter


1 /***
2  * ASM: a very small and fast Java bytecode manipulation framework
3  * Copyright (c) 2000,2002,2003 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  *
30  * Contact: Eric.Bruneton@rd.francetelecom.com
31  *
32  * Author: Eric Bruneton
33  */

34
35 package org.logicalcobwebs.asm.util;
36
37 import org.logicalcobwebs.asm.ClassAdapter;
38 import org.logicalcobwebs.asm.ClassVisitor;
39 import org.logicalcobwebs.asm.CodeVisitor;
40 import org.logicalcobwebs.asm.Constants;
41 import org.logicalcobwebs.asm.Attribute;
42
43 /**
44  * A {@link ClassAdapter ClssAdapter} that checks that its methods are properly
45  * used. More precisely this class adapter checks each method call individually,
46  * based <i>only</i> on its arguments, but does <i>not</i> check the
47  * <i>sequence</i> of method calls. For example, the invalid sequence
48  * <tt>visitField(ACC_PUBLIC, "i", "I", null)</tt> <tt>visitField(ACC_PUBLIC,
49  * "i", "D", null)</tt> will <i>not</i> be detected by this class adapter.
50  */

51
52 public class CheckClassAdapter extends ClassAdapter {
53
54   /**
55    * <tt>true</tt> if the visit method has been called.
56    */

57
58   private boolean start;
59
60   /**
61    * <tt>true</tt> if the visitEnd method has been called.
62    */

63
64   private boolean end;
65
66   /**
67    * Constructs a new {@link CheckClassAdapter CheckClassAdapter} object.
68    *
69    * @param cv the class visitor to which this adapter must delegate calls.
70    */

71
72   public CheckClassAdapter (final ClassVisitor cv) {
73     super(cv);
74   }
75
76   public void visit (
77     final int access,
78     final String JavaDoc name,
79     final String JavaDoc superName,
80     final String JavaDoc[] interfaces,
81     final String JavaDoc sourceFile)
82   {
83     if (start) {
84       throw new IllegalStateException JavaDoc("visit must be called only once");
85     } else {
86       start = true;
87     }
88     checkState();
89     checkAccess(access, 1 + 2 + 4 + 16 + 512 + 1024 + 32 + 65536 + 131072);
90     CheckCodeAdapter.checkInternalName(name, "class name");
91     if (name.equals("java/lang/Object")) {
92       if (superName != null) {
93         throw new IllegalArgumentException JavaDoc(
94           "The super class name of the Object class must be 'null'");
95       }
96     } else {
97       CheckCodeAdapter.checkInternalName(superName, "super class name");
98     }
99     if ((access & Constants.ACC_INTERFACE) != 0) {
100       if (!superName.equals("java/lang/Object")) {
101         throw new IllegalArgumentException JavaDoc(
102           "The super class name of interfaces must be 'java/lang/Object'");
103       }
104     }
105     if (interfaces != null) {
106       for (int i = 0; i < interfaces.length; ++i) {
107         CheckCodeAdapter.checkInternalName(
108           interfaces[i], "interface name at index " + i);
109       }
110     }
111     cv.visit(access, name, superName, interfaces, sourceFile);
112   }
113
114   public void visitInnerClass (
115     final String JavaDoc name,
116     final String JavaDoc outerName,
117     final String JavaDoc innerName,
118     final int access)
119   {
120     checkState();
121     CheckCodeAdapter.checkInternalName(name, "class name");
122     if (outerName != null) {
123       CheckCodeAdapter.checkInternalName(outerName, "outer class name");
124     }
125     if (innerName != null) {
126       CheckCodeAdapter.checkIdentifier(innerName, "inner class name");
127     }
128     checkAccess(access, 1 + 2 + 4 + 8 + 16 + 512 + 1024 + 32);
129     cv.visitInnerClass(name, outerName, innerName, access);
130   }
131
132   public void visitField (
133     final int access,
134     final String JavaDoc name,
135     final String JavaDoc desc,
136     final Object JavaDoc value,
137     final Attribute attrs)
138   {
139     checkState();
140     checkAccess(access, 1 + 2 + 4 + 8 + 16 + 64 + 128 + 65536 + 131072);
141     CheckCodeAdapter.checkIdentifier(name, "field name");
142     CheckCodeAdapter.checkDesc(desc, false);
143     if (value != null) {
144       CheckCodeAdapter.checkConstant(value);
145     }
146     cv.visitField(access, name, desc, value, attrs);
147   }
148
149   public CodeVisitor visitMethod (
150     final int access,
151     final String JavaDoc name,
152     final String JavaDoc desc,
153     final String JavaDoc[] exceptions,
154     final Attribute attrs)
155   {
156     checkState();
157     checkAccess(
158       access, 1 + 2 + 4 + 8 + 16 + 32 + 256 + 1024 + 2048 + 65536 + 131072);
159     CheckCodeAdapter.checkMethodIdentifier(name, "method name");
160     CheckCodeAdapter.checkMethodDesc(desc);
161     if (exceptions != null) {
162       for (int i = 0; i < exceptions.length; ++i) {
163         CheckCodeAdapter.checkInternalName(
164           exceptions[i], "exception name at index " + i);
165       }
166     }
167     return new CheckCodeAdapter(
168       cv.visitMethod(access, name, desc, exceptions, attrs));
169   }
170
171   public void visitAttribute (final Attribute attr) {
172     checkState();
173     if (attr == null) {
174       throw new IllegalArgumentException JavaDoc(
175         "Invalid attribute (must not be null)");
176     }
177   }
178
179   public void visitEnd () {
180     checkState();
181     end = true;
182     cv.visitEnd();
183   }
184
185   // ---------------------------------------------------------------------------
186

187   /**
188    * Checks that the visit method has been called and that visitEnd has not been
189    * called.
190    */

191
192   private void checkState () {
193     if (!start) {
194       throw new IllegalStateException JavaDoc(
195         "Cannot visit member before visit has been called.");
196     }
197     if (end) {
198       throw new IllegalStateException JavaDoc(
199         "Cannot visit member after visitEnd has been called.");
200     }
201   }
202
203   /**
204    * Checks that the given access flags do not contain invalid flags. This
205    * method also checks that mutually incompatible flags are not set
206    * simultaneously.
207    *
208    * @param access the access flags to be checked
209    * @param possibleAccess the valid access flags.
210    */

211
212   static void checkAccess (final int access, final int possibleAccess) {
213     if ((access & ~possibleAccess) != 0) {
214       throw new IllegalArgumentException JavaDoc("Invalid access flags: " + access);
215     }
216     int pub = ((access & Constants.ACC_PUBLIC) != 0 ? 1 : 0);
217     int pri = ((access & Constants.ACC_PRIVATE) != 0 ? 1 : 0);
218     int pro = ((access & Constants.ACC_PROTECTED) != 0 ? 1 : 0);
219     if (pub + pri + pro > 1) {
220       throw new IllegalArgumentException JavaDoc(
221         "public private and protected are mutually exclusive: " + access);
222     }
223     int fin = ((access & Constants.ACC_FINAL) != 0 ? 1 : 0);
224     int abs = ((access & Constants.ACC_ABSTRACT) != 0 ? 1 : 0);
225     if (fin + abs > 1) {
226       throw new IllegalArgumentException JavaDoc(
227         "final and abstract are mutually exclusive: " + access);
228     }
229   }
230 }
231
Popular Tags