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.Map;
 
 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.OpcodeStack.CustomUserValue;
 import  edu.umd.cs.findbugs.ba.ClassContext;

looks for uses of jdbc vendor specific classes and methods making the database access code non portable.
 
 @CustomUserValue
 public class JDBCVendorReliance extends BytecodeScanningDetector
 {	
 	private BugReporter bugReporter;
 	private OpcodeStack stack;
 	private Map<IntegerIntegerjdbcLocals = new HashMap<IntegerInteger>();

constructs a JVR detector given the reporter to report bugs on

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

implements the visitor to reset the stack and jdbc locals

Parameters:
classContext the context object of the currently parsed class
 
 	public void visitClassContext(ClassContext classContext) {
 		 = new OpcodeStack();
 		super.visitClassContext(classContext);
 		 = null;
 		 = null;
 	}
implement the visitor to reset the opcode stack and set of locals that are jdbc objects

Parameters:
obj the context param of the currently parsed method
 
 	public void visitMethod(Method obj) {
 		.resetForMethodEntry(this);
 		
 		int[] parmRegs = RegisterUtils.getParameterRegisters(obj);
 		Type[] argTypes = obj.getArgumentTypes();
 		
 		for (int t = 0; t < argTypes.length; t++) {
 			String sig = argTypes[t].getSignature();
 			if (isJDBCClass(sig)) {
 				.put(Integer.valueOf(parmRegs[t]), 
 						Integer.valueOf(RegisterUtils.getLocalVariableEndRange(obj.getLocalVariableTable(), parmRegs[t], 0)));
 			}	
 		}
 	}
 	
 	public void sawOpcode(int seen) {
 		boolean tosIsJDBC = false;
 		try {
 	        .precomputation(this);
 			
             int curPC = getPC();
             Iterator<Integerit = .values().iterator();
            while (it.hasNext()) {
                Integer endPCRange = it.next();
                if (endPCRange.intValue() < curPC) {
                    it.remove();
                }
            }
            
			if ((seen == INVOKEVIRTUAL)
            ||  (seen == INVOKEINTERFACE)) {
                if (!"java/lang/Object".equals(clsName) && !isJDBCClass(clsName)) {
					int parmCnt = Type.getArgumentTypes(getSigConstantOperand()).length;
					if (.getStackDepth() > parmCnt) {
						OpcodeStack.Item itm = .getStackItem(parmCnt);
						if (itm.getUserValue() != null) {
							.reportBug(new BugInstance(this"JVR_JDBC_VENDOR_RELIANCE", NORMAL_PRIORITY)
										.addClass(this)
										.addMethod(this)
										.addSourceLine(this));
							return;
						}
					}
				}
			}
			if (seen == INVOKEINTERFACE) {
                if (isJDBCClass(infName)) {
					Type retType = Type.getReturnType(sig);
					infName = retType.getSignature();
                    if (isJDBCClass(infName))
						tosIsJDBC = true;
				}
else if ((seen == ASTORE) || ((seen >= ASTORE_0) && (seen <= ASTORE_3))) {
				if (.getStackDepth() > 0) {
					OpcodeStack.Item itm = .getStackItem(0);
					if (itm.getUserValue() != null) {
						int reg = RegisterUtils.getAStoreReg(thisseen);
						.put(Integer.valueOf(reg), Integer.valueOf(RegisterUtils.getLocalVariableEndRange(getMethod().getLocalVariableTable(), reggetNextPC())));
					}	
				}
else if ((seen == ALOAD) || ((seen >= ALOAD_0) && (seen <= ALOAD_3))) {
				int reg = RegisterUtils.getALoadReg(thisseen);
				if (.containsKey(Integer.valueOf(reg)))
					tosIsJDBC = true;
			}
finally {
			TernaryPatcher.pre(seen);
			.sawOpcode(thisseen);
			TernaryPatcher.post(seen);
			if (tosIsJDBC) {
				if (.getStackDepth() > 0) {
					OpcodeStack.Item itm = .getStackItem(0);
					itm.setUserValue(.);
				}
			}
		}
	}
      
    
returns whether the class is a jdbc class

Parameters:
clsName class name or signature of a class
Returns:
if the class name is a jdbc one
    private boolean isJDBCClass(String clsName) {
        if (clsName.endsWith(";"))
            clsName = clsName.substring(1, clsName.length() - 1);
        clsName = clsName.replace('.''/');
        
        if (!clsName.startsWith("java/sql/")
        &&  !clsName.startsWith("javax/sql/"))
            return false;
        
        return (!clsName.endsWith("Exception"));
    }
New to GrepCode? Check out our FAQ X