3 // latest author: Bob Hanson, St. Olaf College, hansonr@stolaf.edu
5 // Requires JSmolCore.js and (for now; probably) JSmol.js
6 // This version of j2slib requires jQuery and works in both Chrome and MSIE locally,
7 // though Chrome cannot read local data files, and MSIE cannot read local binary data files.
9 // Java programming notes by Bob Hanson:
11 // There are a few motifs to avoid when optimizing Java code to work smoothly
12 // with the J2S compiler:
16 // 1. an array with null elements cannot be typed and must be avoided.
17 // 2. instances of Java "instance of" involving arrays must be found and convered to calls to Clazz.isA...
18 // 3. new int[n][] must not be used. Use instead JU.AU.newInt2(n);
19 // 4. new int[] { 1, 2, 3 } has problems because it creates simply [ ] and not IntArray32
23 // 1. Remember that EVERY number in JavaScript is a double -- doesn't matter if it is in IntArray32 or not.
24 // 2. You cannot reliably use Java long, because doubles consume bits for the exponent which cannot be tested.
25 // 3. Bit 31 of an integer is unreliable, since (int) -1 is now , not just 0zFFFFFFFF, and
26 // FFFFFFFF + 1 = 100000000, not 0. In JavaScript, 0xFFFFFFFF is 4294967295, not -1.
27 // This means that writeInt(b) will fail if b is negative. What you need is instead
28 // writeInt((int)(b & 0xFFFFFFFFl) so that JavaScript knocks off the high bits explicitly.
32 // 1. j2sRequireImport xxxx is needed if xxxx is a method used in a static function
33 // 2. URL.getContent() is not supported. Use other means based on URL.toString()
34 // 3. It is critical for performance to avoid any significant amount of function overloading.
35 // In particular, methods such as xxx(int a, int b) and xxx(float a, int b) MUST be renamed,
36 // because JavaScript only has Number, and there is absolutely no way to tell these apart.
37 // It's probably bad Java programming, anyway.
38 // 4. Calls to super(...) can almost always be avoided. These trigger the SAEM
39 // (searchAndExecuteMethod) call, and it is very destructive to performance.
40 // Just find another way to do it.
42 // NOTES by Bob Hanson:
46 // BH 7/18/2015 4:43:38 PM better handling of TypeError and InternalError for e.getMessage() and e.getStackTrace()
47 // BH 7/17/2015 11:51:15 AM adds class.getResource(name) and class.getResourceAsStream(name)
48 // BH 7/16/2015 7:56:49 PM general instantiation using any constructor (in Java here):
49 // BH x = class.forName("my.class.name").newInstance()
51 // BH x = class.forName("my.class.name").getConstructor(String.class,String.class).newInstance(new Object[] {"test", "now"})
52 // BH 7/15/2015 11:34:58 PM adding System.lineSeparator()
53 // BH 7/15/2015 7:32:41 AM adding class.getCanonicalName == getName
54 // BH 5/31/2015 5:38:14 PM NPEExceptionPredicate fix
55 // BH 4/25/2015 9:16:12 AM SAEM misrepresnting Number as Object in parameters and Integer as Number
56 // BH 4/24/2015 7:32:54 AM Object.hashCode() and System.getIdentityHashCode() fail. changed to: return this._$hashcode || (this._$hashcode = ++Clazz._hashCode)
57 // BH 4/23/2015 9:08:59 AM Clazz.instanceOf(a, b) needs to check for a == b.
58 // BH 4/23/2015 9:08:59 AM xx.getContentType() is nonfunctional. Array.newInstance now defines a wrapper for .getClass().getComponentType() that works
59 // BH 4/12/2015 11:48:03 AM added Clazz.getStackTrace(-n) -- reports actual parameter values for n levels
60 // BH 4/10/2015 8:23:05 AM adding Int32Array.prototype.clone and Float64.prototype.clone
61 // BH 4/5/2015 8:12:57 AM refactoring j2slib (this file) to make private functions really private using var
62 // BH 4/3/2015 6:14:34 AM adding anonymous local "ClazzLoader" (Clazz._Loader) --> "_Loader"
63 // BH 4/3/2015 6:14:34 AM adding Clazz._Loader._classPending, Clazz._Loader._classCount
64 // BH 4/3/2015 6:14:34 AM adding Clazz._Loader._checkLoad
65 // -- forces asynchronous class loading
66 // -- builds Clazz._Loader._classPending and Clazz._classCount
67 // -- allows reporting
69 // BH 3/24/2015 4:11:26 AM better file load failure message in _Loader.evaluate
70 // BH 2/28/2015 7:30:25 AM corrects newIntArray32() and newArray() for pre-defined arrays
71 // int[] a = new int[] {1,2,3,343};
72 // int[][] b = new int[][] {new int[]{4,5},new int[]{5,6}};
74 // BH 9/29/2014 11:34:19 PM removing support for getClass().isArray()
75 // BH 8/29/2014 9:15:57 AM total reworking of Java2Script in preparation for all-asynchronous loading
76 // (currently sync loading is only for
77 // LOAD command and load() function without ASYNC
79 // see JSmol.js and Jmol._isAsync flag
80 // BH 5/11/2015 5:58:42 AM adding __signatures for debugging SAEM issues
81 // BH 3/29/2015 8:12:44 PM System.getProperty(x, "") does not return ""
82 // BH 8/23/2014 10:04:19 AM cleaning up a few general methods; Clazz.removeArrayItem
83 // BH 6/1/2014 10:58:46 AM fix for Clazz.isAP() not working
84 // BH 5/26/2014 5:19:29 PM removing superConstructor call in creating Enum constants
85 // BH 4/1/2014 7:55:54 PM removing all $fz references and instances where sub/super classes have same private function names
86 // BH 4/1/2014 4:47:30 PM all $_X removed; this is taken care of by Google Closure Compiler
87 // BH 4/1/2014 6:40:08 AM removing ClassLoader -- equals Clazz._Loader
88 // BH 4/1/2014 6:40:08 AM removing ClassLoaderProgressMonitor -- equals _LoaderProgressMonitor
89 // BH 4/1/2014 6:17:21 AM removing Class -- only used for "Class.forName" in Jmol, which ANT will now change to "Clazz._4Name"
90 // BH 3/7/2014 9:05:06 AM Array.prototype.toString should not be aliased. -- http://sourceforge.net/p/jmol/bugs/560/ with Google Visualization
92 // BH 1/30/2014 12:54:22 PM gave all field variables prefix underscore. This allows Google Closure Compiler to skip them.
93 // BH 12/3/2013 3:39:57 PM window["j2s.lib"].base implemented
94 // BH 12/1/2013 5:34:21 AM removed _LoaderProgressMonitor.initialize and all Clazz.event business; handled by Jmol.clearVars()
95 // BH 11/30/2013 12:43:58 PM adding Clazz.arrayIs() -- avoids Number.constructor.toString() infinite recursion
96 // BH 11/29/2013 6:33:51 AM adding Clazz._profiler -- reports use of SAEM
97 // BH 11/10/2013 9:02:20 AM fixing fading in MSIE
98 // BH 11/3/2013 7:21:39 AM additional wrapping functions for better compressibility
99 // BH 10/30/2013 8:10:58 AM added getClass().getResource() -- returning a relative string, not a URL
100 // BH 10/30/2013 6:43:00 AM removed second System def and added System.$props and default System.property "line.separator"
101 // BH 6/15/2013 8:02:07 AM corrections to Class.isAS to return true if first element is null
102 // BH 6/14/2013 4:41:09 PM corrections to Clazz.isAI and related methods to include check for null object
103 // BH 3/17/2013 11:54:28 AM adds stackTrace for ERROR
105 // BH 3/13/2013 6:58:26 PM adds Clazz.clone(me) for BS clone
106 // BH 3/12/2013 6:30:53 AM fixes Clazz.exceptionOf for ERROR condition trapping
107 // BH 3/2/2013 9:09:53 AM delete globals c$ and $fz
108 // BH 3/2/2013 9:10:45 AM optimizing defineMethod using "look no further" "@" parameter designation (see "\\@" below -- removed 3/23/13)
109 // BH 2/27/2013 optimizing Clazz.getParamsType for common cases () and (Number)
110 // BH 2/27/2013 optimizing SAEM delegation for hashCode and equals -- disallows overloading of equals(Object)
112 // BH 2/23/2013 found String.replaceAll does not work -- solution was to never call it.
113 // BH 2/9/2013 9:18:03 PM Int32Array/Float64Array fixed for MSIE9
114 // BH 1/25/2013 1:55:31 AM moved package.js from j2s/java to j2s/core
115 // BH 1/17/2013 4:37:17 PM String.compareTo() added
116 // BH 1/17/2013 4:52:22 PM Int32Array and Float64Array may not have .prototype.sort method
117 // BH 1/16/2013 6:20:34 PM Float64Array not available in Safari 5.1
118 // BH 1/14/2013 11:28:58 PM Going to all doubles in JavaScript (Float64Array, not Float32Array)
119 // so that (new float[] {13.48f})[0] == 13.48f, effectively
121 // BH 1/14/2013 12:53:41 AM Fix for Opera 10 not loading any files
122 // BH 1/13/2013 11:50:11 PM Fix for MSIE not loading (nonbinary) files locally
124 // BH 12/1/2012 9:52:26 AM Compiler note: Thread.start() cannot be executed within the constructor;
126 // BH 11/24/2012 11:08:39 AM removed unneeded sections
127 // BH 11/24/2012 10:23:22 AM all XHR uses sync loading (_Loader.setLoadingMode)
128 // BH 11/21/2012 7:30:06 PM if (base) map["@" + pkg] = base; critical for multiple applets
130 // BH 10/8/2012 3:27:41 PM if (clazzName.indexOf("Array") >= 0) return "Array"; in Clazz.getClassName for function
131 // BH removed Clazz.ie$plit = "\\2".split (/\\/).length == 1; unnecessary; using RegEx slows process significantly in all browsers
132 // BH 10/6/12 added Int32Array, Float32Array, newArrayBH, upgraded java.lang and java.io
133 // BH added Integer.bitCount in core.z.js
134 // BH changed alert to Clazz.alert in java.lang.Class.js *.ClassLoader.js, java.lang.thread.js
135 // BH removed toString from innerFunctionNames due to infinite recursion
136 // BH note: Logger.error(null, e) does not work -- get no constructor for (String) (TypeError)
137 // BH added j2s.lib.console
138 // BH allowed for alias="."
139 // BH removed alert def --> Clazz.alert
140 // BH added wrapper at line 2856
141 // BH newArray fix at line 2205
142 // BH System.getProperty fix at line 6693
143 // BH added Enum .value() method at line 2183
144 // BH added System.getSecurityManager() at end
145 // BH added String.contains() at end
146 // BH added System.gc() at end
147 // BH added Clazz.exceptionOf = updated
148 // BH added String.getBytes() at end
151 LoadClazz = function() {
153 // BH This is the ONLY global used in J2S now. I do not think it is necessary,
154 // but it is created by the compiler, and I have not found a work-around.
155 // it is used as a local variable in class definitions to point to the
156 // current method. See Clazz.p0p and Clazz.pu$h
160 if (!window["j2s.clazzloaded"])
161 window["j2s.clazzloaded"] = false;
163 if (window["j2s.clazzloaded"])return;
165 window["j2s.clazzloaded"] = true;
167 window["j2s.object.native"] = true;
171 /* http://j2s.sf.net/ *//******************************************************************************
172 * Copyright (c) 2007 java2script.org and others.
173 * All rights reserved. This program and the accompanying materials
174 * are made available under the terms of the Eclipse Public License v1.0
175 * which accompanies this distribution, and is available at
176 * http://www.eclipse.org/legal/epl-v10.html
179 * Zhou Renjian - initial API and implementation
180 *****************************************************************************/
182 * @author zhou renjian
183 * @create Nov 5, 2005
188 * Class Clazz. All the methods are static in this class.
191 /*Class = */ Clazz = {
195 ;(function(Clazz, Jmol) {
197 var __debuggingBH = false;
198 var _globals = ["j2s.clazzloaded", "j2s.object.native"];
199 Clazz.setGlobal = function(a, v) {
204 Clazz.getGlobals = function() {
205 return _globals.sort().join("\n");
208 Clazz.setConsoleDiv = function(d) {
209 window["j2s.lib"] && (window["j2s.lib"].console = d);
212 // BH Clazz.getProfile monitors exactly what is being delegated with SAEM,
213 // which could be a bottle-neck for function calling.
214 // This is critical for performance optimization.
218 var _profile = (window["j2s.doProfile"] && self.JSON ? {} : null);
220 NullObject = function () {};
223 Clazz._supportsNativeObject = window["j2s.object.native"];
225 if (Clazz._supportsNativeObject) {
226 Clazz._O = function () {};
227 Clazz._O.__CLASS_NAME__ = "Object";
228 Clazz._O["getClass"] = function () { return Clazz._O; };
234 Clazz.dateToString = Date.prototype.toString;
237 var addProto = function(proto, name, func) {
238 return proto[name] = func;
242 addProto(proto, "equals", function (obj) {
246 addProto(proto, "hashCode", function () {
248 return this._$hashcode || (this._$hashcode = ++Clazz._hashCode)
252 return this.toString ().hashCode ();
255 for (var s in this) {
258 return str.hashCode ();
262 addProto(proto, "getClass", function () { return Clazz.getClass (this); });
264 addProto(proto, "clone", function () { return Clazz.clone(this); });
266 Clazz.clone = function(me) {
267 // BH allows @j2sNative access without super constructor
268 var o = new me.constructor();
275 * Methods for thread in Object
277 addProto(proto, "finalize", function () {});
278 addProto(proto, "notify", function () {});
279 addProto(proto, "notifyAll", function () {});
280 addProto(proto, "wait", function () {});
281 addProto(proto, "to$tring", Object.prototype.toString);
282 addProto(proto, "toString", function () { return (this.__CLASS_NAME__ ? "[" + this.__CLASS_NAME__ + " object]" : this.to$tring.apply(this, arguments)); });
283 Clazz._extendedObjectMethods = [ "equals", "hashCode", "getClass", "clone", "finalize", "notify", "notifyAll", "wait", "to$tring", "toString" ];
285 })(Clazz._O.prototype);
287 Clazz.extendJO = function(c, name) {
289 c.__CLASS_NAME__ = c.prototype.__CLASS_NAME__ = name;
290 if (Clazz._supportsNativeObject) {
291 for (var i = 0; i < Clazz._extendedObjectMethods.length; i++) {
292 var p = Clazz._extendedObjectMethods[i];
293 addProto(c.prototype, p, Clazz._O.prototype[p]);
299 * Try to fix bug on Safari
301 //InternalFunction = Object;
303 Clazz.extractClassName = function(clazzStr) {
304 // [object Int32Array]
305 var clazzName = clazzStr.substring (1, clazzStr.length - 1);
306 return (clazzName.indexOf("Array") >= 0 ? "Array" // BH -- for Float64Array and Int32Array
307 : clazzName.indexOf ("object ") >= 0 ? clazzName.substring (7) // IE
311 * Return the class name of the given class or object.
313 * @param clazzHost given class or object
317 Clazz.getClassName = function (obj) {
320 if (obj instanceof Clazz.CastedNull)
321 return obj.clazzName;
328 // Always treat the constant string as String object.
329 // This will be compatiable with Java String instance.
332 if (obj.__CLASS_NAME__)
333 return (arguments[1] ? obj.__CLASS_NAME__ : "Class"); /* user defined class name */
334 var s = obj.toString();
335 var idx0 = s.indexOf("function");
337 return (s.charAt(0) == '[' ? Clazz.extractClassName(s) : s.replace(/[^a-zA-Z0-9]/g, ''));
339 var idx2 = s.indexOf ("(", idx1);
342 s = s.substring (idx1, idx2);
343 if (s.indexOf("Array") >= 0)
345 s = s.replace (/^\s+/, "").replace (/\s+$/, "");
346 return (s == "anonymous" || s == "" ? "Function" : s);
348 if (obj.__CLASS_NAME__) // user defined class name
349 return obj.__CLASS_NAME__;
350 if (!obj.constructor)
351 return "Object"; // For HTML Element in IE
352 if (!obj.constructor.__CLASS_NAME__) {
353 if (obj instanceof Number)
355 if (obj instanceof Boolean)
357 if (obj instanceof Array)
359 var s = obj.toString();
360 // "[object Int32Array]"
361 if (s.charAt(0) == '[')
362 return Clazz.extractClassName(s);
364 return Clazz.getClassName (obj.constructor, true);
366 // some new, unidentified class
370 * Return the class of the given class or object.
372 * @param clazzHost given class or object
376 Clazz.getClass = function (clazzHost) {
378 return Clazz._O; // null/undefined is always treated as Object
379 if (typeof clazzHost == "function")
382 if (clazzHost instanceof Clazz.CastedNull) {
383 clazzName = clazzHost.clazzName;
385 switch (typeof clazzHost) {
389 if (!clazzHost.__CLASS_NAME__)
390 return (clazzHost.constructor || Clazz._O);
391 clazzName = clazzHost.__CLASS_NAME__;
394 return clazzHost.constructor;
397 return Clazz.evalType(clazzName, true);
402 var checkInnerFunction = function (hostSuper, funName) {
403 for (var k = 0; k < Clazz.innerFunctionNames.length; k++)
404 if (funName == Clazz.innerFunctionNames[k] &&
405 Clazz._innerFunctions[funName] === hostSuper[funName])
410 var args4InheritClass = function () {};
412 Clazz.inheritArgs = new args4InheritClass ();
415 * Inherit class with "extends" keyword and also copy those static members.
416 * Example, as in Java, if NAME is a static member of ClassA, and ClassB
417 * extends ClassA then ClassB.NAME can be accessed in some ways.
419 * @param clazzThis child class to be extended
420 * @param clazzSuper super class which is inherited from
421 * @param objSuper super class instance
424 Clazz.inheritClass = function (clazzThis, clazzSuper, objSuper) {
425 //var thisClassName = Clazz.getClassName (clazzThis);
426 for (var o in clazzSuper) {
427 if (o != "b$" && o != "prototype" && o != "superClazz"
428 && o != "__CLASS_NAME__" && o != "implementz"
429 && !checkInnerFunction (clazzSuper, o)) {
430 clazzThis[o] = clazzSuper[o];
433 if (Clazz.unloadedClasses[Clazz.getClassName(clazzThis, true)]) {
434 // Don't change clazzThis.protoype! Keep it!
435 } else if (objSuper) {
436 // ! Unsafe reference prototype to an instance!
437 // Feb 19, 2006 --josson
438 // OK for this reference to an instance, as this is anonymous instance,
439 // which is not referenced elsewhere.
441 clazzThis.prototype = objSuper;
442 } else if (clazzSuper !== Number) {
443 clazzThis.prototype = new clazzSuper (Clazz.inheritArgs);
445 clazzThis.prototype = new Number ();
447 clazzThis.superClazz = clazzSuper;
449 * Is it necessary to reassign the class name?
450 * Mar 10, 2006 --josson
452 //clazzThis.__CLASS_NAME__ = thisClassName;
453 clazzThis.prototype.__CLASS_NAME__ = clazzThis.__CLASS_NAME__;
457 * Implementation of Java's keyword "implements".
458 * As in JavaScript there are on "implements" keyword implemented, a property
459 * of "implementz" is added to the class to record the interfaces the class
462 * @param clazzThis the class to implement
463 * @param interfacez Array of interfaces
466 Clazz.implementOf = function (clazzThis, interfacez) {
467 if (arguments.length >= 2) {
468 if (!clazzThis.implementz)
469 clazzThis.implementz = [];
470 var impls = clazzThis.implementz;
471 if (arguments.length == 2) {
472 if (typeof interfacez == "function") {
473 impls.push(interfacez);
474 copyProperties(clazzThis, interfacez);
475 } else if (interfacez instanceof Array) {
476 for (var i = 0; i < interfacez.length; i++) {
477 impls.push(interfacez[i]);
478 copyProperties(clazzThis, interfacez[i]);
482 for (var i = 1; i < arguments.length; i++) {
483 impls.push(arguments[i]);
484 copyProperties(clazzThis, arguments[i]);
491 * Copy members of interface
494 var copyProperties = function(clazzThis, clazzSuper) {
495 for (var o in clazzSuper)
497 && o != "prototype" && o != "superClazz"
498 && o != "__CLASS_NAME__" && o != "implementz"
499 && (typeof clazzSuper[o] != "function" || !checkInnerFunction(clazzSuper, o)))
500 clazzThis[o] = clazzThis.prototype[o] = clazzSuper[o];
504 * TODO: More should be done for interface's inheritance
507 Clazz.extendInterface = Clazz.implementOf;
510 Clazz.equalsOrExtendsLevel = function (clazzThis, clazzAncestor) {
511 if (clazzThis === clazzAncestor)
513 if (clazzThis.implementz) {
514 var impls = clazzThis.implementz;
515 for (var i = 0; i < impls.length; i++) {
516 var level = Clazz.equalsOrExtendsLevel (impls[i], clazzAncestor);
525 Clazz.getInheritedLevel = function (clazzTarget, clazzBase) {
526 if (clazzTarget === clazzBase)
528 var isTgtStr = (typeof clazzTarget == "string");
529 if (isTgtStr && ("void" == clazzTarget || "unknown" == clazzTarget))
531 var isBaseStr = (typeof clazzBase == "string");
532 if (isBaseStr && ("void" == clazzBase || "unknown" == clazzBase))
534 if (clazzTarget === (isTgtStr ? "NullObject" : NullObject)) {
545 clazzTarget = Clazz.evalType(clazzTarget);
547 clazzBase = Clazz.evalType(clazzBase);
548 if (!clazzBase || !clazzTarget)
551 var zzalc = clazzTarget; // zzalc <--> clazz
552 while (zzalc !== clazzBase && level < 10) {
553 /* maybe clazzBase is interface */
554 if (zzalc.implementz) {
555 var impls = zzalc.implementz;
556 for (var i = 0; i < impls.length; i++) {
557 var implsLevel = Clazz.equalsOrExtendsLevel (impls[i], clazzBase);
559 return level + implsLevel + 1;
562 zzalc = zzalc.superClazz;
564 return (clazzBase === Object || clazzBase === Clazz._O ?
565 // getInheritedLevel(String, CharSequence) == 1
566 // getInheritedLevel(String, Object) == 1.5
567 // So if both #test(CharSequence) and #test(Object) existed,
568 // #test("hello") will correctly call #test(CharSequence)
569 // instead of #test(Object).
570 level + 1.5 // 1.5! Special!
579 * Implements Java's keyword "instanceof" in JavaScript's way.
580 * As in JavaScript part of the object inheritance is implemented in only-
583 * @param obj the object to be tested
584 * @param clazz the class to be checked
585 * @return whether the object is an instance of the class
588 Clazz.instanceOf = function (obj, clazz) {
589 // allows obj to be a class already, from arrayX.getClass().isInstance(y)
590 return (obj != null && clazz && (obj == clazz || obj instanceof clazz || Clazz.getInheritedLevel(Clazz.getClassName(obj), clazz) >= 0));
594 * Call super method of the class.
595 * The same effect as Java's expression:
596 * <code> super.* () </code>
598 * @param objThis host object
599 * @param clazzThis class of declaring method scope. It's hard to determine
600 * which super class is right class for "super.*()" call when it's in runtime
601 * environment. For example,
602 * 1. ClasssA has method #run()
603 * 2. ClassB extends ClassA overriding method #run() with "super.run()" call
604 * 3. ClassC extends ClassB
605 * 4. objC is an instance of ClassC
606 * Now we have to decide which super #run() method is to be invoked. Without
607 * explicit clazzThis parameter, we only know that objC.getClass() is ClassC
608 * and current method scope is #run(). We do not known we are in scope
609 * ClassA#run() or scope of ClassB#run(). if ClassB is given, Clazz can search
610 * all super methods that are before ClassB and get the correct super method.
611 * This is the reason why there must be an extra clazzThis parameter.
612 * @param funName method name to be called
613 * @param funParams Array of method parameters
616 Clazz.superCall = function (objThis, clazzThis, funName, funParams) {
619 var clazzFun = objThis[funName];
621 if (clazzFun.claxxOwner) {
622 // claxxOwner is a mark for methods that is single.
623 if (clazzFun.claxxOwner !== clazzThis) {
624 // This is a single method, call directly!
628 } else if (!clazzFun.stacks && !(clazzFun.lastClaxxRef
629 && clazzFun.lastClaxxRef.prototype[funName]
630 && clazzFun.lastClaxxRef.prototype[funName].stacks)) { // super.toString
632 } else { // normal wrapped method
633 var stacks = clazzFun.stacks;
635 stacks = clazzFun.lastClaxxRef.prototype[funName].stacks;
636 for (i = stacks.length; --i >= 0;) {
638 * Once super call is computed precisely, there are no need
639 * to calculate the inherited level but just an equals
642 //var level = Clazz.getInheritedLevel (clazzThis, stacks[i]);
643 if (clazzThis === stacks[i]) { // level == 0
645 fx = stacks[--i].prototype[funName];
648 * Will this case be reachable?
650 * Should never reach here if all things are converted
653 fx = stacks[0].prototype[funName]["\\unknown"];
656 } else if (Clazz.getInheritedLevel (clazzThis, stacks[i]) > 0) {
657 fx = stacks[i].prototype[funName];
661 } // end of normal wrapped method
664 if (funName != "construct") {
665 Clazz.alert (["j2slib","no class found",(funParams).typeString])
666 throw new MethodNotFoundException(objThis, clazzThis, funName,
667 Clazz.getParamsType(funParams).typeString);
669 /* there are members which are initialized out of the constructor */
670 /* No super constructor! */
673 /* there are members which are initialized out of the constructor */
674 if (i == 0 && funName == "construct") {
675 var ss = clazzFun.stacks;
676 if (ss && !ss[0].superClazz && ss[0].con$truct)
677 ss[0].con$truct.apply (objThis, []);
679 /*# {$no.debug.support} >>x #*/
681 if (Clazz.tracingCalling) {
682 var caller = arguments.callee.caller;
683 if (caller === Clazz.superConstructor) {
684 caller = caller.arguments.callee.caller;
686 Clazz._callingStackTraces.push(new Clazz.callingStack (caller, clazzThis));
687 var ret = fx.apply (objThis, (funParams == null) ? [] : funParams);
688 Clazz._callingStackTraces.pop();
693 return fx.apply (objThis, funParams || []);
697 * Call super constructor of the class.
698 * The same effect as Java's expression:
699 * <code> super () </code>
702 Clazz.superConstructor = function (objThis, clazzThis, funParams) {
703 Clazz.superCall (objThis, clazzThis, "construct", funParams);
704 /* If there are members which are initialized out of the constructor */
705 if (clazzThis.con$truct) {
706 clazzThis.con$truct.apply (objThis, []);
711 * Class for null with a given class as to be casted.
712 * This class will be used as an implementation of Java's casting way.
714 * <code> this.call ((String) null); </code>
717 Clazz.CastedNull = function (asClazz) {
719 if (asClazz instanceof String) {
720 this.clazzName = asClazz;
721 } else if (asClazz instanceof Function) {
722 this.clazzName = Clazz.getClassName (asClazz, true);
724 this.clazzName = "" + asClazz;
727 this.clazzName = "Object";
729 this.toString = function () {
732 this.valueOf = function () {
738 * API for Java's casting null.
739 * @see Clazz.CastedNull
741 * @param asClazz given class
742 * @return an instance of class Clazz.CastedNull
745 Clazz.castNullAs = function (asClazz) {
746 return new Clazz.CastedNull (asClazz);
749 /////////////////////////// Exception handling ////////////////////////////
752 * Use to mark that the Throwable instance is created or not.
754 * Called from java.lang.Throwable, as defined in JSmolJavaExt.js
756 * The underscore is important - it tells the JSmol ANT task to NOT
757 * turn this into Clazz_initializingException, because coreBottom2.js does
758 * not include that call, and so Google Closure Compiler does not minify it.
762 Clazz._initializingException = false;
765 * BH: used in Throwable
769 Clazz._callingStackTraces = [];
772 * MethodException will be used as a signal to notify that the method is
773 * not found in the current clazz hierarchy.
776 var MethodException = function () {
777 this.toString = function () {
778 return "J2S MethodException";
782 var MethodNotFoundException = function () {
783 this.toString = function () {
784 return "J2S MethodNotFoundException";
788 var _isNPEExceptionPredicate;
792 /* sgurin: native exception detection mechanism. Only NullPointerException detected and wrapped to java excepions */
793 /** private utility method for creating a general regexp that can be used later
794 * for detecting a certain kind of native exceptions. use with error messages like "blabla IDENTIFIER blabla"
795 * @param msg String - the error message
796 * @param spliterName String, must be contained once in msg
797 * spliterRegex String, a string with the regexp literal for identifying the spitter in exception further error messages.
799 // reproduce NullPointerException for knowing how to detect them, and create detector function Clazz._isNPEExceptionPredicate
805 var _ex_reg = function(msg, spliterName, spliterRegex) {
807 spliterRegex="[^\\s]+";
808 var idx = msg.indexOf (spliterName),
809 str = msg.substring (0, idx) + spliterRegex + msg.substring(idx + spliterName.length),
810 regexp = new RegExp("^"+str+"$");
813 if(/Opera[\/\s](\d+\.\d+)/.test(navigator.userAgent)) {// opera throws an exception with fixed messages like "Statement on line 23: Cannot convert undefined or null to Object Backtrace: Line....long text... "
814 var idx1 = e.message.indexOf(":"), idx2 = e.message.indexOf(":", idx1+2);
815 var _NPEMsgFragment = e.message.substr(idx1+1, idx2-idx1-20);
816 _isNPEExceptionPredicate = function(e) { return e.message.indexOf(_NPEMsgFragment)!=-1; };
817 } else if(navigator.userAgent.toLowerCase().indexOf("webkit")!=-1) { //webkit, google chrome prints the property name accessed.
818 var _exceptionNPERegExp = _ex_reg(e.message, "hello");
819 _isNPEExceptionPredicate = function(e) { return _exceptionNPERegExp.test(e.message); };
820 } else {// ie, firefox and others print the name of the object accessed:
821 var _exceptionNPERegExp = _ex_reg(e.message, "$$o$$");
822 _isNPEExceptionPredicate = function(e) { return _exceptionNPERegExp.test(e.message); };
828 * Implements Java's keyword "instanceof" in JavaScript's way **for exception objects**.
830 * calls Clazz.instanceOf if e is a Java exception. If not, try to detect known native
831 * exceptions, like native NullPointerExceptions and wrap it into a Java exception and
832 * call Clazz.instanceOf again. if the native exception can't be wrapped, false is returned.
834 * @param obj the object to be tested
835 * @param clazz the class to be checked
836 * @return whether the object is an instance of the class
839 Clazz.exceptionOf = function(e, clazz) {
841 return Clazz.instanceOf(e, clazz);
843 e.getMessage = function() {return "" + this};
845 if (!e.printStackTrace) {
846 e.printStackTrace = function(){};
847 alert(e + " try/catch path:" + Clazz.getStackTrace(-5));
850 if (("" + e).indexOf("Error") < 0)
852 System.out.println (Clazz.getStackTrace());
854 // everything here is a Java Exception, not a Java Error
856 return (clazz == Exception || clazz == Throwable
857 || clazz == NullPointerException && _isNPEExceptionPredicate(e));
861 * BH need to limit this, as JavaScript call stack may be recursive
863 Clazz.getStackTrace = function(n) {
865 // updateNode and updateParents cause infinite loop here
867 var c = arguments.callee;
868 var showParams = (n < 0);
871 for (var i = 0; i < n; i++) {
874 var sig = (c.toString ? c.toString().substring(0, c.toString().indexOf("{")) : "<native method>");
875 s += i + " " + (c.exName ? (c.claxxOwner ? c.claxxOwner.__CLASS_NAME__ + "." : "") + c.exName + sig.replace(/function /,""): sig) + "\n";
877 s += "<recursing>\n";
881 var args = c.arguments;
882 for (var j = 0; j < args.length; j++) {
883 var sa = "" + args[j];
885 sa = sa.substring(0, 60) + "...";
886 s += " args[" + j + "]=" + sa.replace(/\s+/g," ") + "\n";
893 ///////////////////// method creation ////////////////////////////////
896 * Make constructor for the class with the given function body and parameters
899 * @param clazzThis host class
900 * @param funBody constructor body
901 * @param funParams constructor parameters signature
904 Clazz.makeConstructor = function (clazzThis, funBody, funParams) {
905 Clazz.defineMethod (clazzThis, "construct", funBody, funParams);
906 if (clazzThis.con$truct) {
907 clazzThis.con$truct.index = clazzThis.con$truct.stacks.length;
909 //clazzThis.con$truct = clazzThis.prototype.con$truct = null;
913 * Override constructor for the class with the given function body and
914 * parameters signature.
916 * @param clazzThis host class
917 * @param funBody constructor body
918 * @param funParams constructor parameters signature
921 Clazz.overrideConstructor = function (clazzThis, funBody, funParams) {
922 Clazz.overrideMethod (clazzThis, "construct", funBody, funParams);
923 if (clazzThis.con$truct) {
924 clazzThis.con$truct.index = clazzThis.con$truct.stacks.length;
926 //clazzThis.con$truct = clazzThis.prototype.con$truct = null;
931 * Define method for the class with the given method name and method
932 * body and method parameter signature.
934 * @param clazzThis host class in which the method to be defined
935 * @param funName method name
936 * @param funBody function object, e.g function () { ... }
937 * @param funParams paramether signature, e.g ["string", "number"]
938 * @return method of the given name. The method may be funBody or a wrapper
939 * of the given funBody.
942 Clazz.defineMethod = function (clazzThis, funName, funBody, funParams) {
943 if (Clazz.assureInnerClass)
944 Clazz.assureInnerClass(clazzThis, funBody);
945 funBody.exName = funName;
946 var fpName = formatParameters(funParams);
947 var proto = clazzThis.prototype;
948 var f$ = proto[funName];
949 if (Clazz._Loader._checkLoad)
950 checkDuplicate(clazzThis, funName, fpName);
951 if (!f$ || (f$.claxxOwner === clazzThis && f$.funParams == fpName)) {
952 // property "funParams" will be used as a mark of only-one method
953 funBody.funParams = fpName;
954 funBody.claxxOwner = clazzThis;
955 funBody.exClazz = clazzThis; // make it traceable
956 return addProto(proto, funName, funBody);
958 // we have found a duplicate
960 var oldStacks = f$.stacks;
962 /* method is not defined by Clazz.defineMethod () */
966 oldStacks[0] = oldFun.claxxOwner;
970 * Method that is already defined in super class will be overridden
971 * with a new proxy method with class hierarchy stored in a stack.
972 * That is to say, the super methods are lost in this class' proxy
974 * When method are being called, methods defined in the new proxy
975 * method will be searched through first. And if no method fitted,
976 * it will then try to search method in the super class stacks.
978 if (!f$.stacks || f$.claxxReference !== clazzThis) {
979 //Generate a new delegating method for the class
981 var delegate = function () {
982 return searchAndExecuteMethod(id, this, arguments.callee.claxxReference, arguments.callee.methodName, arguments);
984 delegate.methodName = funName;
985 delegate.claxxReference = clazzThis;
986 f$ = addProto(proto, funName, delegate);
987 // Keep the class inheritance stacks
989 for (var i = 0; i < oldStacks.length; i++)
990 arr[i] = oldStacks[i];
994 if (findArrayItem(ss, clazzThis) < 0) ss.push(clazzThis);
997 if (oldFun.claxxOwner === clazzThis) {
998 f$[oldFun.funParams] = oldFun;
999 oldFun.claxxOwner = null;
1000 // property "funParams" will be used as a mark of only-one method
1001 oldFun.funParams = null; // null ? safe ? // safe for != null
1002 } else if (!oldFun.claxxOwner) {
1004 * The function is not defined Clazz.defineMethod ().
1005 * Try to fixup the method ...
1006 * As a matter of lost method information, I just suppose
1007 * the method to be fixed is with void parameter!
1009 f$["\\unknown"] = oldFun;
1012 funBody.exClazz = clazzThis; // make it traceable
1013 f$[fpName] = funBody;
1017 duplicatedMethods = {};
1019 var checkDuplicate = function(clazzThis, funName, fpName) {
1020 var proto = clazzThis.prototype;
1021 var f$ = proto[funName];
1022 if (f$ && (f$.claxxOwner || f$.claxxReference) === clazzThis) {
1023 key = clazzThis.__CLASS_NAME__ + "." + funName + fpName;
1024 var m = duplicatedMethods[key];
1026 var s = "Warning! Duplicate method found for " + key;
1027 System.out.println(s);
1029 duplicatedMethods[key] = m + 1;
1031 duplicatedMethods[key] = 1;
1036 Clazz.showDuplicates = function(quiet) {
1038 var a = duplicatedMethods;
1042 s += a[key] + "\t" + key + "\n";
1045 s = "Duplicates: " + n + "\n\n" + s;
1046 System.out.println(s);
1051 var findArrayItem = function(arr, item) {
1053 for (var i = arr.length; --i >= 0;)
1054 if (arr[i] === item)
1059 var removeArrayItem = function(arr, item) {
1060 var i = findArrayItem(arr, item);
1062 var n = arr.length - 1;
1064 arr[i] = arr[i + 1];
1071 * Other developers may need to extend this formatParameters method
1072 * to deal complicated situation.
1075 var formatParameters = function (funParams) {
1076 return (funParams ? funParams.replace (/~([NABSO])/g,
1091 }).replace (/\s+/g, "").replace (/^|,/g, "\\").replace (/\$/g, "org.eclipse.s") : "\\void");
1095 * Override the existed methods which are in the same name.
1096 * Overriding methods is provided for the purpose that the JavaScript
1097 * does not need to search the whole hierarchied methods to find the
1098 * correct method to execute.
1099 * Be cautious about this method. Incorrectly using this method may
1100 * break the inheritance system.
1102 * @param clazzThis host class in which the method to be defined
1103 * @param funName method name
1104 * @param funBody function object, e.g function () { ... }
1105 * @param funParams paramether signature, e.g ["string", "number"]
1108 Clazz.overrideMethod = function(clazzThis, funName, funBody, funParams) {
1109 if (Clazz.assureInnerClass) Clazz.assureInnerClass (clazzThis, funBody);
1110 funBody.exName = funName;
1111 var fpName = formatParameters(funParams);
1112 if (Clazz._Loader._checkLoad)
1113 checkDuplicate(clazzThis, funName, fpName);
1115 * Replace old methods with new method. No super methods are kept.
1117 funBody.funParams = fpName;
1118 funBody.claxxOwner = clazzThis;
1119 return addProto(clazzThis.prototype, funName, funBody);
1122 ////////////// Overridden and Overloaded Java Method Handling //////////////////
1123 // SAEM (SearchAndExecuteMethod)
1128 * BH Clazz.getProfile monitors exactly what is being delegated with SAEM,
1129 * which could be a bottle-neck for function calling.
1130 * This is critical for performance optimization.
1133 var __signatures = "";
1135 Clazz.getProfile = function() {
1139 for (var i in _profile) {
1140 var n = "" + _profile[i];
1141 l.push(" ".substring(n.length) + n + "\t" + i);
1143 s = l.sort().reverse().join("\r\n");
1146 return s + __signatures;
1149 var addProfile = function(c, f, p, id) {
1150 var s = id + " " + c.__CLASS_NAME__ + " " + f + " ";// + JSON.stringify(p);
1151 if (__signatures.indexOf(s) < 0)
1152 __signatures += s + "\n";
1153 _profile[s] || (_profile[s] = 0);
1158 * Called also by Throwable
1161 Clazz.getParamsType = function (funParams) {
1162 // bh: optimization here for very common cases
1163 var n = funParams.length;
1166 var params = ["void"];
1167 params.typeString = "\\void";
1170 // BH just so common
1171 switch (typeof obj) {
1174 params.typeString = "\\n";
1178 params.typeString = "\\b";
1184 params.hasCastedNull = false;
1186 for (var i = 0; i < n; i++) {
1187 params[i] = Clazz.getClassName (funParams[i]);
1188 if (funParams[i] instanceof Clazz.CastedNull) {
1189 params.hasCastedNull = true;
1193 params.typeString = "\\" + params.join ('\\');
1198 //var SAEMarray = [];
1200 * BH: OK, this was an idea that doesn't work. The idea was to tag SAEM calls
1201 * and then refer back to an array. But the id number cannot be put in the right place.
1205 * StringBuffer sb = new StringBuffer();
1206 * sb.append("").append(1);
1208 * Here we have two different append methods to call. They are saved under two
1209 * names: StringBuffer.prototype.append["\\String"]
1210 * and StringBuffer.prototype.append["\\Number"]
1212 * The job of generateDelegatingMethod is to discriminate between those two. We can do
1213 * that, but the real issue is that we have to do that EVERY time a call is made.
1214 * This is a problem that must be handled at compile time. There is no way to
1215 * make .append("") to go one way the first time and another way the second time.
1216 * What we need at run time is something like this:
1218 * Clazz.delegate(sb.append,1,[""]) and Clazz.delegate(sb.append,2,[1])
1219 * The we would be able to log those numbers at run time and refer to them.
1221 * The only real way to avoid SAEM is:
1223 * 1) to never call super() -- always call a differently named function in a superclass.
1224 * 2) don't overload functions
1230 * Search the given class prototype, find the method with the same
1231 * method name and the same parameter signatures by the given
1232 * parameters, and then run the method with the given parameters.
1234 * @param objThis the current host object
1235 * @param claxxRef the current host object's class
1236 * @param fxName the method name
1237 * @param funParams the given arguments
1238 * @return the result of the specified method of the host object,
1239 * the return maybe void.
1240 * @throws MethodNotFoundException if no matched method is found
1243 var searchAndExecuteMethod = function (id, objThis, claxxRef, fxName, args) {
1245 // var fx = SAEMarray[id];
1247 // return fx.apply(objThis, args);
1250 fx = objThis[fxName];
1251 var params = Clazz.getParamsType(args);
1253 try {System.out.println(Clazz.getStackTrace(5))} catch (e){}
1254 _profile && addProfile(claxxRef, fxName, params, id);
1255 // Cache last matched method
1256 if (fx.lastParams == params.typeString && fx.lastClaxxRef === claxxRef) {
1258 if (params.hasCastedNull) {
1260 // For Clazz.CastedNull instances, the type name is
1261 // already used to indentified the method in searchMethod.
1262 for (var k = 0; k < args.length; k++)
1263 methodParams[k] = (args[k] instanceof Clazz.CastedNull ? null : args[k]);
1265 // if (fx.lastMethod) SAEMarray[id] = fx.lastMethod;
1266 methodParams = args;
1268 return (fx.lastMethod ? fx.lastMethod.apply(objThis, methodParams) : null);
1270 fx.lastParams = params.typeString;
1271 fx.lastClaxxRef = claxxRef;
1273 var stacks = fx.stacks;
1275 stacks = claxxRef.prototype[fxName].stacks;
1276 var length = stacks.length;
1279 * Search the inheritance stacks to get the given class' function
1281 var began = false; // began to search its super classes
1282 for (var i = length; --i >= 0;) {
1283 if (began || stacks[i] === claxxRef) {
1285 * First try to search method within the same class scope
1286 * with stacks[i] === claxxRef
1288 var clazzFun = stacks[i].prototype[fxName];
1289 var ret = tryToSearchAndExecute(id, fxName, objThis, clazzFun, params,
1291 if (!(ret instanceof MethodException)) {
1295 * As there are no such methods in current class, Clazz will try
1296 * to search its super class stacks. Here variable began indicates
1297 * that super searchi is began, and there is no need checking
1298 * <code>stacks[i] === claxxRef</code>
1303 if ("construct" == fxName) {
1305 * For non existed constructors, just return without throwing
1306 * exceptions. In Java codes, extending Object can call super
1307 * default Object#constructor, which is not defined in JS.
1311 // TODO: should be java.lang.NoSuchMethodException
1312 throw new MethodNotFoundException(objThis, claxxRef,
1313 fxName, params.typeString);
1318 var tryToSearchAndExecute = function(id, fxName, objThis, clazzFun, params, args, fx) {
1321 for (var fn in clazzFun) {
1322 if (fn.charCodeAt(0) == 92) { // 92 == '\\'.charCodeAt (0)
1323 var ps = fn.substring(1).split("\\");
1324 (ps.length == params.length) && method.push(ps);
1329 * When there is only one method in the class, use the args
1330 * to identify the parameter type.
1332 * AbstractCollection.remove (Object)
1333 * AbstractList.remove (int)
1334 * ArrayList.remove (int)
1336 * Then calling #remove (Object) method on ArrayList instance will
1337 * need to search up to the AbstractCollection.remove (Object),
1338 * which contains only one method.
1341 * See Clazz#defineMethod --Mar 10, 2006, josson
1343 if (generic && fn == "funParams" && clazzFun.funParams) {
1344 fn = clazzFun.funParams;
1345 var ps = fn.substring(1).split ("\\");
1346 (ps.length == params.length) && (method[0] = ps);
1350 if (method.length == 0 || !(method = searchMethod(method, params)))
1351 return new MethodException();
1352 var f = (generic ? clazzFun : clazzFun["\\" + method]);
1354 //{ /* Use the generic method */
1356 * Will this case be reachable?
1357 * March 4, 2006 josson
1359 * Reachable for calling #remove (Object) method on
1360 * ArrayList instance
1361 * May 5, 2006 josson
1363 var methodParams = null;
1364 if (params.hasCastedNull) {
1366 for (var k = 0; k < args.length; k++) {
1367 if (args[k] instanceof Clazz.CastedNull) {
1369 * For Clazz.CastedNull instances, the type name is
1370 * already used to indentify the method in searchMethod.
1372 methodParams[k] = null;
1374 methodParams[k] = args[k];
1378 methodParams = args;
1381 //if (!params.hasCastedNull) SAEMarray[id] = f;
1382 return f.apply(objThis, methodParams);
1386 * Search the existed polymorphic methods to get the matched method with
1387 * the given parameter types.
1389 * @param existedMethods Array of string which contains method parameters
1390 * @param paramTypes Array of string that is parameter type.
1391 * @return string of method parameters seperated by "\\"
1394 var searchMethod = function(roundOne, paramTypes) {
1395 // Filter out all the fitted methods for the given parameters
1397 var len = roundOne.length;
1398 for (var i = 0; i < len; i++) {
1399 var fittedLevel = [];
1400 var isFitted = true;
1401 var len2 = roundOne[i].length;
1402 for (var j = 0; j < len2; j++) {
1403 fittedLevel[j] = Clazz.getInheritedLevel (paramTypes[j],
1405 if (fittedLevel[j] < 0) {
1411 fittedLevel[paramTypes.length] = i; // Keep index for later use
1412 roundTwo.push(fittedLevel);
1415 if (roundTwo.length == 0)
1417 // Find out the best method according to the inheritance.
1418 var resultTwo = roundTwo;
1419 var min = resultTwo[0];
1420 for (var i = 1; i < resultTwo.length; i++) {
1421 var isVectorLesser = true;
1422 for (var j = 0; j < paramTypes.length; j++) {
1423 if (min[j] < resultTwo[i][j]) {
1424 isVectorLesser = false;;
1431 var index = min[paramTypes.length]; // Get the previously stored index
1433 * Return the method parameters' type string as indentifier of the
1436 return roundOne[index].join ('\\');
1439 ////////////////////////////////// package loading ///////////////////////
1442 * all root packages. e.g. java.*, org.*, com.*
1445 Clazz.allPackage = {};
1448 * Will be used to keep value of whether the class is defined or not.
1451 Clazz.allClasses = {};
1453 Clazz.lastPackageName = null;
1454 Clazz.lastPackage = null;
1457 Clazz.unloadedClasses = [];
1460 Clazz.declarePackage = function (pkgName) {
1461 if (Clazz.lastPackageName == pkgName)
1462 return Clazz.lastPackage;
1463 if (pkgName && pkgName.length) {
1464 var pkgFrags = pkgName.split (/\./);
1465 var pkg = Clazz.allPackage;
1466 for (var i = 0; i < pkgFrags.length; i++) {
1467 if (!pkg[pkgFrags[i]]) {
1468 pkg[pkgFrags[i]] = {
1469 __PKG_NAME__ : (pkg.__PKG_NAME__ ?
1470 pkg.__PKG_NAME__ + "." + pkgFrags[i] : pkgFrags[i])
1472 // pkg[pkgFrags[i]] = {};
1475 Clazz.setGlobal(pkgFrags[i], pkg[pkgFrags[i]]);
1478 pkg = pkg[pkgFrags[i]]
1480 Clazz.lastPackageName = pkgName;
1481 Clazz.lastPackage = pkg;
1487 Clazz.evalType = function (typeStr, isQualified) {
1488 var idx = typeStr.lastIndexOf(".");
1490 var pkgName = typeStr.substring (0, idx);
1491 var pkg = Clazz.declarePackage (pkgName);
1492 var clazzName = typeStr.substring (idx + 1);
1493 return pkg[clazzName];
1496 return window[typeStr];
1515 return window[typeStr];
1520 * Define a class or interface.
1522 * @param qClazzName String presents the qualified name of the class
1523 * @param clazzFun Function of the body
1524 * @param clazzParent Clazz to inherit from, may be null
1525 * @param interfacez Clazz may implement one or many interfaces
1526 * interfacez can be Clazz object or Array of Clazz objects.
1527 * @return Ruturn the modified Clazz object
1530 Clazz.defineType = function (qClazzName, clazzFun, clazzParent, interfacez) {
1531 var cf = Clazz.unloadedClasses[qClazzName];
1535 var idx = qClazzName.lastIndexOf (".");
1537 var pkgName = qClazzName.substring (0, idx);
1538 var pkg = Clazz.declarePackage (pkgName);
1539 var clazzName = qClazzName.substring (idx + 1);
1540 if (pkg[clazzName]) {
1541 // already defined! Should throw exception!
1542 return pkg[clazzName];
1544 pkg[clazzName] = clazzFun;
1546 if (window[qClazzName]) {
1547 // already defined! Should throw exception!
1548 return window[qClazzName];
1550 Clazz.setGlobal(qClazzName, clazzFun);
1552 Clazz.decorateAsType(clazzFun, qClazzName, clazzParent, interfacez);
1553 /*# {$no.javascript.support} >>x #*/
1554 var iFun = Clazz._innerFunctions;
1555 clazzFun.defineMethod = iFun.defineMethod;
1556 clazzFun.defineStaticMethod = iFun.defineStaticMethod;
1557 clazzFun.makeConstructor = iFun.makeConstructor;
1562 var isSafari = (navigator.userAgent.indexOf ("Safari") != -1);
1563 var isSafari4Plus = false;
1565 var ua = navigator.userAgent;
1566 var verIdx = ua.indexOf("Version/");
1568 var verStr = ua.substring(verIdx + 8);
1569 var verNumber = parseFloat(verStr);
1570 isSafari4Plus = verNumber >= 4.0;
1575 Clazz.instantialize = function (objThis, args) {
1578 if (args && args.length == 1 && args[0]
1579 && args[0] instanceof args4InheritClass) {
1582 if (objThis instanceof Number) {
1583 objThis.valueOf = function () {
1587 if (isSafari4Plus) { // Fix bug of Safari 4.0+'s over-optimization
1589 for (var k = 0; k < args.length; k++) {
1590 argsClone[k] = args[k];
1595 var c = objThis.construct;
1597 if (!objThis.con$truct) { // no need to init fields
1598 c.apply (objThis, args);
1599 } else if (!objThis.getClass ().superClazz) { // the base class
1600 objThis.con$truct.apply (objThis, []);
1601 c.apply (objThis, args);
1602 } else if ((c.claxxOwner
1603 && c.claxxOwner === objThis.getClass ())
1605 && c.stacks[c.stacks.length - 1] == objThis.getClass ())) {
1607 * This #construct is defined by this class itself.
1608 * #construct will call Clazz.superConstructor, which will
1609 * call #con$truct back
1611 c.apply (objThis, args);
1612 } else { // constructor is a super constructor
1613 if (c.claxxOwner && !c.claxxOwner.superClazz
1614 && c.claxxOwner.con$truct) {
1615 c.claxxOwner.con$truct.apply (objThis, []);
1616 } else if (c.stacks && c.stacks.length == 1
1617 && !c.stacks[0].superClazz) {
1618 c.stacks[0].con$truct.apply (objThis, []);
1620 c.apply (objThis, args);
1621 objThis.con$truct.apply (objThis, []);
1623 } else if (objThis.con$truct) {
1624 objThis.con$truct.apply (objThis, []);
1629 * Once there are other methods registered to the Function.prototype,
1630 * those method names should be add to the following Array.
1633 * static final member of interface may be a class, which may
1637 Clazz.innerFunctionNames = [
1638 "isInstance", "equals", "hashCode", /*"toString",*/ "getName", "getCanonicalName", "getClassLoader", "getResource", "getResourceAsStream" /*# {$no.javascript.support} >>x #*/, "defineMethod", "defineStaticMethod",
1639 "makeConstructor" /*# x<< #*/
1645 Clazz._innerFunctions = {
1647 * Similar to Object#equals
1650 isInstance: function(c) {
1651 return Clazz.instanceOf(c, this);
1654 equals : function (aFun) {
1655 return this === aFun;
1658 hashCode : function () {
1659 return this.getName ().hashCode ();
1662 toString : function () {
1663 return "class " + this.getName ();
1667 * Similar to Class#getName
1669 getName : function () {
1670 return Clazz.getClassName (this, true);
1672 getCanonicalName : function () {
1673 return this.__CLASS_NAME__;
1675 getClassLoader : function () {
1676 var clazzName = this.__CLASS_NAME__;
1677 var baseFolder = Clazz._Loader.getClasspathFor(clazzName);
1678 var x = baseFolder.lastIndexOf (clazzName.replace (/\./g, "/"));
1680 baseFolder = baseFolder.substring (0, x);
1682 baseFolder = Clazz._Loader.getClasspathFor(clazzName, true);
1684 var loader = Clazz._Loader.requireLoaderByBase(baseFolder);
1685 loader.getResourceAsStream = Clazz._innerFunctions.getResourceAsStream;
1686 loader.getResource = Clazz._innerFunctions.getResource; // BH
1690 getResource : function(name) {
1691 var stream = this.getResourceAsStream(name);
1692 return (stream ? stream.url : null);
1695 getResourceAsStream : function (name) {
1698 name = name.replace (/\\/g, '/');
1699 var baseFolder = null;
1701 var clazzName = this.__CLASS_NAME__;
1702 if (arguments.length == 2 && name.indexOf ('/') != 0) { // additional argument
1705 if (name.indexOf ('/') == 0) {
1706 //is.url = name.substring (1);
1707 if (arguments.length == 2) { // additional argument
1708 baseFolder = arguments[1];
1710 baseFolder = Clazz.binaryFolders[0];
1711 } else if (Clazz._Loader) {
1712 baseFolder = Clazz._Loader.getClasspathFor(clazzName, true);
1715 fname = name.substring (1);
1717 baseFolder = baseFolder.replace (/\\/g, '/');
1718 var length = baseFolder.length;
1719 var lastChar = baseFolder.charAt (length - 1);
1720 if (lastChar != '/') {
1723 fname = baseFolder + name.substring (1);
1727 baseFolder = this.base;
1728 } else if (Clazz._Loader) {
1729 baseFolder = Clazz._Loader.getClasspathFor(clazzName);
1730 var x = baseFolder.lastIndexOf (clazzName.replace (/\./g, "/"));
1732 baseFolder = baseFolder.substring (0, x);
1734 //baseFolder = null;
1736 if (baseFolder.indexOf (".z.js") == baseFolder.length - 5
1737 && (y = baseFolder.lastIndexOf ("/")) != -1) {
1738 baseFolder = baseFolder.substring (0, y + 1);
1739 var pkgs = clazzName.split (/\./);
1740 for (var k = 1; k < pkgs.length; k++) {
1742 for (var j = 0; j < k; j++) {
1743 pkgURL += pkgs[j] + "/";
1745 if (pkgURL.length > baseFolder.length) {
1748 if (baseFolder.indexOf (pkgURL) == baseFolder.length - pkgURL.length) {
1749 baseFolder = baseFolder.substring (0, baseFolder.length - pkgURL.length + 1);
1754 baseFolder = Clazz._Loader.getClasspathFor(clazzName, true);
1758 var bins = Clazz.binaryFolders;
1759 if (bins && bins.length) {
1760 baseFolder = bins[0];
1764 baseFolder = "j2s/";
1765 baseFolder = baseFolder.replace (/\\/g, '/');
1766 var length = baseFolder.length;
1767 var lastChar = baseFolder.charAt (length - 1);
1768 if (lastChar != '/') {
1772 fname = baseFolder + name;
1774 var idx = clazzName.lastIndexOf ('.');
1775 if (idx == -1 || this.base) {
1776 fname = baseFolder + name;
1778 fname = baseFolder + clazzName.substring (0, idx)
1779 .replace (/\./g, '/') + "/" + name;
1785 if (fname.indexOf(":/") < 0) {
1786 var d = document.location.href.split("?")[0].split("/");
1787 d[d.length - 1] = fname;
1788 fname = d.join("/");
1790 url = new java.net.URL(fname);
1793 var data = (url == null ? null : Jmol._getFileData(fname.toString()));
1794 if (!data || data == "error" || data.indexOf("[Exception") == 0)
1796 var bytes = new java.lang.String(data).getBytes();
1797 var is = new java.io.BufferedInputStream ( new java.io.ByteArrayInputStream (bytes));
1800 }/*# {$no.javascript.support} >>x #*/,
1803 * For JavaScript programmers
1805 defineMethod : function (methodName, funBody, paramTypes) {
1806 Clazz.defineMethod (this, methodName, funBody, paramTypes);
1810 * For JavaScript programmers
1812 defineStaticMethod : function (methodName, funBody, paramTypes) {
1813 Clazz.defineMethod (this, methodName, funBody, paramTypes);
1814 this[methodName] = this.prototype[methodName];
1818 * For JavaScript programmers
1820 makeConstructor : function (funBody, paramTypes) {
1821 Clazz.makeConstructor (this, funBody, paramTypes);
1830 * BH: I would like to be able to remove "self.c$" here, but that is tricky.
1833 Clazz.pu$h = function (c) {
1834 c || (c = self.c$); // old style
1835 c && cStack.push(c);
1838 Clazz.p0p = function () {
1839 return cStack.pop();
1843 Clazz.decorateAsClass = function (clazzFun, prefix, name, clazzParent,
1844 interfacez, parentClazzInstance, _decorateAsClass) {
1846 var prefixName = null;
1848 prefixName = prefix.__PKG_NAME__;
1850 prefixName = prefix.__CLASS_NAME__;
1852 var qName = (prefixName ? prefixName + "." : "") + name;
1854 if (Clazz._Loader._classPending[qName]) {
1855 delete Clazz._Loader._classPending[qName];
1856 Clazz._Loader._classCountOK++;
1857 Clazz._Loader._classCountPending--;
1859 if (Clazz._Loader && Clazz._Loader._checkLoad) {
1860 System.out.println("decorating class " + prefixName + "." + name);
1862 var cf = Clazz.unloadedClasses[qName];
1867 decorateFunction(clazzFun, prefix, name);
1868 if (parentClazzInstance) {
1869 Clazz.inheritClass (clazzFun, clazzParent, parentClazzInstance);
1870 } else if (clazzParent) {
1871 Clazz.inheritClass (clazzFun, clazzParent);
1874 Clazz.implementOf (clazzFun, interfacez);
1880 var decorateFunction = function (clazzFun, prefix, name, _decorateFunction) {
1883 // e.g. Clazz.declareInterface (null, "ICorePlugin", org.eclipse.ui.IPlugin);
1885 Clazz.setGlobal(name, clazzFun);
1886 } else if (prefix.__PKG_NAME__) {
1887 // e.g. Clazz.declareInterface (org.eclipse.ui, "ICorePlugin", org.eclipse.ui.IPlugin);
1888 qName = prefix.__PKG_NAME__ + "." + name;
1889 prefix[name] = clazzFun;
1890 if (prefix === java.lang)
1891 Clazz.setGlobal(name, clazzFun);
1893 // e.g. Clazz.declareInterface (org.eclipse.ui.Plugin, "ICorePlugin", org.eclipse.ui.IPlugin);
1894 qName = prefix.__CLASS_NAME__ + "." + name;
1895 prefix[name] = clazzFun;
1897 Clazz.extendJO(clazzFun, qName);
1898 var inF = Clazz.innerFunctionNames;
1899 for (var i = 0; i < inF.length; i++) {
1900 clazzFun[inF[i]] = Clazz._innerFunctions[inF[i]];
1904 Clazz._Loader.updateNodeForFunctionDecoration(qName);
1908 Clazz.declareInterface = function (prefix, name, interfacez, _declareInterface) {
1909 var clazzFun = function () {};
1910 decorateFunction(clazzFun, prefix, name);
1912 Clazz.implementOf (clazzFun, interfacez);
1918 Clazz.declareType = function (prefix, name, clazzParent, interfacez,
1919 parentClazzInstance, _declareType) {
1920 var f = function () {
1921 Clazz.instantialize (this, arguments);
1923 return Clazz.decorateAsClass (f, prefix, name, clazzParent, interfacez,
1924 parentClazzInstance);
1928 Clazz.declareAnonymous = function (prefix, name, clazzParent, interfacez,
1929 parentClazzInstance, _declareAnonymous) {
1930 var f = function () {
1931 Clazz.prepareCallback(this, arguments);
1932 Clazz.instantialize (this, arguments);
1934 return Clazz.decorateAsClass (f, prefix, name, clazzParent, interfacez,
1935 parentClazzInstance);
1939 Clazz.decorateAsType = function (clazzFun, qClazzName, clazzParent,
1940 interfacez, parentClazzInstance, inheritClazzFuns, _decorateAsType) {
1941 Clazz.extendJO(clazzFun, qClazzName);
1942 clazzFun.equals = Clazz._innerFunctions.equals;
1943 clazzFun.getName = Clazz._innerFunctions.getName;
1944 if (inheritClazzFuns) {
1945 for (var i = 0; i < Clazz.innerFunctionNames.length; i++) {
1946 var methodName = Clazz.innerFunctionNames[i];
1947 clazzFun[methodName] = Clazz._innerFunctions[methodName];
1950 if (parentClazzInstance) {
1951 Clazz.inheritClass (clazzFun, clazzParent, parentClazzInstance);
1952 } else if (clazzParent) {
1953 Clazz.inheritClass (clazzFun, clazzParent);
1956 Clazz.implementOf (clazzFun, interfacez);
1962 ////////////////////////// default package declarations ////////////////////////
1964 /* sgurin: preserve Number.prototype.toString */
1965 Number.prototype._numberToString=Number.prototype.toString;
1968 Clazz.declarePackage ("java.io");
1969 //Clazz.declarePackage ("java.lang");
1970 Clazz.declarePackage ("java.lang.annotation"); // java.lang
1971 Clazz.declarePackage ("java.lang.instrument"); // java.lang
1972 Clazz.declarePackage ("java.lang.management"); // java.lang
1973 Clazz.declarePackage ("java.lang.reflect"); // java.lang
1974 Clazz.declarePackage ("java.lang.ref"); // java.lang.ref
1975 java.lang.ref.reflect = java.lang.reflect;
1976 Clazz.declarePackage ("java.util");
1977 //var reflect = Clazz.declarePackage ("java.lang.reflect");
1978 Clazz.declarePackage ("java.security");
1982 * Consider these interfaces are basic!
1984 Clazz.declareInterface (java.io,"Closeable");
1985 Clazz.declareInterface (java.io,"DataInput");
1986 Clazz.declareInterface (java.io,"DataOutput");
1987 Clazz.declareInterface (java.io,"Externalizable");
1988 Clazz.declareInterface (java.io,"Flushable");
1989 Clazz.declareInterface (java.io,"Serializable");
1990 Clazz.declareInterface (java.lang,"Iterable");
1991 Clazz.declareInterface (java.lang,"CharSequence");
1992 Clazz.declareInterface (java.lang,"Cloneable");
1993 Clazz.declareInterface (java.lang,"Appendable");
1994 Clazz.declareInterface (java.lang,"Comparable");
1995 Clazz.declareInterface (java.lang,"Runnable");
1996 Clazz.declareInterface (java.util,"Comparator");
1998 java.lang.ClassLoader = {
1999 __CLASS_NAME__ : "ClassLoader"
2002 /******************************************************************************
2003 * Copyright (c) 2007 java2script.org and others.
2004 * All rights reserved. This program and the accompanying materials
2005 * are made available under the terms of the Eclipse Public License v1.0
2006 * which accompanies this distribution, and is available at
2007 * http://www.eclipse.org/legal/epl-v10.html
2010 * Zhou Renjian - initial API and implementation
2011 *****************************************************************************/
2013 * @author zhou renjian
2014 * @create March 10, 2006
2018 * Once ClassExt.js is part of Class.js.
2019 * In order to make the Class.js as small as possible, part of its content
2020 * is moved into this ClassExt.js.
2022 * See also http://j2s.sourceforge.net/j2sclazz/
2026 * Clazz.MethodNotFoundException is used to notify the developer about calling
2027 * methods with incorrect parameters.
2030 // Override the Clazz.MethodNotFoundException in Class.js to give details
2031 var MethodNotFoundException = function (obj, clazz, method, params) {
2034 paramStr = params.substring (1).replace (/\\/g, ",");
2036 var leadingStr = "";
2037 if (method && method != "construct") {
2038 leadingStr = "Method";
2040 leadingStr = "Constructor";
2042 this.message = leadingStr + " " + Clazz.getClassName (clazz, true) + "."
2043 + method + "(" + paramStr + ") is not found!";
2044 this.toString = function () {
2045 return "MethodNotFoundException:" + this.message;
2050 * Prepare "callback" for instance of anonymous Class.
2051 * For example for the callback:
2052 * this.callbacks.MyEditor.sayHello();
2054 * This is specifically for inner classes that are referring to
2055 * outer class methods and fields.
2057 * @param objThis the host object for callback
2058 * @param args arguments object. args[0] will be classThisObj -- the "this"
2059 * object to be hooked
2061 * Attention: parameters should not be null!
2064 Clazz.prepareCallback = function (innerObj, args) {
2065 var outerObj = args[0];
2066 var cbName = "b$"; // "callbacks";
2067 if (innerObj && outerObj && outerObj !== window) {
2068 var className = Clazz.getClassName(outerObj, true);
2070 if (innerObj[cbName]) // must make a copy!
2071 for (var s in innerObj[cbName])
2072 obs[s] = innerObj[cbName][s];
2073 innerObj[cbName] = obs;
2076 * TODO: the following line is SWT-specific! Try to move it out!
2078 // obs[className.replace (/org\.eclipse\.swt\./, "$wt.")] = outerObj;
2080 // all references to outer class and its superclass objects must be here as well
2081 obs[className] = outerObj;
2082 var clazz = Clazz.getClass(outerObj);
2083 while (clazz.superClazz) {
2084 clazz = clazz.superClazz;
2086 * TODO: the following line is SWT-specific! Try to move it out!
2088 // obs[Clazz.getClassName (clazz, true)
2089 // .replace (/org\.eclipse\.swt\./, "$wt.")] = outerObj;
2090 obs[Clazz.getClassName(clazz, true)] = outerObj;
2092 var cbs = outerObj[cbName];
2097 // remove "this" argument
2098 // note that args is an instance of arguments -- NOT an array; does not have the .shift() method!
2099 for (var i = 0; i < args.length - 1; i++)
2100 args[i] = args[i + 1];
2105 * Construct instance of the given inner class.
2107 * @param classInner given inner class, alway with name like "*$*"
2108 * @param innerObj this instance which can be used to call back.
2109 * @param finalVars final variables which the inner class may use
2110 * @return the constructed object
2112 * @see Clazz#cloneFinals
2115 Clazz.innerTypeInstance = function (clazzInner, innerObj, finalVars) {
2117 clazzInner = arguments.callee.caller;
2119 if (finalVars || innerObj.$finals) {
2120 obj = new clazzInner(innerObj, Clazz.inheritArgs);
2121 // f$ is short for the once choosen "$finals"
2125 for (var attr in innerObj.f$)
2126 o[attr] = innerObj.f$[attr];
2127 for (var attr in finalVars)
2128 o[attr] = finalVars[attr];
2133 } else if (innerObj.f$) {
2134 obj.f$ = innerObj.f$;
2137 switch (arguments.length) {
2139 return new clazzInner(innerObj);
2141 return (innerObj.__CLASS_NAME__ == clazzInner.__CLASS_NAME__
2142 && arguments[3] === Clazz.inheritArgs ? innerObj : new clazzInner(innerObj, arguments[3]));
2144 return new clazzInner(innerObj, arguments[3], arguments[4]);
2146 return new clazzInner(innerObj, arguments[3], arguments[4],
2149 return new clazzInner(innerObj, arguments[3], arguments[4],
2150 arguments[5], arguments[6]);
2152 return new clazzInner(innerObj, arguments[3], arguments[4],
2153 arguments[5], arguments[6], arguments[7]);
2155 return new clazzInner(innerObj, arguments[3], arguments[4],
2156 arguments[5], arguments[6], arguments[7], arguments[8]);
2158 return new clazzInner(innerObj, arguments[3], arguments[4],
2159 arguments[5], arguments[6], arguments[7], arguments[8],
2162 //Should construct instance manually.
2163 obj = new clazzInner(innerObj, Clazz.inheritArgs);
2167 var n = arguments.length - 3;
2168 var args = new Array(n);
2169 for (var i = n; --i >= 0;)
2170 args[i] = arguments[i + 3];
2171 Clazz.instantialize(obj, args);
2176 * Clone variables whose modifier is "final".
2177 * Usage: var o = Clazz.cloneFinals ("name", name, "age", age);
2179 * @return Object with all final variables
2182 Clazz.cloneFinals = function () {
2184 var len = arguments.length / 2;
2185 for (var i = len; --i >= 0;)
2186 o[arguments[i + i]] = arguments[i + i + 1];
2191 Clazz.isClassDefined = Clazz.isDefinedClass = function(clazzName) {
2193 return false; /* consider null or empty name as non-defined class */
2194 if (Clazz.allClasses[clazzName])
2196 var pkgFrags = clazzName.split (/\./);
2198 for (var i = 0; i < pkgFrags.length; i++)
2199 if (!(pkg = (pkg ? pkg[pkgFrags[i]] : Clazz.allPackage[pkgFrags[0]]))) {
2202 return (pkg && (Clazz.allClasses[clazzName] = true));
2205 * Define the enum constant.
2206 * @param classEnum enum type
2207 * @param enumName enum constant
2208 * @param enumOrdinal enum ordinal
2209 * @param initialParams enum constant constructor parameters
2210 * @return return defined enum constant
2213 Clazz.defineEnumConstant = function (clazzEnum, enumName, enumOrdinal, initialParams, clazzEnumExt) {
2214 var o = (clazzEnumExt ? new clazzEnumExt() : new clazzEnum());
2215 // BH avoids unnecessary calls to SAEM
2217 o.$ordinal = enumOrdinal;
2218 //Clazz.superConstructor (o, clazzEnum, [enumName, enumOrdinal]);
2219 if (initialParams && initialParams.length)
2220 o.construct.apply (o, initialParams);
2221 clazzEnum[enumName] = o;
2222 clazzEnum.prototype[enumName] = o;
2223 if (!clazzEnum["$ values"]) { // BH added
2224 clazzEnum["$ values"] = [] // BH added
2225 clazzEnum.values = function() { // BH added
2226 return this["$ values"]; // BH added
2229 clazzEnum["$ values"].push(o);
2233 //////// (int) conversions //////////
2235 Clazz.floatToInt = function (x) {
2236 return x < 0 ? Math.ceil(x) : Math.floor(x);
2239 Clazz.floatToByte = Clazz.floatToShort = Clazz.floatToLong = Clazz.floatToInt;
2240 Clazz.doubleToByte = Clazz.doubleToShort = Clazz.doubleToLong = Clazz.doubleToInt = Clazz.floatToInt;
2242 Clazz.floatToChar = function (x) {
2243 return String.fromCharCode (x < 0 ? Math.ceil(x) : Math.floor(x));
2246 Clazz.doubleToChar = Clazz.floatToChar;
2250 ///////////////////////////////// Array additions //////////////////////////////
2252 // BH: these are necessary for integer processing, especially
2256 var getArrayClone = function(nbits) {
2260 var a = (nbits == 32 ? new Int32Array(n) : new Float64Array(n));
2261 for (var i = n; --i >= 0;)
2267 if (self.Int32Array && self.Int32Array != Array) {
2268 Clazz.haveInt32 = true;
2269 if (!Int32Array.prototype.sort)
2270 Int32Array.prototype.sort = Array.prototype.sort
2271 if (!Int32Array.prototype.clone)
2272 Int32Array.prototype.clone = getArrayClone(32);
2274 Int32Array = function(n) {
2276 var b = new Array(n);
2277 b.toString = function(){return "[object Int32Array]"}
2278 for (var i = 0; i < n; i++)b[i] = 0
2281 Clazz.haveInt32 = false;
2282 Int32Array.prototype.sort = Array.prototype.sort
2283 Int32Array.prototype.clone = getArrayClone(32);
2284 Int32Array.prototype.int32Fake = function(){};
2287 if (self.Float64Array && self.Float64Array != Array) {
2288 Clazz.haveFloat64 = true;
2289 if (!Float64Array.prototype.sort)
2290 Float64Array.prototype.sort = Array.prototype.sort
2291 if (!Float64Array.prototype.clone)
2292 Float64Array.prototype.clone = getArrayClone(64);
2294 Clazz.haveFloat64 = false;
2295 Float64Array = function(n) {
2297 var b = new Array(n);
2298 for (var i = 0; i < n; i++)b[i] = 0.0
2301 Float64Array.prototype.sort = Array.prototype.sort
2302 Float64Array.prototype.clone = getArrayClone(64);
2303 Float64Array.prototype.float64Fake = function() {}; // "present"
2304 Float64Array.prototype.toString = function() {return "[object Float64Array]"};
2305 // Darn! Mozilla makes this a double, not a float. It's 64-bit.
2306 // and Safari 5.1 doesn't have Float64Array
2312 * @return the created Array object
2315 Clazz.newArray = function () {
2316 if (arguments[0] instanceof Array) {
2317 // recursive, from newArray(n,m,value)
2318 // as newArray([m, value], newInt32Array)
2319 var args = arguments[0];
2320 var f = arguments[1];
2322 var args = arguments;
2326 if (typeof dim == "string") {
2327 dim = dim.charCodeAt (0); // char
2329 var len = args.length - 1;
2330 var val = args[len];
2331 switch (args.length) {
2334 return []; // maybe never?
2337 return new Array(dim);
2338 if (f === true && Clazz.haveInt32) return new Int32Array(dim);
2339 if (f === false && Clazz.haveFloat64) return new Float64Array(dim);
2340 var arr = (f === true ? new Int32Array() : f === false ? new Float64Array() : dim < 0 ? val : new Array(dim));
2341 for (var i = dim; --i >= 0;)
2345 var xargs = new Array (len);
2346 for (var i = 0; i < len; i++) {
2347 xargs[i] = args[i + 1];
2349 var arr = new Array (dim);
2350 if (val == null || val >= 0 || len > 2)
2351 for (var i = 0; i < dim; i++) {
2352 // Call recursively!
2353 arr[i] = Clazz.newArray (xargs, f);
2359 Clazz.newArray32 = function(args, isInt32) {
2361 if (typeof dim == "string")
2362 dim = dim.charCodeAt (0); // char
2363 var len = args.length - 1;
2364 var val = args[len];
2365 switch (args.length) {
2368 alert ("ERROR IN newArray32 -- args.length < 2");
2369 return new Array(0);
2371 var isDefined = (dim < 0);
2374 var a = (val < 0 ? new Array(dim) : isInt32 ? new Int32Array(dim) : new Float64Array(dim));
2376 for (var i = dim; --i >= 0;)
2380 var xargs = new Array(len);
2381 for (var i = len; --i >= 0;) {
2382 xargs[i] = args[i + 1];
2384 var arr = new Array (dim);
2385 for (var i = 0; i < dim; i++) {
2386 // Call newArray referencing this array type
2387 // only for the final iteration, and only if val === 0
2388 arr[i] = Clazz.newArray (xargs, isInt32);
2397 * @return the created Array object
2400 Clazz.newInt32Array = function () {
2401 return Clazz.newArray32(arguments, true);
2407 * @return the created Array object
2410 Clazz.newFloat64Array = function () {
2411 return Clazz.newArray32(arguments, false);
2414 Clazz.newFloatArray = Clazz.newDoubleArray = Clazz.newFloat64Array;
2415 Clazz.newIntArray = Clazz.newLongArray = Clazz.newShortArray = Clazz.newByteArray = Clazz.newInt32Array;
2416 Clazz.newCharArray = Clazz.newBooleanArray = Clazz.newArray;
2418 //$_AI=Clazz.newIntArray;
2419 //$_AF=Clazz.newFloatArray;
2420 //$_AD=Clazz.newDoubleArray;
2421 //$_AL=Clazz.newLongArray;
2422 //$_AS=Clazz.newShortArray;
2423 //$_AB=Clazz.newByteArray;
2424 //$_AC=Clazz.newCharArray;
2425 //$_Ab=Clazz.newBooleanArray;
2428 var arrayIs = function(a, what) {
2429 // for some reason, Number.constructor.toString() now gives "too much recursion"
2430 return a.constructor && a.constructor != Number && a.constructor.toString().indexOf(what) >= 0
2433 Clazz.isAS = function(a) { // just checking first parameter
2434 return (a && typeof a == "object" && arrayIs(a, " Array") && (typeof a[0] == "string" || typeof a[0] == "undefined"));
2437 Clazz.isASS = function(a) {
2438 return (a && typeof a == "object" && Clazz.isAS(a[0]));
2441 Clazz.isAP = function(a) {
2442 return (a && Clazz.getClassName(a[0]) == "JU.P3");
2445 Clazz.isAI = function(a) {
2446 return (a && typeof a == "object" && (Clazz.haveInt32 ? arrayIs(a, "Int32Array") : a.int32Fake ? true : false));
2449 Clazz.isAII = function(a) { // assumes non-null a[0]
2450 return (a && typeof a == "object" && Clazz.isAI(a[0]));
2453 Clazz.isAF = function(a) {
2454 return (a && typeof a == "object" && (Clazz.haveFloat64 ? arrayIs(a, "Float64Array") : a.float64Fake ? true : false));
2457 Clazz.isAFF = function(a) { // assumes non-null a[0]
2458 return (a && typeof a == "object" && Clazz.isAF(a[0]));
2461 Clazz.isAFFF = function(a) { // assumes non-null a[0]
2462 return (a && typeof a == "object" && Clazz.isAFF(a[0]));
2465 Clazz.isAFloat = function(a) { // just checking first parameter
2466 return (a && typeof a == "object" && arrayIs(a, " Array") && Clazz.instanceOf(a[0], Float));
2471 * Make the RunnableCompatiability instance as a JavaScript function.
2473 * @param jsr Instance of RunnableCompatiability
2474 * @return JavaScript function instance represents the method run of jsr.
2478 Clazz.makeFunction = function (jsr) {
2479 // never used in Jmol -- called by Enum, but not accessible to it -- part of SWT
2480 return function(e) {
2486 switch (jsr.returnSet) {
2488 return jsr.returnNumber;
2490 return jsr.returnBoolean;
2492 return jsr.returnObject;
2499 Clazz.defineStatics = function (clazz) {
2500 for (var j = arguments.length, i = (j - 1) / 2; --i >= 0;) {
2501 var val = arguments[--j]
2502 var name = arguments[--j];
2503 clazz[name] = clazz.prototype[name] = val;
2508 Clazz.prepareFields = function (clazz, fieldsFun) {
2510 if (clazz.con$truct) {
2511 var ss = clazz.con$truct.stacks;
2512 var idx = 0;//clazz.con$truct.index;
2513 for (var i = idx; i < ss.length; i++) {
2517 addProto(clazz.prototype, "con$truct", clazz.con$truct = function () {
2518 var stacks = arguments.callee.stacks;
2520 for (var i = 0; i < stacks.length; i++) {
2521 stacks[i].apply (this, []);
2525 stacks.push(fieldsFun);
2526 clazz.con$truct.stacks = stacks;
2527 clazz.con$truct.index = 0;
2531 * Serialize those public or protected fields in class
2532 * net.sf.j2s.ajax.SimpleSerializable.
2536 Clazz.registerSerializableFields = function (clazz) {
2537 var args = arguments;
2538 var length = args.length;
2540 if (clazz.declared$Fields) {
2541 for (var i = 0; i < clazz.declared$Fields.length; i++) {
2542 newArr[i] = clazz.declared$Fields[i];
2545 clazz.declared$Fields = newArr;
2547 if (length > 0 && length % 2 == 1) {
2548 var fs = clazz.declared$Fields;
2549 var n = (length - 1) / 2;
2550 for (var i = 1; i <= n; i++) {
2551 var o = { name : args[i + i - 1], type : args[i + i] };
2552 var existed = false;
2553 for (var j = 0; j < fs.length; j++) {
2554 if (fs[j].name == o.name) { // reloaded classes
2555 fs[j].type = o.type; // update type
2567 * Get the caller method for those methods that are wrapped by
2568 * Clazz.searchAndExecuteMethod.
2570 * @param args caller method's arguments
2571 * @return caller method, null if there is not wrapped by
2572 * Clazz.searchAndExecuteMethod or is called directly.
2576 Clazz.getMixedCallerMethod = function (args) {
2578 var argc = args.callee.caller; // tryToSearchAndExecute
2579 if (argc && argc !== tryToSearchAndExecute) // inherited method's apply
2580 argc = argc.arguments.callee.caller;
2581 if (argc !== tryToSearchAndExecute
2582 || (argc = argc.arguments.callee.caller) !== Clazz.searchAndExecuteMethod)
2584 o.claxxRef = argc.arguments[1];
2585 o.fxName = argc.arguments[2];
2586 o.paramTypes = Clazz.getParamsType(argc.arguments[3]);
2587 argc = argc.arguments.callee.caller // Clazz.generateDelegatingMethod
2588 && argc.arguments.callee.caller; // the private method's caller
2595 /* BH -- The issue here is a subclass calling its private method FOO when
2596 * there is also a private method of the same name in its super class.
2597 * This can ALWAYS be avoided and, one could argue, is bad
2598 * program design anyway. In Jmol, the presence of this possibility
2599 * creates over 8000 references to the global $fx, which was only
2600 * checked in a few rare cases. We can then also remove $fz references.
2605 * Check and return super private method.
2606 * In order make private methods be executed correctly, some extra javascript
2607 * must be inserted into the beggining of the method body of the non-private
2608 * methods that with the same method signature as following:
2610 * var $private = Clazz.checkPrivateMethod (arguments);
2612 * return $private.apply (this, arguments);
2615 * Be cautious about this. The above codes should be insert by Java2Script
2616 * compiler or with double checks to make sure things work correctly.
2618 * @param args caller method's arguments
2619 * @return private method if there are private method fitted for the current
2620 * calling environment
2625 Clazz.checkPrivateMethod = function (args) {
2626 var m = Clazz.getMixedCallerMethod (args);
2627 if (m == null) return null;
2628 var callerFx = m.claxxRef.prototype[m.caller.exName];
2629 if (callerFx == null) return null; // may not be in the class hierarchies
2631 if (callerFx.claxxOwner ) {
2632 ppFun = callerFx.claxxOwner.prototype[m.fxName];
2634 var stacks = callerFx.stacks;
2635 for (var i = stacks.length - 1; i >= 0; i--) {
2636 var fx = stacks[i].prototype[m.caller.exName];
2637 if (fx === m.caller) {
2638 ppFun = stacks[i].prototype[m.fxName];
2640 for (var fn in fx) {
2641 if (fn.indexOf ('\\') == 0 && fx[fn] === m.caller) {
2642 ppFun = stacks[i].prototype[m.fxName];
2652 if (ppFun && ppFun.claxxOwner == null) {
2653 ppFun = ppFun["\\" + m.paramTypes];
2655 if (ppFun && ppFun.isPrivate && ppFun !== args.callee) {
2663 //$fz = null; // for private method declaration
2666 // /*# {$no.debug.support} >>x #*/
2668 // * Option to switch on/off of stack traces.
2671 //Clazz.tracingCalling = false;
2674 // Clazz.callingStack = function (caller, owner) {
2675 // this.caller = caller;
2676 // this.owner = owner;
2682 * The first folder is considered as the primary folder.
2683 * And try to be compatiable with _Loader system.
2688 /*** not used in Jmol
2690 if (window["_Loader"] && _Loader.binaryFolders) {
2691 Clazz.binaryFolders = _Loader.binaryFolders;
2693 Clazz.binaryFolders = ["j2s/", "", "j2slib/"];
2696 Clazz.addBinaryFolder = function (bin) {
2698 var bins = Clazz.binaryFolders;
2699 for (var i = 0; i < bins.length; i++) {
2700 if (bins[i] == bin) {
2704 bins[bins.length] = bin;
2707 Clazz.removeBinaryFolder = function (bin) {
2709 var bins = Clazz.binaryFolders;
2710 for (var i = 0; i < bins.length; i++) {
2711 if (bins[i] == bin) {
2712 for (var j = i; j < bins.length - 1; j++) {
2713 bins[j] = bins[j + 1];
2722 Clazz.setPrimaryFolder = function (bin) {
2724 Clazz.removeBinaryFolder (bin);
2725 var bins = Clazz.binaryFolders;
2726 for (var i = bins.length - 1; i >= 0; i--) {
2727 bins[i + 1] = bins[i];
2736 ///////////////// special definitions of standard Java class methods ///////////
2739 * This is a simple implementation for Clazz#load. It just ignore dependencies
2740 * of the class. This will be fine for jar *.z.js file.
2741 * It will be overriden by _Loader#load.
2742 * For more details, see _Loader.js
2746 Clazz.load = function (musts, clazz, optionals, declaration) {
2754 * Invade the Object prototype!
2755 * TODO: make sure that invading Object prototype does not affect other
2756 * existed library, such as Dojo, YUI, Prototype, ...
2758 java.lang.Object = Clazz._O;
2760 Clazz._O.getName = Clazz._innerFunctions.getName;
2764 props : null, //new java.util.Properties (),
2766 arraycopy : function (src, srcPos, dest, destPos, length) {
2768 for (var i = 0; i < length; i++) {
2769 dest[destPos + i] = src[srcPos + i];
2773 for (var i = 0; i < length; i++) {
2774 swap[i] = src[srcPos + i];
2776 for (var i = 0; i < length; i++) {
2777 dest[destPos + i] = swap[i];
2781 currentTimeMillis : function () {
2782 return new Date ().getTime ();
2784 gc : function() {}, // bh
2785 getProperties : function () {
2786 return System.props;
2788 getProperty : function (key, def) {
2790 return System.props.getProperty (key, def);
2791 var v = System.$props[key];
2793 return (typeof v != "undefined" ? v : arguments.length == 1 ? null : def == null ? key : def); // BH
2795 getSecurityManager : function() { return null }, // bh
2796 setProperties : function (props) {
2797 System.props = props;
2799 lineSeparator : function() { return '\n' }, // bh
2800 setProperty : function (key, val) {
2802 return System.$props[key] = val; // BH
2803 System.props.setProperty (key, val);
2807 System.setProperty("line.separator", navigator.userAgent.indexOf("Windows")>=0?"\r\n" : "\n") //BH
2808 System.setProperty("os.name", navigator.userAgent) //BH
2809 System.identityHashCode=function(obj){
2813 return obj._$hashcode || (obj._$hashcode = ++Clazz._hashCode)
2817 return obj.toString().hashCode();
2823 return str.hashCode();
2828 System.out = new Clazz._O ();
2829 System.out.__CLASS_NAME__ = "java.io.PrintStream";
2830 System.out.print = function () {};
2831 System.out.printf = function () {};
2832 System.out.println = function () {};
2833 System.out.write = function () {};
2835 System.err = new Clazz._O ();
2836 System.err.__CLASS_NAME__ = "java.io.PrintStream";
2837 System.err.print = function () {};
2838 System.err.printf = function () {};
2839 System.err.println = function () {};
2840 System.err.write = function () {};
2842 Clazz.popup = Clazz.assert = Clazz.log = Clazz.error = window.alert;
2844 Thread = function () {};
2845 Thread.J2S_THREAD = Thread.prototype.J2S_THREAD = new Thread ();
2846 Thread.currentThread = Thread.prototype.currentThread = function () {
2847 return this.J2S_THREAD;
2851 Clazz.intCast = function (n) { // 32bit
2852 var b1 = (n & 0xff000000) >> 24;
2853 var b2 = (n & 0xff0000) >> 16;
2854 var b3 = (n & 0xff00) >> 8;
2856 if ((b1 & 0x80) != 0) {
2857 return -(((b1 & 0x7f) << 24) + (b2 << 16) + (b3 << 8) + b4 + 1);
2859 return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
2862 Clazz.shortCast = function (s) { // 16bit
2863 var b1 = (n & 0xff00) >> 8;
2865 if ((b1 & 0x80) != 0) {
2866 return -(((b1 & 0x7f) << 8) + b2 + 1);
2868 return (b1 << 8) + b4;
2872 Clazz.byteCast = function (b) { // 8bit
2873 if ((b & 0x80) != 0) {
2874 return -((b & 0x7f) + 1);
2880 Clazz.charCast = function (c) { // 8bit
2881 return String.fromCharCode (c & 0xff).charAt (0);
2884 Clazz.floatCast = function (f) { // 32bit
2892 * Try to fix JavaScript's shift operator defects on long type numbers.
2897 Clazz.longMasks = [];
2899 Clazz.longReverseMasks = [];
2901 Clazz.longBits = [];
2905 for (var i = 1; i < 53; i++) {
2906 arr[i] = arr[i - 1] + arr[i - 1]; // * 2 or << 1
2908 Clazz.longBits = arr;
2909 Clazz.longMasks[52] = arr[52];
2910 for (var i = 51; i >= 0; i--) {
2911 Clazz.longMasks[i] = Clazz.longMasks[i + 1] + arr[i];
2913 Clazz.longReverseMasks[0] = arr[0];
2914 for (var i = 1; i < 52; i++) {
2915 Clazz.longReverseMasks[i] = Clazz.longReverseMasks[i - 1] + arr[i];
2920 Clazz.longLeftShift = function (l, o) { // 64bit
2921 if (o == 0) return l;
2922 if (o >= 64) return 0;
2924 error ("[Java2Script] Error : JavaScript does not support long shift!");
2927 if ((l & Clazz.longMasks[o - 1]) != 0) {
2928 error ("[Java2Script] Error : Such shift operator results in wrong calculation!");
2931 var high = l & Clazz.longMasks[52 - 32 + o];
2933 return high * Clazz.longBits[o] + (l & Clazz.longReverseMasks[32 - o]) << 0;
2939 Clazz.intLeftShift = function (n, o) { // 32bit
2940 return (n << o) & 0xffffffff;
2943 Clazz.longRightShift = function (l, o) { // 64bit
2944 if ((l & Clazz.longMasks[52 - 32]) != 0) {
2945 return Math.round((l & Clazz.longMasks[52 - 32]) / Clazz.longBits[32 - o]) + (l & Clazz.longReverseMasks[o]) >> o;
2951 Clazz.intRightShift = function (n, o) { // 32bit
2952 return n >> o; // no needs for this shifting wrapper
2955 Clazz.long0RightShift = function (l, o) { // 64bit
2959 Clazz.int0RightShift = function (n, o) { // 64bit
2960 return n >>> o; // no needs for this shifting wrapper
2964 // Compress the common public API method in shorter name
2966 //$_W=Clazz.declareAnonymous;$_T=Clazz.declareType;
2967 //$_J=Clazz.declarePackage;$_C=Clazz.decorateAsClass;
2968 //$_Z=Clazz.instantialize;$_I=Clazz.declareInterface;$_D=Clazz.isClassDefined;
2969 //$_H=Clazz.pu$h;$_P=Clazz.p0p;$_B=Clazz.prepareCallback;
2970 //$_N=Clazz.innerTypeInstance;$_K=Clazz.makeConstructor;$_U=Clazz.superCall;$_R=Clazz.superConstructor;
2971 //$_M=Clazz.defineMethod;$_V=Clazz.overrideMethod;$_S=Clazz.defineStatics;
2972 //$_E=Clazz.defineEnumConstant;
2973 //$_F=Clazz.cloneFinals;
2974 //$_Y=Clazz.prepareFields;$_A=Clazz.newArray;$_O=Clazz.instanceOf;
2975 //$_G=Clazz.inheritArgs;$_X=Clazz.checkPrivateMethod;$_Q=Clazz.makeFunction;
2976 //$_s=Clazz.registerSerializableFields;
2977 //$_k=Clazz.overrideConstructor;
2980 /////////////////////// inner function support /////////////////////////////////
2983 Clazz.innerFunctionNames = Clazz.innerFunctionNames.concat ([
2984 "getSuperclass", "isAssignableFrom",
2986 "getDeclaredMethod", "getDeclaredMethods",
2987 "getMethod", "getMethods",
2988 "getModifiers", /*"isArray",*/ "newInstance"]);
2991 Clazz._innerFunctions.getSuperclass = function () {
2992 return this.superClazz;
2996 Clazz._innerFunctions.isAssignableFrom = function (clazz) {
2997 return Clazz.getInheritedLevel (clazz, this) >= 0;
3001 Clazz._innerFunctions.getConstructor = function () {
3002 return new java.lang.reflect.Constructor (this, [], [],
3003 java.lang.reflect.Modifier.PUBLIC);
3006 * TODO: fix bug for polymorphic methods!
3009 Clazz._innerFunctions.getDeclaredMethods = Clazz._innerFunctions.getMethods = function () {
3011 var p = this.prototype;
3012 for (var attr in p) {
3013 if (typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) {
3014 /* there are polynormical methods. */
3015 ms.push(new java.lang.reflect.Method (this, attr,
3016 [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC));
3020 for (var attr in p) {
3021 if (typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) {
3022 ms.push(new java.lang.reflect.Method (this, attr,
3023 [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC
3024 | java.lang.reflect.Modifier.STATIC));
3030 Clazz._innerFunctions.getDeclaredMethod = Clazz._innerFunctions.getMethod = function (name, clazzes) {
3031 var p = this.prototype;
3032 for (var attr in p) {
3033 if (name == attr && typeof p[attr] == "function"
3034 && !p[attr].__CLASS_NAME__) {
3035 /* there are polynormical methods. */
3036 return new java.lang.reflect.Method (this, attr,
3037 [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC);
3041 for (var attr in p) {
3042 if (name == attr && typeof p[attr] == "function"
3043 && !p[attr].__CLASS_NAME__) {
3044 return new java.lang.reflect.Method (this, attr,
3045 [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC
3046 | java.lang.reflect.Modifier.STATIC);
3052 Clazz._innerFunctions.getModifiers = function () {
3053 return java.lang.reflect.Modifier.PUBLIC;
3056 Clazz._innerFunctions.newInstance = function (a) {
3058 switch(a == null ? 0 : a.length) {
3062 return new clz(a[0]);
3064 return new clz(a[0], a[1]);
3066 return new clz(a[0], a[1], a[2]);
3068 return new clz(a[0], a[1], a[2], a[3]);
3070 var x = "new " + clz.__CLASS_NAME__ + "(";
3071 for (var i = 0; i < a.length; i++)
3072 x += (i == 0 ? "" : ",") + "a[" + i + "]";
3078 //Object.newInstance = Clazz._innerFunctions.newInstance;
3079 ;(function(){ // BH added wrapper here
3080 var inF = Clazz.innerFunctionNames;
3081 for (var i = 0; i < inF.length; i++) {
3082 Clazz._O[inF[i]] = Clazz._innerFunctions[inF[i]];
3083 Array[inF[i]] = Clazz._innerFunctions[inF[i]];
3085 //Array["isArray"] = function () {
3090 //////////////////////////// hotspot and unloading /////////////////////////////
3091 /* For hotspot and unloading */
3093 if (window["Clazz"] && !window["Clazz"].unloadClass) {
3096 Clazz.unloadClass = function (qClazzName) {
3097 var cc = Clazz.evalType (qClazzName);
3099 Clazz.unloadedClasses[qClazzName] = cc;
3100 var clazzName = qClazzName;
3101 var pkgFrags = clazzName.split (/\./);
3103 for (var i = 0; i < pkgFrags.length - 1; i++)
3104 pkg = (pkg ? pkg[pkgFrags[i]] : Clazz.allPackage[pkgFrags[0]]);
3106 Clazz.allPackage[pkgFrags[0]] = null;
3107 window[pkgFrags[0]] = null;
3108 // also try to unload inner or anonymous classes
3109 for (var c in window) {
3110 if (c.indexOf (qClazzName + "$") == 0) {
3111 Clazz.unloadClass (c);
3116 pkg[pkgFrags[pkgFrags.length - 1]] = null;
3117 // also try to unload inner or anonymous classes
3118 for (var c in pkg) {
3119 if (c.indexOf (pkgFrags[pkgFrags.length - 1] + "$") == 0) {
3120 Clazz.unloadClass (pkg.__PKG_NAME__ + "." + c);
3126 if (Clazz.allClasses[qClazzName]) {
3127 Clazz.allClasses[qClazzName] = false;
3128 // also try to unload inner or anonymous classes
3129 for (var c in Clazz.allClasses) {
3130 if (c.indexOf (qClazzName + "$") == 0) {
3131 Clazz.allClasses[c] = false;
3137 cleanDelegateMethod (cc[m]);
3139 for (var m in cc.prototype) {
3140 cleanDelegateMethod (cc.prototype[m]);
3143 if (Clazz._Loader) {
3144 Clazz._Loader.unloadClassExt(qClazzName);
3153 var cleanDelegateMethod = function (m) {
3156 if (typeof m == "function" && m.lastMethod
3157 && m.lastParams && m.lastClaxxRef) {
3158 m.lastMethod = null;
3159 m.lastParams = null;
3160 m.lastClaxxRef = null;
3164 } // if (window["Clazz"] && !window["Clazz"].unloadClass)
3166 /******************************************************************************
3167 * Copyright (c) 2007 java2script.org and others.
3168 * All rights reserved. This program and the accompanying materials
3169 * are made available under the terms of the Eclipse Public License v1.0
3170 * which accompanies this distribution, and is available at
3171 * http://www.eclipse.org/legal/epl-v10.html
3174 * Zhou Renjian - initial API and implementation
3175 *****************************************************************************/
3177 * @author zhou renjian
3178 * @create July 10, 2006
3181 //if (window["ClazzNode"] == null) {
3184 * Make optimization over class dependency tree.
3188 * ClassLoader Summary
3190 * ClassLoader creates SCRIPT elements and setup class path and onload
3191 * callback to continue class loading.
3193 * In the onload callbacks, _Loader will try to calculate the next-to-be-
3194 * load *.js and load it. In *.js, it will contains some codes like
3195 * Clazz.load (..., "$wt.widgets.Control", ...);
3196 * to provide information to build up the class dependency tree.
3198 * Some known problems of different browsers:
3199 * 1. In IE, loading *.js through SCRIPT will first triggers onreadstatechange
3200 * event, and then executes inner *.js source.
3201 * 2. In Firefox, loading *.js will first executes *.js source and then
3202 * triggers onload event.
3203 * 3. In Opera, similar to IE, but trigger onload event. (TODO: More details
3204 * should be studied. Currently, Opera supports no multiple-thread-loading)
3206 * For class dependency tree, actually, it is not a tree. It is a reference
3207 * net with nodes have n parents and n children. There is a root, which
3208 * ClassLoader knows where to start searching and loading classes, for such
3209 * a net. Each node is a class. Each class may require a set of must-classes,
3210 * which must be loaded before itself getting initialized, and also need a set
3211 * of optional classes, which also be loaded before being called.
3213 * The class loading status will be in 6 stages.
3214 * 1. Unknown, the class is newly introduced by other class.
3215 * 2. Known, the class is already mentioned by other class.
3216 * 3. Loaded, *.js source is in memory, but may not be initialized yet. It
3217 * requires all its must-classes be intiailized, which is in the next stage.
3218 * 4. Musts loaded, all must classes is already loaded and declared.
3219 * 5. Delcared, the class is already declared (_Loader#isClassDefined).
3220 * 6. Optionals loaded, all optional classes is loaded and declared.
3222 * The ClassLoader tries to load all necessary classes in order, and intialize
3223 * them in order. For such job, it will traverse the dependency tree, and try
3224 * to next class to-be-loaded. Sometime, the class dependencies may be in one
3225 * or more cycles, which must be broken down so classes is loaded in correct
3228 * Loading order and intializing order is very important for the ClassLoader.
3229 * The following technical options are considered:
3230 * 1. SCRIPT is loading asynchronously, which means controling order must use
3231 * callback methods to continue.
3232 * 2. Multiple loading threads are later introduced, which requires the
3233 * ClassLoader should use variables to record the class status.
3234 * 3. Different browsers have different loading orders, which means extra tests
3235 * should be tested to make sure loading order won't be broken.
3236 * 4. Java2Script simulator itself have some loading orders that must be
3237 * honored, which means it should be integrated seamlessly to Clazz system.
3238 * 5. Packed *.z.js is introduced to avoid lots of small *.js which requires
3239 * lots of HTTP connections, which means that packed *.z.js should be treated
3240 * specially (There will be mappings for such packed classes).
3241 * 6. *.js or *.css loading may fail according to network status, which means
3242 * another loading try should be performed, so _Loader is more robust.
3243 * 7. SWT lazy loading is later introduced, which means that class loading
3244 * process may be paused and should be resumed later.
3247 * <code>$_L(["$wt.graphics.Drawable","$wt.widgets.Widget"],
3248 * "$wt.widgets.Control", ...</code>
3249 * has errors while must classes in different order such as
3250 * <code>$_L(["$wt.widgets.Widget", "$wt.graphics.Drawable"],
3251 * "$wt.widgets.Control", ...</code>
3254 * Other maybe bug scenarios:
3255 * 1. In <code>_Loader.maxLoadingThreads = 1;</code> single loading thread
3256 * mode, there are no errors, but in default multiple thread loading mode,
3258 * 2. No errors in one browser, but has errors on other browsers (Browser
3259 * script loading order differences).
3260 * 3. First time loading has errors, but reloading it gets no errors (Maybe
3261 * HTTP connections timeout, but should not accur in local file system, or it
3262 * is a loading bug by using JavaScript timeout thread).
3266 * The following comments with "#" are special configurations for a much
3267 * smaller *.js file size.
3269 * @see net.sf.j2s.lib/src/net/sf/j2s/lib/build/SmartJSCompressor.java
3272 * Static class loader class
3274 Clazz._Loader = Clazz.ClazzLoader = function () {};
3277 * Class dependency tree node
3280 var Node = function () {
3283 this.optionals = [];
3284 this.declaration = null;
3285 this.name = null; // id
3287 // this.requires = null;
3288 // this.requiresMap = null;
3289 this.onLoaded = null;
3291 this.random = 0.13412;
3295 ;(function(Clazz, _Loader) {
3297 _Loader._checkLoad = Jmol._checkLoad;
3299 _Loader.updateNodeForFunctionDecoration = function(qName) {
3300 var node = findNode(qName);
3301 if (node && node.status == Node.STATUS_KNOWN) {
3302 window.setTimeout((function(nnn) {
3310 Node.prototype.toString = function() {
3311 return this.name || this.path || "ClazzNode";
3314 Node.STATUS_UNKNOWN = 0;
3315 Node.STATUS_KNOWN = 1;
3316 Node.STATUS_CONTENT_LOADED = 2;
3317 Node.STATUS_MUSTS_LOADED = 3;
3318 Node.STATUS_DECLARED = 4;
3319 Node.STATUS_LOAD_COMPLETE = 5;
3325 _Loader.requireLoaderByBase = function (base) {
3326 for (var i = 0; i < loaders.length; i++) {
3327 if (loaders[i].base == base) {
3331 var loader = new _Loader ();
3333 loaders.push(loader);
3338 * Class dependency tree
3340 var clazzTreeRoot = new Node();
3343 * Used to keep the status whether a given *.js path is loaded or not.
3346 var loadedScripts = {};
3349 * Multiple threads are used to speed up *.js loading.
3352 var inLoadingThreads = 0;
3355 * Maximum of loading threads
3358 var maxLoadingThreads = 6;
3360 var userAgent = navigator.userAgent.toLowerCase ();
3361 var isOpera = (userAgent.indexOf ("opera") != -1);
3362 var isIE = (userAgent.indexOf ("msie") != -1) && !isOpera;
3363 var isGecko = (userAgent.indexOf ("gecko") != -1);
3366 * Opera has different loading order which will result in performance degrade!
3367 * So just return to single thread loading in Opera!
3369 * FIXME: This different loading order also causes bugs in single thread!
3372 maxLoadingThreads = 1;
3373 var index = userAgent.indexOf ("opera/");
3375 var verNumber = 9.0;
3377 verNumber = parseFloat(userAgent.subString (index + 6));
3379 if (verNumber >= 9.6) {
3380 maxLoadingThreads = 6;
3386 * Try to be compatiable with Clazz system.
3387 * In original design _Loader and Clazz are independent!
3388 * -- zhourenjian @ December 23, 2006
3393 if (self.Clazz && Clazz.isClassDefined) {
3394 isClassDefined = Clazz.isClassDefined;
3396 definedClasses = {};
3397 isClassDefined = function (clazzName) {
3398 return definedClasses[clazzName] == true;
3403 * Expand the shortened list of class names.
3405 * JU.Log, $.Display, $.Decorations
3406 * will be expanded to
3407 * JU.Log, JU.Display, JU.Decorations
3408 * where "$." stands for the previous class name's package.
3410 * This method will be used to unwrap the required/optional classes list and
3411 * the ignored classes list.
3414 var unwrapArray = function (arr) {
3415 if (!arr || arr.length == 0)
3418 for (var i = 0; i < arr.length; i++) {
3421 if (arr[i].charAt (0) == '$') {
3422 if (arr[i].charAt (1) == '.') {
3425 var idx = last.lastIndexOf (".");
3427 var prefix = last.substring (0, idx);
3428 arr[i] = prefix + arr[i].substring (1);
3431 arr[i] = "org.eclipse.s" + arr[i].substring (1);
3440 * Used to keep to-be-loaded classes.
3443 var classQueue = [];
3446 var classpathMap = {};
3449 var pkgRefCount = 0;
3452 _Loader.loadPackageClasspath = function (pkg, base, isIndex, fSuccess, mode, pt) {
3453 var map = classpathMap;
3455 fSuccess || (fSuccess = null);
3459 * In some situation, maybe,
3460 * _Loader.packageClasspath ("java", ..., true);
3461 * is called after other _Loader#packageClasspath, e.g.
3463 * _Loader.packageClasspath ("org.eclipse.swt", "...", true);
3464 * _Loader.packageClasspath ("java", "...", true);
3466 * which is not recommended. But _Loader should try to adjust orders
3467 * which requires "java" to be declared before normal _Loader
3468 * #packageClasspath call before that line! And later that line
3469 * should never initialize "java/package.js" again!
3471 var isPkgDeclared = (isIndex && map["@" + pkg]);
3472 if (mode == 0 && isIndex && !map["@java"] && pkg.indexOf ("java") != 0 && needPackage("java")) {
3473 _Loader.loadPackage("java", fSuccess ? function(_package){_Loader.loadPackageClasspath(pkg, base, isIndex, fSuccess, 1)} : null);
3477 if (pkg instanceof Array) {
3480 if (pt < pkg.length)
3481 _Loader.loadPackageClasspath(pkg[pt], base, isIndex, function(_loadPackageClassPath){_Loader.loadPackageClasspath(pkg, base, isIndex, fSuccess, 1, pt + 1)}, 1);
3485 for (var i = 0; i < pkg.length; i++)
3486 _Loader.loadPackageClasspath(pkg[i], base, isIndex, null);
3496 // support ajax for default
3497 var key = "@net.sf.j2s.ajax";
3500 key = "@net.sf.j2s";
3506 pkg = "org.eclipse.swt";
3509 pkg = "net.sf.j2s.ajax";
3515 if (pkg.lastIndexOf(".*") == pkg.length - 2)
3516 pkg = pkg.substring(0, pkg.length - 2);
3519 if (base) // critical for multiple applets
3520 map["@" + pkg] = base;
3521 if (isIndex && !isPkgDeclared && !window[pkg + ".registered"]) {
3524 pkg = "core" // JSmol -- moves java/package.js to core/package.js
3525 _Loader.loadClass(pkg + ".package", function () {
3526 if (--pkgRefCount == 0)
3528 //fSuccess && fSuccess();
3532 fSuccess && fSuccess();
3536 * BH: allows user/developer to load classes even though wrapping and Google
3537 * Closure Compiler has not been run on the class.
3540 Clazz.loadClass = function (name, onLoaded, async) {
3543 Class.forName = Clazz._4Name;
3544 JavaObject = Clazz._O;
3547 return (name && _Loader.loadClass(name, onLoaded, true, async, 1));
3551 * Load the given class ant its related classes.
3554 _Loader.loadClass = function (name, onLoaded, forced, async, mode) {
3556 mode || (mode = 0); // BH: not implemented
3557 (async == null) && (async = false);
3559 if (typeof onLoaded == "boolean")
3560 return Clazz.evalType(name);
3562 System.out.println("loadClass " + name)
3564 // Make sure that packageClasspath ("java", base, true);
3565 // is called before any _Loader#loadClass is called.
3567 if (needPackage("java"))
3568 _Loader.loadPackage("java");
3569 if (needPackage("core"))
3570 _Loader.loadPackage("core");
3572 // var swtPkg = "org.eclipse.swt";
3573 // if (name.indexOf (swtPkg) == 0 || name.indexOf ("$wt") == 0) {
3574 // _Loader.assurePackageClasspath (swtPkg);
3576 // if (name.indexOf ("junit") == 0) {
3577 // _Loader.assurePackageClasspath ("junit");
3580 // Any _Loader#loadClass calls will be queued until java.* core classes are loaded.
3582 _Loader.keepOnLoading = true;
3584 if (!forced && (pkgRefCount && name.lastIndexOf(".package") != name.length - 8
3585 || name.indexOf("java.") != 0 && !isClassDefined(runtimeKeyClass)
3587 queueBe4KeyClazz.push([name, onLoaded]);
3590 System.out.println("loadclass-queuing" + name+ runtimeKeyClass + " "+ isClassDefined(runtimeKeyClass))
3595 if ((b = isClassDefined(name)) || isClassExcluded(name)) {
3596 if (b && onLoaded) {
3597 var nn = findNode(name);
3598 if (!nn || nn.status >= Node.STATUS_LOAD_COMPLETE) {
3600 window.setTimeout(onLoaded, 25);
3608 var path = _Loader.getClasspathFor(name);
3609 var existed = loadedScripts[path];
3610 var qq = classQueue;
3612 for (var i = qq.length; --i >= 0;)
3613 if (qq[i].path == path || qq[i].name == name) {
3619 var n = findNode(name);
3622 n.onLoaded = onLoaded;
3623 } else if (onLoaded != n.onLoaded) {
3624 n.onLoaded = (function (nF, oF) { return function () { nF(); oF() }; }) (n.onLoaded, onLoaded);
3631 var n = (Clazz.unloadedClasses[name] && findNode(name) || new Node());
3634 n.isPackage = (path.lastIndexOf("package.js") == path.length - 10);
3635 mappingPathNameNode(path, name, n);
3636 n.onLoaded = onLoaded;
3637 n.status = Node.STATUS_KNOWN;
3638 var needBeingQueued = false;
3639 for (var i = qq.length; --i >= 0;) {
3640 if (qq[i].status != Node.STATUS_LOAD_COMPLETE) {
3641 needBeingQueued = true;
3646 if (n.isPackage) {//forced
3647 // push class to queue
3649 for (; --pt >= 0;) {
3650 if (qq[pt].isPackage)
3652 qq[pt + 1] = qq[pt];
3655 } else if (needBeingQueued) {
3658 if (!needBeingQueued) { // can be loaded directly
3661 bSave = isLoadingEntryClass;
3662 isLoadingEntryClass = true;
3664 if (forced)onLoaded = null;
3665 addChildClassNode(clazzTreeRoot, n, true);
3666 loadScript(n, n.path, n.requiredBy, false, onLoaded ? function(_loadClass){ isLoadingEntryClass = bSave; onLoaded()}: null);
3671 * Check whether given package's classpath is setup or not.
3672 * Only "java" and "org.eclipse.swt" are accepted in argument.
3675 var needPackage = function(pkg) {
3676 // note that false != null and true != null
3677 return (window[pkg + ".registered"] != null && !classpathMap["@" + pkg]);
3681 _Loader.loadPackage = function(pkg, fSuccess) {
3682 fSuccess || (fSuccess = null);
3683 window[pkg + ".registered"] = false;
3684 _Loader.loadPackageClasspath(pkg,
3685 (_Loader.J2SLibBase || (_Loader.J2SLibBase = (_Loader.getJ2SLibBase() || "j2s/"))),
3690 * Register classes to a given *.z.js path, so only a single *.z.js is loaded
3691 * for all those classes.
3694 _Loader.jarClasspath = function (jar, clazzes) {
3695 if (!(clazzes instanceof Array))
3696 clazzes = [classes];
3697 unwrapArray(clazzes);
3698 for (var i = clazzes.length; --i >= 0;)
3699 classpathMap["#" + clazzes[i]] = jar;
3700 classpathMap["$" + jar] = clazzes;
3704 * Usually be used in .../package.js. All given packages will be registered
3705 * to the same classpath of given prefix package.
3708 _Loader.registerPackages = function (prefix, pkgs) {
3709 //_Loader.checkInteractive ();
3710 var base = _Loader.getClasspathFor (prefix + ".*", true);
3711 for (var i = 0; i < pkgs.length; i++) {
3712 if (window["Clazz"]) {
3713 Clazz.declarePackage (prefix + "." + pkgs[i]);
3715 _Loader.loadPackageClasspath (prefix + "." + pkgs[i], base);
3720 * Using multiple sites to load *.js in multiple threads. Using multiple
3721 * sites may avoid 2 HTTP 1.1 connections recommendation limit.
3722 * Here is a default implementation for http://archive.java2script.org.
3723 * In site archive.java2script.org, there are 6 sites:
3724 * 1. http://archive.java2script.org or http://a.java2script.org
3725 * 2. http://erchive.java2script.org or http://e.java2script.org
3726 * 3. http://irchive.java2script.org or http://i.java2script.org
3727 * 4. http://orchive.java2script.org or http://o.java2script.org
3728 * 5. http://urchive.java2script.org or http://u.java2script.org
3729 * 6. http://yrchive.java2script.org or http://y.java2script.org
3733 _Loader.multipleSites = function (path) {
3734 var deltas = window["j2s.update.delta"];
3735 if (deltas && deltas instanceof Array && deltas.length >= 3) {
3736 var lastOldVersion = null;
3737 var lastNewVersion = null;
3738 for (var i = 0; i < deltas.length / 3; i++) {
3739 var oldVersion = deltas[i + i + i];
3740 if (oldVersion != "$") {
3741 lastOldVersion = oldVersion;
3743 var newVersion = deltas[i + i + i + 1];
3744 if (newVersion != "$") {
3745 lastNewVersion = newVersion;
3747 var relativePath = deltas[i + i + i + 2];
3748 var key = lastOldVersion + "/" + relativePath;
3749 var idx = path.indexOf (key);
3750 if (idx != -1 && idx == path.length - key.length) {
3751 path = path.substring (0, idx) + lastNewVersion + "/" + relativePath;
3756 var length = path.length;
3757 if (maxLoadingThreads > 1
3758 && ((length > 15 && path.substring (0, 15) == "http://archive.")
3759 || (length > 9 && path.substring (0, 9) == "http://a."))) {
3760 var index = path.lastIndexOf("/");
3761 if (index < length - 3) {
3762 var arr = ['a', 'e', 'i', 'o', 'u', 'y'];
3763 var c1 = path.charCodeAt (index + 1);
3764 var c2 = path.charCodeAt (index + 2);
3765 var idx = (length - index) * 3 + c1 * 5 + c2 * 7; // Hash
3766 return path.substring (0, 7) + arr[idx % 6] + path.substring (8);
3774 * Return the *.js path of the given class. Maybe the class is contained
3775 * in a *.z.js jar file.
3776 * @param clazz Given class that the path is to be calculated for. May
3777 * be java.package, or java.lang.String
3778 * @param forRoot Optional argument, if true, the return path will be root
3779 * of the given classs' package root path.
3780 * @param ext Optional argument, if given, it will replace the default ".js"
3784 _Loader.getClasspathFor = function (clazz, forRoot, ext) {
3785 var path = classpathMap["#" + clazz];
3786 if (!path || forRoot || ext) {
3790 clazz = clazz.replace(/\./g, "/");
3791 if ((idx = path.lastIndexOf(clazz)) >= 0
3792 || (idx = clazz.lastIndexOf("/")) >= 0
3793 && (idx = path.lastIndexOf(clazz.substring(0, idx))) >= 0)
3794 base = path.substring(0, idx);
3796 idx = clazz.length + 2;
3797 while ((idx = clazz.lastIndexOf(".", idx - 2)) >= 0)
3798 if ((base = classpathMap["@" + clazz.substring(0, idx)]))
3801 clazz = clazz.replace (/\./g, "/");
3804 var bins = "binaryFolders";
3805 base = (window["Clazz"] && Clazz[bins] && Clazz[bins].length ? Clazz[bins][0]
3806 : _Loader[bins] && _Loader[bins].length ? _Loader[bins][0]
3809 path = (base.lastIndexOf("/") == base.length - 1 ? base : base + "/") + (forRoot ? ""
3810 : clazz.lastIndexOf("/*") == clazz.length - 2 ? clazz.substring(0, idx + 1)
3811 : clazz + (!ext ? ".js" : ext.charAt(0) != '.' ? "." + ext : ext));
3813 return path;//_Loader.multipleSites(path);
3817 * To ignore some classes.
3820 _Loader.ignore = function () {
3821 var clazzes = (arguments.length == 1 && arguments[0] instanceof Array ?
3822 clazzes = arguments[0] : null);
3823 var n = (clazzes ? clazzes.length : arguments.length);
3825 clazzes = new Array(n);
3826 for (var i = 0; i < n; i++)
3827 clazzes[i] = arguments[i];
3829 unwrapArray(clazzes);
3830 for (var i = 0; i < n; i++)
3831 excludeClassMap["@" + clazzes[i]] = 1;
3835 * The following *.script* can be overriden to indicate the
3836 * status of classes loading.
3838 * TODO: There should be a Java interface with name like INativeLoaderStatus
3841 _Loader.onScriptLoading = function (file){};
3844 _Loader.onScriptLoaded = function (file, isError){};
3847 _Loader.onScriptInitialized = function (file){};
3850 _Loader.onScriptCompleted = function (file){};
3853 _Loader.onClassUnloaded = function (clazz){};
3856 * After all the classes are loaded, this method will be called.
3857 * Should be overriden to run *.main([]).
3860 _Loader.onGlobalLoaded = function () {};
3863 _Loader.keepOnLoading = true; // never set false in this code
3867 var mapPath2ClassNode = {};
3870 var isClassExcluded = function (clazz) {
3871 return excludeClassMap["@" + clazz];
3874 /* Used to keep ignored classes */
3876 var excludeClassMap = {};
3879 var evaluate = function(file, js) {
3885 var s = "[Java2Script] The required class file \n\n" + file + (js.indexOf("[Exception") == 0 && js.indexOf("data: no") ?
3886 "\nwas not found.\n"
3887 : "\ncould not be loaded. Script error: " + e.message + " \n\ndata:\n\n" + js) + "\n\n" + Clazz.getStackTrace();
3892 _Loader.onScriptLoaded(file, false);
3893 tryToLoadNext(file);
3897 var failedHandles = {};
3900 var generateRemovingFunction = function (node) {
3901 return function () {
3902 if (node.readyState != "interactive") {
3904 if (node.parentNode)
3905 node.parentNode.removeChild (node);
3913 var removeScriptNode = function (n) {
3914 if (window["j2s.script.debugging"]) {
3917 // lazily remove script nodes.
3918 window.setTimeout (generateRemovingFunction (n), 1);
3922 Clazz._4Name = function(clazzName, applet, state) {
3923 if (Clazz.isClassDefined(clazzName))
3924 return Clazz.evalType(clazzName);
3925 var f = (Jmol._isAsync && applet ? applet._restoreState(clazzName, state) : null);
3927 return null; // must be already being created
3928 if (_Loader.setLoadingMode(f ? _Loader.MODE_SCRIPT : "xhr.sync")) {
3929 _Loader.loadClass(clazzName, f, false, true, 1);
3930 return null; // this will surely throw an error, but that is OK
3932 //alert ("Using Java reflection: " + clazzName + " for " + applet._id + " \n"+ Clazz.getStackTrace());
3933 _Loader.loadClass(clazzName);
3934 return Clazz.evalType(clazzName);
3938 * BH: possibly useful for debugging
3940 Clazz.currentPath= "";
3943 * Load *.js by adding script elements into head. Hook the onload event to
3944 * load the next class in dependency tree.
3947 var loadScript = function (node, file, why, ignoreOnload, fSuccess, _loadScript) {
3948 Clazz.currentPath = file;
3949 if (ignoreOnload)alert("WHY>>")
3950 //BH removed // maybe some scripts are to be loaded without needs to know onload event.
3951 // if (!ignoreOnload && loadedScripts[file]) {
3952 // _Loader.tryToLoadNext(file);
3955 loadedScripts[file] = true;
3956 // also remove from queue
3957 removeArrayItem(classQueue, file);
3959 // forces not-found message
3960 isUsingXMLHttpRequest = true;
3961 isAsynchronousLoading = false;
3962 if (_Loader._checkLoad) {
3963 System.out.println("\t" + file + (why ? "\n -- required by " + why : "") + " ajax=" + isUsingXMLHttpRequest + " async=" + isAsynchronousLoading)
3966 _Loader.onScriptLoading(file);
3967 if (isUsingXMLHttpRequest && !isAsynchronousLoading) {
3968 // alert("\t" + file + (why ? "\n -- required by " + why : "") + " ajax=" + isUsingXMLHttpRequest + " async=" + isAsynchronousLoading + " " + Clazz.getStackTrace())
3969 // synchronous loading
3970 // works in MSIE locally unless a binary file :)
3971 // from Jmol.api.Interface only
3972 var data = Jmol._getFileData(file);
3974 evaluate(file, data);
3976 alert(e + " loading file " + file + " " + node.name + " " + Clazz.getStackTrace());
3979 // System.out.println("firing in loadScript " + file + " " + (fSuccess && fSuccess.toString()))
3986 System.out.println("for file " + file +" fSuccess = " + (fSuccess ? fSuccess.toString() : ""))
3992 success:W3CScriptOnCallback(file, false, fSuccess),
3993 error:W3CScriptOnCallback(file, true, fSuccess)
4000 var W3CScriptOnCallback = function (path, forError, fSuccess) {
4001 var s = Clazz.getStackTrace();
4002 // if (!fSuccess)alert("why no fSuccess?" + s)
4003 return function () {
4004 //System.out.println("returning " + (fSuccess ? fSuccess.toString() : "no function ") + s)
4005 if (forError && __debuggingBH)Clazz.alert ("############ forError=" + forError + " path=" + path + " ####" + (forError ? "NOT" : "") + "LOADED###");
4006 if (isGecko && this.timeoutHandle)
4007 window.clearTimeout(this.timeoutHandle), this.timeoutHandle = null;
4008 if (inLoadingThreads > 0)
4010 //System.out.println("w3ccalback for " + path + " " + inLoadingThreads + " threads")
4012 this.onerror = null;
4014 alert ("There was a problem loading " + path);
4015 _Loader.onScriptLoaded(path, true);
4019 f = function(_W3scriptFS){removeScriptNode(node);tryToLoadNext(path, fSuccess); };
4021 f = function(_W3script){removeScriptNode(node);tryToLoadNext(path)};
4022 if (loadingTimeLag >= 0)
4023 window.setTimeout(function() { tryToLoadNext(path, f); }, loadingTimeLag);
4025 tryToLoadNext(path, f);
4030 var isLoadingEntryClass = true;
4033 var besidesJavaPackage = false;
4036 * After class is loaded, this method will be executed to check whether there
4037 * are classes in the dependency tree that need to be loaded.
4040 var tryToLoadNext = function (file, fSuccess) {
4041 var node = mapPath2ClassNode["@" + file];
4042 if (!node) // maybe class tree root
4045 // check for content loaded
4046 var clazzes = classpathMap["$" + file];
4048 for (var i = 0; i < clazzes.length; i++) {
4049 var name = clazzes[i];
4050 if (name != node.name && (n = findNode(name))) {
4051 if (n.status < Node.STATUS_CONTENT_LOADED) {
4052 n.status = Node.STATUS_CONTENT_LOADED;
4058 var pp = classpathMap["#" + name];
4060 alert (name + " J2S error in tryToLoadNext");
4061 error("Java2Script implementation error! Please report this bug!");
4064 mappingPathNameNode (n.path, name, n);
4065 n.status = Node.STATUS_CONTENT_LOADED;
4066 addChildClassNode(clazzTreeRoot, n, false);
4071 if (node instanceof Array) {
4072 for (var i = 0; i < node.length; i++) {
4073 if (node[i].status < Node.STATUS_CONTENT_LOADED) {
4074 node[i].status = Node.STATUS_CONTENT_LOADED;
4075 updateNode(node[i]);
4078 } else if (node.status < Node.STATUS_CONTENT_LOADED) {
4079 var stillLoading = false;
4080 var ss = document.getElementsByTagName ("SCRIPT");
4081 for (var i = 0; i < ss.length; i++) {
4083 if (ss[i].onreadystatechange && ss[i].onreadystatechange.path == node.path
4084 && ss[i].readyState == "interactive") {
4085 stillLoading = true;
4088 } else if (ss[i].onload && ss[i].onload.path == node.path) {
4089 stillLoading = true;
4093 if (!stillLoading) {
4094 node.status = Node.STATUS_CONTENT_LOADED;
4099 * Maybe in #optinalLoaded inside above _Loader#updateNode calls,
4100 * _Loader.keepOnLoading is set false (Already loaded the wanted
4101 * classes), so here check to stop.
4104 if (!_Loader.keepOnLoading) // set externally
4107 // check for a "must" class that has content and load it
4110 if ((n = findNextMustClass(Node.STATUS_KNOWN))) {
4112 while (inLoadingThreads < maxLoadingThreads) {
4113 if (!(n = findNextMustClass(Node.STATUS_KNOWN)))
4115 loadClassNode(n); // will increase inLoadingThreads!
4117 } else if ((cq = classQueue).length != 0) {
4118 /* queue must be loaded in order! */
4120 if (!loadedScripts[n.path]
4122 || !isLoadingEntryClass
4124 || n.optionals.length) {
4125 addChildClassNode(clazzTreeRoot, n, true);
4126 loadScript(n, n.path, n.requiredBy, false);
4127 } else if (isLoadingEntryClass) {
4129 * The first time reaching here is the time when ClassLoader
4130 * is trying to load entry class. Class with #main method and
4131 * is to be executed is called Entry Class.
4133 * Here when loading entry class, ClassLoader should not call
4134 * the next following loading script. This is because, those
4135 * scripts will try to mark the class as loaded directly and
4136 * then continue to call #onLoaded callback method,
4137 * which results in an script error!
4139 isLoadingEntryClass = false;
4141 } else if ((n = findNextRequiredClass(Node.STATUS_KNOWN))) {
4143 while (inLoadingThreads < maxLoadingThreads) {
4144 if (!(n = findNextRequiredClass(Node.STATUS_KNOWN)))
4146 loadClassNode(n); // will increase inLoadingThreads!
4151 if (working || inLoadingThreads > 0)
4154 // now check all classes that MUST be loaded prior to initialization
4155 // of some other class (static calls, extends, implements)
4156 // and all classes REQUIRED somewhere in that class, possibly by the constructor
4157 // (that is, "new xxxx()" called somewhere in code) and update them
4158 // that have content but are not declared already
4159 var f = [findNextMustClass,findNextRequiredClass];
4160 var lastNode = null;
4161 for (var i = 0; i < 2; i++)
4162 while ((n = f[i](Node.STATUS_CONTENT_LOADED))) {
4163 if (i == 1 && lastNode === n) // Already existed cycle ?
4164 n.status = Node.STATUS_LOAD_COMPLETE;
4169 // check for load cycles
4173 if (!checkCycle(clazzTreeRoot, file))
4177 // and update all MUST and REQUIRED classes that are declared already
4179 for (var i = 0; i < 2; i++) {
4181 while ((n = f[i](Node.STATUS_DECLARED))) {
4184 updateNode(lastNode = n);
4188 for (var i = 0; i < 2; i++)
4189 while ((n = f[i](Node.STATUS_DECLARED)))
4190 done.push(n), n.status = Node.STATUS_LOAD_COMPLETE;
4192 for (var i = 0; i < done.length; i++)
4193 destroyClassNode(done[i]);
4194 for (var i = 0; i < done.length; i++)
4195 if ((f = done[i].onLoaded))
4196 done[i].onLoaded = null, f();
4205 //System.out.println(node.name + " loaded completely" + _Loader.onGlobalLoaded + "\n\n")
4207 //System.out.println("tryToLoadNext firing " + _Loader._classCountOK + "/" + _Loader._classCountPending + " " + fSuccess.toString() + " " + Clazz.getStackTrace())
4209 } else if (_Loader._classCountPending) {
4210 for (var name in _Loader._classPending) {
4211 var n = findNode(name);
4212 System.out.println("class left pending " + name + " " + n);
4220 // System.out.println("I think I'm done "
4221 // + _Loader._classCountOK + "/" + _Loader._classCountPending + " "
4222 //+ _Loader.onGlobalLoaded.toString() + " " + Clazz.getStackTrace()
4224 if (_Loader._checkLoad) {
4225 System.out.println("I think I'm done: SAEM call count: " + SAEMid);
4226 Clazz.showDuplicates(true);
4229 _Loader.onGlobalLoaded();
4236 * There are classes reference cycles. Try to detect and break those cycles.
4239 var checkCycle = function (node, file) {
4241 var len = ts.length;
4242 // add this node to tracks
4246 if (ts[i] === node && ts[i].status >= Node.STATUS_DECLARED)
4249 // this node is already in tracks, and it has been declared already
4250 // for each node in tracks, set its status to "LOAD_COMPLETE"
4251 // update all parents, remove all parents, and fire its onLoaded function
4252 // then clear tracks and return true (keep checking)
4253 if (_Loader._checkLoad) {
4254 var msg = "cycle found loading " + file + " for " + node;
4255 System.out.println(msg)
4257 for (; i < len; i++) {
4259 n.status = Node.STATUS_LOAD_COMPLETE;
4260 destroyClassNode(n); // Same as above
4261 for (var k = 0; k < n.parents.length; k++)
4262 updateNode(n.parents[k]);
4265 if (_Loader._checkLoad) {
4266 var msg = "cycle setting status to LOAD_COMPLETE for " + n.name + (f ? " firing " + f.toString() : "");
4267 System.out.println(msg)
4270 n.onLoaded = null, f();
4275 var a = [node.musts, node.optionals];
4276 for (var j = 0; j < 2; j++)
4277 for (var r = a[j], i = r.length; --i >= 0;)
4278 if (r[i].status == Node.STATUS_DECLARED && checkCycle(r[i], file))
4280 // reset _tracks to its original length
4282 return false; // done
4286 _Loader._classCountPending = 0;
4287 _Loader._classCountOK = 0;
4288 _Loader._classPending = {};
4290 _Loader.showPending = function() {
4292 for (var name in _Loader._classPending) {
4293 var n = findNode(name);
4295 alert("No node for " + name);
4299 System.out.println(showNode("", "", n, "", 0));
4304 var showNode = function(s, names, node, inset, level) {
4305 names += "--" + node.name;
4308 s += inset + " ...\n";
4312 s += inset + "status: " + node.status + "\n";
4313 if (node.parents && node.parents.length && node.parents[0] && node.parents[0].name) {
4314 s += inset + "parents: " + node.parents.length + "\n";
4315 for (var i = 0; i < node.parents.length; i++) {
4316 s = showNode(s, names, node.parents[i], inset + "\t", level+1);
4320 // if (node.requiredBy) {
4321 // s += inset + "requiredBy:\n";
4322 // s = showNode(s, names, node.requiredBy, inset + "\t", level+1);
4329 * Update the dependency tree nodes recursively.
4332 updateNode = function(node, _updateNode) {
4333 if (!node.name || node.status >= Node.STATUS_LOAD_COMPLETE) {
4334 destroyClassNode(node);
4338 // check for declared and also having MUSTS
4339 if (node.musts.length && node.declaration) {
4340 for (var mustLength = node.musts.length, i = mustLength; --i >= 0;) {
4341 var n = node.musts[i];
4342 n.requiredBy = node;
4343 if (n.status < Node.STATUS_DECLARED && isClassDefined (n.name)) {
4344 var nns = []; // a stack for onLoaded events
4345 n.status = Node.STATUS_LOAD_COMPLETE;
4346 destroyClassNode(n); // Same as above
4347 if (n.declaration && n.declaration.clazzList) {
4348 // For those classes within one *.js file, update them synchronously.
4349 for (var j = 0, list = n.declaration.clazzList, l = list.length; j < l; j++) {
4350 var nn = findNode (list[j]);
4351 if (nn && nn.status != Node.STATUS_LOAD_COMPLETE
4353 nn.status = n.status;
4354 nn.declaration = null;
4355 destroyClassNode(nn);
4356 nn.onLoaded && nns.push(nn);
4359 n.declaration = null;
4361 // fire all onLoaded events
4364 for (var j = 0; j < nns.length; j++) {
4365 var onLoaded = nns[j].onLoaded;
4367 nns[j].onLoaded = null;
4372 (n.status == Node.STATUS_CONTENT_LOADED) && updateNode(n); // musts may be changed
4373 if (n.status < Node.STATUS_DECLARED)
4376 if (node.musts.length != mustLength) {
4377 // length changed -- restart!
4378 i = mustLength = node.musts.length;
4385 if (node.status < Node.STATUS_DECLARED) {
4386 var decl = node.declaration;
4388 decl(), decl.executed = true;
4389 if(_Loader._checkLoad) {
4390 if (_Loader._classPending[node.name]) {
4391 delete _Loader._classPending[node.name];
4392 _Loader._classCountOK;
4393 _Loader._classCountPending--;
4394 // System.out.println("OK " + (_Loader._classCountOK) + " FOR " + node.name)
4397 node.status = Node.STATUS_DECLARED;
4399 definedClasses[node.name] = true;
4400 _Loader.onScriptInitialized(node.path);
4401 if (node.declaration && node.declaration.clazzList) {
4402 // For those classes within one *.js file, update them synchronously.
4403 for (var j = 0, list = node.declaration.clazzList, l = list.length; j < l; j++) {
4404 var nn = findNode(list[j]);
4405 if (nn && nn.status != Node.STATUS_DECLARED
4407 nn.status = Node.STATUS_DECLARED;
4409 definedClasses[nn.name] = true;
4410 _Loader.onScriptInitialized(nn.path);
4415 var level = Node.STATUS_DECLARED;
4416 if (node.optionals.length == 0 && node.musts.length == 0
4417 || node.status > Node.STATUS_KNOWN && !node.declaration
4418 || checkStatusIs(node.musts, Node.STATUS_LOAD_COMPLETE)
4419 && checkStatusIs(node.optionals, Node.STATUS_LOAD_COMPLETE)) {
4420 level = Node.STATUS_LOAD_COMPLETE;
4421 if (!doneLoading(node, level))
4423 // For those classes within one *.js file, update them synchronously.
4424 if (node.declaration && node.declaration.clazzList) {
4425 for (var j = 0, list = node.declaration.clazzList, l = list.length; j < l; j++) {
4426 var nn = findNode(list[j]);
4427 if (nn && nn.status != level && nn !== node) {
4428 nn.declaration = null;
4429 if (!doneLoading(nn, level))
4435 // _Loader.updateParents = function (node, level, _updateParents)
4436 if (node.parents && node.parents.length) {
4437 for (var i = 0; i < node.parents.length; i++) {
4438 var p = node.parents[i];
4439 if (p.status < level)
4440 updateNode(p, p.name);
4442 if (level == Node.STATUS_LOAD_COMPLETE)
4448 var checkStatusIs = function(arr, status){
4449 for (var i = arr.length; --i >= 0;)
4450 if (arr[i].status < status)
4455 var doneLoading = function(node, level, _doneLoading) {
4456 node.status = level;
4457 _Loader.onScriptCompleted(node.path);
4459 var onLoaded = node.onLoaded;
4461 node.onLoaded = null;
4463 if (!_Loader.keepOnLoading)
4467 destroyClassNode(node);
4472 * Be used to record already used random numbers. And next new random
4473 * number should not be in the property set.
4481 var getRnd = function() {
4482 while (true) { // get a unique random number
4483 var rnd = Math.random();
4485 if (!usedRandoms[s])
4486 return (usedRandoms[s] = 1, clazzTreeRoot.random = rnd);
4491 var findNode = function(clazzName) {
4493 return findNodeUnderNode(clazzName, clazzTreeRoot);
4497 var findNextRequiredClass = function(status) {
4499 return findNextRequiredNode(clazzTreeRoot, status);
4503 var findNextMustClass = function(status) {
4504 return findNextMustNode(clazzTreeRoot, status);
4508 var findNodeUnderNode = function(clazzName, node) {
4510 // node, then musts then optionals
4511 return (node.name == clazzName ? node
4512 : (n = findNodeWithin(clazzName, node.musts))
4513 || (n = findNodeWithin(clazzName, node.optionals))
4518 var findNodeWithin = function(name, arr) {
4519 var rnd = clazzTreeRoot.random;
4520 for (var i = arr.length; --i >= 0;) {
4524 if (n.random != rnd) {
4526 if ((n = findNodeUnderNode(name, n)))
4534 var checkStatus = function(n, status) {
4535 return (n.status == status
4536 && (status != Node.STATUS_KNOWN || !loadedScripts[n.path])
4537 && (status == Node.STATUS_DECLARED || !isClassDefined (n.name)));
4541 var findNextMustNode = function(node, status) {
4542 for (var i = node.musts.length; --i >= 0;) {
4543 var n = node.musts[i];
4544 if (checkStatus(n, status) || (n = findNextMustNode(n, status)))
4547 return (checkStatus(node, status) ? node : null);
4551 var findNextRequiredNode = function (node, status) {
4552 // search musts first
4553 // search optionals second
4554 // search itself last
4556 return ((n = searchClassArray(node.musts, status))
4557 || (n = searchClassArray(node.optionals, status))
4558 || checkStatus(n = node, status) ? n : null);
4562 var searchClassArray = function (arr, status) {
4564 var rnd = clazzTreeRoot.random;
4565 for (var i = 0; i < arr.length; i++) {
4567 if (checkStatus(n, status))
4569 if (n.random != rnd) {
4570 n.random = rnd; // mark as visited!
4571 if ((n = findNextRequiredNode(n, status)))
4580 * This map variable is used to mark that *.js is correctly loaded.
4581 * In IE, _Loader has defects to detect whether a *.js is correctly
4582 * loaded or not, so inner loading mark is used for detecting.
4585 var innerLoadedScripts = {};
4588 * This method will be called in almost every *.js generated by Java2Script
4592 var load = function (musts, name, optionals, declaration) {
4593 // called as name.load in Jmol
4594 if (name instanceof Array) {
4596 for (var i = 0; i < name.length; i++)
4597 load(musts, name[i], optionals, declaration, name);
4601 if (_Loader._checkLoad) {
4602 if (_Loader._classPending[name]) {
4603 //alert("duplicate load for " + name)
4605 _Loader._classPending[name] = 1;
4606 if (_Loader._classCountPending++ == 0)
4607 _Loader._classCountOK = 0;
4608 System.out.println("Loading class " + name);
4612 // if (clazz.charAt (0) == '$')
4613 // clazz = "org.eclipse.s" + clazz.substring (1);
4614 var node = mapPath2ClassNode["#" + name];
4615 if (!node) { // load called inside *.z.js?
4616 var n = findNode(name);
4617 node = (n ? n : new Node());
4619 node.path = classpathMap["#" + name] || "unknown";
4620 mappingPathNameNode(node.path, name, node);
4621 node.status = Node.STATUS_KNOWN;
4622 addChildClassNode(clazzTreeRoot, node, false);
4624 processRequired(node, musts, true);
4625 if (arguments.length == 5 && declaration) {
4626 declaration.status = node.status;
4627 declaration.clazzList = arguments[4];
4629 node.declaration = declaration;
4631 node.status = Node.STATUS_CONTENT_LOADED;
4632 processRequired(node, optionals, false);
4636 var processRequired = function(node, arr, isMust) {
4637 if (arr && arr.length) {
4639 for (var i = 0; i < arr.length; i++) {
4643 if (isClassDefined(name)
4644 || isClassExcluded(name))
4646 var n = findNode(name);
4650 n.status = Node.STATUS_KNOWN;
4652 n.requiredBy = node;
4653 addChildClassNode(node, n, isMust);
4659 * Try to be compatiable of Clazz
4661 if (window["Clazz"]) {
4664 _Loader.load = load;
4667 * Map different class to the same path! Many classes may be packed into
4675 var mappingPathNameNode = function (path, name, node) {
4676 var map = mapPath2ClassNode;
4677 var keyPath = "@" + path;
4678 var v = map[keyPath];
4680 if (v instanceof Array) {
4681 var existed = false;
4682 for (var i = 0; i < v.length; i++) {
4683 if (v[i].name == name) {
4691 map[keyPath] = [v, node];
4694 map[keyPath] = node;
4696 map["#" + name] = node;
4700 var loadClassNode = function (node) {
4701 var name = node.name;
4702 if (!isClassDefined (name)
4703 && !isClassExcluded (name)) {
4704 var path = _Loader.getClasspathFor (name/*, true*/);
4706 mappingPathNameNode (path, name, node);
4707 if (!loadedScripts[path]) {
4708 loadScript(node, path, node.requiredBy, false);
4719 var runtimeKeyClass = _Loader.runtimeKeyClass = "java.lang.String";
4722 * Queue used to store classes before key class is loaded.
4725 var queueBe4KeyClazz = [];
4731 * Return J2SLib base path from existed SCRIPT src attribute.
4734 _Loader.getJ2SLibBase = function () {
4735 var o = window["j2s.lib"];
4736 return (o ? o.base + (o.alias == "." ? "" : (o.alias ? o.alias : (o.version ? o.version : "1.0.0")) + "/") : null);
4740 * Indicate whether _Loader is loading script synchronously or
4744 var isAsynchronousLoading = true;
4747 var isUsingXMLHttpRequest = false;
4750 var loadingTimeLag = -1;
4752 _Loader.MODE_SCRIPT = 4;
4753 _Loader.MODE_XHR = 2;
4754 _Loader.MODE_SYNC = 1;
4758 * asynchronous modes:
4759 * async(...).script, async(...).xhr, async(...).xmlhttprequest,
4760 * script.async(...), xhr.async(...), xmlhttprequest.async(...),
4763 * synchronous modes:
4764 * sync(...).xhr, sync(...).xmlhttprequest,
4765 * xhr.sync(...), xmlhttprequest.sync(...),
4766 * xmlhttprequest, xhr
4769 * Script 4; XHR 2; SYNC bit 1;
4772 _Loader.setLoadingMode = function (mode, timeLag) {
4775 if (typeof mode == "string") {
4776 mode = mode.toLowerCase();
4777 if (mode.indexOf("script") >= 0)
4780 async = (mode.indexOf("async") >=0);
4781 async = false; // BH
4783 if (mode & _Loader.MODE_SCRIPT)
4786 async = !(mode & _Loader.MODE_SYNC);
4788 isUsingXMLHttpRequest = ajax;
4789 isAsynchronousLoading = async;
4790 loadingTimeLag = (async && timeLag >= 0 ? timeLag: -1);
4795 var runtimeLoaded = function () {
4796 if (pkgRefCount || !isClassDefined(runtimeKeyClass))
4798 var qbs = queueBe4KeyClazz;
4799 for (var i = 0; i < qbs.length; i++)
4800 _Loader.loadClass(qbs[i][0], qbs[i][1]);
4801 queueBe4KeyClazz = [];
4805 * Load those key *.z.js. This *.z.js will be surely loaded before other
4809 _Loader.loadZJar = function (zjarPath, keyClass) {
4810 // used only by package.js for core.z.js
4812 var isArr = (keyClass instanceof Array);
4814 keyClass = keyClass[keyClass.length - 1];
4816 f = (keyClass == runtimeKeyClass ? runtimeLoaded : null);
4817 _Loader.jarClasspath(zjarPath, isArr ? keyClass : [keyClass]);
4818 // BH note: runtimeKeyClass is java.lang.String
4819 _Loader.loadClass(keyClass, f, true);
4826 * The method help constructing the multiple-binary class dependency tree.
4829 var addChildClassNode = function (parent, child, isMust) {
4830 var existed = false;
4834 if (!child.requiredBy)
4835 child.requiredBy = parent;
4836 // if (!parent.requiresMap){
4837 // parent.requires = [];
4838 // parent.requiresMap = {};
4840 // if (!parent.requiresMap[child.name]) {
4841 // parent.requiresMap[child.name] = 1;
4842 // parent.requires.push[child];
4845 arr = parent.optionals;
4847 if (!NodeMap[child.name]) {
4848 _allNodes.push(child)
4849 NodeMap[child.name]=child
4851 for (var i = 0; i < arr.length; i++) {
4852 if (arr[i].name == child.name) {
4859 if (isLoadingEntryClass
4860 && child.name.indexOf("java") != 0
4861 && child.name.indexOf("net.sf.j2s.ajax") != 0) {
4862 if (besidesJavaPackage)
4863 isLoadingEntryClass = false;
4864 besidesJavaPackage = true;
4865 // } else if (child.name.indexOf("org.eclipse.swt") == 0
4866 // || child.name.indexOf("$wt") == 0) {
4867 // window["swt.lazy.loading.callback"] = swtLazyLoading;
4868 // if (needPackage("org.eclipse.swt"))
4869 // return _Loader.loadPackage("org.eclipse.swt", function() {addParentClassNode(child, parent)});
4872 addParentClassNode(child, parent);
4876 var addParentClassNode = function(child, parent) {
4877 if (parent.name && parent != clazzTreeRoot && parent != child)
4878 for (var i = 0; i < child.parents.length; i++)
4879 if (child.parents[i].name == parent.name)
4881 child.parents.push(parent);
4885 var destroyClassNode = function (node) {
4886 var parents = node.parents;
4888 for (var k = parents.length; --k >= 0;)
4889 removeArrayItem(parents[k].musts, node) || removeArrayItem(parents[k].optionals, node);
4893 _Loader.unloadClassExt = function (qClazzName) {
4895 definedClasses[qClazzName] = false;
4896 if (classpathMap["#" + qClazzName]) {
4897 var pp = classpathMap["#" + qClazzName];
4898 classpathMap["#" + qClazzName] = null;
4899 var arr = classpathMap["$" + pp];
4900 removeArrayItem(arr, qClazzName) && (classpathMap["$" + pp] = arr);
4902 var n = findNode(qClazzName);
4904 n.status = Node.STATUS_KNOWN;
4905 loadedScripts[n.path] = false;
4907 var path = _Loader.getClasspathFor (qClazzName);
4908 loadedScripts[path] = false;
4909 innerLoadedScripts[path] && (innerLoadedScripts[path] = false);
4910 _Loader.onClassUnloaded(qClazzName);
4914 var assureInnerClass = function (clzz, fun) {
4915 clzz = clzz.__CLASS_NAME__;
4916 if (Clazz.unloadedClasses[clzz]) {
4917 if (clzz.indexOf("$") >= 0)
4920 var key = clzz + "$";
4921 for (var s in Clazz.unloadedClasses)
4922 if (Clazz.unloadedClasses[s] && s.indexOf(key) == 0)
4928 if ((idx1 = fun.indexOf(key)) < 0 || (idx2 = fun.indexOf("\"", idx1 + key.length)) < 0)
4930 clzz = fun.substring(idx1, idx2);
4931 if (!Clazz.unloadedClasses[clzz] || (idx1 = fun.indexOf("{", idx2) + 1) == 0)
4933 if ((idx2 = fun.indexOf("(" + clzz + ",", idx1 + 3)) < 0
4934 || (idx2 = fun.lastIndexOf("}", idx2 - 1)) < 0)
4936 eval(fun.substring(idx1, idx2));
4937 Clazz.unloadedClasses[clzz] = null;
4941 Clazz.binaryFolders = _Loader.binaryFolders = [ _Loader.getJ2SLibBase() ];
4943 })(Clazz, Clazz._Loader);
4946 /******************************************************************************
4947 * Copyright (c) 2007 java2script.org and others.
4948 * All rights reserved. This program and the accompanying materials
4949 * are made available under the terms of the Eclipse Public License v1.0
4950 * which accompanies this distribution, and is available at
4951 * http://www.eclipse.org/legal/epl-v10.html
4954 * Zhou Renjian - initial API and implementation
4955 *****************************************************************************/
4957 * @author zhou renjian
4958 * @create Jan 11, 2007
4961 Clazz._LoaderProgressMonitor = {};
4963 ;(function(CLPM, Jmol) {
4965 var fadeOutTimer = null;
4967 var monitorEl = null;
4968 var lastScrollTop = 0;
4969 var bindingParent = null;
4971 CLPM.DEFAULT_OPACITY = (Jmol && Jmol._j2sLoadMonitorOpacity ? Jmol._j2sLoadMonitorOpacity : 55);
4974 /*CLPM.initialize = function (parent) {
4975 bindingParent = parent;
4976 if (parent && !attached) {
4978 //Clazz.addEvent (window, "unload", cleanup);
4979 // window.attachEvent ("onunload", cleanup);
4985 CLPM.hideMonitor = function () {
4986 monitorEl.style.display = "none";
4990 CLPM.showStatus = function (msg, fading) {
4995 //Clazz.addEvent (window, "unload", cleanup);
4996 // window.attachEvent ("onunload", cleanup);
4999 clearChildren(monitorEl);
5009 monitorEl.appendChild(document.createTextNode ("" + msg));
5010 if (monitorEl.style.display == "none") {
5011 monitorEl.style.display = "";
5013 setAlpha(CLPM.DEFAULT_OPACITY);
5014 var offTop = getFixedOffsetTop();
5015 if (lastScrollTop != offTop) {
5016 lastScrollTop = offTop;
5017 monitorEl.style.bottom = (lastScrollTop + 4) + "px";
5024 /* private static */
5025 var clearChildren = function (el) {
5028 for (var i = el.childNodes.length; --i >= 0;) {
5029 var child = el.childNodes[i];
5032 if (child.childNodes && child.childNodes.length)
5033 clearChildren (child);
5035 el.removeChild (child);
5040 var setAlpha = function (alpha) {
5041 if (fadeOutTimer && alpha == CLPM.DEFAULT_OPACITY) {
5042 window.clearTimeout (fadeOutTimer);
5043 fadeOutTimer = null;
5046 var ua = navigator.userAgent.toLowerCase();
5047 monitorEl.style.filter = "Alpha(Opacity=" + alpha + ")";
5048 monitorEl.style.opacity = alpha / 100.0;
5051 var hidingOnMouseOver = function () {
5056 var attached = false;
5058 var cleanup = function () {
5060 // monitorEl.onmouseover = null;
5063 bindingParent = null;
5064 //Clazz.removeEvent (window, "unload", cleanup);
5065 //window.detachEvent ("onunload", cleanup);
5069 var createHandle = function () {
5070 var div = document.createElement ("DIV");
5071 div.id = "_Loader-status";
5072 div.style.cssText = "position:absolute;bottom:4px;left:4px;padding:2px 8px;"
5073 + "z-index:" + (window["j2s.lib"].monitorZIndex || 10000) + ";background-color:#8e0000;color:yellow;"
5074 + "font-family:Arial, sans-serif;font-size:10pt;white-space:nowrap;";
5075 div.onmouseover = hidingOnMouseOver;
5077 if (bindingParent) {
5078 bindingParent.appendChild(div);
5080 document.body.appendChild(div);
5086 var fadeOut = function () {
5087 if (monitorEl.style.display == "none") return;
5088 if (fadeAlpha == CLPM.DEFAULT_OPACITY) {
5089 fadeOutTimer = window.setTimeout(function () {
5093 } else if (fadeAlpha - 10 >= 0) {
5094 setAlpha(fadeAlpha - 10);
5095 fadeOutTimer = window.setTimeout(function () {
5099 monitorEl.style.display = "none";
5103 var getFixedOffsetTop = function (){
5104 if (bindingParent) {
5105 var b = bindingParent;
5108 var dua = navigator.userAgent;
5109 var b = document.body;
5110 var p = b.parentNode;
5111 var pcHeight = p.clientHeight;
5112 var bcScrollTop = b.scrollTop + b.offsetTop;
5113 var pcScrollTop = p.scrollTop + p.offsetTop;
5114 return (dua.indexOf("Opera") < 0 && document.all ? (pcHeight == 0 ? bcScrollTop : pcScrollTop)
5115 : dua.indexOf("Gecko") < 0 ? (pcHeight == p.offsetHeight
5116 && pcHeight == p.scrollHeight ? bcScrollTop : pcScrollTop) : bcScrollTop);
5120 if (window["ClazzLoader"]) {
5121 _Loader.onScriptLoading = function(file) {
5122 CLPM.showStatus("Loading " + file + "...");
5124 _Loader.onScriptLoaded = function(file, isError) {
5125 CLPM.showStatus(file + (isError ? " loading failed." : " loaded."), true);
5127 _Loader.onGlobalLoaded = function(file) {
5128 CLPM.showStatus("Application loaded.", true);
5130 _Loader.onClassUnloaded = function(clazz) {
5131 CLPM.showStatus("Class " + clazz + " is unloaded.", true);
5136 })(Clazz._LoaderProgressMonitor, Jmol);
5139 /******************************************************************************
5140 * Copyright (c) 2007 java2script.org and others.
5141 * All rights reserved. This program and the accompanying materials
5142 * are made available under the terms of the Eclipse Public License v1.0
5143 * which accompanies this distribution, and is available at
5144 * http://www.eclipse.org/legal/epl-v10.html
5147 * Zhou Renjian - initial API and implementation
5148 *****************************************************************************/
5150 * @author zhou renjian
5151 * @create Nov 5, 2005
5154 ;(function(Con, Sys) {
5156 * Setting maxTotalLines to -1 will not limit the console result
5159 Con.maxTotalLines = 10000;
5162 Con.setMaxTotalLines = function (lines) {
5163 Con.maxTotalLines = (lines > 0 ? lines : 999999);
5167 Con.maxLatency = 40;
5170 Con.setMaxLatency = function (latency) {
5171 Con.maxLatency = (latency > 0 ? latency : 40);
5175 Con.pinning = false;
5178 Con.enablePinning = function (enabled) {
5179 Con.pinning = enabled;
5186 Con.metLineBreak = false;
5190 * Give an extension point so external script can create and bind the console
5193 * TODO: provide more template of binding console window to browser.
5196 Con.createConsoleWindow = function (parentEl) {
5197 var console = document.createElement ("DIV");
5198 console.style.cssText = "font-family:monospace, Arial, sans-serif;";
5199 document.body.appendChild (console);
5203 var c160 = String.fromCharCode(160); //nbsp;
5204 c160 += c160+c160+c160;
5207 Con.consoleOutput = function (s, color) {
5208 var o = window["j2s.lib"];
5209 var console = (o && o.console);
5210 if (console && typeof console == "string")
5211 console = document.getElementById(console)
5213 return false; // BH this just means we have turned off all console action
5214 if (Con.linesCount > Con.maxTotalLines) {
5215 for (var i = 0; i < Con.linesCount - Con.maxTotalLines; i++) {
5216 if (console && console.childNodes.length > 0) {
5217 console.removeChild (console.childNodes[0]);
5220 Con.linesCount = Con.maxTotalLines;
5223 var willMeetLineBreak = false;
5224 s = (typeof s == "undefined" ? "" : s == null ? "null" : "" + s);
5225 s = s.replace (/\t/g, c160);
5227 switch (s.charAt(s.length - 1)) {
5230 s = (s.length > 1 ? s.substring (0, s.length - (s.charAt (s.length - 2) == '\r' ? 2 : 1)) : "");
5231 willMeetLineBreak = true;
5236 s = s.replace (/\t/g, c160);
5237 lines = s.split(/\r\n|\r|\n/g);
5238 for (var i = 0, last = lines.length - 1; i <= last; i++) {
5239 var lastLineEl = null;
5240 if (Con.metLineBreak || Con.linesCount == 0
5241 || console.childNodes.length < 1) {
5242 lastLineEl = document.createElement ("DIV");
5243 console.appendChild (lastLineEl);
5244 lastLineEl.style.whiteSpace = "nowrap";
5248 lastLineEl = console.childNodes[console.childNodes.length - 1];
5250 lastLineEl = document.createElement ("DIV");
5251 console.appendChild (lastLineEl);
5252 lastLineEl.style.whiteSpace = "nowrap";
5256 var el = document.createElement ("SPAN");
5257 lastLineEl.appendChild (el);
5258 el.style.whiteSpace = "nowrap";
5260 el.style.color = color;
5264 el.appendChild(document.createTextNode(l));
5266 console.scrollTop += 100;
5267 Con.metLineBreak = (i != last || willMeetLineBreak);
5270 var cssClazzName = console.parentNode.className;
5271 if (!Con.pinning && cssClazzName
5272 && cssClazzName.indexOf ("composite") != -1) {
5273 console.parentNode.scrollTop = console.parentNode.scrollHeight;
5275 Con.lastOutputTime = new Date ().getTime ();
5279 * Clear all contents inside the console.
5282 Con.clear = function () {
5284 Con.metLineBreak = true;
5285 var o = window["j2s.lib"];
5286 var console = o && o.console;
5287 if (!console || !(console = document.getElementById (console)))
5289 var childNodes = console.childNodes;
5290 for (var i = childNodes.length; --i >= 0;)
5291 console.removeChild (childNodes[i]);
5297 Clazz.alert = function (s) {
5298 Con.consoleOutput (s + "\r\n");
5303 Sys.out.print = function (s) {
5304 Con.consoleOutput (s);
5307 Sys.out.println = function(s) {
5308 Con.consoleOutput(typeof s == "undefined" ? "\r\n" : s == null ? s = "null\r\n" : s + "\r\n");
5311 Sys.out.write = function (buf, offset, len) {
5312 Sys.out.print(String.instantialize(buf).substring(offset, offset+len));
5316 Sys.err.__CLASS_NAME__ = "java.io.PrintStream";
5319 Sys.err.print = function (s) {
5320 Con.consoleOutput (s, "red");
5324 Sys.err.println = function (s) {
5325 Con.consoleOutput (typeof s == "undefined" ? "\r\n" : s == null ? s = "null\r\n" : s + "\r\n", "red");
5328 Sys.err.write = function (buf, offset, len) {
5329 Sys.err.print(String.instantialize(buf).substring(offset, offset+len));
5332 })(Clazz.Console, System);
5334 })(Clazz, Jmol); // requires JSmolCore.js
5336 }; // called by external application