All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jp.skypencil.findbugs.slf4j.IllegalPassedClassDetector Maven / Gradle / Ivy

package jp.skypencil.findbugs.slf4j;

import static org.apache.bcel.Repository.lookupClass;

import java.util.Deque;
import java.util.LinkedList;

import org.apache.bcel.classfile.JavaClass;

import edu.umd.cs.findbugs.BugInstance;
import edu.umd.cs.findbugs.BugReporter;
import edu.umd.cs.findbugs.OpcodeStack.Item;
import edu.umd.cs.findbugs.bcel.OpcodeStackDetector;

public class IllegalPassedClassDetector extends OpcodeStackDetector {
    private final BugReporter bugReporter;

    public IllegalPassedClassDetector(BugReporter bugReporter) {
        this.bugReporter = bugReporter;
    }

    @Override
    public void afterOpcode(int code) {
        if (code != INVOKEVIRTUAL
                || !"getClass".equals(getNameConstantOperand())
                || !"java/lang/Object".equals(getClassConstantOperand())) {
            if (code != LDC_W) {
                super.afterOpcode(code);
            } else {
                JavaClass storedClass;
                try {
                    String storedClassName = getClassConstantOperand();
                    storedClass = lookupClass(storedClassName);
                } catch (ClassNotFoundException e) {
                    throw new AssertionError(e);
                } finally {
                    super.afterOpcode(code);
                }
                Item returnedClass = getStack().getStackItem(0);
                returnedClass.setUserValue(storedClass);
            }
            return;
        }

        Item caller = getStack().getStackItem(0);
        JavaClass classOfCaller;
        try {
            classOfCaller = caller.getJavaClass();
        } catch (ClassNotFoundException e) {
            throw new AssertionError(e);
        } finally {
            super.afterOpcode(code);
        }
        Item returnedClass = getStack().getStackItem(0);
        returnedClass.setUserValue(classOfCaller);
    }

    @Override
    public void sawOpcode(int code) {
        if (code != INVOKESTATIC) {
            return;
        } else if (!"org/slf4j/LoggerFactory".equals(getClassConstantOperand())
                || !"getLogger".equals(getNameConstantOperand())
                || !"(Ljava/lang/Class;)Lorg/slf4j/Logger;".equals(getSigConstantOperand())) {
            return;
        }
        final Item passedClass = getStack().getStackItem(0);
        if (!(passedClass.getUserValue() instanceof JavaClass)) {
            return;
        }

        final String passedClassName = ((JavaClass) passedClass.getUserValue()).getClassName();
        String callerClassName = getDottedClassName();
        Deque acceptableClasses = new LinkedList();
        while (!callerClassName.isEmpty()) {
            if (callerClassName.equals(passedClassName)) {
                return;
            }
            acceptableClasses.push(callerClassName);
            int index = callerClassName.lastIndexOf('$');
            if (index == -1) {
                break;
            }
            callerClassName = callerClassName.substring(0, index);
        }

        BugInstance bug = new BugInstance(this,
                "SLF4J_ILLEGAL_PASSED_CLASS", HIGH_PRIORITY)
                .addString(acceptableClasses.toString())
                .addSourceLine(this)
                .addClass(this);
        bugReporter.reportBug(bug);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy