KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hammurapi > inspectors > SqlCreateStatementWithoutCloseRule


1 /*
2  * Hammurapi
3  * Automated Java code review system.
4  * Copyright (C) 2004 Johannes Bellert
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19  *
20  * URL: http://www.hammurapi.org
21  * e-Mail: CraftOfObjects@gmail.com
22
23  */

24
25 package org.hammurapi.inspectors;
26
27 import java.util.Collection JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.List JavaDoc;
30 import java.util.Vector JavaDoc;
31
32 import org.hammurapi.InspectorBase;
33
34 import com.pavelvlasov.config.ConfigurationException;
35 import com.pavelvlasov.config.Parameterizable;
36 import com.pavelvlasov.jsel.Code;
37 import com.pavelvlasov.jsel.CompilationUnit;
38 import com.pavelvlasov.jsel.JselException;
39 import com.pavelvlasov.jsel.LanguageElement;
40 import com.pavelvlasov.jsel.Method;
41 import com.pavelvlasov.jsel.Operation;
42 import com.pavelvlasov.jsel.OperationInfo;
43 import com.pavelvlasov.jsel.Repository;
44 import com.pavelvlasov.jsel.VariableDefinition;
45 import com.pavelvlasov.jsel.expressions.Expression;
46 import com.pavelvlasov.jsel.expressions.Ident;
47 import com.pavelvlasov.jsel.expressions.MethodCall;
48 import com.pavelvlasov.jsel.expressions.PlainAssignment;
49 import com.pavelvlasov.jsel.expressions.TypeCast;
50 import com.pavelvlasov.jsel.statements.ReturnStatement;
51 import com.pavelvlasov.review.SourceMarker;
52 import com.pavelvlasov.util.Visitor;
53
54 /**
55  * Fix 5: Ignore all createStatement & preparedStatements method calls which are NOT provided by java.sql.Connection
56  * Fix 4: handle TypeCast of parameters in "releaseSafe" helper methods
57  * Fix 3: find multiple occurance of a "releaseSafe" helper methods
58  * Fix 2: Count create & close statements in a method and report violation if close less than create
59  * Fix 1: ReturnStatement added in visit(MethodCall)
60  */

61 public class SqlCreateStatementWithoutCloseRule extends InspectorBase implements
62         Parameterizable {
63
64     private java.util.Set JavaDoc releaseResourceMethodList = new java.util.HashSet JavaDoc();
65
66     boolean ret;
67
68     //-- State Engine
69
private String JavaDoc currentStatementVarDef = "";
70
71     private Vector JavaDoc createStatementList = new Vector JavaDoc();
72     private Vector JavaDoc closeStatementList = new Vector JavaDoc();
73     private SourceMarker compilationUnitSourcingMarker = null;
74     private SourceMarker methodSourcingMarker = null;
75
76     public void visit(CompilationUnit cu) {
77         compilationUnitSourcingMarker = (SourceMarker)cu;
78     }
79
80     public void visit(Method methodDecl) {
81
82         checkNumberOfCreateCloseAPI(); // initalize State Engine
83

84         //--- re-initialize
85
createStatementList = new Vector JavaDoc();
86         closeStatementList = new Vector JavaDoc();
87         methodSourcingMarker = (SourceMarker)methodDecl;
88     }
89
90     public void visit(MethodCall methodCall) {
91
92
93         //System.out.println( methodCall.getMethodName() );
94

95         checkForReleaseSafeMethod( methodCall );
96         checkForCloseMethod( methodCall );
97         checkForCreateMethod( methodCall );
98     }
99
100     private void checkForReleaseSafeMethod(MethodCall methodCall) {
101         boolean ret = false;
102         try {
103             int i = 0;
104             Object JavaDoc[] releaseResourceMethodStrings = releaseResourceMethodList
105                     .toArray();
106             while (!ret && i < releaseResourceMethodStrings.length) {
107
108                 String JavaDoc releaseResourceMethodName = (String JavaDoc) releaseResourceMethodStrings[i];
109                 i++;
110                 // System.out.println(releaseResourceMethodName +" -- " + methodCall.getMethodName() );
111
if (releaseResourceMethodName
112                         .equals(methodCall.getMethodName())) {
113                     //-- search for parameters
114
List JavaDoc parameterList = methodCall.getParameters();
115                     Iterator JavaDoc pit = parameterList.iterator();
116                     while (pit.hasNext() && !ret) {
117                         Object JavaDoc parameter = pit.next();
118
119                         //!! refactoring: code doublet with method CloseVisitor
120
if (parameter instanceof TypeCast) {
121
122                             if ("Statement".equals( ((TypeCast)parameter).getTypeSpecification().toString())
123                                 || "PreparedStatement".equals( ((TypeCast)parameter).getTypeSpecification().toString()) ){
124
125
126                                 methodSourcingMarker = (SourceMarker) methodCall;
127                                 closeStatementList.add(methodCall);
128                                 ret = true;
129                             }
130
131                         } else if (parameter instanceof Ident) {
132                             Ident p = (Ident) parameter;
133                             String JavaDoc paramName = p.toString();
134                             String JavaDoc paramTypDef = p.getTypeSpecification().getName();
135                             // System.out.println( "paramName " + paramName );
136
// System.out.println( "paramTypDef " + paramTypDef );
137
// System.out.println( "p.getTypeSpecification " + p.getTypeSpecification().getName() );
138
if (("java.sql.Statement".equals(paramTypDef)
139                         // || "java.sql.PreparedStatement".equals(p.getTypeSpecification().getName()))
140
|| "java.sql.PreparedStatement".equals(paramTypDef))
141                                     // && paramName.equals(currentStatementVarDef)
142
) {
143
144                                 methodSourcingMarker = (SourceMarker) methodCall;
145                                 closeStatementList.add(methodCall);
146                                 ret = true;
147                             }
148                         }
149                     }
150                 }
151             }
152         } catch (JselException e1) {
153             // TODO Auto-generated catch block
154
e1.printStackTrace();
155         }
156     }
157
158     private void checkForCloseMethod(MethodCall methodCall) {
159     if ("close".equals(methodCall.getMethodName()) ){
160
161         try {
162             OperationInfo opi = methodCall.getProvider();
163
164             if("java.sql.Statement".equals(opi.getDeclaringType().getName()) ){
165                 methodSourcingMarker = (SourceMarker)methodCall;
166                 this.closeStatementList.add( methodCall );
167             }
168
169         }catch (Exception JavaDoc e){
170             e.printStackTrace();
171         }
172
173         //!! no provider type check ??
174
}
175     }
176
177     private void checkForCreateMethod(MethodCall methodCall) {
178         Code code = ((LanguageElement) methodCall).getEnclosingCode();
179         LanguageElement parentLangElem = ((LanguageElement) methodCall)
180                 .getParent();
181
182         if ("createStatement".equals(methodCall.getMethodName())
183                 || "prepareStatement".equals(methodCall.getMethodName())) {
184
185             
186             
187
188             try {
189
190                 //!! Ugly Quick Hack
191
if (parentLangElem instanceof VariableDefinition) {
192                     VariableDefinition varDef = (VariableDefinition) parentLangElem;
193                     currentStatementVarDef = varDef.getName();
194                 } else if (parentLangElem instanceof Ident) {
195                     Ident id = (Ident) parentLangElem;
196                     final Object JavaDoc provider = id.getProvider();
197                     if (provider != null
198                             && (provider instanceof VariableDefinition)) {
199                         currentStatementVarDef = ((VariableDefinition) provider)
200                                 .getName();
201                     }
202                 } else if (parentLangElem instanceof TypeCast) {
203                     VariableDefinition grandpaLangElem = (VariableDefinition)((LanguageElement) parentLangElem)
204                     .getParent();
205                     
206                     currentStatementVarDef = grandpaLangElem.getName();
207                     
208                 } else if (parentLangElem instanceof PlainAssignment) {
209                     PlainAssignment pa = (PlainAssignment) parentLangElem;
210
211
212                     Collection JavaDoc lt = pa.getOperands();
213                     if ( !lt.isEmpty() ){
214                             Iterator JavaDoc it = lt.iterator();
215                             String JavaDoc str = ((Ident)it.next()).getText();
216                             currentStatementVarDef = str;
217                     } else {
218                         //!!
219
context.warn(parentLangElem, "!!!!!!!!! currentStatementVarDef could not be determined for " + parentLangElem);
220                     }
221                 }
222
223                 else if (parentLangElem instanceof ReturnStatement) {
224                     // Fix 1
225
ReturnStatement pa = (ReturnStatement) parentLangElem;
226                     Expression ex = pa.getExpression();
227                     if (ex instanceof MethodCall) {
228
229                         //--- this is not the Statement name but we can use it
230
// instead of a "NA" or null value.
231
currentStatementVarDef = ((LanguageElement) ex)
232                                 .getAst().getFirstToken().getText();
233
234                         //!! only method calls referenced to a var are handled
235
// .. recurively resolution of nested method calls
236
// needed.
237
// currentStatementVarDef =
238
// methodCallX.getTypeSpecification().getName().toString();
239
}
240
241                 } else {
242                     context.warn((SourceMarker) methodCall,
243                             " methodCall has no varDef ");
244                 }
245
246                 // System.out.println(" currentStatementVarDef " +
247
// currentStatementVarDef);
248
if (code != null) {
249                     Operation op = (Operation) code;
250                     OperationInfo opi = methodCall.getProvider();
251                     try {
252                         if ("java.sql.Connection".equals(opi.getDeclaringType()
253                                 .getName())) {
254                             
255                             createStatementList.add(methodCall);
256                             //--reinit
257
ret = false;
258                             op.accept(new CloseVisitor());
259                             if (!ret) {
260                                 code.accept(new CloseVisitor());
261                             }
262
263                             if (!ret) {
264                                 context
265                                         .reportViolation((SourceMarker) methodCall);
266                             }
267                         }
268                     } catch (JselException e) {
269                         context.warn(op, e);
270                     }
271
272                 }
273             } catch (JselException e) {
274                 context.warn((SourceMarker) methodCall, e);
275             }
276         }
277     }
278     public void checkNumberOfCreateCloseAPI (){
279         if( closeStatementList.size()< createStatementList.size() ){
280             StringBuffer JavaDoc str = new StringBuffer JavaDoc();
281         str.append( "Found " + createStatementList.size() );
282         str.append( " calls of create Statements but only " );
283         str.append( closeStatementList.size() );
284         str.append( " close() calls" );
285
286         // context.reportViolation( this.methodSourcingMarker , str.toString() );
287
context.getSession().getContext("ER-209").reportViolation( this.methodSourcingMarker , str.toString() );
288
289         }
290     }
291
292     public void leave(Repository repo) {
293               this.checkNumberOfCreateCloseAPI();
294     }
295
296
297     class CloseVisitor implements Visitor {
298
299         /**
300          * Demonstrates usage of VisitorStack
301          */

302         /*
303          * public void visit(MethodCall mc) throws JselException { if
304          * (VisitorStack.getThreadInstance().isIn(ForStatement.class)) {
305          * context.reportViolation((SourceMarker) mc, "Method call from for
306          * loop"); } }
307          */

308         public boolean visit(Object JavaDoc target) {
309             try {
310                 if (target instanceof MethodCall) {
311                     MethodCall subMethCall = (MethodCall) target;
312
313                     //-- check for close
314
if ("close".equals(subMethCall.getMethodName())) {
315                         OperationInfo opi = subMethCall.getProvider();
316
317                         if ("java.sql.Statement".equals(opi.getDeclaringType().getName())
318                                 || "java.sql.PreparedStatement".equals(opi.getDeclaringType().getName())) {
319
320                             Collection JavaDoc lt = ((MethodCall) target).getName().getOperands();
321                             Iterator JavaDoc it = lt.iterator();
322
323                             String JavaDoc str = ((Ident)it.next()).getText();
324                             if ( !lt.isEmpty() && str != null
325                                     && str.equals ( currentStatementVarDef ) ) {
326                                ret = true;
327                             }
328                         }
329                     } else {
330
331                         int i =0;
332                         Object JavaDoc[] releaseResourceMethodStrings = releaseResourceMethodList.toArray();
333                         while ( !ret && i < releaseResourceMethodStrings.length ){
334
335                             String JavaDoc releaseResourceMethodName = (String JavaDoc)releaseResourceMethodStrings[i];
336                             i++;
337                             // System.out.println( " check for " + releaseResourceMethodName.toString());
338
if (releaseResourceMethodName.equals(subMethCall.getMethodName())) {
339
340                         //-- search for parameters
341
List JavaDoc parameterList = subMethCall.getParameters();
342                         Iterator JavaDoc pit = parameterList.iterator();
343                         while (pit.hasNext() && !ret) {
344                             Object JavaDoc parameter = pit.next();
345
346 //!! refactoring: code doublet with method checkForReleaseSafeMethod
347
if (parameter instanceof TypeCast) {
348                                     context.debug((SourceMarker) parameter, "((TypeCast)parameter).getTypeSpecification().toString() " + ((TypeCast)parameter).getTypeSpecification().toString());
349                                     if ("Statement".equals( ((TypeCast)parameter).getTypeSpecification().toString())
350                                         || "PreparedStatement".equals( ((TypeCast)parameter).getTypeSpecification().toString()) ){
351
352
353                                         methodSourcingMarker = (SourceMarker)target;
354                                         ret = true;
355                                     }
356
357                               }else if (parameter instanceof Ident) {
358                                 Ident p = (Ident) parameter;
359                                 String JavaDoc paramName = p.toString();
360                                 String JavaDoc paramTypDef = p.getTypeSpecification()
361                                         .getName();
362                                 if (("java.sql.Statement".equals(paramTypDef)
363                                         || "java.sql.PreparedStatement".equals(paramTypDef ))
364                                         && paramName.equals(currentStatementVarDef)) {
365
366                                     methodSourcingMarker = (SourceMarker)target;
367                                    // closeStatementList.add( target );
368
ret = true;
369                                 }
370                             }
371
372
373
374                         }
375                     }}
376
377                     }
378                 }
379             } catch (JselException e) {
380                 context.warn((SourceMarker) target, e);
381             }
382             return true;
383         }
384     }
385
386     /**
387      * Configures the rule. Reads in the values of the parameter copyright.
388      *
389      * @param name
390      * the name of the parameter being loaded from Hammurapi
391      * configuration
392      * @exception ConfigurationException
393      * in case of a not supported parameter
394      */

395     public boolean setParameter(String JavaDoc name, Object JavaDoc parameter)
396             throws ConfigurationException {
397         if ("release-resource-method".equals(name)) {
398             String JavaDoc s = parameter.toString();
399             releaseResourceMethodList.add(s);
400             return true;
401         }
402
403         throw new ConfigurationException("Parameter '" + name
404                 + "' is not supported by " + getClass().getName());
405     }
406     /**
407      * Gives back the preconfigured values.
408      */

409     public String JavaDoc getConfigInfo() {
410         StringBuffer JavaDoc ret=new StringBuffer JavaDoc("Configured releaseResource method names:\n");
411         Iterator JavaDoc it=releaseResourceMethodList.iterator();
412         while (it.hasNext()) {
413             ret.append(" " + it.next() + "\n");
414         }
415         return ret.toString();
416     }
417
418 }
419
Popular Tags