KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * FindBugs - Find bugs in Java programs
3  * Copyright (C) 2004,2005 Dave Brosius <dbrosius@users.sourceforge.net>
4  * Copyright (C) 2004,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  
21 package edu.umd.cs.findbugs.detect;
22
23
24 import edu.umd.cs.findbugs.*;
25 import org.apache.bcel.classfile.Method;
26
27 public class WrongMapIterator extends BytecodeScanningDetector implements StatelessDetector {
28     private BugReporter bugReporter;
29     private static final int SAW_NOTHING = 0;
30     private static final int SAW_MAP_LOAD1 = 1;
31     private static final int SAW_KEYSET = 2;
32     private static final int SAW_KEYSET_STORE = 3;
33     private static final int SAW_ITERATOR = 4;
34     private static final int SAW_ITERATOR_STORE = 5;
35     private static final int SAW_ITERATOR_LOAD = 6;
36     private static final int SAW_NEXT = 7;
37     private static final int SAW_CHECKCAST_ON_NEXT = 8;
38     private static final int SAW_KEY_STORE = 9;
39     private static final int NEED_KEYSET_LOAD = 10;
40     private static final int SAW_MAP_LOAD2 = 11;
41     private static final int SAW_KEY_LOAD = 12;
42     
43     private int state;
44     private int loadedRegister;
45     private int mapRegister;
46     private int keySetRegister;
47     private int iteratorRegister;
48     private int keyRegister;
49     
50
51     public WrongMapIterator(BugReporter bugReporter) {
52         this.bugReporter = bugReporter;
53     }
54     
55
56
57     @Override JavaDoc
58          public void visit(Method obj) {
59         state = SAW_NOTHING;
60         loadedRegister = -1;
61         mapRegister = -1;
62         keySetRegister = -1;
63         iteratorRegister = -1;
64         keyRegister = -1;
65     }
66     
67     @Override JavaDoc
68     public void sawOpcode(int seen) {
69         switch (state)
70         {
71             case SAW_NOTHING:
72                 loadedRegister = getLoadStoreRegister( seen, true );
73                 if (loadedRegister >= 0)
74                     state = SAW_MAP_LOAD1;
75             break;
76             
77             case SAW_MAP_LOAD1:
78                 if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL))
79                 && ("keySet".equals(getNameConstantOperand()))
80                 && ("()Ljava/util/Set;".equals(getSigConstantOperand()))) {
81                     mapRegister = loadedRegister;
82                     state = SAW_KEYSET;
83                 }
84                 else {
85                     state = SAW_NOTHING;
86                 }
87             break;
88             
89             case SAW_KEYSET:
90                 keySetRegister = getLoadStoreRegister( seen, false );
91                 if (keySetRegister >= 0)
92                     state = SAW_KEYSET_STORE;
93                 else if ((seen == INVOKEINTERFACE)
94                 && ("iterator".equals(getNameConstantOperand()))
95                 && ("()Ljava/util/Iterator;".equals(getSigConstantOperand())))
96                     state = SAW_ITERATOR;
97                 else
98                     state = SAW_NOTHING;
99             break;
100             
101             case SAW_KEYSET_STORE:
102                 if ((seen == INVOKEINTERFACE)
103                 && ("iterator".equals(getNameConstantOperand()))
104                 && ("()Ljava/util/Iterator;".equals(getSigConstantOperand())))
105                     state = SAW_ITERATOR;
106                 else
107                     state = NEED_KEYSET_LOAD;
108             break;
109             
110             case NEED_KEYSET_LOAD:
111                 loadedRegister = getLoadStoreRegister( seen, true );
112                 if (loadedRegister == iteratorRegister)
113                     state = SAW_ITERATOR;
114             break;
115             
116             case SAW_ITERATOR:
117                 iteratorRegister = getLoadStoreRegister( seen, false );
118                 if (iteratorRegister >= 0)
119                     state = SAW_ITERATOR_STORE;
120                 else
121                     state = SAW_NOTHING;
122             break;
123             
124             case SAW_ITERATOR_STORE:
125                 loadedRegister = getLoadStoreRegister( seen, true );
126                 if (loadedRegister == iteratorRegister)
127                     state = SAW_ITERATOR_LOAD;
128             break;
129             
130             case SAW_ITERATOR_LOAD:
131                 if ((seen == INVOKEINTERFACE)
132                 && ("next".equals(getNameConstantOperand()))
133                 && ("()Ljava/lang/Object;".equals(getSigConstantOperand())))
134                     state = SAW_NEXT;
135                 else
136                     state = SAW_ITERATOR_STORE;
137             break;
138             
139             case SAW_NEXT:
140                 if (seen == CHECKCAST)
141                     state = SAW_CHECKCAST_ON_NEXT;
142                 else {
143                     keyRegister = getLoadStoreRegister( seen, false );
144                     if (keyRegister >= 0)
145                         state = SAW_KEY_STORE;
146                     else
147                         seen = SAW_NOTHING;
148                 }
149             break;
150             
151             case SAW_CHECKCAST_ON_NEXT:
152                 keyRegister = getLoadStoreRegister( seen, false );
153                 if (keyRegister >= 0)
154                     state = SAW_KEY_STORE;
155             break;
156             
157             case SAW_KEY_STORE:
158                 loadedRegister = getLoadStoreRegister( seen, true );
159                 if (loadedRegister == mapRegister)
160                     state = SAW_MAP_LOAD2;
161             break;
162             
163             case SAW_MAP_LOAD2:
164                 loadedRegister = getLoadStoreRegister( seen, true );
165                 if (loadedRegister == keyRegister)
166                     state = SAW_KEY_LOAD;
167                 else
168                     state = SAW_KEY_STORE;
169             break;
170             
171             case SAW_KEY_LOAD:
172                 if (((seen == INVOKEINTERFACE) || (seen == INVOKEVIRTUAL))
173                 && ("get".equals(getNameConstantOperand()))
174                 && ("(Ljava/lang/Object;)Ljava/lang/Object;".equals(getSigConstantOperand()))) {
175                     MethodAnnotation ma = MethodAnnotation.fromVisitedMethod(this);
176                     bugReporter.reportBug(
177                         new BugInstance("WMI_WRONG_MAP_ITERATOR", NORMAL_PRIORITY)
178                                                         .addClass(this)
179                                                         .addMethod(ma)
180                                                         .addSourceLine(this, getPC()));
181                     state = SAW_NOTHING;
182                 }
183             break;
184         }
185     }
186     
187     private int getLoadStoreRegister(int seen, boolean doLoad)
188     {
189         switch (seen)
190         {
191             case ALOAD_0:
192             case ALOAD_1:
193             case ALOAD_2:
194             case ALOAD_3:
195                 if (doLoad)
196                     return seen - ALOAD_0;
197             break;
198             
199             case ALOAD:
200                 if (doLoad)
201                     return getRegisterOperand();
202             break;
203                 
204             case ASTORE_0:
205             case ASTORE_1:
206             case ASTORE_2:
207             case ASTORE_3:
208                 if (!doLoad)
209                     return seen - ASTORE_0;
210             break;
211                 
212             case ASTORE:
213                 if (!doLoad)
214                     return getRegisterOperand();
215             break;
216         }
217         
218         return -1;
219     }
220 }
221
Popular Tags