00001 package edu.ksu.cis.bandera.specification.ast;
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 import edu.ksu.cis.bandera.specification.predicate.datastructure.*;
00036 import edu.ksu.cis.bandera.specification.assertion.datastructure.*;
00037 import edu.ksu.cis.bandera.jjjc.symboltable.Package;
00038 import ca.mcgill.sable.soot.*;
00039 import ca.mcgill.sable.soot.jimple.*;
00040 import ca.mcgill.sable.soot.grimp.*;
00041 import edu.ksu.cis.bandera.jext.*;
00042 import edu.ksu.cis.bandera.jjjc.*;
00043 import edu.ksu.cis.bandera.jjjc.node.*;
00044 import edu.ksu.cis.bandera.jjjc.symboltable.*;
00045 import edu.ksu.cis.bandera.specification.analysis.*;
00046 import edu.ksu.cis.bandera.specification.datastructure.*;
00047 import edu.ksu.cis.bandera.specification.node.*;
00048 import java.util.*;
00049 public class Checker extends DepthFirstAdapter {
00050 private static Grimp grimp = Grimp.v();
00051 private Hashtable importedType;
00052 private Hashtable importedPackage;
00053 private Hashtable importedAssertion;
00054 private Hashtable importedAssertionSet;
00055 private Hashtable importedPredicate;
00056 private Hashtable importedPredicateSet;
00057
00058 private Hashtable tlPredicates = new Hashtable();
00059 private Hashtable tlQuantifiers = new Hashtable();
00060 private Hashtable tlQuantifiedVariables = new Hashtable();
00061 private Hashtable asAssertions = new Hashtable();
00062 private Hashtable pqTable = new Hashtable();
00063 private Vector exceptions = new Vector();
00064
00065 private String currentId;
00066 private SootClass currentSootClass;
00067 private Hashtable currentQuantifiers;
00068 private Hashtable currentPredicates;
00069 private Hashtable currentAssertions;
00070 private Vector currentTLQuantifiedVariables;
00071 private java.util.Vector args;
00072 private java.util.Vector quantifiedVariables;
00073 private Value constraint;
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083 public Checker(Set importedType, Set importedPackage, Set importedAssertion, Set importedAssertionSet, Set importedPredicate, Set importedPredicateSet) {
00084 this.importedType = new Hashtable();
00085 this.importedPackage = new Hashtable();
00086 this.importedAssertion = new Hashtable();
00087 this.importedAssertionSet = new Hashtable();
00088 this.importedPredicate = new Hashtable();
00089 this.importedPredicateSet = new Hashtable();
00090
00091 Hashtable compiledClasses = CompilationManager.getCompiledClasses();
00092
00093 for (Iterator i = importedType.iterator(); i.hasNext();) {
00094 Name name = (Name) i.next();
00095 SootClass sc = (SootClass) compiledClasses.get(name.toString());
00096 if (sc != null) {
00097 this.importedType.put(name, sc);
00098 } else {
00099 exceptions.addElement("Imported type named '" + name + "' is not declared");
00100 }
00101 }
00102
00103 Hashtable compiledPackages = new Hashtable();
00104 for (Enumeration e = compiledClasses.keys(); e.hasMoreElements();) {
00105 Name name = new Name((String) e.nextElement());
00106 if (name.isSimpleName()) {
00107 this.importedType.put(name, compiledClasses.get(name.toString()));
00108 }
00109 name = name.getSuperName();
00110 try {
00111 compiledPackages.put(name, Package.getPackage(name));
00112 } catch (Exception ex) {}
00113 }
00114
00115 for (Iterator i = importedPackage.iterator(); i.hasNext();) {
00116 Name name = (Name) i.next();
00117 Package p = (Package) compiledPackages.get(name);
00118 if (p != null) {
00119 this.importedPackage.put(name, p);
00120 } else {
00121 exceptions.addElement("Imported package named '" + name + "' is not declared");
00122 }
00123 }
00124
00125 for (Iterator i = importedAssertion.iterator(); i.hasNext();) {
00126 Name name = (Name) i.next();
00127 try {
00128 Assertion as = AssertionSet.getAssertion(name);
00129 this.importedAssertion.put(name, as);
00130 } catch (Exception e) {
00131 exceptions.addElement(e.getMessage());
00132 }
00133 }
00134
00135 for (Iterator i = importedAssertionSet.iterator(); i.hasNext();) {
00136 Name name = (Name) i.next();
00137 try {
00138 AssertionSet as = AssertionSet.getAssertionSet(name);
00139 this.importedAssertionSet.put(name, as);
00140 } catch (Exception e) {
00141 exceptions.addElement(e.getMessage());
00142 }
00143 }
00144
00145 for (Iterator i = importedPredicate.iterator(); i.hasNext();) {
00146 Name name = (Name) i.next();
00147 try {
00148 Predicate p = PredicateSet.getPredicate(name);
00149 this.importedPredicate.put(name, p);
00150 } catch (Exception e) {
00151 exceptions.addElement(e.getMessage());
00152 }
00153 }
00154
00155 for (Iterator i = importedPredicateSet.iterator(); i.hasNext();) {
00156 Name name = (Name) i.next();
00157 try {
00158 PredicateSet ps = PredicateSet.getPredicateSet(name);
00159 this.importedPredicateSet.put(name, ps);
00160 } catch (Exception e) {
00161 exceptions.addElement(e.getMessage());
00162 }
00163 }
00164 }
00165
00166
00167
00168
00169 public void caseAArgsArgs(AArgsArgs node) {
00170 node.getArgs().apply(this);
00171 args.add(node.getId().toString().trim());
00172 }
00173
00174
00175
00176
00177 public void caseAIdArgs(AIdArgs node) {
00178 args.add(node.getId().toString().trim());
00179 }
00180
00181
00182
00183
00184 public void caseAIdIds(AIdIds node) {
00185 String id = node.toString().trim();
00186 if (currentQuantifiers.get(id) != null) {
00187 exceptions.addElement("Can't redefine quantifier with identifier '" + id + "'");
00188 } else {
00189 QuantifiedVariable qv = new QuantifiedVariable(id, RefType.v(currentSootClass.getName()));
00190 quantifiedVariables.add(qv);
00191 currentQuantifiers.put(id, qv);
00192 }
00193 }
00194
00195
00196
00197
00198 public void caseAIdsIds(AIdsIds node) {
00199 node.getIds().apply(this);
00200 String id = node.getId().toString().trim();
00201 if (currentQuantifiers.get(id) != null) {
00202 exceptions.addElement("Can't redefine quantifier with identifier '" + id + "'");
00203 } else {
00204 QuantifiedVariable qv = new QuantifiedVariable(id, RefType.v(currentSootClass.getName()));
00205 quantifiedVariables.add(qv);
00206 currentQuantifiers.put(id, qv);
00207 }
00208 }
00209
00210
00211
00212
00213 public void caseANameNames(ANameNames node) {
00214 Name name = new Name(node.toString());
00215 try {
00216 Assertion a = resolveAssertion(name);
00217 currentAssertions.put(a.getName(), a);
00218 } catch (Exception e) {
00219 exceptions.addElement(e.getMessage());
00220 }
00221 }
00222
00223
00224
00225
00226 public void caseANamePrimaryTypeExp(ANamePrimaryTypeExp node) {
00227 String name = node.getName().toString().trim();
00228 QuantifiedVariable qv = (QuantifiedVariable) currentQuantifiers.get(name);
00229 Name className;
00230 RefType rt;
00231 if (qv != null) {
00232 rt = (RefType) qv.getType();
00233 className = new Name(rt.className);
00234 } else {
00235 className = new Name(name);
00236 rt = RefType.v(name);
00237 }
00238 try {
00239 currentSootClass = resolveType(className);
00240 if (qv != null) {
00241 constraint = grimp.newEqExpr(new Local("@this", rt), new Local("quantification$" + qv.getName(), qv.getType()));
00242 } else {
00243 constraint = grimp.newInstanceOfExpr(new Local("@this", rt), rt);
00244 }
00245 } catch (Exception e) {
00246 exceptions.addElement(e.getMessage());
00247 }
00248 }
00249
00250
00251
00252
00253 public void caseANamesNames(ANamesNames node) {
00254 node.getNames().apply(this);
00255 Name name = new Name(node.getName().toString());
00256 try {
00257 Assertion a = resolveAssertion(name);
00258 currentAssertions.put(a.getName(), a);
00259 } catch (Exception e) {
00260 exceptions.addElement(e.getMessage());
00261 }
00262 }
00263
00264
00265
00266
00267 public void caseAOpTypeExp(AOpTypeExp node) {
00268 SootClass lType, rType = null;
00269 Value lConstraint, rConstraint;
00270 node.getPrimaryTypeExp().apply(this);
00271 lType = currentSootClass;
00272 lConstraint = constraint;
00273 node.getTypeExp().apply(this);
00274 rType = currentSootClass;
00275 rConstraint = constraint;
00276 currentSootClass = lub(lType, rType);
00277 if (node.getTypeOp() instanceof AFilterTypeOp) {
00278 constraint = new LogicalAndExpr(lConstraint, new ComplementExpr(rConstraint));
00279 } else {
00280 constraint = new LogicalOrExpr(lConstraint, rConstraint);
00281 }
00282 }
00283
00284
00285
00286
00287 public void caseAPredicateExp(APredicateExp node) {
00288 Name name = new Name(node.getName().toString());
00289 try {
00290 Predicate p = resolvePredicate(name);
00291 currentPredicates.put(node, p);
00292 args = new Vector();
00293 if (node.getArgs() != null) {
00294 node.getArgs().apply(this);
00295 }
00296 if (pqTable.get(node) == null) {
00297 pqTable.put(node, new Vector());
00298 }
00299 if (!p.isStatic()) {
00300 String qId = (String) args.remove(0);
00301 QuantifiedVariable q = (QuantifiedVariable) currentQuantifiers.get(qId);
00302 if (q == null) {
00303 exceptions.addElement("A quantifier with identifier '" + qId + "' is not declared");
00304 return;
00305 }
00306 if (!p.getType().getFullyQualifiedName().equals(q.getType().toString())) {
00307 exceptions.addElement("Type mismatch in " + node);
00308 } else {
00309 ((Vector) pqTable.get(node)).add(q);
00310 }
00311 }
00312 for (int i = 0; i < args.size(); i++) {
00313 String qId = (String) args.elementAt(i);
00314 QuantifiedVariable q = (QuantifiedVariable) currentQuantifiers.get(qId);
00315 if (q == null) {
00316 exceptions.addElement("A quantifier with identifier '" + qId + "' is not declared");
00317 return;
00318 }
00319 ClassOrInterfaceType ct = Package.getClassOrInterfaceType(new Name(p.getParamType(i).getFullyQualifiedName()));
00320 ClassOrInterfaceType qt = Package.getClassOrInterfaceType(new Name(q.getType().toString()));
00321 if ((ct == qt) || (ct.hasSuperClass(qt)) || (ct.hasSuperInterface(qt))) {
00322 ((Vector) pqTable.get(node)).add(q);
00323 } else {
00324 exceptions.addElement("Type mismatch in " + node);
00325 }
00326 }
00327 } catch (Exception e) {
00328 exceptions.addElement(e.getMessage());
00329 }
00330 }
00331
00332
00333
00334
00335 public void caseAQtl(AQtl node) {
00336 quantifiedVariables = new Vector();
00337 constraint = null;
00338 node.getTypeExp().apply(this);
00339 if (constraint instanceof InstanceOfExpr) {
00340 constraint = null;
00341 }
00342 if (node.getIds() != null) {
00343 node.getIds().apply(this);
00344 }
00345 for (Iterator i = quantifiedVariables.iterator(); i.hasNext();) {
00346 QuantifiedVariable qv = (QuantifiedVariable) i.next();
00347 qv.setExact(node.getQtlBinding() instanceof AExactQtlBinding);
00348 qv.setConstraint(constraint);
00349 currentTLQuantifiedVariables.add(qv);
00350 }
00351 quantifiedVariables = null;
00352 constraint = null;
00353 }
00354
00355
00356
00357
00358 public void caseATl(ATl node) {
00359 currentId = node.getId().toString().trim();
00360 currentQuantifiers = new Hashtable();
00361 currentPredicates = new Hashtable();
00362 currentTLQuantifiedVariables = new Vector();
00363 {
00364 Object temp[] = node.getQtl().toArray();
00365 for (int i = 0; i < temp.length; i++) {
00366 ((PQtl) temp[i]).apply(this);
00367 }
00368 }
00369 {
00370 Object temp[] = node.getWord().toArray();
00371 for (int i = 0; i < temp.length; i++) {
00372 ((PWord) temp[i]).apply(this);
00373 }
00374 }
00375 tlPredicates.put(currentId, currentPredicates);
00376 tlQuantifiers.put(currentId, currentQuantifiers);
00377 tlQuantifiedVariables.put(currentId, currentTLQuantifiedVariables);
00378 }
00379
00380
00381
00382
00383
00384 public edu.ksu.cis.bandera.jjjc.node.PName createASTName(Name name) {
00385 if (name.isSimpleName()) {
00386 return new edu.ksu.cis.bandera.jjjc.node.ASimpleName(new edu.ksu.cis.bandera.jjjc.node.TId(name.toString()));
00387 } else {
00388 return new edu.ksu.cis.bandera.jjjc.node.AQualifiedName(createASTName(name.getSuperName()), new edu.ksu.cis.bandera.jjjc.node.TDot(), new edu.ksu.cis.bandera.jjjc.node.TId(name.getLastIdentifier()));
00389 }
00390 }
00391
00392
00393
00394
00395 public Hashtable getAEnabledAssertionsTable() {
00396 return asAssertions;
00397 }
00398
00399
00400
00401
00402 public Vector getExceptions() {
00403 return exceptions;
00404 }
00405
00406
00407
00408
00409 public Hashtable getPredicateQuantifierTable() {
00410 return pqTable;
00411 }
00412
00413
00414
00415
00416 public Hashtable getTLPredicatesTable() {
00417 return tlPredicates;
00418 }
00419
00420
00421
00422
00423 public java.util.Hashtable getTLQuantifiedVariables() {
00424 return tlQuantifiedVariables;
00425 }
00426
00427
00428
00429
00430 public Hashtable getTLQuantifiersTable() {
00431 return tlQuantifiers;
00432 }
00433
00434
00435
00436
00437
00438
00439 public SootClass lub(SootClass sc1, SootClass sc2) {
00440 if (sc1 == sc2) return sc1;
00441 ClassOrInterfaceType cit1 = null, cit2 = null;
00442 try {
00443 cit1 = Package.getClassOrInterfaceType(new Name(sc1.getName()));
00444 cit1.loadReferences();
00445 cit2 = Package.getClassOrInterfaceType(new Name(sc2.getName()));
00446 cit2.loadReferences();
00447 } catch (Exception e) {
00448 exceptions.add(e.getMessage());
00449 return null;
00450 }
00451
00452 HashSet set = new HashSet();
00453 boolean isInterface = true;
00454 ClassOrInterfaceType base;
00455
00456 if (!cit1.isInterface() && !cit2.isInterface()) {
00457 isInterface = false;
00458 base = cit1;
00459 set.add(cit2);
00460 for (Enumeration e = cit1.getSuperClasses(); e.hasMoreElements();) {
00461 set.add(e.nextElement());
00462 }
00463 for (Enumeration e = cit2.getSuperClasses(); e.hasMoreElements();) {
00464 set.add(e.nextElement());
00465 }
00466 } else if (cit1.isInterface() && cit2.isInterface()) {
00467 base = cit1;
00468 set.add(cit2);
00469 for (Enumeration e = cit1.getSuperInterfaces(); e.hasMoreElements();) {
00470 set.add(e.nextElement());
00471 }
00472 for (Enumeration e = cit2.getSuperInterfaces(); e.hasMoreElements();) {
00473 set.add(e.nextElement());
00474 }
00475 } else if (cit1.isInterface() && !cit2.isInterface()) {
00476 base = cit1;
00477 for (Enumeration e = cit1.getSuperInterfaces(); e.hasMoreElements();) {
00478 set.add(e.nextElement());
00479 }
00480 for (Enumeration e = cit2.getSuperInterfaces(); e.hasMoreElements();) {
00481 set.add(e.nextElement());
00482 }
00483 } else {
00484 base = cit2;
00485 for (Enumeration e = cit1.getSuperInterfaces(); e.hasMoreElements();) {
00486 set.add(e.nextElement());
00487 }
00488 for (Enumeration e = cit2.getSuperInterfaces(); e.hasMoreElements();) {
00489 set.add(e.nextElement());
00490 }
00491 }
00492
00493 ClassOrInterfaceType result = null;
00494 if (isInterface) {
00495 for (Iterator i = set.iterator(); i.hasNext();) {
00496 ClassOrInterfaceType type = (ClassOrInterfaceType) i.next();
00497 if (base == type) {
00498 result = base;
00499 break;
00500 } else if (base.hasSuperInterface(type)) {
00501 if (result == null) {
00502 result = type;
00503 } else {
00504 if (type.hasSuperInterface(result)) {
00505 result = type;
00506 }
00507 }
00508 }
00509 }
00510 } else {
00511 for (Iterator i = set.iterator(); i.hasNext();) {
00512 ClassOrInterfaceType type = (ClassOrInterfaceType) i.next();
00513 if (base == type) {
00514 result = base;
00515 break;
00516 } else if (base.hasSuperClass(type)) {
00517 if (result == null) {
00518 result = type;
00519 } else {
00520 if (type.hasSuperClass(result)) {
00521 result = type;
00522 }
00523 }
00524 }
00525 }
00526 }
00527 return CompilationManager.getSootClassManager().getClass(result.getFullyQualifiedName());
00528 }
00529
00530
00531
00532
00533
00534 public Assertion resolveAssertion(Name name) throws java.lang.Exception {
00535 Assertion a = (Assertion) importedAssertion.get(name);
00536 if (a != null)
00537 return a;
00538
00539 if (!name.isSimpleName()) {
00540 try {
00541 return AssertionSet.getAssertion(name);
00542 } catch (Exception e) {
00543 throw new Exception("Can't resolve assertion with name '" + name + "'");
00544 }
00545 }
00546
00547 Vector v = new Vector();
00548
00549 for (Enumeration e = importedAssertionSet.elements(); e.hasMoreElements();) {
00550 AssertionSet as = (AssertionSet) e.nextElement();
00551 if (as.getAssertionTable().get(new Name(as.getName(), name)) != null) {
00552 v.add(as);
00553 }
00554 }
00555
00556 if (v.size() > 1)
00557 throw new Exception("Ambiguous assertion with name '" + name + "'");
00558 if (v.size() < 1)
00559 throw new Exception("Can't resolve assertion with name '" + name + "'");
00560
00561 AssertionSet as = (AssertionSet) v.firstElement();
00562 a = (Assertion) as.getAssertionTable().get(new Name(as.getName(), name));
00563 return a;
00564 }
00565
00566
00567
00568
00569
00570
00571 public Predicate resolvePredicate(Name name) throws java.lang.Exception {
00572 Predicate p = (Predicate) importedPredicate.get(name);
00573 if (p != null)
00574 return p;
00575
00576 if (!name.isSimpleName()) {
00577 try {
00578 return PredicateSet.getPredicate(name);
00579 } catch (Exception e) {
00580 throw new Exception("Can't resolve predicate with name '" + name + "'");
00581 }
00582 }
00583
00584 Vector v = new Vector();
00585
00586 for (Enumeration e = importedPredicateSet.elements(); e.hasMoreElements();) {
00587 PredicateSet ps = (PredicateSet) e.nextElement();
00588 if (ps.getPredicateTable().get(new Name(ps.getName(), name)) != null) {
00589 v.add(ps);
00590 }
00591 }
00592
00593 if (v.size() > 1)
00594 throw new Exception("Ambiguous predicate with name '" + name + "'");
00595 if (v.size() < 1)
00596 throw new Exception("Can't resolve predicate with name '" + name + "'");
00597
00598 PredicateSet ps = (PredicateSet) v.firstElement();
00599 p = (Predicate) ps.getPredicateTable().get(new Name(ps.getName(), name));
00600 return p;
00601 }
00602
00603
00604
00605
00606
00607 public SootClass resolveType(Name name) throws java.lang.Exception {
00608 SootClass sc = (SootClass) importedType.get(name);
00609 if (sc != null)
00610 return sc;
00611
00612 Hashtable compiledClasses = CompilationManager.getCompiledClasses();
00613
00614 if (!name.isSimpleName()) {
00615 sc = (SootClass) compiledClasses.get(name.toString());
00616 if (sc != null)
00617 return sc;
00618 throw new Exception("Can't resolve type with name '" + name + "'");
00619 }
00620
00621 Vector v = new Vector();
00622
00623 for (Enumeration e = importedPackage.elements(); e.hasMoreElements();) {
00624 Package p = (Package) e.nextElement();
00625 if (p.hasType(name)) {
00626 if (compiledClasses.get(new Name(p.getName(), name).toString()) != null) {
00627 v.add(p);
00628 }
00629 }
00630 }
00631
00632 if (v.size() > 1)
00633 throw new Exception("Ambiguous type with name '" + name + "'");
00634 if (v.size() < 1)
00635 throw new Exception("Can't resolve type with name '" + name + "'");
00636
00637 sc = (SootClass) compiledClasses.get(new Name(((Package) v.firstElement()).getName(), name).toString());
00638 return sc;
00639 }
00640 }