1 28 29 package com.caucho.es; 30 31 import com.caucho.es.parser.Parser; 32 import com.caucho.es.wrapper.Wrapper; 33 import com.caucho.java.LineMap; 34 import com.caucho.loader.DynamicClassLoader; 35 import com.caucho.loader.SimpleLoader; 36 import com.caucho.log.Log; 37 import com.caucho.util.FreeList; 38 import com.caucho.util.IntMap; 39 import com.caucho.util.LruCache; 40 import com.caucho.vfs.Path; 41 42 import java.lang.ref.SoftReference ; 43 import java.util.Date ; 44 import java.util.HashMap ; 45 import java.util.logging.Logger ; 46 47 50 public class Global extends ESBase { 51 private static Integer LOCK = new Integer (0); 52 private static final Logger log = Log.open(Global.class); 53 54 private final static int OBJECT = 0; 55 private final static int FUNCTION = OBJECT + 1; 56 private final static int ARRAY = FUNCTION + 1; 57 private final static int STRING = ARRAY + 1; 58 private final static int BOOL = STRING + 1; 59 private final static int NUM = BOOL + 1; 60 private final static int DATE = NUM + 1; 61 private final static int MATH = DATE + 1; 62 private final static int REGEXP = MATH + 1; 63 private final static int PACKAGES = REGEXP + 1; 64 private final static int CAUCHO = PACKAGES + 1; 65 private final static int JAVA = CAUCHO + 1; 66 private final static int JAVAX = JAVA + 1; 67 68 private static Global goldGlobal; 69 private static IntMap propertyMap; 70 71 private ESGlobal global; 72 private Global root; 73 74 ESObject objProto; 75 ESObject object; 76 77 ESObject funProto; 78 ESObject fun; 79 80 ESObject arrayProto; 81 ESObject array; 82 83 ESObject stringProto; 84 ESObject string; 85 86 ESObject boolProto; 87 ESObject bool; 88 89 ESObject numProto; 90 ESObject num; 91 92 ESObject dateProto; 93 ESObject date; 94 95 ESObject math; 96 97 ESRegexp regexpProto; 98 ESRegexpWrapper regExp; 99 100 ESPackage pkg; 101 102 HashMap properties; 103 HashMap globalProperties; 104 105 107 private static final ThreadLocal <Global> _globals 108 = new ThreadLocal <Global>(); 109 110 private static Thread lastThread; 111 private static Global lastGlobal; 112 113 115 private final static LruCache<Class ,ESBase> _staticWraps 116 = new LruCache<Class ,ESBase>(256); 117 private final static LruCache<Class ,ESBase> _staticClassWraps 118 = new LruCache<Class ,ESBase>(256); 119 120 122 private static FreeList<Call> _freeCalls = new FreeList<Call>(2); 123 124 private static HashMap <String ,SoftReference <Script>> _runtimeScripts; 125 126 127 private ClassLoader parentLoader; 128 private ClassLoader loader; 129 private Path scriptPath; 130 private Path classDir; 131 private HashMap importScripts; 132 private HashMap importGlobals; 133 134 int markCount; 135 136 139 private Global(boolean init) 140 { 141 ESBase.init(null); 142 143 151 152 propertyMap = new IntMap(); 153 propertyMap.put(ESId.intern("Object"), OBJECT); 154 propertyMap.put(ESId.intern("Function"), FUNCTION); 155 propertyMap.put(ESId.intern("Array"), ARRAY); 156 propertyMap.put(ESId.intern("String"), STRING); 157 propertyMap.put(ESId.intern("Boolean"), BOOL); 158 propertyMap.put(ESId.intern("Number"), NUM); 159 propertyMap.put(ESId.intern("Date"), DATE); 160 propertyMap.put(ESId.intern("Math"), MATH); 161 propertyMap.put(ESId.intern("RegExp"), REGEXP); 162 propertyMap.put(ESId.intern("Packages"), PACKAGES); 163 propertyMap.put(ESId.intern("caucho"), CAUCHO); 164 propertyMap.put(ESId.intern("java"), JAVA); 165 propertyMap.put(ESId.intern("javax"), JAVAX); 166 167 globalProperties = new HashMap (); 168 169 object = NativeObject.create(this); 170 fun = NativeFunction.create(this); 171 object.prototype = funProto; 172 173 int flags = ESBase.DONT_ENUM; 174 int allflags = (ESBase.DONT_ENUM|ESBase.DONT_DELETE|ESBase.READ_ONLY); 175 176 array = NativeArray.create(this); 177 string = NativeString.create(this); 178 bool = NativeBoolean.create(this); 179 num = NativeNumber.create(this); 180 math = NativeMath.create(this); 181 date = NativeDate.create(this); 182 183 regExp = NativeRegexp.create(this); 184 185 pkg = ESPackage.create(); 186 187 NativeGlobal.create(this); 188 NativeFile.create(this); 189 190 globalProperties.put(ESId.intern("NaN"), ESNumber.create(0.0/0.0)); 191 globalProperties.put(ESId.intern("Infinity"), ESNumber.create(1.0/0.0)); 192 } 193 194 203 Global(HashMap properties, Object proto, 204 Path classDir, Path scriptPath, ClassLoader parentLoader) 205 throws Throwable 206 { 207 synchronized (LOCK) { 208 if (goldGlobal == null) 209 goldGlobal = new Global(true); 210 } 211 212 root = this; 213 this.parentLoader = parentLoader; 214 this.loader = SimpleLoader.create(parentLoader, classDir, null); 215 this.classDir = classDir; 216 this.scriptPath = scriptPath; 217 218 objProto = (ESObject) goldGlobal.objProto.resinCopy(); 220 object = (ESObject) goldGlobal.object.resinCopy(); 221 222 224 funProto = (ESObject) goldGlobal.funProto.resinCopy(); 225 funProto.prototype = objProto; 226 object.prototype = funProto; 227 228 fun = (ESObject) goldGlobal.fun.resinCopy(); 229 fun.prototype = funProto; 230 231 233 arrayProto = (ESObject) goldGlobal.arrayProto.resinCopy(); 234 arrayProto.prototype = objProto; 235 236 array = (ESObject) goldGlobal.array.resinCopy(); 237 array.prototype = funProto; 238 239 241 stringProto = (ESObject) goldGlobal.stringProto.resinCopy(); 242 stringProto.prototype = objProto; 243 244 string = (ESObject) goldGlobal.string.resinCopy(); 245 string.prototype = funProto; 246 247 249 boolProto = (ESObject) goldGlobal.boolProto.resinCopy(); 250 boolProto.prototype = objProto; 251 252 bool = (ESObject) goldGlobal.bool.resinCopy(); 253 bool.prototype = funProto; 254 255 257 numProto = (ESObject) goldGlobal.numProto.resinCopy(); 258 numProto.prototype = objProto; 259 260 num = (ESObject) goldGlobal.num.resinCopy(); 261 num.prototype = funProto; 262 263 265 math = (ESObject) goldGlobal.math.resinCopy(); 266 math.prototype = objProto; 267 268 270 dateProto = (ESObject) goldGlobal.dateProto.resinCopy(); 271 dateProto.prototype = objProto; 272 273 date = (ESObject) goldGlobal.date.resinCopy(); 274 date.prototype = funProto; 275 276 278 281 285 pkg = ESPackage.create(); 286 287 if (proto != null) { 288 prototype = objectWrap(proto); 289 prototype.prototype = objProto; 290 } 291 else 292 prototype = objProto; 293 294 if (properties != null) 295 this.properties = properties; 296 297 globalProperties = goldGlobal.globalProperties; 298 } 299 300 Global(Global root) 301 { 302 this.root = root; 303 304 objProto = root.objProto; 305 object = root.object; 306 funProto = root.funProto; 307 fun = root.fun; 308 arrayProto = root.arrayProto; 309 array = root.array; 310 stringProto = root.stringProto; 311 string = root.string; 312 boolProto = root.boolProto; 313 bool = root.bool; 314 numProto = root.numProto; 315 num = root.num; 316 math = root.math; 317 dateProto = root.dateProto; 318 date = root.date; 319 regexpProto = root.regexpProto; 320 regExp = root.regExp; 321 pkg = root.pkg; 322 properties = root.properties; 323 prototype = root.prototype; 324 globalProperties = root.globalProperties; 325 326 _runtimeScripts = root._runtimeScripts; 327 } 328 329 void addProperty(ESId id, ESBase value) 330 { 331 globalProperties.put(id, value); 332 } 333 334 public ESBase getProperty(ESString id) 335 throws Throwable 336 { 337 int index = propertyMap.get(id); 338 339 switch (index) { 340 case OBJECT: 341 return snap(id, object); 342 343 case FUNCTION: 344 return snap(id, fun); 345 346 case ARRAY: 347 return snap(id, array); 348 349 case STRING: 350 return snap(id, string); 351 352 case BOOL: 353 return snap(id, bool); 354 355 case NUM: 356 return snap(id, num); 357 358 case DATE: 359 return snap(id, date); 360 361 case MATH: 362 return snap(id, math); 363 364 case REGEXP: 365 return snap(id, getRegexp()); 366 367 case PACKAGES: 368 return snap(id, pkg); 369 370 case CAUCHO: 371 return snap(id, pkg.getProperty("com").getProperty("caucho")); 372 373 case JAVA: 374 return snap(id, pkg.getProperty("java")); 375 376 case JAVAX: 377 return snap(id, pkg.getProperty("javax")); 378 379 default: 380 ESBase value = prototype == null ? null : prototype.getProperty(id); 381 Object obj; 382 if (value != null && value != esEmpty) 383 return snap(id, value); 384 else if (properties != null && 385 (obj = properties.get(id.toString())) != null) 386 return snap(id, objectWrap(obj)); 387 else if ((value = (ESBase) globalProperties.get(id)) != null) 388 return snap(id, value); 389 else { 390 return esEmpty; 391 } 392 } 393 } 394 395 private ESBase snap(ESString id, ESBase value) 396 { 397 if (value == null) 398 throw new RuntimeException (); 399 400 global.put(id, value, DONT_ENUM); 401 return value; 402 } 403 404 ESRegexpWrapper getRegexp() 405 { 406 if (regExp != null) 407 return regExp; 408 409 else if (root.regExp != null) { 410 regExp = root.regExp; 411 return regExp; 412 } 413 414 initRegexp(); 415 416 return regExp; 417 } 418 419 ESRegexp getRegexpProto() 420 { 421 if (regexpProto != null) 422 return regexpProto; 423 424 else if (root.regexpProto != null) { 425 regexpProto = root.regexpProto; 426 return regexpProto; 427 } 428 429 initRegexp(); 430 431 return regexpProto; 432 } 433 434 private void initRegexp() 435 { 436 437 root.regexpProto = (ESRegexp) goldGlobal.regexpProto.resinCopy(); 438 root.regexpProto.prototype = root.objProto; 439 440 root.regExp = (ESRegexpWrapper) goldGlobal.regExp.resinCopy(); 441 root.regExp.prototype = root.funProto; 442 root.regExp.regexp = root.regexpProto; 443 444 regexpProto = root.regexpProto; 445 regExp = root.regExp; 446 } 447 448 454 public void addScript(String name, Script script) 455 { 456 if (_runtimeScripts != null) 457 _runtimeScripts.put(name, new SoftReference <Script>(script)); 458 } 459 460 467 LineMap getLineMap(String className) 468 { 469 try { 470 int p = className.indexOf('$'); 471 472 if (p > 0) 473 className = className.substring(0, p); 474 475 Script script = null; 476 477 if (_runtimeScripts != null) { 478 SoftReference <Script> ref = _runtimeScripts.get(className); 479 480 if (ref != null) 481 script = ref.get(); 482 } 483 484 if (script != null) 485 return script.getLineMap(); 486 else 487 return null; 488 } catch (Exception e) { 489 return null; 490 } 491 } 492 493 497 Script findScript(String className) 498 throws Throwable 499 { 500 Script script = (Script) importScripts.get(className); 501 502 if (script != null) 503 return script; 504 505 Parser parser = new Parser(); 506 parser.setScriptPath(getScriptPath()); 507 parser.setClassLoader(getClassLoader()); 508 parser.setWorkDir(getClassDir()); 509 510 return parser.parse(className); 511 } 512 513 516 public static Global getGlobalProto() 517 { 518 return (Global) _globals.get(); 519 } 520 521 526 Global begin() 527 { 528 Global oldGlobal = (Global) _globals.get(); 529 _globals.set(this); 530 531 return oldGlobal; 532 } 533 534 539 static void end(Global oldGlobal) 540 { 541 _globals.set(oldGlobal); 542 } 543 544 545 Call getCall() 546 { 547 Call call = _freeCalls.allocate(); 548 if (call == null) 549 return new Call(); 550 else { 551 call.clear(); 552 return call; 553 } 554 } 555 556 void freeCall(Call call) 557 { 558 call.free(); 559 _freeCalls.free(call); 560 } 561 562 ESBase objectWrap(Object object) 563 throws Throwable 564 { 565 if (object == null) 566 return ESBase.esNull; 567 568 Class cl = object.getClass(); 569 String clName = cl.getName(); 570 571 if (object instanceof ESBase) 572 return (ESBase) object; 573 if (clName.equals("java.lang.String")) 574 return new ESString(object.toString()); 575 if (clName.equals("java.lang.Double")) 576 return ESNumber.create(((Double ) object).doubleValue()); 577 if (clName.equals("java.util.Date")) 578 return convertDate(object); 579 580 ESBase wrapper; 581 synchronized (_staticWraps) { 582 wrapper = _staticWraps.get(cl); 583 } 584 585 if (wrapper == null || ((DynamicClassLoader) wrapper.getClass().getClassLoader()).isDestroyed()) { 586 ESBase []values = Wrapper.bean(this, cl); 587 588 if (values == null) 589 return ESBase.esNull; 590 591 ESBase clWrapper = values[0]; 592 wrapper = values[1]; 593 if (wrapper.getClass().getClassLoader().getParent().equals(getClass().getClassLoader())) { 594 synchronized (_staticWraps) { 595 _staticClassWraps.put(cl, clWrapper); 596 _staticWraps.put(cl, wrapper); 597 } 598 } 599 } 600 601 if (wrapper instanceof ESJavaWrapper) 602 return ((ESJavaWrapper) wrapper).wrap(object); 603 else { 604 return ((ESBeanWrapper) wrapper).wrap(object); 605 } 606 } 607 608 private ESBase convertDate(Object object) 609 { 610 return ESDate.create(((Date ) object).getTime()); 611 } 612 613 public static ESBase wrap(Object object) 615 throws Throwable 616 { 617 return getGlobalProto().objectWrap(object); 618 } 619 620 ESBase classWrap(Class cl) 621 throws Throwable 622 { 623 if (cl == null) 624 throw new RuntimeException (); 625 626 ESBase clWrapper; 627 628 synchronized (_staticWraps) { 629 clWrapper = _staticClassWraps.get(cl); 630 } 631 632 if (clWrapper == null || ((DynamicClassLoader) clWrapper.getClass().getClassLoader()).isDestroyed()) { 633 ESBase []values = Wrapper.bean(this, cl); 634 clWrapper = values[0]; 635 ESBase wrapper = values[1]; 636 637 synchronized (_staticWraps) { 638 _staticWraps.put(cl, wrapper); 639 _staticClassWraps.put(cl, clWrapper); 640 } 641 } 642 643 return clWrapper; 644 } 645 646 public ClassLoader getClassLoader() 647 { 648 return loader != null ? loader : root.loader; 649 } 650 651 public ClassLoader getParentLoader() 652 { 653 return parentLoader != null ? parentLoader : root.parentLoader; 654 } 655 656 public Path getClassDir() 657 { 658 return classDir != null ? classDir : root.classDir; 659 } 660 661 public Path getScriptPath() 662 { 663 return scriptPath != null ? scriptPath : root.scriptPath; 664 } 665 666 public void importScript(ESObject global, String name) 667 throws Throwable 668 { 669 if (importScripts == null) { 670 importScripts = new HashMap (); 671 importGlobals = new HashMap (); 672 } 673 674 ESGlobal scriptGlobal = (ESGlobal) importGlobals.get(name); 675 676 if (scriptGlobal == null) { 677 if (importScripts.get(name) != null) 678 return; 679 680 Parser parser = new Parser(); 681 parser.setScriptPath(getScriptPath()); 682 parser.setClassLoader(getClassLoader()); 683 parser.setWorkDir(getClassDir()); 684 685 Script script = parser.parse(name); 686 687 importScripts.put(name, script); 688 689 scriptGlobal = script.initClass(this); 690 691 importGlobals.put(name, scriptGlobal); 692 693 scriptGlobal.execute(); 694 } 695 696 scriptGlobal.export(global); 697 } 698 699 ESGlobal getGlobal() 700 { 701 return global; 702 } 703 704 public void setGlobal(ESGlobal global) 705 { 706 this.global = global; 707 } 708 709 public Object toJavaObject() 710 throws ESException 711 { 712 Object o = prototype.toJavaObject(); 713 return (o == null) ? this : o; 714 } 715 716 720 721 public ESObject createObject() 722 { 723 return new ESObject("Object", objProto); 724 } 725 726 730 ESArray createArray() 731 { 732 ESArray array = new ESArray(); 733 734 array.prototype = arrayProto; 735 736 return array; 737 } 738 739 void clearMark() 740 { 741 markCount = 0; 742 } 743 744 int addMark() 745 { 746 return ++markCount; 747 } 748 } 749 | Popular Tags |