[Fb-contrib-commit] fb-contrib/src/com/mebigfatguy/fbcontrib/detect SluggishGui.java,NONE,1.1
Brought to you by:
dbrosius
From: Dave B. <dbr...@us...> - 2006-02-02 06:18:11
|
Update of /cvsroot/fb-contrib/fb-contrib/src/com/mebigfatguy/fbcontrib/detect In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12608/src/com/mebigfatguy/fbcontrib/detect Added Files: SluggishGui.java Log Message: new SG - initial checkin --- NEW FILE: SluggishGui.java --- /* * fb-contrib - Auxilliary detectors for Java programs * Copyright (C) 2005-2006 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.HashSet; import java.util.Set; import org.apache.bcel.classfile.Code; 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.StatelessDetector; import edu.umd.cs.findbugs.ba.ClassContext; public class SluggishGui extends BytecodeScanningDetector implements StatelessDetector { private static final Set<String> expensiveCalls = new HashSet<String>(); static { expensiveCalls.add("java/io/BufferedOutputStream:<init>"); expensiveCalls.add("java/io/DataOutputStream:<init>"); expensiveCalls.add("java/io/FileOutputStream:<init>"); expensiveCalls.add("java/io/ObjectOutputStream:<init>"); expensiveCalls.add("java/io/PipedOutputStream:<init>"); expensiveCalls.add("java/io/BufferedInputStream:<init>"); expensiveCalls.add("java/io/DataInputStream:<init>"); expensiveCalls.add("java/io/FileInputStream:<init>"); expensiveCalls.add("java/io/ObjectInputStream:<init>"); expensiveCalls.add("java/io/PipedInputStream:<init>"); expensiveCalls.add("java/io/BufferedWriter:<init>"); expensiveCalls.add("java/io/FileWriter:<init>"); expensiveCalls.add("java/io/OutpuStreamWriter:<init>"); expensiveCalls.add("java/io/BufferedReader:<init>"); expensiveCalls.add("java/io/FileReader:<init>"); expensiveCalls.add("java/io/InputStreamReader:<init>"); expensiveCalls.add("java/io/RandomAccessFile:<init>"); expensiveCalls.add("java/lang/Class:getResourceAsStream:<init>"); expensiveCalls.add("java/lang/ClassLoader:getResourceAsStream:<init>"); expensiveCalls.add("java/sql/DriverManager:getConnection"); expensiveCalls.add("java/sql/Connection:createStatement"); expensiveCalls.add("java/sql/Connection:prepareStatement"); expensiveCalls.add("java/sql/Connection:prepareCall"); expensiveCalls.add("javax/sql/DataSource:getConnection"); } private BugReporter bugReporter; private Set<JavaClass> guiInterfaces = new HashSet<JavaClass>(); private boolean isListenerMethod = false; private boolean methodReported = false; /** * constructs a SG detector given the reporter to report bugs on * @param bugReporter the sync of bug reports */ public SluggishGui(BugReporter bugReporter) { this.bugReporter = bugReporter; } /** * clone this detector so that it can be a StatelessDetector * * @return a clone of this object */ @Override public Object clone() throws CloneNotSupportedException { return super.clone(); } /** * overrides the visitor to reset look for gui interfaces * * @param obj the context object for the currently parsed class */ @Override public void visitClassContext(ClassContext classContext) { try { guiInterfaces.clear(); JavaClass cls = classContext.getJavaClass(); JavaClass[] infs = cls.getAllInterfaces(); for (JavaClass inf : infs) { String name = inf.getClassName(); if ((name.startsWith("java.awt.") || name.startsWith("javax.swing.")) && name.endsWith("Listener")) { guiInterfaces.add(inf); } } if (guiInterfaces.size() > 0) super.visitClassContext(classContext); } catch (ClassNotFoundException cnfe) { bugReporter.reportMissingClass(cnfe); } } /** * overrides the visitor to find methods that override listeners * * @param obj the context object of the currently parsed method */ @Override public void visitMethod(Method obj) { isListenerMethod = false; methodReported = false; if (!obj.isPublic()) return; String methodSig = obj.getSignature(); Type r = Type.getReturnType(methodSig); if (!r.equals(Type.VOID)) return; Type[] args = Type.getArgumentTypes(methodSig); if (args.length != 1) return; if (args[0].getSignature().charAt(0) != 'L') return; String methodName = obj.getName(); for (JavaClass inf : guiInterfaces) { Method[] methods = inf.getMethods(); for (Method m : methods) { if (m.getName().equals(methodName)) { if (m.getSignature().equals(methodSig)) { isListenerMethod = true; return; } } } } } /** * overrides the visitor to check whether to parse method if its a listener * * @param obj the context object of the currently parsed code block */ @Override public void visitCode(Code obj) { if (isListenerMethod) super.visitCode(obj); } /** * overrides the visitor to look for the execution of expensive calls * * @param seen the currently parsed opcode */ public void sawOpcode(int seen) { if (methodReported) return; if ((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL) || (seen == INVOKESPECIAL) || (seen == INVOKESTATIC)) { String clsName = getClassConstantOperand(); String methodName = getNameConstantOperand(); String info = clsName + ":" + methodName; if (expensiveCalls.contains(info)) { bugReporter.reportBug(new BugInstance(this, "SG_SLUGGISH_GUI", NORMAL_PRIORITY) .addClass(this) .addMethod(this) .addSourceLine(this)); methodReported = true; } } } } |