Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * fb-contrib - Auxiliary detectors for Java programs
   * Copyright (C) 2005-2013 Dave Brosius
   *
   * 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 2.1 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, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 package com.mebigfatguy.fbcontrib.detect;
 
 import java.util.Set;
 
 import  org.apache.bcel.Repository;
 import  org.apache.bcel.classfile.Code;
 import  org.apache.bcel.classfile.Constant;
 import  org.apache.bcel.classfile.ConstantClass;
 import  org.apache.bcel.classfile.ConstantPool;
 import  org.apache.bcel.classfile.ConstantUtf8;
 import  org.apache.bcel.classfile.JavaClass;
 import  org.apache.bcel.classfile.Method;
 import  org.apache.bcel.generic.Type;
 
 
 import  edu.umd.cs.findbugs.BugInstance;
 import  edu.umd.cs.findbugs.BugReporter;
 import  edu.umd.cs.findbugs.BytecodeScanningDetector;
 import  edu.umd.cs.findbugs.OpcodeStack;
 import  edu.umd.cs.findbugs.ba.ClassContext;
 
 public class LoggerOddities extends BytecodeScanningDetector {
 	private static JavaClass THROWABLE_CLASS;
 	private static Set<StringloggerMethods;
 
 	static {
 		try {
 			 = Repository.lookupClass("java/lang/Throwable");
 
 			.add("trace");
 			.add("debug");
 			.add("info");
 			.add("warn");
 			.add("error");
 			.add("fatal");
 		} catch (ClassNotFoundException cnfe) {
 			 = null;
 		}
 	}
 	private final BugReporter bugReporter;
 	private OpcodeStack stack;
 	private String clsName;

    
constructs a LO detector given the reporter to report bugs on.

Parameters:
bugReporter the sync of bug reports
 
 	public LoggerOddities(final BugReporter bugReporter) {
 		this. = bugReporter;
 	}


implements the visitor to discover what the class name is if it is a normal class, or the owning class, if the class is an anonymous class.

Parameters:
classContext the context object of the currently parsed class
 
     @Override
     public void visitClassContext(ClassContext classContext) {
         try {
              = new OpcodeStack();
              = classContext.getJavaClass().getClassName();
             int subclassIndex = .indexOf('$');
             while (subclassIndex >= 0) {
                 String simpleName = .substring(subclassIndex+1);
                 try {
                     Integer.parseInt(simpleName);
                      = .substring(0, subclassIndex);
                     subclassIndex = .indexOf('$');
                 } catch (NumberFormatException nfe) {
                     subclassIndex = -1;
                 }
             }
              = .replace('.''/');
             super.visitClassContext(classContext);
         } finally {
             = null;
        }
    }

    
implements the visitor to reset the stack

Parameters:
obj the context object of the currently parsed code block
    @Override
    public void visitCode(Code obj) {
        .resetForMethodEntry(this);
        Method m = getMethod();
        if ("<init>".equals(m.getName())) {
        	Type[] types = Type.getArgumentTypes(m.getSignature());
        	for (Type t : types)
        	{
        		String parmSig = t.getSignature();
        		if ("Lorg/slf4j/Logger;".equals(parmSig)
        		||  "Lorg/apache/log4j/Logger;".equals(parmSig)
        		||  "Lorg/apache/commons/logging/Log;".equals(parmSig)) {
                    .reportBug(new BugInstance(this"LO_SUSPECT_LOG_PARAMETER", NORMAL_PRIORITY)
                    .addClass(this)
                    .addMethod(this)
                    .addSourceLine(this));
        		}
        	}
        }
        super.visitCode(obj);
    }

    
implements the visitor to look for calls to Logger.getLogger with the wrong class name

Parameters:
seen the opcode of the currently parsed instruction
    @Override
    public void sawOpcode(int seen) {
        String ldcClassName = null;
        int exMessageReg = -1;
        try {
            if ((seen == LDC) || (seen == LDC_W)) {
                Constant c = getConstantRefOperand();
                if (c instanceof ConstantClass) {
                    ConstantPool pool = getConstantPool();
                    ldcClassName = ((ConstantUtf8)pool.getConstant(((ConstantClass) c).getNameIndex())).getBytes();
                }
            } else if (seen == INVOKESTATIC) {
                String callingClsName = getClassConstantOperand();
                String mthName = getNameConstantOperand();
                String loggingClassName = null;
                if ("org/slf4j/LoggerFactory".equals(callingClsName)
                &&  "getLogger".equals(mthName)) {
                    String signature = getSigConstantOperand();
                    if ("(Ljava/lang/Class;)Lorg/slf4j/Logger;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getUserValue();
	                    }
                    } else if ("(Ljava/lang/String;)Lorg/slf4j/Logger;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getConstant();
	                        if (loggingClassName != null) {
								loggingClassName = loggingClassName.replace('.''/');
							}
	                    }
                    }
                } else if ("org/apache/log4j/Logger".equals(callingClsName)
                       &&  "getLogger".equals(mthName)) {
                    String signature = getSigConstantOperand();
                    if ("(Ljava/lang/Class;)Lorg/apache/log4j/Logger;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getUserValue();
	                    }
                    } else if ("(Ljava/lang/String;)Lorg/apache/log4j/Logger;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getConstant();
	                        if (loggingClassName != null) {
								loggingClassName = loggingClassName.replace('.''/');
							}
	                    }
                    } else if ("(Ljava/lang/String;Lorg/apache/log4j/spi/LoggerFactory;)Lorg/apache/log4j/Logger;".equals(signature)) {
                    	if (.getStackDepth() > 1) {
	                        OpcodeStack.Item item = .getStackItem(1);
	                        loggingClassName = (String)item.getConstant();
	                        if (loggingClassName != null) {
								loggingClassName = loggingClassName.replace('.''/');
							}
	                    }
                    }
                } else if ("org/apache/commons/logging/LogFactory".equals(callingClsName)
                	&& "getLog".equals(mthName)) {
            		String signature = getSigConstantOperand();
                    if ("(Ljava/lang/Class;)Lorg/apache/commons/logging/Log;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getUserValue();
	                    }
                    } else if ("(Ljava/lang/String;)Lorg/apache/commons/logging/Log;".equals(signature)) {
                    	if (.getStackDepth() > 0) {
	                        OpcodeStack.Item item = .getStackItem(0);
	                        loggingClassName = (String)item.getConstant();
	                        if (loggingClassName != null) {
								loggingClassName = loggingClassName.replace('.''/');
							}
	                    }
                    }
                }
                if (loggingClassName != null) {
                    if (.getStackDepth() > 0) {
                        if (!loggingClassName.equals()) {
                            boolean isPrefix = .startsWith(loggingClassName);
                            boolean isAnonClassPrefix;
                            if (isPrefix) {
                                String anonClass = .substring(loggingClassName.length());
                                isAnonClassPrefix = anonClass.matches("(\\$\\d+)+");
                            } else {
                                isAnonClassPrefix = false;
                            }
                            if (!isAnonClassPrefix) {
                                .reportBug(new BugInstance(this"LO_SUSPECT_LOG_CLASS", NORMAL_PRIORITY)
                                            .addClass(this)
                                            .addMethod(this)
                                            .addSourceLine(this));
                            }
                        }
                    }
                }
            } else if (((seen == INVOKEVIRTUAL) || (seen == INVOKEINTERFACE)) && ( != null)) {
                String mthName = getNameConstantOperand();
                if (mthName.equals("getMessage")) {
                	String callingClsName = getClassConstantOperand();
                	JavaClass cls = Repository.lookupClass(callingClsName);
                	if (cls.instanceOf()) {
                		if (.getStackDepth() > 0) {
                			OpcodeStack.Item exItem = .getStackItem(0);
                			exMessageReg = exItem.getRegisterNumber();
                		}
                	}
                } else if (.contains(mthName)) {
                	String callingClsName = getClassConstantOperand();
                	if (callingClsName.endsWith("Log") || (callingClsName.endsWith("Logger"))) {
                		String sig = getSigConstantOperand();
                		if ("(Ljava/lang/String;Ljava/lang/Throwable;)V".equals(sig) || "(Ljava/lang/Object;Ljava/lang/Throwable;)V".equals(sig)) {
                			if (.getStackDepth() >= 2) {
                				OpcodeStack.Item exItem = .getStackItem(0);
                				OpcodeStack.Item msgItem = .getStackItem(1);
                				Integer exReg = (Integer)msgItem.getUserValue();
                				if (exReg != null) {
                					if (exReg.intValue() ==  exItem.getRegisterNumber()) {
                						.reportBug(new BugInstance(this"LO_STUTTERED_MESSAGE", NORMAL_PRIORITY)
                															.addClass(this)
                															.addMethod(this)
                															.addSourceLine(this));
                					}
                				}
                			}
                		}
                	}
                }
            }
        } catch (ClassNotFoundException cnfe) {
        	.reportMissingClass(cnfe);
        } finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
            if (ldcClassName != null) {
                if (.getStackDepth() > 0) {
                    OpcodeStack.Item item = .getStackItem(0);
                    item.setUserValue(ldcClassName);
                }
            }
            if (exMessageReg >= 0) {
            	if (.getStackDepth() > 0) {
            		OpcodeStack.Item item = .getStackItem(0);
            		item.setUserValue(Integer.valueOf(exMessageReg));
            	}
            }
        }
    }
New to GrepCode? Check out our FAQ X