1 24 25 package org.hammurapi.inspectors; 26 27 import java.util.Collection ; 28 import java.util.Iterator ; 29 import java.util.List ; 30 import java.util.Vector ; 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 61 public class SqlCreateStatementWithoutCloseRule extends InspectorBase implements 62 Parameterizable { 63 64 private java.util.Set releaseResourceMethodList = new java.util.HashSet (); 65 66 boolean ret; 67 68 private String currentStatementVarDef = ""; 70 71 private Vector createStatementList = new Vector (); 72 private Vector closeStatementList = new Vector (); 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(); 84 createStatementList = new Vector (); 86 closeStatementList = new Vector (); 87 methodSourcingMarker = (SourceMarker)methodDecl; 88 } 89 90 public void visit(MethodCall methodCall) { 91 92 93 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 [] releaseResourceMethodStrings = releaseResourceMethodList 105 .toArray(); 106 while (!ret && i < releaseResourceMethodStrings.length) { 107 108 String releaseResourceMethodName = (String ) releaseResourceMethodStrings[i]; 109 i++; 110 if (releaseResourceMethodName 112 .equals(methodCall.getMethodName())) { 113 List parameterList = methodCall.getParameters(); 115 Iterator pit = parameterList.iterator(); 116 while (pit.hasNext() && !ret) { 117 Object parameter = pit.next(); 118 119 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 paramName = p.toString(); 134 String paramTypDef = p.getTypeSpecification().getName(); 135 if (("java.sql.Statement".equals(paramTypDef) 139 || "java.sql.PreparedStatement".equals(paramTypDef)) 141 ) { 143 144 methodSourcingMarker = (SourceMarker) methodCall; 145 closeStatementList.add(methodCall); 146 ret = true; 147 } 148 } 149 } 150 } 151 } 152 } catch (JselException e1) { 153 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 e){ 170 e.printStackTrace(); 171 } 172 173 } 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 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 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 lt = pa.getOperands(); 213 if ( !lt.isEmpty() ){ 214 Iterator it = lt.iterator(); 215 String str = ((Ident)it.next()).getText(); 216 currentStatementVarDef = str; 217 } else { 218 context.warn(parentLangElem, "!!!!!!!!! currentStatementVarDef could not be determined for " + parentLangElem); 220 } 221 } 222 223 else if (parentLangElem instanceof ReturnStatement) { 224 ReturnStatement pa = (ReturnStatement) parentLangElem; 226 Expression ex = pa.getExpression(); 227 if (ex instanceof MethodCall) { 228 229 currentStatementVarDef = ((LanguageElement) ex) 232 .getAst().getFirstToken().getText(); 233 234 } 240 241 } else { 242 context.warn((SourceMarker) methodCall, 243 " methodCall has no varDef "); 244 } 245 246 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 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 str = new StringBuffer (); 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.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 302 308 public boolean visit(Object target) { 309 try { 310 if (target instanceof MethodCall) { 311 MethodCall subMethCall = (MethodCall) target; 312 313 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 lt = ((MethodCall) target).getName().getOperands(); 321 Iterator it = lt.iterator(); 322 323 String 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 [] releaseResourceMethodStrings = releaseResourceMethodList.toArray(); 333 while ( !ret && i < releaseResourceMethodStrings.length ){ 334 335 String releaseResourceMethodName = (String )releaseResourceMethodStrings[i]; 336 i++; 337 if (releaseResourceMethodName.equals(subMethCall.getMethodName())) { 339 340 List parameterList = subMethCall.getParameters(); 342 Iterator pit = parameterList.iterator(); 343 while (pit.hasNext() && !ret) { 344 Object parameter = pit.next(); 345 346 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 paramName = p.toString(); 360 String 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 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 395 public boolean setParameter(String name, Object parameter) 396 throws ConfigurationException { 397 if ("release-resource-method".equals(name)) { 398 String 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 409 public String getConfigInfo() { 410 StringBuffer ret=new StringBuffer ("Configured releaseResource method names:\n"); 411 Iterator it=releaseResourceMethodList.iterator(); 412 while (it.hasNext()) { 413 ret.append(" " + it.next() + "\n"); 414 } 415 return ret.toString(); 416 } 417 418 } 419 | Popular Tags |