KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > edu > umd > cs > findbugs > detect > MultithreadedInstanceAccess


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2005 Dave Brosius <dbrosius@users.sourceforge.net>
4  * Copyright (C) 2005 University of Maryland
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  */

20 package edu.umd.cs.findbugs.detect;
21
22
23 import edu.umd.cs.findbugs.*;
24 import edu.umd.cs.findbugs.ba.ClassContext;
25 import java.util.*;
26 import org.apache.bcel.Repository;
27 import org.apache.bcel.classfile.*;
28
29
30 public class MultithreadedInstanceAccess extends BytecodeScanningDetector
31 {
32     private static final String JavaDoc STRUTS_ACTION_NAME = "org.apache.struts.action.Action";
33     private static final String JavaDoc SERVLET_NAME = "javax.servlet.Servlet";
34     private BugReporter bugReporter;
35     private Set<JavaClass> mtClasses;
36     private String JavaDoc mtClassName;
37     private int monitorCount;
38     private boolean writingField;
39     private Set<String JavaDoc> alreadyReported;
40     
41     public MultithreadedInstanceAccess(BugReporter bugReporter) {
42         this.bugReporter = bugReporter;
43     }
44     
45     private Set<JavaClass> getMtClasses() {
46         if (mtClasses != null)
47             return mtClasses;
48         
49         mtClasses = new HashSet<JavaClass>();
50         try {
51             mtClasses.add(Repository.lookupClass(STRUTS_ACTION_NAME));
52         } catch (ClassNotFoundException JavaDoc cnfe) {
53             //probably would be annoying to report
54
}
55         try {
56             mtClasses.add(Repository.lookupClass(SERVLET_NAME));
57         } catch (ClassNotFoundException JavaDoc cnfe) {
58             //probably would be annoying to report
59
}
60         
61         return mtClasses;
62     }
63     
64     @Override JavaDoc
65          public void visitClassContext(ClassContext classContext) {
66         try {
67             JavaClass cls = classContext.getJavaClass();
68             String JavaDoc superClsName = cls.getSuperclassName();
69             if ("java.lang.Object".equals(superClsName))
70                 return;
71             
72             if (STRUTS_ACTION_NAME.equals(superClsName)) {
73                 mtClassName = STRUTS_ACTION_NAME;
74                 super.visitClassContext(classContext);
75             }
76             else if (SERVLET_NAME.equals(superClsName)) {
77                 mtClassName = SERVLET_NAME;
78                 super.visitClassContext(classContext);
79             }
80             else {
81                 for (JavaClass mtClass : getMtClasses()) {
82                     /* note: We could just call cls.instanceOf(mtClass) and it would work for both
83                      * classes and interfaces, but if mtClass is an interface it is more efficient
84                      * to call cls.implementationOf() and since we're doing this on each visit that's
85                      * what we'll do.
86                      * also note: implementationOf(mtClass) throws an IllegalArgumentException when
87                      * mtClass is not an interface. See bug#1428253. */

88                     if (mtClass.isClass() ? cls.instanceOf(mtClass) : cls.implementationOf(mtClass)) {
89                         mtClassName = mtClass.getClassName();
90                         super.visitClassContext(classContext);
91                         return;
92                     }
93                 }
94             }
95         } catch (Exception JavaDoc e) {
96             //already reported
97
}
98     }
99     
100     @Override JavaDoc
101          public void visitMethod(Method obj) {
102         monitorCount = 0;
103         alreadyReported = new HashSet<String JavaDoc>();
104         writingField = false;
105     }
106     
107     @Override JavaDoc
108          public void visitCode(Code obj) {
109         if (!getMethodName().equals("<init>") && !getMethodName().equals("init"))
110             super.visitCode(obj);
111     }
112     
113     @Override JavaDoc
114          public void sawField() {
115         if ((monitorCount > 0) || (!writingField))
116             return;
117         
118         ConstantFieldref fieldRef;
119         Constant c = getConstantRefOperand();
120         if (c instanceof ConstantFieldref) {
121             fieldRef = (ConstantFieldref)c;
122             
123             String JavaDoc className = fieldRef.getClass(getConstantPool()).replace('.', '/');
124             if (className.equals( this.getClassName())) {
125                 ConstantPool cp = getConstantPool();
126                 int nameAndTypeIdx = fieldRef.getNameAndTypeIndex();
127                 ConstantNameAndType ntc = (ConstantNameAndType)cp.getConstant(nameAndTypeIdx);
128                 int nameIdx = ntc.getNameIndex();
129
130                 Field[] flds = getClassContext().getJavaClass().getFields();
131
132                 for (Field fld : flds) {
133                     if (fld.getNameIndex() == nameIdx) {
134                         if (!fld.isStatic()) {
135                             ConstantUtf8 nameCons = (ConstantUtf8) cp.getConstant(nameIdx);
136                             ConstantUtf8 typeCons = (ConstantUtf8) cp.getConstant(ntc.getSignatureIndex());
137
138                             if (alreadyReported.contains(nameCons.getBytes()))
139                                 return;
140                             alreadyReported.add(nameCons.getBytes());
141                             bugReporter.reportBug(new BugInstance(this,
142                                     STRUTS_ACTION_NAME.equals(mtClassName) ? "MTIA_SUSPECT_STRUTS_INSTANCE_FIELD" : "MTIA_SUSPECT_SERVLET_INSTANCE_FIELD",
143                                     LOW_PRIORITY)
144                                     .addField(new FieldAnnotation(getClassName(), nameCons.getBytes(), typeCons.getBytes(), false))
145                                     .addClass(this).addSourceLine(this)
146                                     );
147                         }
148                         break;
149                     }
150                 }
151             }
152         }
153     }
154     
155     @Override JavaDoc
156          public void sawOpcode(int seen) {
157         if (seen == MONITORENTER)
158             monitorCount++;
159         else if (seen == MONITOREXIT)
160             monitorCount--;
161         
162         writingField = ((seen == PUTFIELD) || (seen == PUTFIELD_QUICK) || (seen == PUTFIELD_QUICK_W));
163     }
164
165     
166
167 }
168
Popular Tags