/*
* Copyright (c) 2001-2004 Ant-Contrib project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on Jan 9, 2005
*/
package net.sf.antcontrib.design;
import java.io.File;
import org.apache.bcel.Constants;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.CodeException;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.EmptyVisitor;
import org.apache.bcel.classfile.ExceptionTable;
import org.apache.bcel.classfile.Field;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.LineNumberTable;
import org.apache.bcel.classfile.LocalVariable;
import org.apache.bcel.classfile.Method;
import org.apache.bcel.classfile.Utility;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.Instruction;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.MethodGen;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
class VisitorImpl extends EmptyVisitor {
private ConstantPool pool;
private Log log;
private Design design;
private ConstantPoolGen poolGen;
private InstructionVisitor visitor;
private Location location;
public VisitorImpl(ConstantPool pool, Log log, Design d, Location loc) {
this.pool = pool;
this.log = log;
this.design = d;
this.location = loc;
this.poolGen = new ConstantPoolGen(pool);
visitor = new InstructionVisitor(poolGen, log, d);
}
private void log(String s, int level) {
log.log(s, level);
}
public void visitJavaClass(JavaClass c) {
log(" super=" + c.getSuperclassName(), Project.MSG_VERBOSE);
String[] names = c.getInterfaceNames();
String superClass = c.getSuperclassName();
design.checkClass(superClass);
for (int i = 0; i < names.length; i++) {
log(" interfaces=" + names[i], Project.MSG_VERBOSE);
design.checkClass(names[i]);
}
}
/**
* @see org.apache.bcel.classfile.Visitor#visitField(org.apache.bcel.classfile.Field)
*/
public void visitField(Field f) {
String type = Utility.methodSignatureReturnType(f.getSignature());
log(" field type=" + type, Project.MSG_VERBOSE);
design.checkClass(type);
}
/**
* @see org.apache.bcel.classfile.Visitor#visitLocalVariable(org.apache.bcel.classfile.LocalVariable)
*/
public void visitLocalVariable(LocalVariable v) {
String type = Utility.methodSignatureReturnType(v.getSignature());
log(" localVar type=" + type, Project.MSG_VERBOSE);
design.checkClass(type);
}
/**
* @see org.apache.bcel.classfile.Visitor#visitMethod(org.apache.bcel.classfile.Method)
*/
public void visitMethod(Method m) {
log(" method=" + m.getName(), Project.MSG_VERBOSE);
String retType = Utility.methodSignatureReturnType(m.getSignature());
log(" method ret type=" + retType, Project.MSG_VERBOSE);
if (!"void".equals(retType))
design.checkClass(retType);
String[] types = Utility.methodSignatureArgumentTypes(m.getSignature());
for (int i = 0; i < types.length; i++) {
log(" method param[" + i + "]=" + types[i],
Project.MSG_VERBOSE);
design.checkClass(types[i]);
}
ExceptionTable excs = m.getExceptionTable();
if (excs != null) {
types = excs.getExceptionNames();
for (int i = 0; i < types.length; i++) {
log(" exc=" + types[i], Project.MSG_VERBOSE);
design.checkClass(types[i]);
}
}
processInstructions(m);
}
private void processInstructions(Method m) {
MethodGen mg = new MethodGen(m, design.getCurrentClass(), poolGen);
if (!mg.isAbstract() && !mg.isNative()) {
InstructionHandle ih = mg.getInstructionList().getStart();
for (; ih != null; ih = ih.getNext()) {
Instruction i = ih.getInstruction();
log(" instr=" + i, Project.MSG_DEBUG);
// if (i instanceof BranchInstruction) {
// branch_map.put(i, ih); // memorize container
// }
// if (ih.hasTargeters()) {
// if (i instanceof BranchInstruction) {
// _out.println(" InstructionHandle ih_"
// + ih.getPosition() + ";");
// } else {
// _out.print(" InstructionHandle ih_"
// + ih.getPosition() + " = ");
// }
// } else {
// _out.print(" ");
// }
// if (!visitInstruction(i))
i.accept(visitor);
}
// CodeExceptionGen[] handlers = mg.getExceptionHandlers();
//
// log("handlers len="+handlers.length, Project.MSG_DEBUG);
// for (int i = 0; i < handlers.length; i++) {
// CodeExceptionGen h = handlers[i];
// ObjectType t = h.getCatchType();
// log("type="+t, Project.MSG_DEBUG);
// if(t != null) {
// log("type="+t.getClassName(), Project.MSG_DEBUG);
// }
// }
// updateExceptionHandlers();
}
}
public void visitCodeException(CodeException c) {
String s = c.toString(pool, false);
int catch_type = c.getCatchType();
if (catch_type == 0)
return;
String temp = pool.getConstantString(catch_type,
Constants.CONSTANT_Class);
String str = Utility.compactClassName(temp, false);
log(" catch=" + str, Project.MSG_DEBUG);
design.checkClass(str);
}
//
public void visitCode(Code c) {
LineNumberTable table = c.getLineNumberTable();
// LocalVariableTable table = c.getLocalVariableTable();
if (table == null)
throw new BuildException(getNoDebugMsg(design.getCurrentClass()), location);
}
public static String getNoDebugMsg(String className) {
String s = "Class="+className+" was not compiled with the debug option(-g) and\n" +
"therefore verifydesign cannot be used on this jar. Please compile your code\n"+
"with -g option in javac or debug=\"true\" in the ant build.xml file";
return s;
}
/**
* @param jarName
* @return
*/
public static String getNoFileMsg(File jarName) {
String s = "File you specified in your path(or jar attribute)='"+jarName.getAbsolutePath()+"' does not exist";
return s;
}
}