1 28 29 package com.caucho.es.wrapper; 30 31 import com.caucho.es.ESArrayWrapper; 32 import com.caucho.es.ESBase; 33 import com.caucho.es.ESBeanWrapper; 34 import com.caucho.es.Global; 35 import com.caucho.java.JavaCompiler; 36 import com.caucho.loader.SimpleLoader; 37 import com.caucho.log.Log; 38 import com.caucho.server.util.CauchoSystem; 39 import com.caucho.util.CharBuffer; 40 import com.caucho.util.IntMap; 41 import com.caucho.vfs.JarPath; 42 import com.caucho.vfs.MergePath; 43 import com.caucho.vfs.Path; 44 import com.caucho.vfs.Vfs; 45 import com.caucho.vfs.WriteStream; 46 47 import java.beans.PropertyDescriptor ; 48 import java.io.IOException ; 49 import java.lang.reflect.Constructor ; 50 import java.lang.reflect.Field ; 51 import java.lang.reflect.Method ; 52 import java.lang.reflect.Modifier ; 53 import java.net.URL ; 54 import java.util.ArrayList ; 55 import java.util.HashMap ; 56 import java.util.Iterator ; 57 import java.util.Map ; 58 import java.util.logging.Logger ; 59 60 public class Wrapper { 61 private static final Integer LOCK = new Integer (0); 62 private static final Logger log = Log.open(Wrapper.class); 63 64 private String name; 65 private String javaClassName; 66 private Class cl; 67 private boolean isPublic; 68 private Path dest; 69 private WriteStream os; 70 private ClassLoader loader; 71 private JavaCompiler compiler; 72 73 private ESBeanInfo beanInfo; 74 private IntMap hasDispatch; 75 private IntMap staticHasDispatch; 76 private IntMap setDispatch; 77 private IntMap staticSetDispatch; 78 private IntMap methodDispatch; 79 private IntMap staticMethodDispatch; 80 private HashMap namedProperties; 81 82 private ArrayList overloadDispatch; 83 84 private int depth; 85 private boolean isNewline; 86 private Class esBase; 87 88 94 private Wrapper(Global resin, Class cl) 95 { 96 name = cl.getName().replace('/', '.'); 97 98 MergePath mergePath = new MergePath(); 99 mergePath.addClassPath(cl.getClassLoader()); 100 Path destClass = mergePath.lookup(name.replace('.', '/') + ".class"); 101 102 if (! destClass.exists() && cl.getInterfaces().length > 0) { 104 cl = cl.getInterfaces()[0]; 105 name = cl.getName().replace('/', '.'); 106 } 107 108 javaClassName = toJavaClassName(name); 109 110 CharBuffer cb = new CharBuffer(); 111 for (int i = 0; i < name.length(); i++) { 112 char ch = name.charAt(i); 113 114 if (ch == '$') 115 cb.append("_0"); 116 else if (ch == '_') 117 cb.append("__"); 118 else 119 cb.append(ch); 120 } 121 122 name = "_jsbean." + cb + "_es"; 123 124 this.cl = cl; 125 126 isPublic = Modifier.isPublic(cl.getModifiers()); 127 128 loader = cl.getClassLoader(); 130 131 compiler = JavaCompiler.create(loader); 132 Path workPath = CauchoSystem.getWorkPath(); 134 135 dest = workPath.lookup(name.replace('.', '/') + ".java"); 136 137 hasDispatch = new IntMap(); 138 staticHasDispatch = new IntMap(); 139 setDispatch = new IntMap(); 140 staticSetDispatch = new IntMap(); 141 methodDispatch = new IntMap(); 142 staticMethodDispatch = new IntMap(); 143 namedProperties = new HashMap (); 144 145 overloadDispatch = new ArrayList (); 146 147 try { 148 esBase = Class.forName("com.caucho.es.ESBase"); 149 } catch (Exception e) { 150 } 151 } 152 153 public static ESBase []bean(Global resin, Class cl) 154 throws Throwable 155 { 156 Wrapper wrapper = null; 157 158 if (cl.isArray()) { 159 ESBase arrayWrapper = ESArrayWrapper.wrapper(resin, cl); 160 return new ESBase[] { arrayWrapper.getProperty("CONSTRUCTOR"), 161 arrayWrapper }; 162 } 163 164 synchronized (LOCK) { 165 wrapper = new Wrapper(resin, cl); 166 ESBeanWrapper beanWrapper = wrapper.wrap(); 167 beanWrapper.n = 0; 168 169 return new ESBase[] { beanWrapper.wrapStatic(), beanWrapper }; 170 } 171 } 172 173 176 private ESBeanWrapper wrap() throws Throwable 177 { 178 dest.getParent().mkdirs(); 179 180 Path workPath = CauchoSystem.getWorkPath(); 181 Path destClass = workPath.lookup(name.replace('.', '/') + ".class"); 182 183 ClassLoader beanLoader; 184 beanLoader = SimpleLoader.create(loader, 185 CauchoSystem.getWorkPath(), 186 name); 187 ESBeanWrapper wrapper; 188 189 try { 190 Class cl = CauchoSystem.loadClass(name, false, beanLoader); 191 wrapper = (ESBeanWrapper) cl.newInstance(); 192 193 if (! wrapper.isModified() && wrapper.getVersionId() == CauchoSystem.getVersionId()) 194 return wrapper; 195 } catch (Throwable e) { 196 } 197 198 destClass.remove(); 199 os = dest.openWrite(); 200 201 beanInfo = ESIntrospector.getBeanInfo(cl); 202 203 try { 204 printHeader(); 205 printConstructors(); 206 printHasProperty(); 207 printSetProperty(); 208 printKeys(); 209 printDeletes(); 210 printMethods(); 211 printInit(); 212 printFooter(); 213 } finally { 214 os.close(); 215 } 216 217 compiler.compile(name.replace('.', '/') + ".java", null); 218 219 beanLoader = SimpleLoader.create(loader, 220 CauchoSystem.getWorkPath(), 221 name); 222 223 try { 224 Class cl = CauchoSystem.loadClass(name, false, beanLoader); 225 wrapper = (ESBeanWrapper) cl.newInstance(); 226 } catch (NoClassDefFoundError e) { 227 e.printStackTrace(); 228 throw e; 229 } 230 231 return wrapper; 232 } 233 234 private long getSourceLastModified(Class cl) 235 { 236 long lastModified = 0; 237 String classPath; 238 239 URL resource = null; 240 String clName = cl.getName().replace('.', '/') + ".class"; 241 String name; 242 243 if (loader != null) 244 resource = loader.getResource(clName); 245 246 String fileName = resource != null ? resource.toExternalForm() : null; 247 248 if (resource == null || 250 fileName.startsWith("systemresource:") || 251 fileName.startsWith("jar:")) 252 return getClassPathLastModified(cl); 253 254 Path path = Vfs.lookup(fileName); 255 256 if (path != null && path.canRead()) 257 return path.getLastModified(); 258 else 259 return 0; 260 } 261 262 private long getClassPathLastModified(Class cl) 263 { 264 String clName = cl.getName().replace('.', '/') + ".class"; 265 266 String classPath = System.getProperty("java.class.path"); 267 268 char sep = CauchoSystem.getPathSeparatorChar(); 269 int head = 0; 270 int tail; 271 for (; (tail = classPath.indexOf(sep, head)) >= 0; head = tail + 1) { 272 String name = classPath.substring(head, tail); 273 Path path = Vfs.lookupNative(name); 274 275 if (name.endsWith(".jar") || name.endsWith(".zip")) 276 path = JarPath.create(path); 277 278 if (path != null && path.lookup(clName).canRead()) { 279 return path.lookup(clName).getLastModified(); 280 } 281 } 282 283 String name = classPath.substring(head); 284 Path path = Vfs.lookupNative(name); 285 286 if (name.endsWith(".jar") || name.endsWith(".zip")) 287 path = JarPath.create(path); 288 289 if (path != null && path.lookup(clName).canRead()) 290 return path.lookup(clName).getLastModified(); 291 292 return 0; 293 } 294 295 private void printHeader() throws IOException 296 { 297 int p = name.lastIndexOf('.'); 298 String pkg = name.substring(0, p); 299 String clName = name.substring(p + 1); 300 301 println("package " + pkg + ";"); 302 println("import com.caucho.es.*;"); 303 Iterator iter = beanInfo.getNonPkgClasses().iterator(); 304 while (iter.hasNext()) { 305 String name = (String ) iter.next(); 306 println("import " + name + ";"); 307 } 308 println(); 309 println("public class " + clName + " extends ESBeanWrapper {"); 310 pushDepth(); 311 if (isPublic) 312 println("private " + javaClassName + " _value;"); 313 314 println(); 315 println("public long getVersionId() { return " + 316 CauchoSystem.getVersionId() + "L; }"); 317 318 println(); 319 println("protected ESBeanWrapper dup()"); 320 println("{"); 321 println(" return new " + clName + "();"); 322 println("}"); 323 324 println(); 325 println("public ESBeanWrapper wrap(Object value)"); 326 println("{"); 327 pushDepth(); 328 println("if (value == null) throw new NullPointerException();"); 329 println(name + " child = new " + name + "();"); 330 println("child.value = value;"); 331 if (isPublic) 332 println("child._value = (" + javaClassName + ") value;"); 333 println("child.hasDispatch = instanceHasDispatch;"); 334 println("child.setDispatch = instanceSetDispatch;"); 335 println("child.methodDispatch = instanceMethodDispatch;"); 336 println("child.n = -1;"); 337 println("return child;"); 338 popDepth(); 339 println("}"); 340 341 println(); 342 println("public ESBeanWrapper wrapStatic()"); 343 println("{"); 344 pushDepth(); 345 println(name + " child = new " + name + "();"); 346 println("child.hasDispatch = staticHasDispatch;"); 347 println("child.setDispatch = staticSetDispatch;"); 348 println("child.methodDispatch = staticMethodDispatch;"); 349 println("child.n = -2;"); 350 println("child.name = \"" + javaClassName + "\";"); 351 println("try {"); 352 println(" child.value = Class.forName(child.name);"); 353 println("} catch (Exception e) {}"); 354 println("return child;"); 355 popDepth(); 356 println("}"); 357 358 println(); 359 println("public Class getJavaType()"); 360 println("{"); 361 pushDepth(); 362 println("return value.getClass();"); 363 popDepth(); 364 println("}"); 365 } 366 367 private void printConstructors() throws IOException 368 { 369 println(); 370 println("public ESBase construct(Call call, int length)"); 371 println(" throws Throwable"); 372 println("{"); 373 pushDepth(); 374 println("if (n != -2)"); 375 println(" throw new ESException(\"can't create `" + javaClassName + "'\");"); 376 println(); 377 378 if (printMethodConstructor()) { 379 popDepth(); 380 println("}"); 381 return; 382 } 383 384 ArrayList overload = beanInfo.getConstructors(); 385 if (Modifier.isAbstract(cl.getModifiers())) 386 overload = null; 387 388 if (overload == null || overload.size() == 0) { 389 println(" throw new ESException(\"can't create `" + javaClassName + "'\");"); 390 } 391 else { 392 393 Constructor last = null; 394 for (int i = 0; i < overload.size(); i++) { 395 if (overload.get(i) instanceof Constructor ) 396 last = (Constructor ) overload.get(i); 397 } 398 399 for (int i = 0; i < overload.size(); i++) { 400 Object o = overload.get(i); 401 if (! (o instanceof Constructor )) 402 continue; 403 404 Constructor constructor = (Constructor ) o; 405 if (constructor != last) { 406 println("if (length <= " + i + ")"); 407 print(" "); 408 } 409 410 print("return wrap(new " + javaClassName + "("); 411 Class []param = constructor.getParameterTypes(); 412 for (int j = 0; j < param.length; j++) { 413 if (j > 0) 414 print(", "); 415 416 printArgToJava(param[j], j); 417 } 418 println("));"); 419 } 420 421 if (last == null) 422 println("throw new ESException(\"can't create `" + javaClassName + "'\");"); 423 } 424 425 popDepth(); 426 println("}"); 427 } 428 429 private boolean printMethodConstructor() throws IOException 430 { 431 ArrayList overload = (ArrayList ) beanInfo._staticMethodMap.get("create"); 432 if (overload != null) { 433 printMethod(Integer.MIN_VALUE, "create", overload, null); 434 return true; 435 } 436 else 437 return false; 438 } 439 440 443 private void printHasProperty() throws IOException 444 { 445 println(); 446 println("public ESBase hasProperty(ESString name)"); 447 println(" throws Throwable"); 448 println("{"); 449 pushDepth(); 450 println("ESBase temp;"); 451 println("switch (hasDispatch.get(name)) {"); 452 453 PropertyDescriptor []props = beanInfo.getPropertyDescriptors(); 454 455 int index = 1; 456 for (int i = 0; i < props.length; i++) { 457 if (props[i] instanceof NamedPropertyDescriptor) 458 index = doHasNamedProperty(index, (NamedPropertyDescriptor) props[i]); 459 else if (props[i] instanceof ESIndexedPropertyDescriptor) 460 index = doHasIndexProperty(index, 461 (ESIndexedPropertyDescriptor) props[i]); 462 else if (props[i] instanceof ESPropertyDescriptor) 463 index = doHasProperty(index, (ESPropertyDescriptor) props[i]); 464 else 465 throw new RuntimeException (); 466 } 467 println("default:"); 468 println(" return ESBase.esEmpty;"); 469 println("}"); 470 popDepth(); 471 println("}"); 472 } 473 474 private int doHasIndexProperty(int i, ESIndexedPropertyDescriptor prop) 475 throws IOException 476 { 477 Named named = new Named(prop.getName(), namedProperties.size()); 478 int n = named.n; 479 480 namedProperties.put(prop.getName(), named); 481 hasDispatch.put(prop.getName(), i); 482 483 println("case " + i + ":"); 484 pushDepth(); 485 println("if (name" + n + " == null) {"); 486 println(" name" + n + " = new " + name + "();"); 487 println(" name" + n + ".value = value;"); 488 if (isPublic) 489 println(" name" + n + "._value = _value;"); 490 println(" name" + n + ".hasDispatch = has" + n + ";"); 491 println(" name" + n + ".setDispatch = set" + n + ";"); 492 println(" name" + n + ".delId = " + n + ";"); 493 println("}"); 494 println("return name" + n + ";"); 495 popDepth(); 496 497 i += 1; 498 499 ESMethodDescriptor md = prop.getESReadMethod(); 500 if (md == null) 501 return i; 502 503 println("case " + i + ":"); 504 pushDepth(); 505 named.get = i; 506 507 ESMethodDescriptor size = prop.getESSizeMethod(); 508 509 if (size != null) { 510 println("if (name.equals(LENGTH)) {"); 511 pushDepth(); 512 Method method = size.getMethod(); 513 Class resultClass = method.getReturnType(); 514 print("return "); 515 startJavaToES(resultClass); 516 startProp(size); 517 print(")"); 518 endJavaToES(resultClass); 519 println(";"); 520 popDepth(); 521 println("} else {"); 522 pushDepth(); 523 } 524 Method method = md.getMethod(); 525 Class resultClass = method.getReturnType(); 526 print("return "); 527 startJavaToES(resultClass); 528 int p = startProp(md); 529 if (p > 0) 530 print(", "); 531 print("name.toInt32())"); 532 endJavaToES(resultClass); 533 println(";"); 534 if (size != null) { 535 popDepth(); 536 println("}"); 537 } 538 539 popDepth(); 540 541 return i + 1; 542 } 543 544 private int doHasNamedProperty(int i, NamedPropertyDescriptor prop) 545 throws IOException 546 { 547 Named named = new Named(prop.getName(), namedProperties.size()); 548 int n = named.n; 549 550 namedProperties.put(prop.getName(), named); 551 hasDispatch.put(prop.getName(), i); 552 553 println("case " + i + ":"); 554 pushDepth(); 555 println("if (name" + n + " == null) {"); 556 println(" name" + n + " = new " + name + "();"); 557 println(" name" + n + ".value = value;"); 558 if (isPublic) 559 println(" name" + n + "._value = _value;"); 560 println(" name" + n + ".hasDispatch = has" + n + ";"); 561 println(" name" + n + ".setDispatch = set" + n + ";"); 562 println(" name" + n + ".delId = " + n + ";"); 563 println("}"); 564 println("return name" + n + ";"); 565 popDepth(); 566 567 i += 1; 568 569 ESMethodDescriptor md = prop.getNamedReadMethod(); 570 if (md == null) 571 return i; 572 573 println("case " + i + ":"); 574 pushDepth(); 575 named.get = i; 576 577 Method method = md.getMethod(); 578 if (Modifier.isStatic(method.getModifiers()) && ! md.isStaticVirtual()) 579 staticHasDispatch.put(prop.getName(), i - 1); 580 581 Class resultClass = method.getReturnType(); 582 print("return "); 583 startJavaToES(resultClass); 584 int p = startProp(md); 585 if (p > 0) 586 print(", "); 587 print("name.toJavaString())"); 588 endJavaToES(resultClass); 589 println(";"); 590 popDepth(); 591 592 return i + 1; 593 } 594 595 private int doHasProperty(int i, ESPropertyDescriptor prop) 596 throws IOException 597 { 598 Field field = prop.getESField(); 599 ESMethodDescriptor md = prop.getESReadMethod(); 600 601 if (field != null && ! Modifier.isPublic(field.getModifiers())) 602 field = null; 603 604 if (md == null && field == null) 605 return i; 606 607 hasDispatch.put(prop.getName(), i); 608 609 println("case " + i + ":"); 610 pushDepth(); 611 612 if (field != null) { 613 Class resultClass = field.getType(); 614 print("return "); 615 startJavaToES(resultClass); 616 if (isPublic && field.getDeclaringClass().getName().equals(cl.getName())) 617 print("_value."); 618 else if (Modifier.isStatic(field.getModifiers())) 619 print(toJavaClassName(field.getDeclaringClass().getName()) + "."); 620 else 621 print("((" + toJavaClassName(field.getDeclaringClass().getName()) + ") value)."); 622 print(field.getName()); 623 endJavaToES(resultClass); 624 println(";"); 625 popDepth(); 626 627 if (Modifier.isStatic(field.getModifiers())) 628 staticHasDispatch.put(prop.getName(), i); 629 630 return i + 1; 631 } 632 633 Method method = md.getMethod(); 634 635 if (Modifier.isStatic(method.getModifiers()) && ! md.isStaticVirtual()) 636 staticHasDispatch.put(prop.getName(), i); 637 638 print("return "); 639 640 Class resultClass = method.getReturnType(); 641 642 startJavaToES(resultClass); 643 int p = startProp(md); 644 print(")"); 645 endJavaToES(resultClass); 646 println(";"); 647 popDepth(); 648 649 return i + 1; 650 } 651 652 private void printSetProperty() throws IOException 653 { 654 println(); 655 println("public void setProperty(ESString name, ESBase newValue)"); 656 println(" throws Throwable"); 657 println("{"); 658 pushDepth(); 659 println("ESBase temp;"); 660 println("switch (setDispatch.get(name)) {"); 661 662 PropertyDescriptor []props = beanInfo.getPropertyDescriptors(); 663 664 int index = 0; 665 for (int i = 0; i < props.length; i++) { 666 if (props[i] instanceof NamedPropertyDescriptor) { 667 index = doSetNamedProperty(index, 668 (NamedPropertyDescriptor) props[i]); 669 } 670 else if (props[i] instanceof ESIndexedPropertyDescriptor) { 671 index = doSetIndexProperty(index, 672 (ESIndexedPropertyDescriptor) props[i]); 673 } 674 else if (props[i] instanceof ESPropertyDescriptor) 675 index = doSetProperty(index, (ESPropertyDescriptor) props[i]); 676 else 677 throw new RuntimeException (); 678 } 679 println("default:"); 680 println(" return;"); 681 println("}"); 682 popDepth(); 683 println("}"); 684 } 685 686 private int doSetNamedProperty(int i, NamedPropertyDescriptor prop) 687 throws IOException 688 { 689 Named named = (Named) namedProperties.get(prop.getName()); 690 if (named == null) 691 return i; 692 693 int n = named.n; 694 695 ESMethodDescriptor md = prop.getNamedWriteMethod(); 696 if (md == null) 697 return i; 698 699 println("case " + i + ":"); 700 pushDepth(); 701 named.set = i; 702 703 int p = startProp(md); 704 Class []param = md.getParameterTypes(); 705 706 if (p != 0) 707 print(", "); 708 print("name.toJavaString(), "); 709 printValueToJava(param[1], "newValue"); 710 println(");"); 711 712 println("return;"); 713 popDepth(); 714 715 return i + 1; 716 } 717 718 private int doSetIndexProperty(int i, ESIndexedPropertyDescriptor prop) 719 throws IOException 720 { 721 Named named = (Named) namedProperties.get(prop.getName()); 722 if (named == null) 723 return i; 724 725 int n = named.n; 726 727 ESMethodDescriptor md = prop.getESWriteMethod(); 728 if (md == null) 729 return i; 730 731 println("case " + i + ":"); 732 pushDepth(); 733 named.set = i; 734 735 int p = startProp(md); 736 Class []param = md.getParameterTypes(); 737 738 if (p != 0) 739 print(", "); 740 print("name.toInt32(), "); 741 printValueToJava(param[1], "newValue"); 742 println(");"); 743 744 println("return;"); 745 popDepth(); 746 747 return i + 1; 748 } 749 750 private int doSetProperty(int i, ESPropertyDescriptor prop) 751 throws IOException 752 { 753 ESMethodDescriptor md = prop.getESWriteMethod(); 754 Field field = prop.getESField(); 755 if (field != null && Modifier.isFinal(field.getModifiers())) 756 field = null; 757 758 if (md == null && field == null) 759 return i; 760 761 println("case " + i + ":"); 762 pushDepth(); 763 764 setDispatch.put(prop.getName(), i); 765 766 if (field != null) { 767 Class resultClass = field.getType(); 768 if (isPublic) 769 print("_value."); 770 else 771 print("((" + field.getDeclaringClass().getName() + ") value)."); 772 print(field.getName()); 773 print(" = "); 774 printValueToJava(resultClass, "newValue"); 775 println(";"); 776 println("return;"); 777 popDepth(); 778 return i + 1; 779 } 780 781 Method method = md.getMethod(); 782 783 if (Modifier.isStatic(method.getModifiers()) && ! md.isStaticVirtual()) 784 staticSetDispatch.put(prop.getName(), i); 785 786 Class []param = md.getParameterTypes(); 787 788 int p = startProp(md); 789 if (p != 0) 790 print(", "); 791 printValueToJava(param[0], "newValue"); 792 println(");"); 793 794 println("return;"); 795 796 popDepth(); 797 798 return i + 1; 799 } 800 801 private void printKeys() throws IOException 802 { 803 println(); 804 println("public java.util.Iterator keys()"); 805 println(" throws Throwable"); 806 println("{"); 807 pushDepth(); 808 println("switch (delId) {"); 809 810 ESMethodDescriptor md = beanInfo.iterator; 811 if (md != null) { 812 println("case -1:"); 813 print(" return Call.toESIterator("); 814 startProp(md); 815 println("));"); 816 } 817 818 PropertyDescriptor []props = beanInfo.getPropertyDescriptors(); 819 for (int i = 0; i < props.length; i++) { 820 if (props[i] instanceof NamedPropertyDescriptor) 821 printNamedKey((NamedPropertyDescriptor) props[i]); 822 } 823 824 println("default:"); 825 println(" return super.keys();"); 826 println("}"); 827 popDepth(); 828 println("}"); 829 } 830 831 private void printNamedKey(NamedPropertyDescriptor prop) 832 throws IOException 833 { 834 ESMethodDescriptor md = prop.getNamedIteratorMethod(); 835 if (md == null) 836 return; 837 838 Named named = (Named) namedProperties.get(prop.getName()); 839 println("case " + named.n + ":"); 840 pushDepth(); 841 print("return Call.toESIterator("); 842 int p = startProp(md); 843 println("));"); 844 popDepth(); 845 } 846 847 private void printDeletes() throws IOException 848 { 849 println(); 850 println("public ESBase delete(ESString key)"); 851 println(" throws Throwable"); 852 println("{"); 853 pushDepth(); 854 println("switch (delId) {"); 855 856 PropertyDescriptor []props = beanInfo.getPropertyDescriptors(); 857 for (int i = 0; i < props.length; i++) { 858 if (props[i] instanceof NamedPropertyDescriptor) 859 printNamedDelete((NamedPropertyDescriptor) props[i]); 860 } 861 862 println("default:"); 863 println(" return ESBoolean.FALSE;"); 864 println("}"); 865 popDepth(); 866 println("}"); 867 } 868 869 private void printNamedDelete(NamedPropertyDescriptor prop) 870 throws IOException 871 { 872 ESMethodDescriptor md = prop.getNamedRemoveMethod(); 873 if (md == null) 874 return; 875 876 Named named = (Named) namedProperties.get(prop.getName()); 877 println("case " + named.n + ":"); 878 pushDepth(); 879 int p = startProp(md); 880 if (p > 0) 881 print(", "); 882 println("key.toJavaString());"); 883 println("return ESBoolean.TRUE;"); 884 popDepth(); 885 } 886 887 890 private void printMethods() throws IOException 891 { 892 println(); 893 println("public ESBase call(Call call, int length, int n)"); 894 println(" throws Throwable"); 895 println("{"); 896 pushDepth(); 897 println("ESBase temp;"); 898 println("switch (n) {"); 899 900 ArrayList overload = (ArrayList ) beanInfo._methodMap.get("call"); 901 if (overload != null) 902 printMethod(-1, "call", overload, null); 903 904 ArrayList create = (ArrayList ) beanInfo._staticMethodMap.get("create"); 906 ArrayList call = (ArrayList ) beanInfo._staticMethodMap.get("call"); 907 if (create != null) 908 printMethod(-2, "create", create, null); 909 else if (call != null) 910 printMethod(-2, "call", create, null); 911 else { 912 println("case -2:"); 913 println(" return construct(call, length);"); 914 } 915 916 Iterator iter = beanInfo._methodMap.entrySet().iterator(); 917 int i = 0; 918 while (iter.hasNext()) { 919 Map.Entry entry = (Map.Entry) iter.next(); 920 overload = (ArrayList ) entry.getValue(); 921 String name = (String ) entry.getKey(); 922 923 i = printMethod(i, name, overload, methodDispatch); 924 } 925 926 iter = beanInfo._staticMethodMap.entrySet().iterator(); 927 while (iter.hasNext()) { 928 Map.Entry entry = (Map.Entry) iter.next(); 929 overload = (ArrayList ) entry.getValue(); 930 String name = (String ) entry.getKey(); 931 932 i = printMethod(i, name, overload, staticMethodDispatch); 933 } 934 935 println("}"); 936 println("return ESBase.esUndefined;"); 937 popDepth(); 938 println("}"); 939 } 940 941 944 private int printMethod(int i, String name, ArrayList overload, 945 IntMap dispatch) 946 throws IOException 947 { 948 ESMethodDescriptor []last = null; 949 950 if (overload == null) 951 return i; 952 953 for (int j = 0; j < overload.size(); j++) { 954 last = (ESMethodDescriptor []) overload.get(j); 955 } 956 957 if (last == null) { 958 return i; 959 } 960 961 if (i > -100) { 962 println("case " + i + ":"); 963 pushDepth(); 964 if (dispatch != null) 965 dispatch.put(name, i++); 966 } 967 968 if (overload.size() > 2) { 969 ESMethodDescriptor []mds = (ESMethodDescriptor []) overload.get(2); 970 971 for (int j = 0; mds != null && j < mds.length; j++) { 972 Class []cl = mds[j].getParameterTypes(); 973 int p = cl.length - 2; 974 975 if (cl[0].getName().equals("com.caucho.es.Call") && 976 cl[1].getName().equals("int")) { 977 printMethod(mds[j], dispatch == null); 978 popDepth(); 979 return i; 980 } 981 } 982 } 983 984 for (int j = 0; j < overload.size(); j++) { 985 Object o = overload.get(j); 986 987 if (o == null) 988 continue; 989 990 ESMethodDescriptor []mds = (ESMethodDescriptor []) o; 991 if (mds != last) { 992 println("if (length <= " + j + ") {"); 993 pushDepth(); 994 } 995 996 if (mds.length == 1) 997 printMethod(mds[0], dispatch == null); 998 else { 999 String var = "dispatch" + overloadDispatch.size(); 1000 1001 overloadDispatch.add(mds); 1002 1003 println("switch (" + var + ".select(call, length)) {"); 1004 for (int k = 0; k < mds.length; k++) { 1005 println("case " + k + ":"); 1006 pushDepth(); 1007 printMethod(mds[k], dispatch == null); 1008 popDepth(); 1009 } 1010 1011 println("default:"); 1012 println(" throw new ESException(\"no matching method " + mds[0].getName() + "\");"); 1013 println("}"); 1014 } 1015 1016 if (mds != last) { 1017 popDepth(); 1018 println("}"); 1019 } 1020 } 1021 1022 if (i > -100) { 1023 popDepth(); 1024 } 1025 1026 return i; 1027 } 1028 1029 1035 private void printMethod(ESMethodDescriptor md, boolean isProp) 1036 throws IOException 1037 { 1038 boolean hasThrowable = hasException(md.getMethod().getExceptionTypes(), 1039 Throwable .class); 1040 1041 1047 1048 Class returnCl = md.getReturnType(); 1049 if (! returnCl.getName().equals("void")) { 1050 print("return "); 1051 startJavaToES(returnCl); 1052 } 1053 1054 Class []param = md.getParameterTypes(); 1055 1056 int p; 1057 1058 if (isProp) 1059 p = startProp(md); 1060 else 1061 p = startCall(md); 1062 1063 if (param.length == 2 && 1064 param[0].getName().equals("com.caucho.es.Call") && 1065 param[1].getName().equals("int")) { 1066 if (p > 0) 1067 print(", "); 1068 print("call, length"); 1069 } 1070 else { 1071 for (int j = 0; j < param.length; j++) { 1072 if (j + p > 0) 1073 print(", "); 1074 1075 printArgToJava(param[j], j); 1076 } 1077 } 1078 1079 if (returnCl.getName().equals("void")) { 1080 println(");"); 1081 println("return ESBase.esUndefined;"); 1082 } 1083 else { 1084 print(")"); 1085 endJavaToES(returnCl); 1086 println(";"); 1087 } 1088 1089 1103 } 1104 1105 private boolean hasException(Class []exn, Class cl) 1106 { 1107 for (int i = 0; i < exn.length; i++) 1108 if (exn[i].isAssignableFrom(cl)) 1109 return true; 1110 1111 return false; 1112 } 1113 1114 1117 private int startProp(ESMethodDescriptor md) 1118 throws IOException 1119 { 1120 Method method = md.getMethod(); 1121 1122 int p = 0; 1123 if (md.isStaticVirtual()) { 1124 print(md.getMethodClassName()); 1125 print("."); 1126 print(md.getMethod().getName()); 1127 if (isPublic) 1128 print("(_value"); 1129 else 1130 print("((" + toJavaClassName(md.getObjectClassName()) + ") value"); 1131 p = 1; 1132 } else if (Modifier.isStatic(method.getModifiers())) { 1133 print(md.getMethodClassName()); 1134 print("."); 1135 print(md.getMethod().getName()); 1136 print("("); 1137 } else { 1138 if (isPublic) 1139 print("_value."); 1140 else 1141 print("((" + toJavaClassName(md.getObjectClassName()) + ") value)."); 1142 print(md.getMethod().getName()); 1143 print("("); 1144 } 1145 1146 return p; 1147 } 1148 1149 private int startCall(ESMethodDescriptor md) 1150 throws IOException 1151 { 1152 Method method = md.getMethod(); 1153 1154 int p = 0; 1155 if (md.isStaticVirtual()) { 1156 print(toJavaClassName(md.getMethodClassName())); 1157 print("."); 1158 print(md.getMethod().getName()); 1159 print("((" + md.getObjectClassName() + ") call.getThisWrapper()"); 1160 p = 1; 1161 } else if (Modifier.isStatic(method.getModifiers())) { 1162 print(toJavaClassName(md.getMethodClassName())); 1163 print("."); 1164 print(md.getMethod().getName()); 1165 print("("); 1166 } else { 1167 print("((" + toJavaClassName(md.getObjectClassName()) + ") call.getThisWrapper())."); 1168 print(md.getMethod().getName()); 1169 print("("); 1170 } 1171 1172 return p; 1173 } 1174 1175 private void startJavaToES(Class cl) 1176 throws IOException 1177 { 1178 String name = cl.getName(); 1179 1180 switch (classTypes.get(name)) { 1181 case T_V: 1182 break; 1184 1185 case T_Z: 1186 print("ESBoolean.create("); 1187 break; 1188 1189 case T_C: 1190 print("ESString.createFromCharCode("); 1191 break; 1192 1193 case T_B: case T_S: case T_I: case T_L: 1194 case T_F: case T_D: 1195 print("ESNumber.create("); 1196 break; 1197 1198 case T_STRING: 1199 print("ESString.toStr("); 1200 break; 1201 1202 default: 1203 if (esBase.isAssignableFrom(cl)) 1204 print("((temp = "); 1205 else 1206 print("Global.wrap("); 1207 break; 1208 } 1209 } 1210 1211 private void endJavaToES(Class cl) 1212 throws IOException 1213 { 1214 String name = cl.getName(); 1215 1216 switch (classTypes.get(name)) { 1217 case T_V: 1218 break; 1220 1221 case T_Z: 1222 case T_C: 1223 case T_B: case T_S: case T_I: case T_L: 1224 case T_F: case T_D: 1225 case T_STRING: 1226 print(")"); 1227 break; 1228 1229 default: 1230 if (esBase.isAssignableFrom(cl)) 1231 print(") == null ? ESBase.esNull : temp)"); 1232 else 1233 print(")"); 1234 break; 1235 } 1236 } 1237 1238 private void printValueToJava(Class cl, String value) 1239 throws IOException 1240 { 1241 String name = cl.getName(); 1242 1243 switch (classTypes.get(name)) { 1244 case T_V: 1245 throw new RuntimeException (); 1246 1247 case T_Z: 1248 print(value + ".toBoolean()"); 1249 break; 1250 1251 case T_C: 1252 print("(char) " + value + ".toStr().carefulCharAt(0)"); 1253 break; 1254 1255 case T_B: 1256 print("(byte) " + value + ".toInt32()"); 1257 break; 1258 1259 case T_S: 1260 print("(short) " + value + ".toInt32()"); 1261 break; 1262 1263 case T_I: 1264 print(value + ".toInt32()"); 1265 break; 1266 1267 case T_L: 1268 print("(long)" + value + ".toNum()"); 1269 break; 1270 1271 case T_F: 1272 print("(float)" + value + ".toNum()"); 1273 break; 1274 1275 case T_D: 1276 print(value + ".toNum()"); 1277 break; 1278 1279 case T_STRING: 1280 print("(" + value + ").toJavaString()"); 1281 break; 1282 1283 default: 1284 if (cl.isAssignableFrom(esBase)) 1285 print(value); 1286 else if (esBase.isAssignableFrom(cl)) { 1287 print("("); 1288 printClassType(cl); 1289 print(") " + value); 1290 } 1291 else { 1292 print("("); 1293 printClassType(cl); 1294 print(") " + value + ".toJavaObject()"); 1295 } 1296 break; 1297 } 1298 } 1299 1300 private void printArgToJava(Class cl, int i) 1301 throws IOException 1302 { 1303 String name = cl.getName(); 1304 1305 switch (classTypes.get(name)) { 1306 case T_V: 1307 throw new RuntimeException (); 1308 1309 case T_Z: 1310 print("call.getArg(" + i + ", length).toBoolean()"); 1311 break; 1312 1313 case T_C: 1314 print("(char) call.getArg(" + i + ", length).toStr().carefulCharAt(0)"); 1315 break; 1316 1317 case T_B: 1318 print("(byte) call.getArgInt32(" + i + ", length)"); 1319 break; 1320 1321 case T_S: 1322 print("(short) call.getArgInt32(" + i + ", length)"); 1323 break; 1324 1325 case T_I: 1326 print("call.getArgInt32(" + i + ", length)"); 1327 break; 1328 1329 case T_L: 1330 print("(long) call.getArgNum(" + i + ", length)"); 1331 break; 1332 1333 case T_F: 1334 print("(float)call.getArgNum(" + i + ", length)"); 1335 break; 1336 1337 case T_D: 1338 print("call.getArgNum(" + i + ", length)"); 1339 break; 1340 1341 case T_STRING: 1342 print("call.getArgString(" + i + ", length)"); 1343 break; 1344 1345 default: 1346 if (cl.isAssignableFrom(esBase) && 1347 ! cl.getName().equals("java.lang.Object")) 1348 print("call.getArg(" + i + ", length)"); 1349 else if (esBase.isAssignableFrom(cl)) { 1350 print("("); 1351 printClassType(cl); 1352 print(") "); 1353 print("call.getArg(" + i + ", length)"); 1354 } 1355 else { 1356 print("("); 1357 printClassType(cl); 1358 print(") call.getArgObject(" + i + ", length)"); 1359 } 1360 break; 1361 } 1362 } 1363 1364 private void printClassType(Class cl) 1365 throws IOException 1366 { 1367 if (cl.isArray()) { 1368 printClassType(cl.getComponentType()); 1369 print("[]"); 1370 } 1371 else { 1372 print(cl.getName().replace('$', '.')); 1373 } 1374 } 1375 1376 private void printInit() throws IOException 1377 { 1378 println("private int delId = -1;"); 1379 println(); 1380 println("private static com.caucho.util.IntMap instanceHasDispatch;"); 1381 println("private static com.caucho.util.IntMap instanceSetDispatch;"); 1382 println("private static com.caucho.util.IntMap instanceMethodDispatch;"); 1383 println("private static com.caucho.util.IntMap staticMethodDispatch;"); 1384 println("private static com.caucho.util.IntMap staticHasDispatch;"); 1385 println("private static com.caucho.util.IntMap staticSetDispatch;"); 1386 Iterator iter = namedProperties.values().iterator(); 1387 while (iter.hasNext()) { 1388 Named named = (Named) iter.next(); 1389 println(name + " name" + named.n + ";"); 1390 print("private static ConstIntMap has" + named.n); 1391 println(" = new ConstIntMap(" + named.get + ");"); 1392 print("private static ConstIntMap set" + named.n); 1393 println(" = new ConstIntMap(" + named.set + ");"); 1394 } 1395 1396 for (int i = 0; i < overloadDispatch.size(); i++) { 1397 print("private static com.caucho.es.wrapper.MethodDispatcher dispatch" + i); 1398 println(" = new com.caucho.es.wrapper.MethodDispatcher(new Class[][] {"); 1399 pushDepth(); 1400 1401 ESMethodDescriptor []mds; 1402 mds = (ESMethodDescriptor []) overloadDispatch.get(i); 1403 1404 for (int j = 0; j < mds.length; j++) { 1405 print("new Class[] {"); 1406 1407 Class []param = mds[j].getParameterTypes(); 1408 1409 for (int k = 0; k < param.length; k++) { 1410 printClass(param[k]); 1411 print(", "); 1412 } 1413 println("},"); 1414 } 1415 popDepth(); 1416 println("});"); 1417 } 1418 1419 println(); 1420 println("static { _init(); }"); 1421 1422 println(); 1423 println("public boolean isModified()"); 1424 println("{"); 1425 pushDepth(); 1426 com.caucho.make.ClassDependency dep = new com.caucho.make.ClassDependency(cl); 1427 println("try {"); 1428 println(" Class cl = Class.forName(\"" + cl.getName() + "\", false, Thread.currentThread().getContextClassLoader());"); 1429 println(" return new com.caucho.make.ClassDependency(cl, " + dep.getDigest() + "L).isModified();"); 1430 println("} catch (Throwable e) {"); 1431 println(" return true;"); 1432 println("}"); 1433 popDepth(); 1434 println("}"); 1435 1436 println(); 1437 println("private static void _init()"); 1438 println("{"); 1439 1440 pushDepth(); 1441 println("instanceHasDispatch = new com.caucho.util.IntMap();"); 1442 iter = hasDispatch.iterator(); 1443 while (iter.hasNext()) { 1444 String key = (String ) iter.next(); 1445 1446 println("instanceHasDispatch.put(ESId.intern(\"" + key + "\"), " + 1447 hasDispatch.get(key) + ");"); 1448 } 1449 1450 println(); 1451 println("staticHasDispatch = new com.caucho.util.IntMap();"); 1452 iter = staticHasDispatch.iterator(); 1453 while (iter.hasNext()) { 1454 String key = (String ) iter.next(); 1455 1456 println("staticHasDispatch.put(ESId.intern(\"" + key + "\"), " + 1457 staticHasDispatch.get(key) + ");"); 1458 } 1459 1460 println(); 1461 println("instanceSetDispatch = new com.caucho.util.IntMap();"); 1462 iter = setDispatch.iterator(); 1463 while (iter.hasNext()) { 1464 String key = (String ) iter.next(); 1465 1466 println("instanceSetDispatch.put(ESId.intern(\"" + key + "\"), " + 1467 setDispatch.get(key) + ");"); 1468 } 1469 1470 println(); 1471 println("staticSetDispatch = new com.caucho.util.IntMap();"); 1472 iter = staticSetDispatch.iterator(); 1473 while (iter.hasNext()) { 1474 String key = (String ) iter.next(); 1475 1476 println("staticSetDispatch.put(ESId.intern(\"" + key + "\"), " + 1477 staticSetDispatch.get(key) + ");"); 1478 } 1479 1480 println(); 1481 println("instanceMethodDispatch = new com.caucho.util.IntMap();"); 1482 iter = methodDispatch.iterator(); 1483 while (iter.hasNext()) { 1484 String key = (String ) iter.next(); 1485 1486 println("instanceMethodDispatch.put(ESId.intern(\"" + key + "\"), " + 1487 methodDispatch.get(key) + ");"); 1488 } 1489 1490 println(); 1491 println("staticMethodDispatch = new com.caucho.util.IntMap();"); 1492 iter = staticMethodDispatch.iterator(); 1493 while (iter.hasNext()) { 1494 String key = (String ) iter.next(); 1495 1496 println("staticMethodDispatch.put(ESId.intern(\"" + key + "\"), " + 1497 staticMethodDispatch.get(key) + ");"); 1498 } 1499 1500 popDepth(); 1501 println("}"); 1502 } 1503 1504 private void printClass(Class cl) 1505 throws IOException 1506 { 1507 if (! cl.isArray()) { 1508 print(cl.getName() + ".class"); 1509 return; 1510 } 1511 1512 print("(new "); 1513 printArrayClass(cl.getComponentType()); 1514 print("[0]).getClass()"); 1515 } 1516 1517 private void printArrayClass(Class cl) 1518 throws IOException 1519 { 1520 if (cl.isArray()) { 1521 printArrayClass(cl.getComponentType()); 1522 print("[]"); 1523 } 1524 else 1525 print(cl.getName()); 1526 } 1527 1528 private void printFooter() throws IOException 1529 { 1530 popDepth(); 1531 println("}"); 1532 } 1533 1534 private void pushDepth() 1535 { 1536 depth += 2; 1537 } 1538 1539 private void popDepth() 1540 { 1541 depth -= 2; 1542 } 1543 1544 private void print(String s) throws IOException 1545 { 1546 if (isNewline) 1547 printDepth(); 1548 os.print(s); 1549 } 1550 1551 private void println(String s) throws IOException 1552 { 1553 if (isNewline) 1554 printDepth(); 1555 os.println(s); 1556 isNewline = true; 1557 } 1558 1559 private void println() throws IOException 1560 { 1561 if (isNewline) 1562 printDepth(); 1563 os.println(); 1564 isNewline = true; 1565 } 1566 1567 private void printDepth() throws IOException 1568 { 1569 for (int i = 0; i < depth; i++) 1570 os.print(' '); 1571 isNewline = false; 1572 } 1573 1574 private String toJavaClassName(String name) 1575 { 1576 CharBuffer cb = CharBuffer.allocate(); 1577 for (int i = 0; i < name.length(); i++) { 1578 char ch = name.charAt(i); 1579 1580 if (ch == '$' && i > 0 && name.charAt(i - 1) != '.') 1581 cb.append("."); 1582 else 1583 cb.append(ch); 1584 } 1585 return cb.close(); 1586 } 1587 1588 static HashMap <String ,String > classNames; 1589 static { 1590 classNames = new HashMap <String ,String >(); 1591 classNames.put("void", "V"); 1592 classNames.put("boolean", "Z"); 1593 classNames.put("byte", "B"); 1594 classNames.put("short", "S"); 1595 classNames.put("char", "C"); 1596 classNames.put("int", "I"); 1597 classNames.put("long", "J"); 1598 classNames.put("float", "F"); 1599 classNames.put("double", "D"); 1600 } 1601 1602 static IntMap classTypes; 1603 static final int T_V = 0; 1604 static final int T_Z = T_V + 1; 1605 static final int T_B = T_Z + 1; 1606 static final int T_S = T_B + 1; 1607 static final int T_C = T_S + 1; 1608 static final int T_I = T_C + 1; 1609 static final int T_L = T_I + 1; 1610 static final int T_F = T_L + 1; 1611 static final int T_D = T_F + 1; 1612 static final int T_STRING = T_D + 1; 1613 static { 1614 classTypes = new IntMap(); 1615 classTypes.put("void", T_V); 1616 classTypes.put("boolean", T_Z); 1617 classTypes.put("byte", T_B); 1618 classTypes.put("short", T_S); 1619 classTypes.put("char", T_C); 1620 classTypes.put("int", T_I); 1621 classTypes.put("long", T_L); 1622 classTypes.put("float", T_F); 1623 classTypes.put("double", T_D); 1624 classTypes.put("java.lang.String", T_STRING); 1625 } 1626 1627 static class Named { 1628 String name; 1629 int n; 1630 int get = -1; 1631 int set = -1; 1632 int keys = -1; 1633 int remove = -1; 1634 1635 Named(String name, int n) 1636 { 1637 this.name = name; 1638 this.n = n; 1639 } 1640 } 1641} 1642 1643 | Popular Tags |