blob: 7de46fb790078f4d249606c7fc84c44b01ba7ebb [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
package org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.core;
import org.apache.myfaces.extensions.scripting.core.engine.dependencyScan.api.DependencyRegistry;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
import org.objectweb.asm.signature.SignatureReader;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A scan visitor on method level
* to cope with method scoped dependencies like inlined
* fully qualified names, annotations, local variables
* etc...
*
* @author Werner Punz (latest modification by $Author$)
* @version $Revision$ $Date$
*/
class MethodScanVisitor implements MethodVisitor {
// static final Logger log = Logger.getLogger("ClassScanVisitor");
String _currentlyVisitedClass = null;
String _rootClass;
Integer _engineType = null;
DependencyRegistry _dependencyRegistry = null;
static Logger _log = Logger.getLogger(MethodScanVisitor.class.getName());
public MethodScanVisitor(Integer engineType, String rootClass, String currentlyVisitedClass, DependencyRegistry registry) {
_currentlyVisitedClass = currentlyVisitedClass;
_dependencyRegistry = registry;
_engineType = engineType;
_rootClass = rootClass;
}
public AnnotationVisitor visitAnnotationDefault() {
return null;
}
public AnnotationVisitor visitAnnotation(String description, boolean b) {
if(description != null) {
registerDependency(Type.getType(description));
}
return null;
}
public AnnotationVisitor visitParameterAnnotation(int opCode, String description, boolean b) {
if(description != null) {
registerDependency(Type.getType(description));
}
return null;
}
public void visitAttribute(Attribute attribute) {
if (_log.isLoggable(Level.FINEST))
_log.log(Level.FINEST, "visitAttribute {0}", attribute.type);
}
public void visitCode() {
//log.log(Level.INFO, "Method code");
}
public void visitFrame(int opCode1, int opCode2, Object[] objects, int opCode3, Object[] objects1) {
if (_log.isLoggable(Level.FINEST))
_log.log(Level.FINEST, "visitFrame {0}", "");
}
public void visitInsn(int opCode) {
}
public void visitIntInsn(int opCode1, int opCode2) {
}
public void visitVarInsn(int opCode1, int opCode2) {
}
public void visitTypeInsn(int opCode, String castType) {
//cast
// log.log(Level.INFO, "TypeInsn: {0} ", new String[]{castType});
if (castType != null) {
registerDependency(Type.getObjectType(castType));
if (_log.isLoggable(Level.FINEST))
_log.log(Level.FINEST, "visitTypeInsn {0}", castType);
}
}
private void registerDependency(Type dependency) {
String className = dependency.getClassName();
if (className.endsWith("[]")) {
className = className.substring(0, className.indexOf("["));
}
if (_dependencyRegistry != null) {
_dependencyRegistry.addDependency(_engineType, _rootClass, _currentlyVisitedClass, className);
}
}
/**
* @param opCode the opCode of the insert statement
* @param owner hosting classname of field (always the calling class afaik)
* @param name internal descriptor
* @param descriptor field type
*/
public void visitFieldInsn(int opCode, String owner, String name, String descriptor) {
// log.log(Level.INFO, "visitFieldInsn {0} {1} {2}", new Object[]{owner, name, descriptor});
//we have to deal with static imports as special case of field insertions
if (name != null && name.length() > 6 && name.startsWith("class$")) {
//special fallback for groovy static imports which are added as fields
name = "L" + name.substring(6).replaceAll("\\$", ".") + ";";
registerDependency(Type.getType(name));
}
if (descriptor != null) {
registerDependency(Type.getType(descriptor));
}
if (_log.isLoggable(Level.FINEST))
_log.log(Level.FINEST, "visitFieldInsn {0}", descriptor);
}
/**
* Method call
*
* @param opc internal opcode
* @param owner hosting classname of the method
* @param name method name
* @param desc descriptor string
*/
public void visitMethodInsn(int opc, String owner, String name, String desc) {
//s2 arguments list
if (desc != null) {
registerDependency(Type.getReturnType(desc));
Type[] argumentTypes = Type.getArgumentTypes(desc);
if (argumentTypes != null) {
for (Type argumentType : argumentTypes) {
registerDependency(argumentType);
}
}
}
if (owner != null)
registerDependency(Type.getObjectType(owner));
}
public void visitJumpInsn(int i, Label label) {
}
public void visitLabel(Label label) {
}
public void visitLdcInsn(Object o) {
}
public void visitIincInsn(int i, int i1) {
}
public void visitTableSwitchInsn(int i, int i1, Label label, Label[] labels) {
}
public void visitLookupSwitchInsn(Label label, int[] ints, Label[] labels) {
}
public void visitMultiANewArrayInsn(String s, int i) {
if (_log.isLoggable(Level.FINEST))
_log.log(Level.FINEST, "visitMultiANewArrayInsn {0}", s);
}
public void visitTryCatchBlock(Label label, Label label1, Label label2, String catchType) {
//try catch block type information in the last string
//log.log(Level.INFO, "visitTryCatchBlock: {0} {1} {2} {3}", new Object[]{label.toString(), label1.toString(), label2.toString(), catchType});
if (catchType != null) {
registerDependency(Type.getObjectType(catchType));
}
}
public void visitLocalVariable(String name, String description, String signature, Label label, Label label1, int i) {
//local variable on method level
if (description != null) {
registerDependency(Type.getType(description));
}
if (signature != null) {
handleGenerics(signature);
}
}
public void visitLineNumber(int i, Label label) {
}
public void visitMaxs(int i, int i1) {
}
public void visitEnd() {
}
private void handleGenerics(String signature) {
if (signature != null && signature.contains("<")) {
SignatureReader reader = new SignatureReader(signature);
reader.acceptType(new DependencySignatureVisitor(_dependencyRegistry, _engineType, _rootClass, _currentlyVisitedClass));
}
}
}