/*
* MicroJIAC - A Lightweight Agent Framework
* This file is part of MicroJIAC Config.
*
* Copyright (c) 2007-2012 DAI-Labor, Technische Universität Berlin
*
* This library includes software developed at DAI-Labor, Technische
* Universität Berlin (http://www.dai-labor.de)
*
* This library is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* $Id$
*/
package de.jiac.micro.config.analysis;
import java.util.HashSet;
import java.util.List;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.AnalyzerAdapter;
import org.objectweb.asm.commons.EmptyVisitor;
/**
* @author Marcel Patzlaff
* @version $Revision:$
*/
class ComponentAnalyser implements ClassVisitor, FieldVisitor, Opcodes {
protected final static HashSet<String> HANDLE_SOURCES;
static {
HANDLE_SOURCES= new HashSet<String>();
HANDLE_SOURCES.add("de/jiac/micro/core/scope/Scope");
HANDLE_SOURCES.add("de/jiac/micro/core/IAgent");
HANDLE_SOURCES.add("de/jiac/micro/core/INode");
HANDLE_SOURCES.add("de/jiac/micro/core/IContainer");
}
private static abstract class MethodAnalyser extends EmptyVisitor {
protected AnalyzerAdapter stackAnalyzer;
protected MethodAnalyser() {}
protected final MethodVisitor reset(String owner, int access, String name, String desc) {
stackAnalyzer= new AnalyzerAdapter(owner, access, name, desc, this);
return stackAnalyzer;
}
}
private final class HandleGetterVisitor extends MethodAnalyser {
protected HandleGetterVisitor() {}
@Override
public void visitInsn(int opcode) {
if(opcode == ARETURN) {
List stack= stackAnalyzer.stack;
Object s= stack.get(stack.size() - 1);
if(s instanceof Type) {
providedHandleClassName= ((Type) s).getClassName();
} else {
providedHandleClassName= (String) s;
}
}
}
}
private final class NormalMethodVisitor extends MethodAnalyser {
private String _handleClassName;
private boolean _awaitClassName;
protected NormalMethodVisitor() {}
@Override
public void visitFieldInsn(int opcode, String owner, String name, String desc) {
if(_awaitClassName) {
return;
}
if(opcode == GETSTATIC && name.startsWith("class$") && desc.equals("Ljava/lang/Class;")) {
// class version < 49.0
_awaitClassName= true;
}
}
@Override
public void visitLdcInsn(Object cst) {
if(_awaitClassName) {
_handleClassName= (String) cst;
_awaitClassName= false;
} else if(cst instanceof Type) {
_handleClassName= ((Type) cst).getClassName();
}
}
@Override
public void visitMethodInsn(int opcode, String owner, String name, String desc) {
if(HANDLE_SOURCES.contains(owner) && desc.equals("(Ljava/lang/Class;)Lde/jiac/micro/core/IHandle;")) {
if((opcode == INVOKESTATIC && name.equals("getScopeHandle")) || (opcode == INVOKEINTERFACE && name.equals("getHandle"))) {
requiredHandles.add(_handleClassName);
_handleClassName= null;
}
}
}
}
private final HandleGetterVisitor _handleGetterVisitor= new HandleGetterVisitor();
private final NormalMethodVisitor _normalMethodVisitor= new NormalMethodVisitor();
private String _componentClassName;
protected HashSet<String> requiredHandles= new HashSet<String>();
protected String providedHandleClassName;
public void clear() {
requiredHandles= new HashSet<String>();
providedHandleClassName= null;
}
/////////////////////
// CLASS VISITOR
///////////////////
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
_componentClassName= name;
}
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) {
return this;
}
public void visitInnerClass(String name, String outerName, String innerName, int access) {}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
MethodVisitor result;
if(desc.equals("()Lde/jiac/micro/core/IHandle;") && (name.equals("getHandle") || name.equals("getScopeHandle"))) {
result= _handleGetterVisitor.reset(_componentClassName, access, name, desc);
} else {
result= _normalMethodVisitor.reset(_componentClassName, access, name, desc);
}
return result;
}
public void visitOuterClass(String owner, String name, String desc) {}
public void visitSource(String source, String debug) {}
/////////////////////
// GENERIC
///////////////////
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
return null;
}
public void visitAttribute(Attribute attr) {}
public void visitEnd() {}
}