1 33 34 package edu.rice.cs.drjava.model.repl; 35 36 import koala.dynamicjava.interpreter.error.*; 37 import koala.dynamicjava.interpreter.*; 38 import koala.dynamicjava.interpreter.context.*; 39 import koala.dynamicjava.tree.*; 40 41 import java.util.List ; 42 import java.util.LinkedList ; 43 import java.util.Iterator ; 44 import java.util.StringTokenizer ; 45 import java.lang.reflect.*; 46 47 import edu.rice.cs.drjava.model.repl.newjvm.ClassPathManager; 48 import edu.rice.cs.util.UnexpectedException; 49 50 60 public class JavaDebugInterpreter extends DynamicJavaAdapter { 61 62 63 protected final String _name; 64 65 66 protected String _thisClassName; 67 68 69 protected String _thisPackageName; 70 71 74 protected IdentityVisitor _translationVisitor; 75 76 80 public JavaDebugInterpreter(String name, String className) { 81 super(new ClassPathManager()); 82 _name = name; 83 setClassName(className); 84 _translationVisitor = makeTranslationVisitor(); 85 } 86 87 91 public Node processTree(Node node) { return node.acceptVisitor(_translationVisitor); } 92 93 public GlobalContext makeGlobalContext(TreeInterpreter i) { 94 return new GlobalContext(i) { 95 public boolean exists(String name) { 96 return (super.exists(name)) || 97 (_getObjectFieldAccessForField(name, this) != null) || 98 (_getStaticFieldAccessForField(name, this) != null) || 99 (_getReferenceTypeForField(name, this) != null); 100 } 101 }; 102 } 103 104 110 private boolean hasAnonymous(String className) { 111 StringTokenizer st = new StringTokenizer (className, "$"); 112 while (st.hasMoreElements()) { 113 String currToken = st.nextToken(); 114 try { 115 Integer.valueOf(currToken); 117 return true; 118 } 119 catch(NumberFormatException nfe) { 120 } 122 } 123 return false; 124 } 125 126 129 private String _getFullyQualifiedClassNameForThis() { 130 String cName = _thisClassName; 131 if (!_thisPackageName.equals("")) { 132 cName = _thisPackageName + "." + cName; 133 } 134 return cName; 135 } 136 137 private Class <?> _loadClassForThis(Context context) { 138 try { 139 return context.lookupClass(_getFullyQualifiedClassNameForThis()); 140 } 141 catch(ClassNotFoundException e) { 142 throw new UnexpectedException(e); 143 } 144 } 145 146 153 protected ObjectFieldAccess _getObjectFieldAccessForField(String field, Context context) { 154 AbstractTypeChecker tc = makeTypeChecker(context); 155 int numDollars = _getNumDollars(_thisClassName); 156 157 if (hasAnonymous(_thisClassName)) { 159 Class <?> c = _loadClassForThis(context); 161 Field[] fields = c.getDeclaredFields(); 162 163 for (int i = 0; i < fields.length; i++) { 165 if (fields[i].getName().startsWith("this$")) { 166 String fieldName = fields[i].getName(); 167 int lastIndex = fieldName.lastIndexOf("$"); 168 numDollars = Integer.valueOf(fieldName.substring(lastIndex+1, fieldName.length())).intValue() + 1; 169 break; 170 } 171 } 172 } 173 for (int i = 0; i <= numDollars; i++) { 174 Expression expr = _buildObjectFieldAccess(i, numDollars); 175 Expression newExpr = new ObjectFieldAccess(expr, field); 176 try { 177 tc.visit((ObjectFieldAccess) newExpr); 179 return (ObjectFieldAccess) newExpr; 180 } 181 catch (ExecutionError e) { 182 newExpr = new ObjectFieldAccess(expr, "val$" + field); 184 try { 185 tc.visit((ObjectFieldAccess)newExpr); 187 return (ObjectFieldAccess)newExpr; 188 } 189 catch (ExecutionError e2) { 190 } 192 } 193 } 194 195 return null; 196 } 197 198 207 protected ObjectMethodCall _getObjectMethodCallForFunction(MethodCall method, Context context) { 208 AbstractTypeChecker tc = makeTypeChecker(context); 209 int numDollars = _getNumDollars(_thisClassName); 210 String methodName = method.getMethodName(); 211 List <Expression> args = method.getArguments(); 212 213 if (hasAnonymous(_thisClassName)) { 215 Class <?> c = _loadClassForThis(context); 217 Field[] fields = c.getDeclaredFields(); 218 219 for (int i = 0; i < fields.length; i++) { 221 if (fields[i].getName().startsWith("this$")) { 222 String fieldName = fields[i].getName(); 223 int lastIndex = fieldName.lastIndexOf("$"); 224 numDollars = Integer.valueOf(fieldName.substring(lastIndex+1, fieldName.length())).intValue() + 1; 225 break; 226 } 227 } 228 } 229 for (int i = 0; i <= numDollars; i++) { 230 Expression expr = _buildObjectFieldAccess(i, numDollars); 231 expr = new ObjectMethodCall(expr, methodName, args, null, 0, 0, 0, 0); 232 try { 233 tc.visit((ObjectMethodCall)expr); 235 return (ObjectMethodCall)expr; 236 } 237 catch (ExecutionError e2) { 238 } 240 } 241 return null; 242 } 243 244 253 protected StaticFieldAccess _getStaticFieldAccessForField(String field, Context context) { 254 AbstractTypeChecker tc = makeTypeChecker(context); 255 int numDollars = _getNumDollars(_thisClassName); 256 String currClass = _getFullyQualifiedClassNameForThis(); 257 int index = currClass.length(); 258 for (int i = 0; i <= numDollars; i++) { 260 currClass = currClass.substring(0, index); 261 ReferenceType rt = new ReferenceType(currClass); 262 StaticFieldAccess expr = new StaticFieldAccess(rt, field); 263 try { 264 tc.visit(expr); 266 return expr; 267 } 268 catch (ExecutionError e2) { 269 index = currClass.lastIndexOf("$"); 271 } 272 } 273 return null; 274 } 275 276 285 protected StaticMethodCall _getStaticMethodCallForFunction(MethodCall method, Context context) { 286 AbstractTypeChecker tc = makeTypeChecker(context); 287 int numDollars = _getNumDollars(_thisClassName); 288 String methodName = method.getMethodName(); 289 List <Expression> args = method.getArguments(); 290 String currClass = _getFullyQualifiedClassNameForThis(); 291 int index = currClass.length(); 292 for (int i = 0; i <= numDollars; i++) { 294 currClass = currClass.substring(0, index); 295 ReferenceType rt = new ReferenceType(currClass); 296 StaticMethodCall expr = new StaticMethodCall(rt, methodName, args); 297 try { 298 tc.visit(expr); 300 return expr; 301 } 302 catch (ExecutionError e2) { 303 index = currClass.lastIndexOf("$"); 305 } 306 } 307 return null; 308 } 309 310 320 protected ReferenceType _getReferenceTypeForField(String field, Context context) { 321 AbstractTypeChecker tc = makeTypeChecker(context); 322 int index = _indexOfWithinBoundaries(_getFullyQualifiedClassNameForThis(), field); 323 if (index != -1) { 324 int lastDollar = field.lastIndexOf("$"); 328 int lastDot = field.lastIndexOf("."); 329 if (lastDollar != -1) { 330 field = field.substring(lastDollar + 1, field.length()); 331 } 332 else { 333 if (lastDot != -1) { 334 field = field.substring(lastDot + 1, field.length()); 335 } 336 } 337 LinkedList <IdentifierToken> list = new LinkedList <IdentifierToken>(); 338 StringTokenizer st = new StringTokenizer (_getFullyQualifiedClassNameForThis(), "$."); 339 String currString = st.nextToken(); 340 while (!currString.equals(field)) { 341 list.add(new Identifier(currString)); 342 currString = st.nextToken(); 343 } 344 list.add(new Identifier(field)); 345 ReferenceType rt = new ReferenceType(list); 346 try { 347 tc.visit(rt); 349 return rt; 350 } 351 catch (ExecutionError e) { 352 return null; 353 } 354 } 355 else { 356 return null; 357 } 358 } 359 360 361 362 protected void setClassName(String className) { 363 int indexLastDot = className.lastIndexOf("."); 364 if (indexLastDot == -1) _thisPackageName = ""; 365 else _thisPackageName = className.substring(0,indexLastDot); 366 _thisClassName = className.substring(indexLastDot + 1); 367 } 368 369 373 protected QualifiedName _convertThisToName(ThisExpression node) { 374 List <IdentifierToken> ids = new LinkedList <IdentifierToken>(); ids.add(new Identifier("this", node.getBeginLine(), node.getBeginColumn(), 377 node.getEndLine(), node.getEndColumn())); 378 return new QualifiedName(ids, node.getFilename(), node.getBeginLine(), node.getBeginColumn(), 380 node.getEndLine(), node.getEndColumn()); 381 } 382 383 389 protected Expression _convertThisToObjectFieldAccess(ThisExpression node) { 390 String className = node.getClassName(); 391 int numToWalk = verifyClassName(className); 392 int numDollars = _getNumDollars(_thisClassName); 393 if (numToWalk == -1) { 395 throw new ExecutionError("malformed.expression", node); 396 } 397 else { 398 return _buildObjectFieldAccess(numToWalk, numDollars); 399 } 400 } 401 402 406 protected ThisExpression buildUnqualifiedThis() { 407 LinkedList <IdentifierToken> ids = new LinkedList <IdentifierToken>(); 408 return new ThisExpression(ids, "", 0, 0, 0, 0); 409 } 410 411 418 private Expression _buildObjectFieldAccess(int numToWalk, int numDollars) { 419 if (numToWalk == 0) { 420 return _convertThisToName(buildUnqualifiedThis()); 421 } 422 else { 423 return new ObjectFieldAccess(_buildObjectFieldAccess(numToWalk - 1, numDollars), "this$" + (numDollars - numToWalk)); 424 } 425 } 426 427 435 private int _indexOfWithinBoundaries(String string, String subString) { 436 int index = string.indexOf(subString); 437 if (index == -1) { 438 return index; 439 } 440 else { 442 if (((string.length() == subString.length() + index) || 444 (string.charAt(subString.length() + index) == '$')) 445 && 446 ((index == 0) || 448 (string.charAt(index-1) == '$') || 449 (string.charAt(index-1) == '.'))) { 450 return index; 451 } 452 else { 453 return -1; 454 } 455 } 456 } 457 458 464 private int _getNumDollars(String className) { 465 int numDollars = 0; 466 int index = className.indexOf("$"); 467 while (index != -1) { 468 numDollars++; 469 index = className.indexOf("$", index + 1); 470 } 471 return numDollars; 472 } 473 474 479 protected int verifyClassName(String className) { 480 boolean hasPackage = false; 481 if (!_thisPackageName.equals("")) { 482 int index = className.indexOf(_thisPackageName); 483 if (index == 0) { 484 hasPackage = true; 485 index = _thisPackageName.length() + 1; 487 if (index >= className.length()) { 488 return -1; 489 } 490 className = className.substring(index, className.length()); 492 } 493 } 494 495 className = className.replace('.', '$'); 496 int indexWithBoundaries = _indexOfWithinBoundaries(_thisClassName, className); 497 if ((hasPackage && indexWithBoundaries != 0) || 498 (indexWithBoundaries == -1)) { 499 return -1; 500 } 501 else { 502 return _getNumDollars(_thisClassName.substring(indexWithBoundaries + className.length())); 503 } 504 } 505 506 513 protected Expression visitThis(ThisExpression node) { 514 if (node.getClassName().equals("")) { 515 return _convertThisToName(node); 516 } 517 else { 518 return _convertThisToObjectFieldAccess(node); 519 } 520 } 521 522 527 public IdentityVisitor makeTranslationVisitor() { 528 return new IdentityVisitor() { 529 public Node visit(ThisExpression node) { 530 Expression e = visitThis(node); 531 if (e instanceof QualifiedName) { 532 return visit((QualifiedName)e); 533 } 534 else if (e instanceof ObjectFieldAccess) { 535 return visit((ObjectFieldAccess)e); 536 } 537 else { 538 throw new UnexpectedException(new IllegalArgumentException ("Illegal type of Expression")); 539 } 540 } 541 }; 542 } 543 544 571 577 public NameVisitor makeNameVisitor(final Context nameContext) { 578 return new NameVisitor(nameContext) { 579 public Node visit(QualifiedName node) { 604 try { 605 return super.visit(node); 606 } 607 catch(ExecutionError e) { 608 final List <IdentifierToken> ids = node.getIdentifiers(); 611 final Iterator <IdentifierToken> iter = ids.iterator(); 612 final StringBuilder fieldBuf = new StringBuilder (iter.next().image()); 613 while (iter.hasNext()) { 614 IdentifierToken t = iter.next(); 615 fieldBuf.append('$').append(t.image()); 616 } 617 String field = fieldBuf.toString(); 618 if (nameContext.isDefined("this")) { 619 ObjectFieldAccess ofa = _getObjectFieldAccessForField(field, nameContext); 622 if (ofa != null) return ofa; 623 } 624 else { 625 StaticFieldAccess sfa = _getStaticFieldAccessForField(field, nameContext); 627 if (sfa != null) return sfa; 628 else { 629 ReferenceType rt = _getReferenceTypeForField(field, nameContext); 634 if (rt != null) return rt; 635 } 636 } 637 throw e; 639 } 640 } 641 public Node visit(ObjectMethodCall node) { 642 MethodCall method = (MethodCall) super.visit(node); 643 if (method != null) { 646 if (method instanceof StaticMethodCall) { 647 return method; 648 } 649 else if (nameContext.isDefined("this")) { 651 ObjectMethodCall omc = _getObjectMethodCallForFunction(method, nameContext); 652 if (omc != null) { 653 return omc; 654 } 655 else { 656 return method; 657 } 658 } 659 else { 661 StaticMethodCall smc = _getStaticMethodCallForFunction(method, nameContext); 662 if (smc != null) { 663 return smc; 664 } 665 else { 666 return method; 667 } 668 } 669 } 670 else { 671 return null; 672 } 673 } 674 }; 675 } 676 677 682 public AbstractTypeChecker makeTypeChecker(final Context context) { 683 if (Float.valueOf(System.getProperty("java.specification.version")) < 1.5) { 684 return new TypeChecker14(context) { 685 689 public Class <?> visit(QualifiedName node) { 690 String var = node.getRepresentation(); 691 if ("this".equals(var)) { 692 Class <?> c = _loadClassForThis(context); 698 node.setProperty(NodeProperties.TYPE, c); 699 node.setProperty(NodeProperties.MODIFIER, context.getModifier(node)); 700 return c; 701 } 702 else return super.visit(node); 703 } 704 705 }; 706 } 707 else { 708 return new TypeChecker15(context) { 709 713 public Class <?> visit(QualifiedName node) { 714 String var = node.getRepresentation(); 715 if ("this".equals(var)) { 716 Class <?> c = _loadClassForThis(context); 722 node.setProperty(NodeProperties.TYPE, c); 723 node.setProperty(NodeProperties.MODIFIER, context.getModifier(node)); 724 return c; 725 } 726 else return super.visit(node); 727 } 728 729 }; 730 } 731 } 732 733 } 734 | Popular Tags |