001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.object.tools;
006:
007: import com.tc.asm.AnnotationVisitor;
008: import com.tc.asm.Attribute;
009: import com.tc.asm.ClassVisitor;
010: import com.tc.asm.FieldVisitor;
011: import com.tc.asm.Label;
012: import com.tc.asm.MethodVisitor;
013: import com.tc.asm.Opcodes;
014:
015: import java.util.Map;
016: import java.util.Set;
017:
018: public class BootJarClassDependencyVisitor implements ClassVisitor {
019:
020: private Set bootJarClassNames;
021: private Map offendingClasses;
022: private String currentClassName = "";
023: private String currentMethodName = "";
024: private int currentLineNumber = 0;
025:
026: private static final String classSlashNameToDotName(
027: final String name) {
028: return name.replace('/', '.');
029: }
030:
031: private final boolean check(final String name, String desc) {
032: if (name.startsWith("com/tc/")
033: || name.startsWith("com/tcclient/")) {
034: boolean exists = bootJarClassNames
035: .contains(BootJarClassDependencyVisitor
036: .classSlashNameToDotName(name));
037: if (!exists) {
038: this .offendingClasses.put(
039: classSlashNameToDotName(name), desc + " from "
040: + this .currentClassName);
041: }
042: return exists;
043: } else {
044: return true;
045: }
046: }
047:
048: public BootJarClassDependencyVisitor(Set bootJarClassNames,
049: Map offendingClasses) {
050: this .bootJarClassNames = bootJarClassNames;
051: this .offendingClasses = offendingClasses;
052: }
053:
054: public void visit(int version, int access, String name,
055: String signature, String super Name, String[] interfaces) {
056: this .currentClassName = BootJarClassDependencyVisitor
057: .classSlashNameToDotName(name);
058:
059: // check the referenced class
060: check(name, "reference to the class itself");
061:
062: // check it's superclass
063: check(super Name, "reference to 'extend' class declaration");
064:
065: // check it's interfaces
066: for (int i = 0; i < interfaces.length; i++) {
067: check(interfaces[i],
068: "reference to 'implements' interface declaration");
069: }
070: }
071:
072: public AnnotationVisitor visitAnnotation(String desc,
073: boolean visible) {
074: if (visible) {
075: check(desc, "reference to class annotation");
076: }
077: return null;
078: }
079:
080: public void visitAttribute(Attribute attr) {
081: check(attr.type,
082: "reference to a non-standard attribute of class '"
083: + this .currentClassName + "'");
084: }
085:
086: public void visitEnd() {
087: // nothing to do here
088: }
089:
090: public FieldVisitor visitField(int access, String name,
091: String desc, String signature, Object value) {
092: check(desc, "reference to a declared class field");
093: return null;
094: }
095:
096: public void visitInnerClass(String name, String outerName,
097: String innerName, int access) {
098: check(name, "reference to inner-class");
099: }
100:
101: public MethodVisitor visitMethod(int access, String name,
102: String desc, String signature, String[] exceptions) {
103: this .currentMethodName = name;
104: if (exceptions != null) {
105: for (int i = 0; i < exceptions.length; i++) {
106: check(exceptions[i],
107: "reference to a declared exception");
108: }
109: }
110: MethodVisitor mv = new BootJarClassDependencyMethodVisitor();
111: return mv;
112: }
113:
114: public void visitOuterClass(String owner, String name, String desc) {
115: check(owner, "reference to outer-class");
116: }
117:
118: public void visitSource(String source, String debug) {
119: // nothing to do here
120: }
121:
122: private class BootJarClassDependencyMethodVisitor implements
123: MethodVisitor, Opcodes {
124:
125: public AnnotationVisitor visitAnnotation(String desc,
126: boolean visible) {
127: if (visible) {
128: check(desc, "reference to method annotation for method");
129: }
130: return null;
131: }
132:
133: public AnnotationVisitor visitAnnotationDefault() {
134: return null;
135: }
136:
137: public void visitAttribute(Attribute attr) {
138: check(attr.type,
139: "reference to a non-standard attrbute of method");
140: }
141:
142: public void visitCode() {
143: // nothing to do here
144: }
145:
146: public void visitEnd() {
147: // nothing to do here
148: }
149:
150: public void visitFieldInsn(int opcode, String owner,
151: String name, String desc) {
152: check(owner, "reference in field get or put");
153: }
154:
155: public void visitFrame(int type, int nLocal, Object[] local,
156: int nStack, Object[] stack) {
157: // nothing to do here
158: }
159:
160: public void visitIincInsn(int var, int increment) {
161: // nothing to do here
162: }
163:
164: public void visitInsn(int opcode) {
165: // nothing to do here
166: }
167:
168: public void visitIntInsn(int opcode, int operand) {
169: // nothing to do here
170: }
171:
172: public void visitJumpInsn(int opcode, Label label) {
173: // nothing to do here
174: }
175:
176: public void visitLabel(Label label) {
177: // nothing to do here
178: }
179:
180: public void visitLdcInsn(Object cst) {
181: // nothing to do here
182: }
183:
184: public void visitLineNumber(int line, Label start) {
185: currentLineNumber = line;
186: }
187:
188: public void visitLocalVariable(String name, String desc,
189: String signature, Label start, Label end, int index) {
190: check(desc, "reference in local variable declaration");
191: }
192:
193: public void visitLookupSwitchInsn(Label dflt, int[] keys,
194: Label[] labels) {
195: // nothing to do here
196: }
197:
198: public void visitMaxs(int maxStack, int maxLocals) {
199: // nothing to do here
200: }
201:
202: public void visitMethodInsn(int opcode, String owner,
203: String name, String desc) {
204: check(owner,
205: "reference in either virtual, interface, constructor, or static invocation");
206: }
207:
208: public void visitMultiANewArrayInsn(String desc, int dims) {
209: check(desc, "reference in mutli-array type declaration");
210: }
211:
212: public AnnotationVisitor visitParameterAnnotation(
213: int parameter, String desc, boolean visible) {
214: if (visible) {
215: check(desc, "reference to method annotation");
216: }
217: return null;
218: }
219:
220: public void visitTableSwitchInsn(int min, int max, Label dflt,
221: Label[] labels) {
222: // nothing to do here
223: }
224:
225: public void visitTryCatchBlock(Label start, Label end,
226: Label handler, String type) {
227: if (type != null) {
228: check(type, "reference in try-catch block");
229: }
230: }
231:
232: public void visitTypeInsn(int opcode, String desc) {
233: check(
234: desc,
235: "reference in type-cast, class instantiation, type-check, or type-array declaration");
236: }
237:
238: public void visitVarInsn(int opcode, int var) {
239: // nothing to do here
240: }
241: }
242: }
|