KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > es > Global


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

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 JavaDoc;
43 import java.util.Date JavaDoc;
44 import java.util.HashMap JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46
47 /**
48  * Implementation class for the global prototype
49  */

50 public class Global extends ESBase {
51   private static Integer JavaDoc LOCK = new Integer JavaDoc(0);
52   private static final Logger JavaDoc 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 JavaDoc properties;
103   HashMap JavaDoc globalProperties;
104
105   // static lookup of current Global
106

107   private static final ThreadLocal JavaDoc<Global> _globals
108     = new ThreadLocal JavaDoc<Global>();
109   
110   private static Thread JavaDoc lastThread;
111   private static Global lastGlobal;
112
113   // bean wrapping
114

115   private final static LruCache<Class JavaDoc,ESBase> _staticWraps
116     = new LruCache<Class JavaDoc,ESBase>(256);
117   private final static LruCache<Class JavaDoc,ESBase> _staticClassWraps
118     = new LruCache<Class JavaDoc,ESBase>(256);
119
120   // cache
121

122   private static FreeList<Call> _freeCalls = new FreeList<Call>(2);
123   
124   private static HashMap JavaDoc<String JavaDoc,SoftReference JavaDoc<Script>> _runtimeScripts;
125   /* = new HashMap<String,SoftReference<Script>>(); */
126
127   private ClassLoader JavaDoc parentLoader;
128   private ClassLoader JavaDoc loader;
129   private Path scriptPath;
130   private Path classDir;
131   private HashMap JavaDoc importScripts;
132   private HashMap JavaDoc importGlobals;
133   
134   int markCount;
135
136   /**
137    * Null constructor
138    */

139   private Global(boolean init)
140   {
141     ESBase.init(null);
142
143     /*
144     if (_globals == null) {
145       _globals = new ThreadLocal();
146       _staticWraps = new LruCache<Class,ESBase>(256);
147       _staticClassWraps = new LruCache<Class,ESBase>(256);
148       ESId.intern("foo"); // XXX: bogus to fix stupid kaffe static init.
149     }
150     */

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 JavaDoc();
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   /**
195    * Creates a new global object for a script thread.
196    *
197    * @param properties any global properties for the script
198    * @param proto a Java prototype object underlying the global object
199    * @param classDir work directory where generated classes will go
200    * @param scriptPath a path for searching scripts
201    * @param parentLoader the parent class loader.
202    */

203   Global(HashMap JavaDoc properties, Object JavaDoc proto,
204          Path classDir, Path scriptPath, ClassLoader JavaDoc parentLoader)
205     throws Throwable JavaDoc
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     // Object
219
objProto = (ESObject) goldGlobal.objProto.resinCopy();
220     object = (ESObject) goldGlobal.object.resinCopy();
221
222     // Function
223

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     // Array
232

233     arrayProto = (ESObject) goldGlobal.arrayProto.resinCopy();
234     arrayProto.prototype = objProto;
235
236     array = (ESObject) goldGlobal.array.resinCopy();
237     array.prototype = funProto;
238
239     // String
240

241     stringProto = (ESObject) goldGlobal.stringProto.resinCopy();
242     stringProto.prototype = objProto;
243       
244     string = (ESObject) goldGlobal.string.resinCopy();
245     string.prototype = funProto;
246
247     // Boolean
248

249     boolProto = (ESObject) goldGlobal.boolProto.resinCopy();
250     boolProto.prototype = objProto;
251       
252     bool = (ESObject) goldGlobal.bool.resinCopy();
253     bool.prototype = funProto;
254
255     // Number
256

257     numProto = (ESObject) goldGlobal.numProto.resinCopy();
258     numProto.prototype = objProto;
259       
260     num = (ESObject) goldGlobal.num.resinCopy();
261     num.prototype = funProto;
262
263     // Math
264

265     math = (ESObject) goldGlobal.math.resinCopy();
266     math.prototype = objProto;
267
268     // Date
269

270     dateProto = (ESObject) goldGlobal.dateProto.resinCopy();
271     dateProto.prototype = objProto;
272       
273     date = (ESObject) goldGlobal.date.resinCopy();
274     date.prototype = funProto;
275
276     // RegExp
277

278     //regexpProto = (ESRegexp) goldGlobal.regexpProto.resinCopy();
279
//regexpProto.prototype = objProto;
280

281     //regExp = (ESRegexpWrapper) goldGlobal.regExp.resinCopy();
282
//regExp.prototype = funProto;
283
//regExp.regexp = regexpProto;
284

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 JavaDoc
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 JavaDoc 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 JavaDoc();
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   /**
449    * Sets a running script.
450    *
451    * @param name classname of the script.
452    * @param script the script itself.
453    */

454   public void addScript(String JavaDoc name, Script script)
455   {
456     if (_runtimeScripts != null)
457       _runtimeScripts.put(name, new SoftReference JavaDoc<Script>(script));
458   }
459
460   /**
461    * Returns the line map for the named class to translate Java line
462    * numbers to javascript line numbers.
463    *
464    * @param className class throwing the error.
465    * @return the line map.
466    */

467   LineMap getLineMap(String JavaDoc 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 JavaDoc<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 JavaDoc e) {
489       return null;
490     }
491   }
492
493   /**
494    * Returns the named script. If the script has already been loaded,
495    * return the old script.
496    */

497   Script findScript(String JavaDoc className)
498     throws Throwable JavaDoc
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   /**
514    * Returns the global prototype for the current thread.
515    */

516   public static Global getGlobalProto()
517   {
518     return (Global) _globals.get();
519   }
520
521   /**
522    * Starts execution of a JavaScript thread.
523    *
524    * @return the old global context for the thread.
525    */

526   Global begin()
527   {
528     Global oldGlobal = (Global) _globals.get();
529     _globals.set(this);
530
531     return oldGlobal;
532   }
533
534   /**
535    * Completes execution of a JavaScript thread, restoring the global context.
536    *
537    * @param oldGlobal the old global context for the thread.
538    */

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 JavaDoc object)
563     throws Throwable JavaDoc
564   {
565     if (object == null)
566       return ESBase.esNull;
567
568     Class JavaDoc cl = object.getClass();
569     String JavaDoc 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 JavaDoc) 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 JavaDoc object)
609   {
610     return ESDate.create(((Date JavaDoc) object).getTime());
611   }
612
613   // XXX: backwards -- s/b wrap and staticWrap
614
public static ESBase wrap(Object JavaDoc object)
615     throws Throwable JavaDoc
616   {
617     return getGlobalProto().objectWrap(object);
618   }
619
620   ESBase classWrap(Class JavaDoc cl)
621     throws Throwable JavaDoc
622   {
623     if (cl == null)
624       throw new RuntimeException JavaDoc();
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 JavaDoc getClassLoader()
647   {
648     return loader != null ? loader : root.loader;
649   }
650
651   public ClassLoader JavaDoc 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 JavaDoc name)
667     throws Throwable JavaDoc
668   {
669     if (importScripts == null) {
670       importScripts = new HashMap JavaDoc();
671       importGlobals = new HashMap JavaDoc();
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 JavaDoc toJavaObject()
710     throws ESException
711   {
712     Object JavaDoc o = prototype.toJavaObject();
713     return (o == null) ? this : o;
714   }
715
716   /*
717    * Somewhat bogus for creating based on globals.
718    * "this" is the global
719    */

720
721   public ESObject createObject()
722   {
723     return new ESObject("Object", objProto);
724   }
725   
726   /**
727    * Somewhat bogus for creating based on globals.
728    * "this" is the global
729    */

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