// j2sjmol.js // latest author: Bob Hanson, St. Olaf College, hansonr@stolaf.edu // Requires JSmolCore.js and (for now; probably) JSmol.js // This version of j2slib requires jQuery and works in both Chrome and MSIE locally, // though Chrome cannot read local data files, and MSIE cannot read local binary data files. // Java programming notes by Bob Hanson: // // There are a few motifs to avoid when optimizing Java code to work smoothly // with the J2S compiler: // // arrays: // // 1. an array with null elements cannot be typed and must be avoided. // 2. instances of Java "instance of" involving arrays must be found and convered to calls to Clazz.isA... // 3. new int[n][] must not be used. Use instead JU.AU.newInt2(n); // 4. new int[] { 1, 2, 3 } has problems because it creates simply [ ] and not IntArray32 // // numbers: // // 1. Remember that EVERY number in JavaScript is a double -- doesn't matter if it is in IntArray32 or not. // 2. You cannot reliably use Java long, because doubles consume bits for the exponent which cannot be tested. // 3. Bit 31 of an integer is unreliable, since (int) -1 is now , not just 0zFFFFFFFF, and // FFFFFFFF + 1 = 100000000, not 0. In JavaScript, 0xFFFFFFFF is 4294967295, not -1. // This means that writeInt(b) will fail if b is negative. What you need is instead // writeInt((int)(b & 0xFFFFFFFFl) so that JavaScript knocks off the high bits explicitly. // // general: // // 1. j2sRequireImport xxxx is needed if xxxx is a method used in a static function // 2. URL.getContent() is not supported. Use other means based on URL.toString() // 3. It is critical for performance to avoid any significant amount of function overloading. // In particular, methods such as xxx(int a, int b) and xxx(float a, int b) MUST be renamed, // because JavaScript only has Number, and there is absolutely no way to tell these apart. // It's probably bad Java programming, anyway. // 4. Calls to super(...) can almost always be avoided. These trigger the SAEM // (searchAndExecuteMethod) call, and it is very destructive to performance. // Just find another way to do it. // NOTES by Bob Hanson: // J2S class changes: // BH 7/24/2015 6:48:50 AM adding optional ?j2sdebug flag on page URL // -- switches to using j2s/core/corexxx.js, not j2s/core/corexxx.z.js // -- adds ";//# sourceURL="+file in eval(js) // -- enables DebugJS.$(msg) call to debugger; // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/debugger // see https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Debug_eval_sources // BH 7/23/2015 6:45:55 PM added sourceURL in each js class eval(), allowing full // breakpoint debugging and code checking in Firefox and Chrome // BH 7/19/2015 6:18:17 PM added os.name, line.separator, etc. to System.getProperty() // BH 7/19/2015 5:39:10 PM added java.lang.System = System // BH 7/19/2015 10:33:10 AM fix for SAEM equating "null" with number or boolean // BH 7/18/2015 6:08:05 PM for Jmol I was able to remove the $private/$fx business, but now // I see that in general that cannot be done. Thinking about a strategy... // BH 7/18/2015 4:43:38 PM better handling of TypeError and InternalError for e.getMessage() and e.getStackTrace() // BH 7/17/2015 11:51:15 AM adds class.getResource(name) and class.getResourceAsStream(name) // BH 7/16/2015 7:56:49 PM general instantiation using any constructor (in Java here): // BH x = class.forName("my.class.name").newInstance() // BH or // BH x = class.forName("my.class.name").getConstructor(String.class,String.class).newInstance(new Object[] {"test", "now"}) // BH 7/15/2015 11:34:58 PM adding System.lineSeparator() // BH 7/15/2015 7:32:41 AM adding class.getCanonicalName == getName // BH 5/31/2015 5:38:14 PM NPEExceptionPredicate fix // BH 4/25/2015 9:16:12 AM SAEM misrepresnting Number as Object in parameters and Integer as Number // BH 4/24/2015 7:32:54 AM Object.hashCode() and System.getIdentityHashCode() fail. changed to: return this._$hashcode || (this._$hashcode = ++Clazz._hashCode) // BH 4/23/2015 9:08:59 AM Clazz.instanceOf(a, b) needs to check for a == b. // BH 4/23/2015 9:08:59 AM xx.getContentType() is nonfunctional. Array.newInstance now defines a wrapper for .getClass().getComponentType() that works // BH 4/12/2015 11:48:03 AM added Clazz.getStackTrace(-n) -- reports actual parameter values for n levels // BH 4/10/2015 8:23:05 AM adding Int32Array.prototype.clone and Float64.prototype.clone // BH 4/5/2015 8:12:57 AM refactoring j2slib (this file) to make private functions really private using var // BH 4/3/2015 6:14:34 AM adding anonymous local "ClazzLoader" (Clazz._Loader) --> "_Loader" // BH 4/3/2015 6:14:34 AM adding Clazz._Loader._classPending, Clazz._Loader._classCount // BH 4/3/2015 6:14:34 AM adding Clazz._Loader._checkLoad // -- forces asynchronous class loading // -- builds Clazz._Loader._classPending and Clazz._classCount // -- allows reporting // BH 3/24/2015 4:11:26 AM better file load failure message in _Loader.evaluate // BH 2/28/2015 7:30:25 AM corrects newIntArray32() and newArray() for pre-defined arrays // int[] a = new int[] {1,2,3,343}; // int[][] b = new int[][] {new int[]{4,5},new int[]{5,6}}; // BH 9/29/2014 11:34:19 PM removing support for getClass().isArray() // BH 8/29/2014 9:15:57 AM total reworking of Java2Script in preparation for all-asynchronous loading // (currently sync loading is only for // LOAD command and load() function without ASYNC // getInterface() // see JSmol.js and Jmol._isAsync flag // BH 5/11/2015 5:58:42 AM adding __signatures for debugging SAEM issues // BH 3/29/2015 8:12:44 PM System.getProperty(x, "") does not return "" // BH 8/23/2014 10:04:19 AM cleaning up a few general methods; Clazz.removeArrayItem // BH 6/1/2014 10:58:46 AM fix for Clazz.isAP() not working // BH 5/26/2014 5:19:29 PM removing superConstructor call in creating Enum constants // BH 4/1/2014 7:55:54 PM removing all $fz references and instances where sub/super classes have same private function names // BH 4/1/2014 4:47:30 PM all $_X removed; this is taken care of by Google Closure Compiler // BH 4/1/2014 6:40:08 AM removing ClassLoader -- equals Clazz._Loader // BH 4/1/2014 6:40:08 AM removing ClassLoaderProgressMonitor -- equals _LoaderProgressMonitor // 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" // 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 // BH 1/30/2014 12:54:22 PM gave all field variables prefix underscore. This allows Google Closure Compiler to skip them. // BH 12/3/2013 3:39:57 PM window["j2s.lib"].base implemented // BH 12/1/2013 5:34:21 AM removed _LoaderProgressMonitor.initialize and all Clazz.event business; handled by Jmol.clearVars() // BH 11/30/2013 12:43:58 PM adding Clazz.arrayIs() -- avoids Number.constructor.toString() infinite recursion // BH 11/29/2013 6:33:51 AM adding Clazz._profiler -- reports use of SAEM // BH 11/10/2013 9:02:20 AM fixing fading in MSIE // BH 11/3/2013 7:21:39 AM additional wrapping functions for better compressibility // BH 10/30/2013 8:10:58 AM added getClass().getResource() -- returning a relative string, not a URL // BH 10/30/2013 6:43:00 AM removed second System def and added System.$props and default System.property "line.separator" // BH 6/15/2013 8:02:07 AM corrections to Class.isAS to return true if first element is null // BH 6/14/2013 4:41:09 PM corrections to Clazz.isAI and related methods to include check for null object // BH 3/17/2013 11:54:28 AM adds stackTrace for ERROR // BH 3/13/2013 6:58:26 PM adds Clazz.clone(me) for BS clone // BH 3/12/2013 6:30:53 AM fixes Clazz.exceptionOf for ERROR condition trapping // BH 3/2/2013 9:09:53 AM delete globals c$ and $fz // BH 3/2/2013 9:10:45 AM optimizing defineMethod using "look no further" "@" parameter designation (see "\\@" below -- removed 3/23/13) // BH 2/27/2013 optimizing Clazz.getParamsType for common cases () and (Number) // BH 2/27/2013 optimizing SAEM delegation for hashCode and equals -- disallows overloading of equals(Object) // BH 2/23/2013 found String.replaceAll does not work -- solution was to never call it. // BH 2/9/2013 9:18:03 PM Int32Array/Float64Array fixed for MSIE9 // BH 1/25/2013 1:55:31 AM moved package.js from j2s/java to j2s/core // BH 1/17/2013 4:37:17 PM String.compareTo() added // BH 1/17/2013 4:52:22 PM Int32Array and Float64Array may not have .prototype.sort method // BH 1/16/2013 6:20:34 PM Float64Array not available in Safari 5.1 // BH 1/14/2013 11:28:58 PM Going to all doubles in JavaScript (Float64Array, not Float32Array) // so that (new float[] {13.48f})[0] == 13.48f, effectively // BH 1/14/2013 12:53:41 AM Fix for Opera 10 not loading any files // BH 1/13/2013 11:50:11 PM Fix for MSIE not loading (nonbinary) files locally // BH 12/1/2012 9:52:26 AM Compiler note: Thread.start() cannot be executed within the constructor; // BH 11/24/2012 11:08:39 AM removed unneeded sections // BH 11/24/2012 10:23:22 AM all XHR uses sync loading (_Loader.setLoadingMode) // BH 11/21/2012 7:30:06 PM if (base) map["@" + pkg] = base; critical for multiple applets // BH 10/8/2012 3:27:41 PM if (clazzName.indexOf("Array") >= 0) return "Array"; in Clazz.getClassName for function // BH removed Clazz.ie$plit = "\\2".split (/\\/).length == 1; unnecessary; using RegEx slows process significantly in all browsers // BH 10/6/12 added Int32Array, Float32Array, newArrayBH, upgraded java.lang and java.io // BH added Integer.bitCount in core.z.js // BH changed alert to Clazz.alert in java.lang.Class.js *.ClassLoader.js, java.lang.thread.js // BH removed toString from innerFunctionNames due to infinite recursion // BH note: Logger.error(null, e) does not work -- get no constructor for (String) (TypeError) // BH added j2s.lib.console // BH allowed for alias="." // BH removed alert def --> Clazz.alert // BH added wrapper at line 2856 // BH newArray fix at line 2205 // BH System.getProperty fix at line 6693 // BH added Enum .value() method at line 2183 // BH added System.getSecurityManager() at end // BH added String.contains() at end // BH added System.gc() at end // BH added Clazz.exceptionOf = updated // BH added String.getBytes() at end LoadClazz = function() { // BH This is the ONLY global used in J2S now. I do not think it is necessary, // but it is created by the compiler, and I have not found a work-around. // it is used as a local variable in class definitions to point to the // current method. See Clazz.p0p and Clazz.pu$h c$ = null; if (!window["j2s.clazzloaded"]) window["j2s.clazzloaded"] = false; if (window["j2s.clazzloaded"])return; window["j2s.clazzloaded"] = true; window["j2s.object.native"] = true; // Clazz changes: /* http://j2s.sf.net/ *//****************************************************************************** * Copyright (c) 2007 java2script.org and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhou Renjian - initial API and implementation *****************************************************************************/ /******* * @author zhou renjian * @create Nov 5, 2005 *******/ /** * Class Clazz. All the methods are static in this class. */ /* static */ /*Class = */ Clazz = { _isQuiet: false, _debugging: false }; ;(function(Clazz, Jmol) { try { Clazz._debugging = (document.location.href.indexOf("j2sdebug") >= 0); } catch (e) { } var __debuggingBH = false; var _globals = ["j2s.clazzloaded", "j2s.object.native"]; Clazz.setGlobal = function(a, v) { _globals.push(a); window[a] = v; } Clazz.getGlobals = function() { return _globals.sort().join("\n"); } Clazz.setConsoleDiv = function(d) { window["j2s.lib"] && (window["j2s.lib"].console = d); }; // BH Clazz.getProfile monitors exactly what is being delegated with SAEM, // which could be a bottle-neck for function calling. // This is critical for performance optimization. // Jmol.getProfile() var _profile = (window["j2s.doProfile"] && self.JSON ? {} : null); NullObject = function () {}; /* protected */ Clazz._supportsNativeObject = window["j2s.object.native"]; if (Clazz._supportsNativeObject) { Clazz._O = function () {}; Clazz._O.__CLASS_NAME__ = "Object"; Clazz._O["getClass"] = function () { return Clazz._O; }; } else { Clazz._O = Object; } Clazz.Console = {}; Clazz.dateToString = Date.prototype.toString; Clazz._hashCode = 0; var addProto = function(proto, name, func) { return proto[name] = func; }; ;(function(proto) { addProto(proto, "equals", function (obj) { return this == obj; }); addProto(proto, "hashCode", function () { return this._$hashcode || (this._$hashcode = ++Clazz._hashCode) try { return this.toString ().hashCode (); } catch (e) { var str = ":"; for (var s in this) { str += s + ":" } return str.hashCode (); } }); addProto(proto, "getClass", function () { return Clazz.getClass (this); }); addProto(proto, "clone", function () { return Clazz.clone(this); }); Clazz.clone = function(me) { // BH allows @j2sNative access without super constructor var o = new me.constructor(); for (var i in me) { o[i] = me[i]; } return o; } /* * Methods for thread in Object */ addProto(proto, "finalize", function () {}); addProto(proto, "notify", function () {}); addProto(proto, "notifyAll", function () {}); addProto(proto, "wait", function () {}); addProto(proto, "to$tring", Object.prototype.toString); addProto(proto, "toString", function () { return (this.__CLASS_NAME__ ? "[" + this.__CLASS_NAME__ + " object]" : this.to$tring.apply(this, arguments)); }); Clazz._extendedObjectMethods = [ "equals", "hashCode", "getClass", "clone", "finalize", "notify", "notifyAll", "wait", "to$tring", "toString" ]; })(Clazz._O.prototype); Clazz.extendJO = function(c, name) { if (name) c.__CLASS_NAME__ = c.prototype.__CLASS_NAME__ = name; if (Clazz._supportsNativeObject) { for (var i = 0; i < Clazz._extendedObjectMethods.length; i++) { var p = Clazz._extendedObjectMethods[i]; addProto(c.prototype, p, Clazz._O.prototype[p]); } } }; /** * Try to fix bug on Safari */ //InternalFunction = Object; Clazz.extractClassName = function(clazzStr) { // [object Int32Array] var clazzName = clazzStr.substring (1, clazzStr.length - 1); return (clazzName.indexOf("Array") >= 0 ? "Array" // BH -- for Float64Array and Int32Array : clazzName.indexOf ("object ") >= 0 ? clazzName.substring (7) // IE : clazzName); } /** * Return the class name of the given class or object. * * @param clazzHost given class or object * @return class name */ /* public */ Clazz.getClassName = function (obj) { if (obj == null) return "NullObject"; if (obj instanceof Clazz.CastedNull) return obj.clazzName; switch(typeof obj) { case "number": return "n"; case "boolean": return "b"; case "string": // Always treat the constant string as String object. // This will be compatiable with Java String instance. return "String"; case "function": if (obj.__CLASS_NAME__) return (arguments[1] ? obj.__CLASS_NAME__ : "Class"); /* user defined class name */ var s = obj.toString(); var idx0 = s.indexOf("function"); if (idx0 < 0) return (s.charAt(0) == '[' ? Clazz.extractClassName(s) : s.replace(/[^a-zA-Z0-9]/g, '')); var idx1 = idx0 + 8; var idx2 = s.indexOf ("(", idx1); if (idx2 < 0) return "Object"; s = s.substring (idx1, idx2); if (s.indexOf("Array") >= 0) return "Array"; s = s.replace (/^\s+/, "").replace (/\s+$/, ""); return (s == "anonymous" || s == "" ? "Function" : s); case "object": if (obj.__CLASS_NAME__) // user defined class name return obj.__CLASS_NAME__; if (!obj.constructor) return "Object"; // For HTML Element in IE if (!obj.constructor.__CLASS_NAME__) { if (obj instanceof Number) return "Number"; if (obj instanceof Boolean) return "Boolean"; if (obj instanceof Array) return "Array"; var s = obj.toString(); // "[object Int32Array]" if (s.charAt(0) == '[') return Clazz.extractClassName(s); } return Clazz.getClassName (obj.constructor, true); } // some new, unidentified class return "Object"; }; /** * Return the class of the given class or object. * * @param clazzHost given class or object * @return class name */ /* public */ Clazz.getClass = function (clazzHost) { if (!clazzHost) return Clazz._O; // null/undefined is always treated as Object if (typeof clazzHost == "function") return clazzHost; var clazzName; if (clazzHost instanceof Clazz.CastedNull) { clazzName = clazzHost.clazzName; } else { switch (typeof clazzHost) { case "string": return String; case "object": if (!clazzHost.__CLASS_NAME__) return (clazzHost.constructor || Clazz._O); clazzName = clazzHost.__CLASS_NAME__; break; default: return clazzHost.constructor; } } return Clazz.evalType(clazzName, true); }; /* private */ var checkInnerFunction = function (hostSuper, funName) { for (var k = 0; k < Clazz.innerFunctionNames.length; k++) if (funName == Clazz.innerFunctionNames[k] && Clazz._innerFunctions[funName] === hostSuper[funName]) return true; return false; }; var args4InheritClass = function () {}; Clazz.inheritArgs = new args4InheritClass (); /** * Inherit class with "extends" keyword and also copy those static members. * Example, as in Java, if NAME is a static member of ClassA, and ClassB * extends ClassA then ClassB.NAME can be accessed in some ways. * * @param clazzThis child class to be extended * @param clazzSuper super class which is inherited from * @param objSuper super class instance */ /* protected */ Clazz.inheritClass = function (clazzThis, clazzSuper, objSuper) { //var thisClassName = Clazz.getClassName (clazzThis); for (var o in clazzSuper) { if (o != "b$" && o != "prototype" && o != "superClazz" && o != "__CLASS_NAME__" && o != "implementz" && !checkInnerFunction (clazzSuper, o)) { clazzThis[o] = clazzSuper[o]; } } if (Clazz.unloadedClasses[Clazz.getClassName(clazzThis, true)]) { // Don't change clazzThis.protoype! Keep it! } else if (objSuper) { // ! Unsafe reference prototype to an instance! // Feb 19, 2006 --josson // OK for this reference to an instance, as this is anonymous instance, // which is not referenced elsewhere. // March 13, 2006 clazzThis.prototype = objSuper; } else if (clazzSuper !== Number) { clazzThis.prototype = new clazzSuper (Clazz.inheritArgs); } else { // Number clazzThis.prototype = new Number (); } clazzThis.superClazz = clazzSuper; /* * Is it necessary to reassign the class name? * Mar 10, 2006 --josson */ //clazzThis.__CLASS_NAME__ = thisClassName; clazzThis.prototype.__CLASS_NAME__ = clazzThis.__CLASS_NAME__; }; /** * Implementation of Java's keyword "implements". * As in JavaScript there are on "implements" keyword implemented, a property * of "implementz" is added to the class to record the interfaces the class * is implemented. * * @param clazzThis the class to implement * @param interfacez Array of interfaces */ /* public */ Clazz.implementOf = function (clazzThis, interfacez) { if (arguments.length >= 2) { if (!clazzThis.implementz) clazzThis.implementz = []; var impls = clazzThis.implementz; if (arguments.length == 2) { if (typeof interfacez == "function") { impls.push(interfacez); copyProperties(clazzThis, interfacez); } else if (interfacez instanceof Array) { for (var i = 0; i < interfacez.length; i++) { impls.push(interfacez[i]); copyProperties(clazzThis, interfacez[i]); } } } else { for (var i = 1; i < arguments.length; i++) { impls.push(arguments[i]); copyProperties(clazzThis, arguments[i]); } } } }; /* * Copy members of interface */ /* private */ var copyProperties = function(clazzThis, clazzSuper) { for (var o in clazzSuper) if (o != "b$" && o != "prototype" && o != "superClazz" && o != "__CLASS_NAME__" && o != "implementz" && (typeof clazzSuper[o] != "function" || !checkInnerFunction(clazzSuper, o))) clazzThis[o] = clazzThis.prototype[o] = clazzSuper[o]; }; /** * TODO: More should be done for interface's inheritance */ /* public */ Clazz.extendInterface = Clazz.implementOf; /* protected */ Clazz.equalsOrExtendsLevel = function (clazzThis, clazzAncestor) { if (clazzThis === clazzAncestor) return 0; if (clazzThis.implementz) { var impls = clazzThis.implementz; for (var i = 0; i < impls.length; i++) { var level = Clazz.equalsOrExtendsLevel (impls[i], clazzAncestor); if (level >= 0) return level + 1; } } return -1; }; /* protected */ Clazz.getInheritedLevel = function (clazzTarget, clazzBase) { if (clazzTarget === clazzBase) return 0; var isTgtStr = (typeof clazzTarget == "string"); if (isTgtStr && ("void" == clazzTarget || "unknown" == clazzTarget)) return -1; var isBaseStr = (typeof clazzBase == "string"); if (isBaseStr && ("void" == clazzBase || "unknown" == clazzBase)) return -1; if (clazzTarget === (isTgtStr ? "NullObject" : NullObject)) { switch (clazzBase) { case "n": case "b": return -1; case Number: case Boolean: case NullObject: break; default: return 0; } } if (isTgtStr) clazzTarget = Clazz.evalType(clazzTarget); if (isBaseStr) clazzBase = Clazz.evalType(clazzBase); if (!clazzBase || !clazzTarget) return -1; var level = 0; var zzalc = clazzTarget; // zzalc <--> clazz while (zzalc !== clazzBase && level < 10) { /* maybe clazzBase is interface */ if (zzalc.implementz) { var impls = zzalc.implementz; for (var i = 0; i < impls.length; i++) { var implsLevel = Clazz.equalsOrExtendsLevel (impls[i], clazzBase); if (implsLevel >= 0) return level + implsLevel + 1; } } zzalc = zzalc.superClazz; if (!zzalc) return (clazzBase === Object || clazzBase === Clazz._O ? // getInheritedLevel(String, CharSequence) == 1 // getInheritedLevel(String, Object) == 1.5 // So if both #test(CharSequence) and #test(Object) existed, // #test("hello") will correctly call #test(CharSequence) // instead of #test(Object). level + 1.5 // 1.5! Special! : -1); level++; } return level; }; /** * Implements Java's keyword "instanceof" in JavaScript's way. * As in JavaScript part of the object inheritance is implemented in only- * JavaScript way. * * @param obj the object to be tested * @param clazz the class to be checked * @return whether the object is an instance of the class */ /* public */ Clazz.instanceOf = function (obj, clazz) { // allows obj to be a class already, from arrayX.getClass().isInstance(y) return (obj != null && clazz && (obj == clazz || obj instanceof clazz || Clazz.getInheritedLevel(Clazz.getClassName(obj), clazz) >= 0)); }; /** * Call super method of the class. * The same effect as Java's expression: * super.* () * * @param objThis host object * @param clazzThis class of declaring method scope. It's hard to determine * which super class is right class for "super.*()" call when it's in runtime * environment. For example, * 1. ClasssA has method #run() * 2. ClassB extends ClassA overriding method #run() with "super.run()" call * 3. ClassC extends ClassB * 4. objC is an instance of ClassC * Now we have to decide which super #run() method is to be invoked. Without * explicit clazzThis parameter, we only know that objC.getClass() is ClassC * and current method scope is #run(). We do not known we are in scope * ClassA#run() or scope of ClassB#run(). if ClassB is given, Clazz can search * all super methods that are before ClassB and get the correct super method. * This is the reason why there must be an extra clazzThis parameter. * @param funName method name to be called * @param funParams Array of method parameters */ /* public */ Clazz.superCall = function (objThis, clazzThis, funName, funParams) { var fx = null; var i = -1; var clazzFun = objThis[funName]; if (clazzFun) { if (clazzFun.claxxOwner) { // claxxOwner is a mark for methods that is single. if (clazzFun.claxxOwner !== clazzThis) { // This is a single method, call directly! fx = clazzFun; } } else if (!clazzFun.stacks && !(clazzFun.lastClaxxRef && clazzFun.lastClaxxRef.prototype[funName] && clazzFun.lastClaxxRef.prototype[funName].stacks)) { // super.toString fx = clazzFun; } else { // normal wrapped method var stacks = clazzFun.stacks; if (!stacks) stacks = clazzFun.lastClaxxRef.prototype[funName].stacks; for (i = stacks.length; --i >= 0;) { /* * Once super call is computed precisely, there are no need * to calculate the inherited level but just an equals * comparision */ //var level = Clazz.getInheritedLevel (clazzThis, stacks[i]); if (clazzThis === stacks[i]) { // level == 0 if (i > 0) { fx = stacks[--i].prototype[funName]; } else { /* * Will this case be reachable? * March 4, 2006 * Should never reach here if all things are converted * by Java2Script */ fx = stacks[0].prototype[funName]["\\unknown"]; } break; } else if (Clazz.getInheritedLevel (clazzThis, stacks[i]) > 0) { fx = stacks[i].prototype[funName]; break; } } // end of for loop } // end of normal wrapped method } // end of clazzFun if (!fx) { if (funName != "construct") { Clazz.alert (["j2slib","no class found",(funParams).typeString]) newMethodNotFoundException(objThis, clazzThis, funName, Clazz.getParamsType(funParams).typeString); } /* there are members which are initialized out of the constructor */ /* No super constructor! */ return; } /* there are members which are initialized out of the constructor */ if (i == 0 && funName == "construct") { var ss = clazzFun.stacks; if (ss && !ss[0].superClazz && ss[0].con$truct) ss[0].con$truct.apply (objThis, []); } /*# {$no.debug.support} >>x #*/ /* not used in Jmol if (Clazz.tracingCalling) { var caller = arguments.callee.caller; if (caller === Clazz.superConstructor) { caller = caller.arguments.callee.caller; } Clazz._callingStackTraces.push(new Clazz.callingStack (caller, clazzThis)); var ret = fx.apply (objThis, (funParams == null) ? [] : funParams); Clazz._callingStackTraces.pop(); return ret; } */ /*# x<< #*/ return fx.apply (objThis, funParams || []); }; /** * Call super constructor of the class. * The same effect as Java's expression: * super () */ /* public */ Clazz.superConstructor = function (objThis, clazzThis, funParams) { Clazz.superCall (objThis, clazzThis, "construct", funParams); /* If there are members which are initialized out of the constructor */ if (clazzThis.con$truct) { clazzThis.con$truct.apply (objThis, []); } }; /** * Class for null with a given class as to be casted. * This class will be used as an implementation of Java's casting way. * For example, * this.call ((String) null); */ /* public */ Clazz.CastedNull = function (asClazz) { if (asClazz) { if (asClazz instanceof String) { this.clazzName = asClazz; } else if (asClazz instanceof Function) { this.clazzName = Clazz.getClassName (asClazz, true); } else { this.clazzName = "" + asClazz; } } else { this.clazzName = "Object"; } this.toString = function () { return null; }; this.valueOf = function () { return null; }; }; /** * API for Java's casting null. * @see Clazz.CastedNull * * @param asClazz given class * @return an instance of class Clazz.CastedNull */ /* public */ Clazz.castNullAs = function (asClazz) { return new Clazz.CastedNull (asClazz); }; /////////////////////////// Exception handling //////////////////////////// /* * Use to mark that the Throwable instance is created or not. * * Called from java.lang.Throwable, as defined in JSmolJavaExt.js * * The underscore is important - it tells the JSmol ANT task to NOT * turn this into Clazz_initializingException, because coreBottom2.js does * not include that call, and so Google Closure Compiler does not minify it. * */ /* public */ Clazz._initializingException = false; /** * BH: used in Throwable * */ /* public */ Clazz._callingStackTraces = []; /** * MethodException will be used as a signal to notify that the method is * not found in the current clazz hierarchy. */ /* private */ var MethodException = function () { this.toString = function () { return "J2S MethodException"; }; }; /* private */ //var MethodNotFoundException = function () { // this.toString = function () { // return "J2S MethodNotFoundException"; // }; //}; var _isNPEExceptionPredicate; /* super private */ ;(function() { /* sgurin: native exception detection mechanism. Only NullPointerException detected and wrapped to java excepions */ /** private utility method for creating a general regexp that can be used later * for detecting a certain kind of native exceptions. use with error messages like "blabla IDENTIFIER blabla" * @param msg String - the error message * @param spliterName String, must be contained once in msg * spliterRegex String, a string with the regexp literal for identifying the spitter in exception further error messages. */ // reproduce NullPointerException for knowing how to detect them, and create detector function Clazz._isNPEExceptionPredicate var $$o$$ = null; try { $$o$$.hello(); } catch (e) { var _ex_reg = function(msg, spliterName, spliterRegex) { if(!spliterRegex) spliterRegex="[^\\s]+"; var idx = msg.indexOf (spliterName), str = msg.substring (0, idx) + spliterRegex + msg.substring(idx + spliterName.length), regexp = new RegExp("^"+str+"$"); return regexp; }; 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... " var idx1 = e.message.indexOf(":"), idx2 = e.message.indexOf(":", idx1+2); var _NPEMsgFragment = e.message.substr(idx1+1, idx2-idx1-20); _isNPEExceptionPredicate = function(e) { return e.message.indexOf(_NPEMsgFragment)!=-1; }; } else if(navigator.userAgent.toLowerCase().indexOf("webkit")!=-1) { //webkit, google chrome prints the property name accessed. var _exceptionNPERegExp = _ex_reg(e.message, "hello"); _isNPEExceptionPredicate = function(e) { return _exceptionNPERegExp.test(e.message); }; } else {// ie, firefox and others print the name of the object accessed: var _exceptionNPERegExp = _ex_reg(e.message, "$$o$$"); _isNPEExceptionPredicate = function(e) { return _exceptionNPERegExp.test(e.message); }; } }; })(); /**sgurin * Implements Java's keyword "instanceof" in JavaScript's way **for exception objects**. * * calls Clazz.instanceOf if e is a Java exception. If not, try to detect known native * exceptions, like native NullPointerExceptions and wrap it into a Java exception and * call Clazz.instanceOf again. if the native exception can't be wrapped, false is returned. * * @param obj the object to be tested * @param clazz the class to be checked * @return whether the object is an instance of the class * @author: sgurin */ Clazz.exceptionOf = function(e, clazz) { if(e.__CLASS_NAME__) return Clazz.instanceOf(e, clazz); if (!e.getMessage) { e.getMessage = function() {return "" + this}; } if (!e.printStackTrace) { e.printStackTrace = function(){}; alert(e + " try/catch path:" + Clazz.getStackTrace(-10)); } if(clazz == Error) { if (("" + e).indexOf("Error") < 0) return false; System.out.println (Clazz.getStackTrace()); return true; // everything here is a Java Exception, not a Java Error } return (clazz == Exception || clazz == Throwable || clazz == NullPointerException && _isNPEExceptionPredicate(e)); }; /** * BH need to limit this, as JavaScript call stack may be recursive */ Clazz.getStackTrace = function(n) { n || (n = 25); // updateNode and updateParents cause infinite loop here var s = "\n"; var c = arguments.callee; var showParams = (n < 0); if (showParams) n = -n; for (var i = 0; i < n; i++) { if (!(c = c.caller)) break; var sig = (c.toString ? c.toString().substring(0, c.toString().indexOf("{")) : ""); s += i + " " + (c.exName ? (c.claxxOwner ? c.claxxOwner.__CLASS_NAME__ + "." : "") + c.exName + sig.replace(/function /,""): sig) + "\n"; if (c == c.caller) { s += "\n"; break; } if (showParams) { var args = c.arguments; for (var j = 0; j < args.length; j++) { var sa = "" + args[j]; if (sa.length > 60) sa = sa.substring(0, 60) + "..."; s += " args[" + j + "]=" + sa.replace(/\s+/g," ") + "\n"; } } } return s; } ///////////////////// method creation //////////////////////////////// /** * Make constructor for the class with the given function body and parameters * signature. * * @param clazzThis host class * @param funBody constructor body * @param funParams constructor parameters signature */ /* public */ Clazz.makeConstructor = function (clazzThis, funBody, funParams) { Clazz.defineMethod (clazzThis, "construct", funBody, funParams); if (clazzThis.con$truct) { clazzThis.con$truct.index = clazzThis.con$truct.stacks.length; } //clazzThis.con$truct = clazzThis.prototype.con$truct = null; }; /** * Override constructor for the class with the given function body and * parameters signature. * * @param clazzThis host class * @param funBody constructor body * @param funParams constructor parameters signature */ /* public */ Clazz.overrideConstructor = function (clazzThis, funBody, funParams) { Clazz.overrideMethod (clazzThis, "construct", funBody, funParams); if (clazzThis.con$truct) { clazzThis.con$truct.index = clazzThis.con$truct.stacks.length; } //clazzThis.con$truct = clazzThis.prototype.con$truct = null; }; /* * Define method for the class with the given method name and method * body and method parameter signature. * * @param clazzThis host class in which the method to be defined * @param funName method name * @param funBody function object, e.g function () { ... } * @param funParams paramether signature, e.g ["string", "number"] * @return method of the given name. The method may be funBody or a wrapper * of the given funBody. */ /* public */ Clazz.defineMethod = function (clazzThis, funName, funBody, funParams) { if (Clazz.assureInnerClass) Clazz.assureInnerClass(clazzThis, funBody); funBody.exName = funName; var fpName = formatParameters(funParams); var proto = clazzThis.prototype; var f$ = proto[funName]; if (Clazz._Loader._checkLoad) checkDuplicate(clazzThis, funName, fpName); if (!f$ || (f$.claxxOwner === clazzThis && f$.funParams == fpName)) { // property "funParams" will be used as a mark of only-one method funBody.funParams = fpName; funBody.claxxOwner = clazzThis; funBody.exClazz = clazzThis; // make it traceable return addProto(proto, funName, funBody); } // we have found a duplicate var oldFun = null; var oldStacks = f$.stacks; if (!oldStacks) { /* method is not defined by Clazz.defineMethod () */ oldStacks = []; oldFun = f$; if (f$.claxxOwner) { oldStacks[0] = oldFun.claxxOwner; } } /* * Method that is already defined in super class will be overridden * with a new proxy method with class hierarchy stored in a stack. * That is to say, the super methods are lost in this class' proxy * method. * When method are being called, methods defined in the new proxy * method will be searched through first. And if no method fitted, * it will then try to search method in the super class stacks. */ if (!f$.stacks || f$.claxxReference !== clazzThis) { //Generate a new delegating method for the class var id = ++SAEMid; var delegate = function () { return searchAndExecuteMethod(id, this, arguments.callee.claxxReference, arguments.callee.methodName, arguments); }; delegate.methodName = funName; delegate.claxxReference = clazzThis; f$ = addProto(proto, funName, delegate); // Keep the class inheritance stacks var arr = []; for (var i = 0; i < oldStacks.length; i++) arr[i] = oldStacks[i]; f$.stacks = arr; } var ss = f$.stacks; if (findArrayItem(ss, clazzThis) < 0) ss.push(clazzThis); if (oldFun) { if (oldFun.claxxOwner === clazzThis) { f$[oldFun.funParams] = oldFun; oldFun.claxxOwner = null; // property "funParams" will be used as a mark of only-one method oldFun.funParams = null; // null ? safe ? // safe for != null } else if (!oldFun.claxxOwner) { /* * The function is not defined Clazz.defineMethod (). * Try to fixup the method ... * As a matter of lost method information, I just suppose * the method to be fixed is with void parameter! */ f$["\\unknown"] = oldFun; } } funBody.exClazz = clazzThis; // make it traceable f$[fpName] = funBody; return f$; }; duplicatedMethods = {}; var checkDuplicate = function(clazzThis, funName, fpName) { var proto = clazzThis.prototype; var f$ = proto[funName]; if (f$ && (f$.claxxOwner || f$.claxxReference) === clazzThis) { key = clazzThis.__CLASS_NAME__ + "." + funName + fpName; var m = duplicatedMethods[key]; if (m) { var s = "Warning! Duplicate method found for " + key; System.out.println(s); Clazz.alert(s); duplicatedMethods[key] = m + 1; } else { duplicatedMethods[key] = 1; } } } Clazz.showDuplicates = function(quiet) { var s = ""; var a = duplicatedMethods; var n = 0; for (var key in a) if (a[key] > 1) { s += a[key] + "\t" + key + "\n"; n++; } s = "Duplicates: " + n + "\n\n" + s; System.out.println(s); if (!quiet) alert(s); } var findArrayItem = function(arr, item) { if (arr && item) for (var i = arr.length; --i >= 0;) if (arr[i] === item) return i; return -1; } var removeArrayItem = function(arr, item) { var i = findArrayItem(arr, item); if (i >= 0) { var n = arr.length - 1; for (; i < n; i++) arr[i] = arr[i + 1]; arr.length--; return true; } } /* * Other developers may need to extend this formatParameters method * to deal complicated situation. */ /* protected */ var formatParameters = function (funParams) { return (funParams ? funParams.replace (/~([NABSO])/g, function ($0, $1) { switch ($1) { case 'N': return "n"; case 'B': return "b"; case 'S': return "String"; case 'O': return "Object"; case 'A': return "Array"; } return "Unknown"; }).replace (/\s+/g, "").replace (/^|,/g, "\\").replace (/\$/g, "org.eclipse.s") : "\\void"); }; /* * Override the existed methods which are in the same name. * Overriding methods is provided for the purpose that the JavaScript * does not need to search the whole hierarchied methods to find the * correct method to execute. * Be cautious about this method. Incorrectly using this method may * break the inheritance system. * * @param clazzThis host class in which the method to be defined * @param funName method name * @param funBody function object, e.g function () { ... } * @param funParams paramether signature, e.g ["string", "number"] */ /* public */ Clazz.overrideMethod = function(clazzThis, funName, funBody, funParams) { if (Clazz.assureInnerClass) Clazz.assureInnerClass (clazzThis, funBody); funBody.exName = funName; var fpName = formatParameters(funParams); if (Clazz._Loader._checkLoad) checkDuplicate(clazzThis, funName, fpName); /* * Replace old methods with new method. No super methods are kept. */ funBody.funParams = fpName; funBody.claxxOwner = clazzThis; return addProto(clazzThis.prototype, funName, funBody); }; ////////////// Overridden and Overloaded Java Method Handling ////////////////// // SAEM (SearchAndExecuteMethod) // adapted by BH // /* * BH Clazz.getProfile monitors exactly what is being delegated with SAEM, * which could be a bottle-neck for function calling. * This is critical for performance optimization. */ var __signatures = ""; Clazz.getProfile = function() { var s = ""; if (_profile) { var l = []; for (var i in _profile) { var n = "" + _profile[i]; l.push(" ".substring(n.length) + n + "\t" + i); } s = l.sort().reverse().join("\r\n"); _profile = {}; } return s + __signatures; } var addProfile = function(c, f, p, id) { var s = id + " " + c.__CLASS_NAME__ + " " + f + " ";// + JSON.stringify(p); if (__signatures.indexOf(s) < 0) __signatures += s + "\n"; _profile[s] || (_profile[s] = 0); _profile[s]++; } /** * Called also by Throwable * /* public */ Clazz.getParamsType = function (funParams) { // bh: optimization here for very common cases var n = funParams.length; switch (n) { case 0: var params = ["void"]; params.typeString = "\\void"; return params; case 1: // BH just so common switch (typeof obj) { case "number": var params = ["n"]; params.typeString = "\\n"; return params; case "boolean": var params = ["b"]; params.typeString = "\\b"; return params; } } var params = []; params.hasCastedNull = false; if (funParams) { for (var i = 0; i < n; i++) { params[i] = Clazz.getClassName (funParams[i]); if (funParams[i] instanceof Clazz.CastedNull) { params.hasCastedNull = true; } } } params.typeString = "\\" + params.join ('\\'); return params; }; var SAEMid = 0; xxxSAEMlist = ""; //var SAEMarray = []; /** * BH: OK, this was an idea that doesn't work. The idea was to tag SAEM calls * and then refer back to an array. But the id number cannot be put in the right place. * * Say we have this: * * StringBuffer sb = new StringBuffer(); * sb.append("").append(1); * * Here we have two different append methods to call. They are saved under two * names: StringBuffer.prototype.append["\\String"] * and StringBuffer.prototype.append["\\Number"] * * The job of generateDelegatingMethod is to discriminate between those two. We can do * that, but the real issue is that we have to do that EVERY time a call is made. * This is a problem that must be handled at compile time. There is no way to * make .append("") to go one way the first time and another way the second time. * What we need at run time is something like this: * * Clazz.delegate(sb.append,1,[""]) and Clazz.delegate(sb.append,2,[1]) * The we would be able to log those numbers at run time and refer to them. * * The only real way to avoid SAEM is: * * 1) to never call super() -- always call a differently named function in a superclass. * 2) don't overload functions * */ /** * Search the given class prototype, find the method with the same * method name and the same parameter signatures by the given * parameters, and then run the method with the given parameters. * * @param objThis the current host object * @param claxxRef the current host object's class * @param fxName the method name * @param funParams the given arguments * @return the result of the specified method of the host object, * the return maybe void. * @throws MethodNotFoundException if no matched method is found */ /* protected */ var searchAndExecuteMethod = function (id, objThis, claxxRef, fxName, args, _saem) { // var fx = SAEMarray[id]; // if (fx) { // return fx.apply(objThis, args); // } fx = objThis[fxName]; var params = Clazz.getParamsType(args); var s = "SAEM " + claxxRef.__CLASS_NAME__ + "." + fxName + "(" + params+ ")\n"; if (xxxSAEMlist.length > 300)xxxSAEMlist = ""; xxxSAEMlist += s; if (!fx) try {System.out.println(Clazz.getStackTrace(5))} catch (e){} _profile && addProfile(claxxRef, fxName, params, id); // Cache last matched method if (fx.lastParams == params.typeString && fx.lastClaxxRef === claxxRef) { var methodParams; if (params.hasCastedNull) { methodParams = []; // For Clazz.CastedNull instances, the type name is // already used to indentified the method in searchMethod. for (var k = 0; k < args.length; k++) methodParams[k] = (args[k] instanceof Clazz.CastedNull ? null : args[k]); } else { // if (fx.lastMethod) SAEMarray[id] = fx.lastMethod; methodParams = args; } return (fx.lastMethod ? fx.lastMethod.apply(objThis, methodParams) : null); } fx.lastParams = params.typeString; fx.lastClaxxRef = claxxRef; var stacks = fx.stacks; if (!stacks) stacks = claxxRef.prototype[fxName].stacks; var length = stacks.length; /* * Search the inheritance stacks to get the given class' function */ var began = false; // began to search its super classes for (var i = length; --i >= 0;) { if (began || stacks[i] === claxxRef) { /* * First try to search method within the same class scope * with stacks[i] === claxxRef */ var clazzFun = stacks[i].prototype[fxName]; var ret = tryToSearchAndExecute(id, fxName, objThis, clazzFun, params, args, fx); if (!(ret instanceof MethodException)) { return ret; } /* * As there are no such methods in current class, Clazz will try * to search its super class stacks. Here variable began indicates * that super searchi is began, and there is no need checking * stacks[i] === claxxRef */ began = true; } // end of if } // end of for if ("construct" == fxName) { /* * For non existed constructors, just return without throwing * exceptions. In Java codes, extending Object can call super * default Object#constructor, which is not defined in JS. */ return; } newMethodNotFoundException(objThis, claxxRef, fxName, params.typeString); }; /* private */ var tryToSearchAndExecute = function(id, fxName, objThis, clazzFun, params, args, fx, _ttsaem) { var method = []; var generic = true; for (var fn in clazzFun) { if (fn.charCodeAt(0) == 92) { // 92 == '\\'.charCodeAt (0) var ps = fn.substring(1).split("\\"); (ps.length == params.length) && method.push(ps); generic = false; continue; } /* * When there is only one method in the class, use the args * to identify the parameter type. * * AbstractCollection.remove (Object) * AbstractList.remove (int) * ArrayList.remove (int) * * Then calling #remove (Object) method on ArrayList instance will * need to search up to the AbstractCollection.remove (Object), * which contains only one method. */ /* * See Clazz#defineMethod --Mar 10, 2006, josson */ if (generic && fn == "funParams" && clazzFun.funParams) { fn = clazzFun.funParams; var ps = fn.substring(1).split ("\\"); (ps.length == params.length) && (method[0] = ps); break; } } var debug = false;//(method.length > 1 && method.join().indexOf("Listen")< 0 && params.join().indexOf("Null") >= 0) if (debug)alert(fxName + " -- " + method.join("|") + " -- searching for method with " + params) if (method.length == 0 || !(method = searchMethod(method, params, debug))) return new MethodException(); if (debug) alert("OK: \\" + method) var f = (generic ? clazzFun : clazzFun["\\" + method]); //if (generic) //{ /* Use the generic method */ /* * Will this case be reachable? * March 4, 2006 josson * * Reachable for calling #remove (Object) method on * ArrayList instance * May 5, 2006 josson */ var methodParams = null; if (params.hasCastedNull) { methodParams = []; for (var k = 0; k < args.length; k++) { if (args[k] instanceof Clazz.CastedNull) { /* * For Clazz.CastedNull instances, the type name is * already used to indentify the method in searchMethod. */ methodParams[k] = null; } else { methodParams[k] = args[k]; } } } else { methodParams = args; } fx.lastMethod = f; //if (!params.hasCastedNull) SAEMarray[id] = f; return f.apply(objThis, methodParams); }; /** * Search the existed polymorphic methods to get the matched method with * the given parameter types. * * @param existedMethods Array of string which contains method parameters * @param paramTypes Array of string that is parameter type. * @return string of method parameters seperated by "\\" */ /* private */ var searchMethod = function(roundOne, paramTypes, debug) { // Filter out all the fitted methods for the given parameters var roundTwo = []; var len = roundOne.length; for (var i = 0; i < len; i++) { var fittedLevel = []; var isFitted = true; var len2 = roundOne[i].length; for (var j = 0; j < len2; j++) { fittedLevel[j] = Clazz.getInheritedLevel (paramTypes[j], roundOne[i][j]); //if (debug)alert([paramTypes[j],fittedLevel[j],roundOne[i][j]]) if (fittedLevel[j] < 0) { isFitted = false; break; } } if (isFitted) { fittedLevel[paramTypes.length] = i; // Keep index for later use roundTwo.push(fittedLevel); } } if (roundTwo.length == 0) return null; // Find out the best method according to the inheritance. var resultTwo = roundTwo; var min = resultTwo[0]; for (var i = 1; i < resultTwo.length; i++) { var isVectorLesser = true; for (var j = 0; j < paramTypes.length; j++) { if (min[j] < resultTwo[i][j]) { isVectorLesser = false;; break; } } if (isVectorLesser) min = resultTwo[i]; } var index = min[paramTypes.length]; // Get the previously stored index /* * Return the method parameters' type string as indentifier of the * choosen method. */ return roundOne[index].join ('\\'); }; ////////////////////////////////// package loading /////////////////////// /* * all root packages. e.g. java.*, org.*, com.* */ /* protected */ Clazz.allPackage = {}; /** * Will be used to keep value of whether the class is defined or not. */ /* protected */ Clazz.allClasses = {}; Clazz.lastPackageName = null; Clazz.lastPackage = null; /* protected */ Clazz.unloadedClasses = []; /* public */ Clazz.declarePackage = function (pkgName) { if (Clazz.lastPackageName == pkgName) return Clazz.lastPackage; if (pkgName && pkgName.length) { var pkgFrags = pkgName.split (/\./); var pkg = Clazz.allPackage; for (var i = 0; i < pkgFrags.length; i++) { if (!pkg[pkgFrags[i]]) { pkg[pkgFrags[i]] = { __PKG_NAME__ : (pkg.__PKG_NAME__ ? pkg.__PKG_NAME__ + "." + pkgFrags[i] : pkgFrags[i]) }; // pkg[pkgFrags[i]] = {}; if (i == 0) { // eval ... Clazz.setGlobal(pkgFrags[i], pkg[pkgFrags[i]]); } } pkg = pkg[pkgFrags[i]] } Clazz.lastPackageName = pkgName; Clazz.lastPackage = pkg; return pkg; } }; /* protected */ Clazz.evalType = function (typeStr, isQualified) { var idx = typeStr.lastIndexOf("."); if (idx != -1) { var pkgName = typeStr.substring (0, idx); var pkg = Clazz.declarePackage (pkgName); var clazzName = typeStr.substring (idx + 1); return pkg[clazzName]; } if (isQualified) return window[typeStr]; switch (typeStr) { case "string": return String; case "number": return Number; case "object": return Clazz._O; case "boolean": return Boolean; case "function": return Function; case "void": case "undefined": case "unknown": return typeStr; case "NullObject": return NullObject; default: return window[typeStr]; } }; /** * Define a class or interface. * * @param qClazzName String presents the qualified name of the class * @param clazzFun Function of the body * @param clazzParent Clazz to inherit from, may be null * @param interfacez Clazz may implement one or many interfaces * interfacez can be Clazz object or Array of Clazz objects. * @return Ruturn the modified Clazz object */ /* public */ Clazz.defineType = function (qClazzName, clazzFun, clazzParent, interfacez) { var cf = Clazz.unloadedClasses[qClazzName]; if (cf) { clazzFun = cf; } var idx = qClazzName.lastIndexOf ("."); if (idx != -1) { var pkgName = qClazzName.substring (0, idx); var pkg = Clazz.declarePackage (pkgName); var clazzName = qClazzName.substring (idx + 1); if (pkg[clazzName]) { // already defined! Should throw exception! return pkg[clazzName]; } pkg[clazzName] = clazzFun; } else { if (window[qClazzName]) { // already defined! Should throw exception! return window[qClazzName]; } Clazz.setGlobal(qClazzName, clazzFun); } Clazz.decorateAsType(clazzFun, qClazzName, clazzParent, interfacez); /*# {$no.javascript.support} >>x #*/ var iFun = Clazz._innerFunctions; clazzFun.defineMethod = iFun.defineMethod; clazzFun.defineStaticMethod = iFun.defineStaticMethod; clazzFun.makeConstructor = iFun.makeConstructor; /*# x<< #*/ return clazzFun; }; var isSafari = (navigator.userAgent.indexOf ("Safari") != -1); var isSafari4Plus = false; if (isSafari) { var ua = navigator.userAgent; var verIdx = ua.indexOf("Version/"); if (verIdx != -1) { var verStr = ua.substring(verIdx + 8); var verNumber = parseFloat(verStr); isSafari4Plus = verNumber >= 4.0; } } /* public */ Clazz.instantialize = function (objThis, args) { if (args && args.length == 1 && args[0] && args[0] instanceof args4InheritClass) { return; } if (objThis instanceof Number) { objThis.valueOf = function () { return this; }; } if (isSafari4Plus) { // Fix bug of Safari 4.0+'s over-optimization var argsClone = []; for (var k = 0; k < args.length; k++) { argsClone[k] = args[k]; } args = argsClone; } var c = objThis.construct; if (c) { if (!objThis.con$truct) { // no need to init fields c.apply (objThis, args); } else if (!objThis.getClass ().superClazz) { // the base class objThis.con$truct.apply (objThis, []); c.apply (objThis, args); } else if ((c.claxxOwner && c.claxxOwner === objThis.getClass ()) || (c.stacks && c.stacks[c.stacks.length - 1] == objThis.getClass ())) { /* * This #construct is defined by this class itself. * #construct will call Clazz.superConstructor, which will * call #con$truct back */ c.apply (objThis, args); } else { // constructor is a super constructor if (c.claxxOwner && !c.claxxOwner.superClazz && c.claxxOwner.con$truct) { c.claxxOwner.con$truct.apply (objThis, []); } else if (c.stacks && c.stacks.length == 1 && !c.stacks[0].superClazz) { c.stacks[0].con$truct.apply (objThis, []); } c.apply (objThis, args); objThis.con$truct.apply (objThis, []); } } else if (objThis.con$truct) { objThis.con$truct.apply (objThis, []); } }; /** * Once there are other methods registered to the Function.prototype, * those method names should be add to the following Array. */ /* * static final member of interface may be a class, which may * be function. */ /* protected */ Clazz.innerFunctionNames = [ "isInstance", "equals", "hashCode", /*"toString",*/ "getName", "getCanonicalName", "getClassLoader", "getResource", "getResourceAsStream" /*# {$no.javascript.support} >>x #*/, "defineMethod", "defineStaticMethod", "makeConstructor" /*# x<< #*/ ]; /* * Static methods */ Clazz._innerFunctions = { /* * Similar to Object#equals */ isInstance: function(c) { return Clazz.instanceOf(c, this); }, equals : function (aFun) { return this === aFun; }, hashCode : function () { return this.getName ().hashCode (); }, toString : function () { return "class " + this.getName (); }, /* * Similar to Class#getName */ getName : function () { return Clazz.getClassName (this, true); }, getCanonicalName : function () { return this.__CLASS_NAME__; }, getClassLoader : function () { var clazzName = this.__CLASS_NAME__; var baseFolder = Clazz._Loader.getClasspathFor(clazzName); var x = baseFolder.lastIndexOf (clazzName.replace (/\./g, "/")); if (x != -1) { baseFolder = baseFolder.substring (0, x); } else { baseFolder = Clazz._Loader.getClasspathFor(clazzName, true); } var loader = Clazz._Loader.requireLoaderByBase(baseFolder); loader.getResourceAsStream = Clazz._innerFunctions.getResourceAsStream; loader.getResource = Clazz._innerFunctions.getResource; // BH return loader; }, getResource : function(name) { var stream = this.getResourceAsStream(name); return (stream ? stream.url : null); }, getResourceAsStream : function (name) { if (!name) return null; name = name.replace (/\\/g, '/'); var baseFolder = null; var fname = name; var clazzName = this.__CLASS_NAME__; if (arguments.length == 2 && name.indexOf ('/') != 0) { // additional argument name = "/" + name; } if (name.indexOf ('/') == 0) { //is.url = name.substring (1); if (arguments.length == 2) { // additional argument baseFolder = arguments[1]; if (!baseFolder) baseFolder = Clazz.binaryFolders[0]; } else if (Clazz._Loader) { baseFolder = Clazz._Loader.getClasspathFor(clazzName, true); } if (!baseFolder) { fname = name.substring (1); } else { baseFolder = baseFolder.replace (/\\/g, '/'); var length = baseFolder.length; var lastChar = baseFolder.charAt (length - 1); if (lastChar != '/') { baseFolder += "/"; } fname = baseFolder + name.substring (1); } } else { if (this.base) { baseFolder = this.base; } else if (Clazz._Loader) { baseFolder = Clazz._Loader.getClasspathFor(clazzName); var x = baseFolder.lastIndexOf (clazzName.replace (/\./g, "/")); if (x != -1) { baseFolder = baseFolder.substring (0, x); } else { //baseFolder = null; var y = -1; if (baseFolder.indexOf (".z.js") == baseFolder.length - 5 && (y = baseFolder.lastIndexOf ("/")) != -1) { baseFolder = baseFolder.substring (0, y + 1); var pkgs = clazzName.split (/\./); for (var k = 1; k < pkgs.length; k++) { var pkgURL = "/"; for (var j = 0; j < k; j++) { pkgURL += pkgs[j] + "/"; } if (pkgURL.length > baseFolder.length) { break; } if (baseFolder.indexOf (pkgURL) == baseFolder.length - pkgURL.length) { baseFolder = baseFolder.substring (0, baseFolder.length - pkgURL.length + 1); break; } } } else { baseFolder = Clazz._Loader.getClasspathFor(clazzName, true); } } } else { var bins = Clazz.binaryFolders; if (bins && bins.length) { baseFolder = bins[0]; } } if (!baseFolder) baseFolder = "j2s/"; baseFolder = baseFolder.replace (/\\/g, '/'); var length = baseFolder.length; var lastChar = baseFolder.charAt (length - 1); if (lastChar != '/') { baseFolder += "/"; } if (this.base) { fname = baseFolder + name; } else { var idx = clazzName.lastIndexOf ('.'); if (idx == -1 || this.base) { fname = baseFolder + name; } else { fname = baseFolder + clazzName.substring (0, idx) .replace (/\./g, '/') + "/" + name; } } } var url = null; try { if (fname.indexOf(":/") < 0) { var d = document.location.href.split("?")[0].split("/"); d[d.length - 1] = fname; fname = d.join("/"); } url = new java.net.URL(fname); } catch (e) { } var data = (url == null ? null : Jmol._getFileData(fname.toString())); if (!data || data == "error" || data.indexOf("[Exception") == 0) return null; var bytes = new java.lang.String(data).getBytes(); var is = new java.io.BufferedInputStream ( new java.io.ByteArrayInputStream (bytes)); is.url = url; return is; }/*# {$no.javascript.support} >>x #*/, /* * For JavaScript programmers */ defineMethod : function (methodName, funBody, paramTypes) { Clazz.defineMethod (this, methodName, funBody, paramTypes); }, /* * For JavaScript programmers */ defineStaticMethod : function (methodName, funBody, paramTypes) { Clazz.defineMethod (this, methodName, funBody, paramTypes); this[methodName] = this.prototype[methodName]; }, /* * For JavaScript programmers */ makeConstructor : function (funBody, paramTypes) { Clazz.makeConstructor (this, funBody, paramTypes); } /*# x<< #*/ }; var cStack = []; /** * BH: I would like to be able to remove "self.c$" here, but that is tricky. */ Clazz.pu$h = function (c) { c || (c = self.c$); // old style c && cStack.push(c); }; Clazz.p0p = function () { return cStack.pop(); }; /* protected */ Clazz.decorateAsClass = function (clazzFun, prefix, name, clazzParent, interfacez, parentClazzInstance, _decorateAsClass) { var prefixName = null; if (prefix) { prefixName = prefix.__PKG_NAME__; if (!prefixName) prefixName = prefix.__CLASS_NAME__; } var qName = (prefixName ? prefixName + "." : "") + name; if (Clazz._Loader._classPending[qName]) { delete Clazz._Loader._classPending[qName]; Clazz._Loader._classCountOK++; Clazz._Loader._classCountPending--; } if (Clazz._Loader && Clazz._Loader._checkLoad) { System.out.println("decorating class " + prefixName + "." + name); } var cf = Clazz.unloadedClasses[qName]; if (cf) { clazzFun = cf; } var qName = null; decorateFunction(clazzFun, prefix, name); if (parentClazzInstance) { Clazz.inheritClass (clazzFun, clazzParent, parentClazzInstance); } else if (clazzParent) { Clazz.inheritClass (clazzFun, clazzParent); } if (interfacez) { Clazz.implementOf (clazzFun, interfacez); } return clazzFun; }; /* private */ var decorateFunction = function (clazzFun, prefix, name, _decorateFunction) { var qName; if (!prefix) { // e.g. Clazz.declareInterface (null, "ICorePlugin", org.eclipse.ui.IPlugin); qName = name; Clazz.setGlobal(name, clazzFun); } else if (prefix.__PKG_NAME__) { // e.g. Clazz.declareInterface (org.eclipse.ui, "ICorePlugin", org.eclipse.ui.IPlugin); qName = prefix.__PKG_NAME__ + "." + name; prefix[name] = clazzFun; if (prefix === java.lang) Clazz.setGlobal(name, clazzFun); } else { // e.g. Clazz.declareInterface (org.eclipse.ui.Plugin, "ICorePlugin", org.eclipse.ui.IPlugin); qName = prefix.__CLASS_NAME__ + "." + name; prefix[name] = clazzFun; } Clazz.extendJO(clazzFun, qName); var inF = Clazz.innerFunctionNames; for (var i = 0; i < inF.length; i++) { clazzFun[inF[i]] = Clazz._innerFunctions[inF[i]]; } if (Clazz._Loader) Clazz._Loader.updateNodeForFunctionDecoration(qName); }; /* protected */ Clazz.declareInterface = function (prefix, name, interfacez, _declareInterface) { var clazzFun = function () {}; decorateFunction(clazzFun, prefix, name); if (interfacez) { Clazz.implementOf (clazzFun, interfacez); } return clazzFun; }; /* public */ Clazz.declareType = function (prefix, name, clazzParent, interfacez, parentClazzInstance, _declareType) { var f = function () { Clazz.instantialize (this, arguments); }; return Clazz.decorateAsClass (f, prefix, name, clazzParent, interfacez, parentClazzInstance); }; /* public */ Clazz.declareAnonymous = function (prefix, name, clazzParent, interfacez, parentClazzInstance, _declareAnonymous) { var f = function () { Clazz.prepareCallback(this, arguments); Clazz.instantialize (this, arguments); }; return Clazz.decorateAsClass (f, prefix, name, clazzParent, interfacez, parentClazzInstance); }; /* public */ Clazz.decorateAsType = function (clazzFun, qClazzName, clazzParent, interfacez, parentClazzInstance, inheritClazzFuns, _decorateAsType) { Clazz.extendJO(clazzFun, qClazzName); clazzFun.equals = Clazz._innerFunctions.equals; clazzFun.getName = Clazz._innerFunctions.getName; if (inheritClazzFuns) { for (var i = 0; i < Clazz.innerFunctionNames.length; i++) { var methodName = Clazz.innerFunctionNames[i]; clazzFun[methodName] = Clazz._innerFunctions[methodName]; } } if (parentClazzInstance) { Clazz.inheritClass (clazzFun, clazzParent, parentClazzInstance); } else if (clazzParent) { Clazz.inheritClass (clazzFun, clazzParent); } if (interfacez) { Clazz.implementOf (clazzFun, interfacez); } return clazzFun; }; ////////////////////////// default package declarations //////////////////////// /* sgurin: preserve Number.prototype.toString */ Number.prototype._numberToString=Number.prototype.toString; Clazz.declarePackage ("java.io"); //Clazz.declarePackage ("java.lang"); Clazz.declarePackage ("java.lang.annotation"); // java.lang Clazz.declarePackage ("java.lang.instrument"); // java.lang Clazz.declarePackage ("java.lang.management"); // java.lang Clazz.declarePackage ("java.lang.reflect"); // java.lang Clazz.declarePackage ("java.lang.ref"); // java.lang.ref java.lang.ref.reflect = java.lang.reflect; Clazz.declarePackage ("java.util"); //var reflect = Clazz.declarePackage ("java.lang.reflect"); Clazz.declarePackage ("java.security"); /* * Consider these interfaces are basic! */ Clazz.declareInterface (java.io,"Closeable"); Clazz.declareInterface (java.io,"DataInput"); Clazz.declareInterface (java.io,"DataOutput"); Clazz.declareInterface (java.io,"Externalizable"); Clazz.declareInterface (java.io,"Flushable"); Clazz.declareInterface (java.io,"Serializable"); Clazz.declareInterface (java.lang,"Iterable"); Clazz.declareInterface (java.lang,"CharSequence"); Clazz.declareInterface (java.lang,"Cloneable"); Clazz.declareInterface (java.lang,"Appendable"); Clazz.declareInterface (java.lang,"Comparable"); Clazz.declareInterface (java.lang,"Runnable"); Clazz.declareInterface (java.util,"Comparator"); java.lang.ClassLoader = { __CLASS_NAME__ : "ClassLoader" }; /****************************************************************************** * Copyright (c) 2007 java2script.org and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhou Renjian - initial API and implementation *****************************************************************************/ /******* * @author zhou renjian * @create March 10, 2006 *******/ /** * Once ClassExt.js is part of Class.js. * In order to make the Class.js as small as possible, part of its content * is moved into this ClassExt.js. * * See also http://j2s.sourceforge.net/j2sclazz/ */ /** * Clazz.MethodNotFoundException is used to notify the developer about calling * methods with incorrect parameters. */ /* protected */ // Override the Clazz.MethodNotFoundException in Class.js to give details var newMethodNotFoundException = function (obj, clazz, method, params) { var paramStr = ""; if (params) { paramStr = params.substring (1).replace (/\\/g, ","); } var leadingStr = ""; if (method && method != "construct") { leadingStr = "Method"; } else { leadingStr = "Constructor"; } var message = leadingStr + " " + Clazz.getClassName (clazz, true) + "." + method + "(" + paramStr + ") is not found!"; throw new java.lang.NoSuchMethodException(message); }; /** * Prepare "callback" for instance of anonymous Class. * For example for the callback: * this.callbacks.MyEditor.sayHello(); * * This is specifically for inner classes that are referring to * outer class methods and fields. * * @param objThis the host object for callback * @param args arguments object. args[0] will be classThisObj -- the "this" * object to be hooked * * Attention: parameters should not be null! */ /* protected */ Clazz.prepareCallback = function (innerObj, args) { var outerObj = args[0]; var cbName = "b$"; // "callbacks"; if (innerObj && outerObj && outerObj !== window) { var className = Clazz.getClassName(outerObj, true); var obs = {}; if (innerObj[cbName]) // must make a copy! for (var s in innerObj[cbName]) obs[s] = innerObj[cbName][s]; innerObj[cbName] = obs; /* * TODO: the following line is SWT-specific! Try to move it out! */ // obs[className.replace (/org\.eclipse\.swt\./, "$wt.")] = outerObj; // all references to outer class and its superclass objects must be here as well obs[className] = outerObj; var clazz = Clazz.getClass(outerObj); while (clazz.superClazz) { clazz = clazz.superClazz; /* * TODO: the following line is SWT-specific! Try to move it out! */ // obs[Clazz.getClassName (clazz, true) // .replace (/org\.eclipse\.swt\./, "$wt.")] = outerObj; obs[Clazz.getClassName(clazz, true)] = outerObj; } var cbs = outerObj[cbName]; if (cbs) for (var s in cbs) obs[s] = cbs[s]; } // remove "this" argument // note that args is an instance of arguments -- NOT an array; does not have the .shift() method! for (var i = 0; i < args.length - 1; i++) args[i] = args[i + 1]; args.length--; }; /** * Construct instance of the given inner class. * * @param classInner given inner class, alway with name like "*$*" * @param innerObj this instance which can be used to call back. * @param finalVars final variables which the inner class may use * @return the constructed object * * @see Clazz#cloneFinals */ /* public */ Clazz.innerTypeInstance = function (clazzInner, innerObj, finalVars) { if (!clazzInner) clazzInner = arguments.callee.caller; var obj; if (finalVars || innerObj.$finals) { obj = new clazzInner(innerObj, Clazz.inheritArgs); // f$ is short for the once choosen "$finals" if (finalVars) { if (innerObj.f$) { var o = {}; for (var attr in innerObj.f$) o[attr] = innerObj.f$[attr]; for (var attr in finalVars) o[attr] = finalVars[attr]; obj.f$ = o; } else { obj.f$ = finalVars; } } else if (innerObj.f$) { obj.f$ = innerObj.f$; } } else { switch (arguments.length) { case 3: return new clazzInner(innerObj); case 4: return (innerObj.__CLASS_NAME__ == clazzInner.__CLASS_NAME__ && arguments[3] === Clazz.inheritArgs ? innerObj : new clazzInner(innerObj, arguments[3])); case 5: return new clazzInner(innerObj, arguments[3], arguments[4]); case 6: return new clazzInner(innerObj, arguments[3], arguments[4], arguments[5]); case 7: return new clazzInner(innerObj, arguments[3], arguments[4], arguments[5], arguments[6]); case 8: return new clazzInner(innerObj, arguments[3], arguments[4], arguments[5], arguments[6], arguments[7]); case 9: return new clazzInner(innerObj, arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8]); case 10: return new clazzInner(innerObj, arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); default: //Should construct instance manually. obj = new clazzInner(innerObj, Clazz.inheritArgs); break; } } var n = arguments.length - 3; var args = new Array(n); for (var i = n; --i >= 0;) args[i] = arguments[i + 3]; Clazz.instantialize(obj, args); return obj; }; /** * Clone variables whose modifier is "final". * Usage: var o = Clazz.cloneFinals ("name", name, "age", age); * * @return Object with all final variables */ /* public */ Clazz.cloneFinals = function () { var o = {}; var len = arguments.length / 2; for (var i = len; --i >= 0;) o[arguments[i + i]] = arguments[i + i + 1]; return o; }; /* public */ Clazz.isClassDefined = Clazz.isDefinedClass = function(clazzName) { if (!clazzName) return false; /* consider null or empty name as non-defined class */ if (Clazz.allClasses[clazzName]) return true; var pkgFrags = clazzName.split (/\./); var pkg = null; for (var i = 0; i < pkgFrags.length; i++) if (!(pkg = (pkg ? pkg[pkgFrags[i]] : Clazz.allPackage[pkgFrags[0]]))) { return false; } return (pkg && (Clazz.allClasses[clazzName] = true)); }; /** * Define the enum constant. * @param classEnum enum type * @param enumName enum constant * @param enumOrdinal enum ordinal * @param initialParams enum constant constructor parameters * @return return defined enum constant */ /* public */ Clazz.defineEnumConstant = function (clazzEnum, enumName, enumOrdinal, initialParams, clazzEnumExt) { var o = (clazzEnumExt ? new clazzEnumExt() : new clazzEnum()); // BH avoids unnecessary calls to SAEM o.$name = enumName; o.$ordinal = enumOrdinal; //Clazz.superConstructor (o, clazzEnum, [enumName, enumOrdinal]); if (initialParams && initialParams.length) o.construct.apply (o, initialParams); clazzEnum[enumName] = o; clazzEnum.prototype[enumName] = o; if (!clazzEnum["$ values"]) { // BH added clazzEnum["$ values"] = [] // BH added clazzEnum.values = function() { // BH added return this["$ values"]; // BH added }; // BH added } clazzEnum["$ values"].push(o); return o; }; //////// (int) conversions ////////// Clazz.floatToInt = function (x) { return x < 0 ? Math.ceil(x) : Math.floor(x); }; Clazz.floatToByte = Clazz.floatToShort = Clazz.floatToLong = Clazz.floatToInt; Clazz.doubleToByte = Clazz.doubleToShort = Clazz.doubleToLong = Clazz.doubleToInt = Clazz.floatToInt; Clazz.floatToChar = function (x) { return String.fromCharCode (x < 0 ? Math.ceil(x) : Math.floor(x)); }; Clazz.doubleToChar = Clazz.floatToChar; ///////////////////////////////// Array additions ////////////////////////////// // // BH: these are necessary for integer processing, especially // // var getArrayClone = function(nbits) { return function() { var me = this; var n = me.length; var a = (nbits == 32 ? new Int32Array(n) : new Float64Array(n)); for (var i = n; --i >= 0;) a[i] = me[i]; return a; } } if (self.Int32Array && self.Int32Array != Array) { Clazz.haveInt32 = true; if (!Int32Array.prototype.sort) Int32Array.prototype.sort = Array.prototype.sort if (!Int32Array.prototype.clone) Int32Array.prototype.clone = getArrayClone(32); } else { Int32Array = function(n) { if (!n) n = 0; var b = new Array(n); b.toString = function(){return "[object Int32Array]"} for (var i = 0; i < n; i++)b[i] = 0 return b; } Clazz.haveInt32 = false; Int32Array.prototype.sort = Array.prototype.sort Int32Array.prototype.clone = getArrayClone(32); Int32Array.prototype.int32Fake = function(){}; } if (self.Float64Array && self.Float64Array != Array) { Clazz.haveFloat64 = true; if (!Float64Array.prototype.sort) Float64Array.prototype.sort = Array.prototype.sort if (!Float64Array.prototype.clone) Float64Array.prototype.clone = getArrayClone(64); } else { Clazz.haveFloat64 = false; Float64Array = function(n) { if (!n) n = 0; var b = new Array(n); for (var i = 0; i < n; i++)b[i] = 0.0 return b; }; Float64Array.prototype.sort = Array.prototype.sort Float64Array.prototype.clone = getArrayClone(64); Float64Array.prototype.float64Fake = function() {}; // "present" Float64Array.prototype.toString = function() {return "[object Float64Array]"}; // Darn! Mozilla makes this a double, not a float. It's 64-bit. // and Safari 5.1 doesn't have Float64Array } /** * Make arrays. * * @return the created Array object */ /* public */ Clazz.newArray = function () { if (arguments[0] instanceof Array) { // recursive, from newArray(n,m,value) // as newArray([m, value], newInt32Array) var args = arguments[0]; var f = arguments[1]; } else { var args = arguments; var f = Array; } var dim = args[0]; if (typeof dim == "string") { dim = dim.charCodeAt (0); // char } var len = args.length - 1; var val = args[len]; switch (args.length) { case 0: // never case 1: return []; // maybe never? case 2: if (val == null) return new Array(dim); if (f === true && Clazz.haveInt32) return new Int32Array(dim); if (f === false && Clazz.haveFloat64) return new Float64Array(dim); var arr = (f === true ? new Int32Array() : f === false ? new Float64Array() : dim < 0 ? val : new Array(dim)); for (var i = dim; --i >= 0;) arr[i] = val; return arr; default: var xargs = new Array (len); for (var i = 0; i < len; i++) { xargs[i] = args[i + 1]; } var arr = new Array (dim); if (val == null || val >= 0 || len > 2) for (var i = 0; i < dim; i++) { // Call recursively! arr[i] = Clazz.newArray (xargs, f); } return arr; } }; Clazz.newArray32 = function(args, isInt32) { var dim = args[0]; if (typeof dim == "string") dim = dim.charCodeAt (0); // char var len = args.length - 1; var val = args[len]; switch (args.length) { case 0: case 1: alert ("ERROR IN newArray32 -- args.length < 2"); return new Array(0); case 2: var isDefined = (dim < 0); if (isDefined) dim = val.length; var a = (val < 0 ? new Array(dim) : isInt32 ? new Int32Array(dim) : new Float64Array(dim)); if (isDefined) for (var i = dim; --i >= 0;) a[i] = val[i]; return a; } var xargs = new Array(len); for (var i = len; --i >= 0;) { xargs[i] = args[i + 1]; } var arr = new Array (dim); for (var i = 0; i < dim; i++) { // Call newArray referencing this array type // only for the final iteration, and only if val === 0 arr[i] = Clazz.newArray (xargs, isInt32); } return arr; }; /** * Make arrays. * * @return the created Array object */ /* public */ Clazz.newInt32Array = function () { return Clazz.newArray32(arguments, true); } /** * Make arrays. * * @return the created Array object */ /* public */ Clazz.newFloat64Array = function () { return Clazz.newArray32(arguments, false); } Clazz.newFloatArray = Clazz.newDoubleArray = Clazz.newFloat64Array; Clazz.newIntArray = Clazz.newLongArray = Clazz.newShortArray = Clazz.newByteArray = Clazz.newInt32Array; Clazz.newCharArray = Clazz.newBooleanArray = Clazz.newArray; //$_AI=Clazz.newIntArray; //$_AF=Clazz.newFloatArray; //$_AD=Clazz.newDoubleArray; //$_AL=Clazz.newLongArray; //$_AS=Clazz.newShortArray; //$_AB=Clazz.newByteArray; //$_AC=Clazz.newCharArray; //$_Ab=Clazz.newBooleanArray; var arrayIs = function(a, what) { // for some reason, Number.constructor.toString() now gives "too much recursion" return a.constructor && a.constructor != Number && a.constructor.toString().indexOf(what) >= 0 } Clazz.isAS = function(a) { // just checking first parameter return (a && typeof a == "object" && arrayIs(a, " Array") && (typeof a[0] == "string" || typeof a[0] == "undefined")); } Clazz.isASS = function(a) { return (a && typeof a == "object" && Clazz.isAS(a[0])); } Clazz.isAP = function(a) { return (a && Clazz.getClassName(a[0]) == "JU.P3"); } Clazz.isAI = function(a) { return (a && typeof a == "object" && (Clazz.haveInt32 ? arrayIs(a, "Int32Array") : a.int32Fake ? true : false)); } Clazz.isAII = function(a) { // assumes non-null a[0] return (a && typeof a == "object" && Clazz.isAI(a[0])); } Clazz.isAF = function(a) { return (a && typeof a == "object" && (Clazz.haveFloat64 ? arrayIs(a, "Float64Array") : a.float64Fake ? true : false)); } Clazz.isAFF = function(a) { // assumes non-null a[0] return (a && typeof a == "object" && Clazz.isAF(a[0])); } Clazz.isAFFF = function(a) { // assumes non-null a[0] return (a && typeof a == "object" && Clazz.isAFF(a[0])); } Clazz.isAFloat = function(a) { // just checking first parameter return (a && typeof a == "object" && arrayIs(a, " Array") && Clazz.instanceOf(a[0], Float)); } /** * Make the RunnableCompatiability instance as a JavaScript function. * * @param jsr Instance of RunnableCompatiability * @return JavaScript function instance represents the method run of jsr. */ /* public */ /* Clazz.makeFunction = function (jsr) { // never used in Jmol -- called by Enum, but not accessible to it -- part of SWT return function(e) { if (!e) e = window.event; if (jsr.setEvent) jsr.setEvent(e); jsr.run(); switch (jsr.returnSet) { case 1: return jsr.returnNumber; case 2: return jsr.returnBoolean; case 3: return jsr.returnObject; } }; }; */ /* protected */ Clazz.defineStatics = function (clazz) { for (var j = arguments.length, i = (j - 1) / 2; --i >= 0;) { var val = arguments[--j] var name = arguments[--j]; clazz[name] = clazz.prototype[name] = val; } }; /* public */ Clazz.prepareFields = function (clazz, fieldsFun) { var stacks = []; if (clazz.con$truct) { var ss = clazz.con$truct.stacks; var idx = 0;//clazz.con$truct.index; for (var i = idx; i < ss.length; i++) { stacks[i] = ss[i]; } } addProto(clazz.prototype, "con$truct", clazz.con$truct = function () { var stacks = arguments.callee.stacks; if (stacks) { for (var i = 0; i < stacks.length; i++) { stacks[i].apply (this, []); } } }); stacks.push(fieldsFun); clazz.con$truct.stacks = stacks; clazz.con$truct.index = 0; }; /* * Serialize those public or protected fields in class * net.sf.j2s.ajax.SimpleSerializable. */ /* protected */ /* Clazz.registerSerializableFields = function (clazz) { var args = arguments; var length = args.length; var newArr = []; if (clazz.declared$Fields) { for (var i = 0; i < clazz.declared$Fields.length; i++) { newArr[i] = clazz.declared$Fields[i]; } } clazz.declared$Fields = newArr; if (length > 0 && length % 2 == 1) { var fs = clazz.declared$Fields; var n = (length - 1) / 2; for (var i = 1; i <= n; i++) { var o = { name : args[i + i - 1], type : args[i + i] }; var existed = false; for (var j = 0; j < fs.length; j++) { if (fs[j].name == o.name) { // reloaded classes fs[j].type = o.type; // update type existed = true; break; } } if (!existed) fs.push(o); } } }; */ /* * Get the caller method for those methods that are wrapped by * Clazz.searchAndExecuteMethod. * * @param args caller method's arguments * @return caller method, null if there is not wrapped by * Clazz.searchAndExecuteMethod or is called directly. */ /* protected */ /* Clazz.getMixedCallerMethod = function (args) { var o = {}; var argc = args.callee.caller; // tryToSearchAndExecute if (argc && argc !== tryToSearchAndExecute) // inherited method's apply argc = argc.arguments.callee.caller; if (argc !== tryToSearchAndExecute || (argc = argc.arguments.callee.caller) !== Clazz.searchAndExecuteMethod) return null; o.claxxRef = argc.arguments[1]; o.fxName = argc.arguments[2]; o.paramTypes = Clazz.getParamsType(argc.arguments[3]); argc = argc.arguments.callee.caller // Clazz.generateDelegatingMethod && argc.arguments.callee.caller; // the private method's caller if (!argc) return null; o.caller = argc; return o; }; */ /* BH -- The issue here is a subclass calling its private method FOO when * there is also a private method of the same name in its super class. * This can ALWAYS be avoided and, one could argue, is bad * program design anyway. In Jmol, the presence of this possibility * creates over 8000 references to the global $fx, which was only * checked in a few rare cases. We can then also remove $fz references. * */ /* * Check and return super private method. * In order make private methods be executed correctly, some extra javascript * must be inserted into the beggining of the method body of the non-private * methods that with the same method signature as following: * * var $private = Clazz.checkPrivateMethod (arguments); * if ($private) { * return $private.apply (this, arguments); * } * * Be cautious about this. The above codes should be insert by Java2Script * compiler or with double checks to make sure things work correctly. * * @param args caller method's arguments * @return private method if there are private method fitted for the current * calling environment */ /* public */ Clazz.checkPrivateMethod = function () { // get both this one and the one calling it me = arguments.callee.caller; caller = arguments.callee.caller.caller; var stack = me.stacks; // if their classes are the same, no issue var mySig = "\\" + Clazz.getParamsType(arguments[0]).join("\\") if (!me.privateNote) { me.privateNote = "You are seeing this note because the method " + me.exName + mySig + " in class " + me.exClazz.__CLASS_NAME__ + " has a superclass method by the same name (possibly with the same parameters) that is private and " + " therefore might be called improperly from this class. If your " + " code does not run properly, or you want to make it run faster, change the name of this method to something else." System.out.println(me.privateNote); alert(me.privateNote); } /* alert([me.exClazz.__CLASS_NAME__, me.exName, caller.exClazz.__CLASS_NAME__, caller.exName,stack,mySig]) if (stack == null || caller.exClazz == me.exClazz) return null; // I am being called by a different class... for (var i = stack.length; --i >= 0;) { if (stacks[i] != caller.claxxRef) continue; // and it is on MY class stack // if ( } */ /* var m = Clazz.getMixedCallerMethod (args); if (m == null) return null; var callerFx = m.claxxRef.prototype[m.caller.exName]; if (callerFx == null) return null; // may not be in the class hierarchies var ppFun = null; if (callerFx.claxxOwner ) { ppFun = callerFx.claxxOwner.prototype[m.fxName]; } else { var stacks = callerFx.stacks; for (var i = stacks.length - 1; i >= 0; i--) { var fx = stacks[i].prototype[m.caller.exName]; if (fx === m.caller) { ppFun = stacks[i].prototype[m.fxName]; } else if (fx ) { for (var fn in fx) { if (fn.indexOf ('\\') == 0 && fx[fn] === m.caller) { ppFun = stacks[i].prototype[m.fxName]; break; } } } if (ppFun) { break; } } } if (ppFun && ppFun.claxxOwner == null) { ppFun = ppFun["\\" + m.paramTypes]; } if (ppFun && ppFun.isPrivate && ppFun !== args.callee) { return ppFun; } */ return null; }; //$fz = null; // for private method declaration // /*# {$no.debug.support} >>x #*/ // /* // * Option to switch on/off of stack traces. // */ // /* protect */ //Clazz.tracingCalling = false; // /* private */ // Clazz.callingStack = function (caller, owner) { // this.caller = caller; // this.owner = owner; // }; /*# x<< #*/ /** * The first folder is considered as the primary folder. * And try to be compatiable with _Loader system. */ /* private */ /*** not used in Jmol * * if (window["_Loader"] && _Loader.binaryFolders) { Clazz.binaryFolders = _Loader.binaryFolders; } else { Clazz.binaryFolders = ["j2s/", "", "j2slib/"]; } Clazz.addBinaryFolder = function (bin) { if (bin) { var bins = Clazz.binaryFolders; for (var i = 0; i < bins.length; i++) { if (bins[i] == bin) { return ; } } bins[bins.length] = bin; } }; Clazz.removeBinaryFolder = function (bin) { if (bin) { var bins = Clazz.binaryFolders; for (var i = 0; i < bins.length; i++) { if (bins[i] == bin) { for (var j = i; j < bins.length - 1; j++) { bins[j] = bins[j + 1]; } bins.length--; return bin; } } } return null; }; Clazz.setPrimaryFolder = function (bin) { if (bin) { Clazz.removeBinaryFolder (bin); var bins = Clazz.binaryFolders; for (var i = bins.length - 1; i >= 0; i--) { bins[i + 1] = bins[i]; } bins[0] = bin; } }; ***/ ///////////////// special definitions of standard Java class methods /////////// /** * This is a simple implementation for Clazz#load. It just ignore dependencies * of the class. This will be fine for jar *.z.js file. * It will be overriden by _Loader#load. * For more details, see _Loader.js */ /* protected */ /* Clazz.load = function (musts, clazz, optionals, declaration) { // not used in Jmol if (declaration) declaration (); }; */ /* * Invade the Object prototype! * TODO: make sure that invading Object prototype does not affect other * existed library, such as Dojo, YUI, Prototype, ... */ java.lang.Object = Clazz._O; Clazz._O.getName = Clazz._innerFunctions.getName; java.lang.System = System = { props : null, //new java.util.Properties (), $props : {}, arraycopy : function (src, srcPos, dest, destPos, length) { if (src !== dest) { for (var i = 0; i < length; i++) { dest[destPos + i] = src[srcPos + i]; } } else { var swap = []; for (var i = 0; i < length; i++) { swap[i] = src[srcPos + i]; } for (var i = 0; i < length; i++) { dest[destPos + i] = swap[i]; } } }, currentTimeMillis : function () { return new Date ().getTime (); }, gc : function() {}, // bh getProperties : function () { return System.props; }, getProperty : function (key, def) { if (System.props) return System.props.getProperty (key, def); var v = System.$props[key]; if (typeof v != "undefined") return v; if (key.indexOf(".") > 0) { v = null; switch (key) { case "java.version": v = "1.6"; case "file.separator": case "path.separator": v = "/"; break; case "line.separator": v = (navigator.userAgent.indexOf("Windows") >= 0 ? "\r\n" : "\n"); break; case "os.name": case "os.version": v = navigator.userAgent; break; } if (v) return System.$props[key] = v; } return (arguments.length == 1 ? null : def == null ? key : def); // BH }, getSecurityManager : function() { return null }, // bh setProperties : function (props) { System.props = props; }, lineSeparator : function() { return '\n' }, // bh setProperty : function (key, val) { if (!System.props) return System.$props[key] = val; // BH System.props.setProperty (key, val); } }; System.identityHashCode=function(obj){ if(obj==null) return 0; return obj._$hashcode || (obj._$hashcode = ++Clazz._hashCode) /* try{ return obj.toString().hashCode(); }catch(e){ var str=":"; for(var s in obj){ str+=s+":" } return str.hashCode(); } */ } System.out = new Clazz._O (); System.out.__CLASS_NAME__ = "java.io.PrintStream"; System.out.print = function () {}; System.out.printf = function () {}; System.out.println = function () {}; System.out.write = function () {}; System.err = new Clazz._O (); System.err.__CLASS_NAME__ = "java.io.PrintStream"; System.err.print = function () {}; System.err.printf = function () {}; System.err.println = function () {}; System.err.write = function () {}; Clazz.popup = Clazz.assert = Clazz.log = Clazz.error = window.alert; Thread = function () {}; Thread.J2S_THREAD = Thread.prototype.J2S_THREAD = new Thread (); Thread.currentThread = Thread.prototype.currentThread = function () { return this.J2S_THREAD; }; /* not used in Jmol Clazz.intCast = function (n) { // 32bit var b1 = (n & 0xff000000) >> 24; var b2 = (n & 0xff0000) >> 16; var b3 = (n & 0xff00) >> 8; var b4 = n & 0xff; if ((b1 & 0x80) != 0) { return -(((b1 & 0x7f) << 24) + (b2 << 16) + (b3 << 8) + b4 + 1); } else { return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4; } }; Clazz.shortCast = function (s) { // 16bit var b1 = (n & 0xff00) >> 8; var b2 = n & 0xff; if ((b1 & 0x80) != 0) { return -(((b1 & 0x7f) << 8) + b2 + 1); } else { return (b1 << 8) + b4; } }; Clazz.byteCast = function (b) { // 8bit if ((b & 0x80) != 0) { return -((b & 0x7f) + 1); } else { return b & 0xff; } }; Clazz.charCast = function (c) { // 8bit return String.fromCharCode (c & 0xff).charAt (0); }; Clazz.floatCast = function (f) { // 32bit return f; }; */ /* * Try to fix JavaScript's shift operator defects on long type numbers. */ /* not used in Jmol Clazz.longMasks = []; Clazz.longReverseMasks = []; Clazz.longBits = []; ;(function () { var arr = [1]; for (var i = 1; i < 53; i++) { arr[i] = arr[i - 1] + arr[i - 1]; // * 2 or << 1 } Clazz.longBits = arr; Clazz.longMasks[52] = arr[52]; for (var i = 51; i >= 0; i--) { Clazz.longMasks[i] = Clazz.longMasks[i + 1] + arr[i]; } Clazz.longReverseMasks[0] = arr[0]; for (var i = 1; i < 52; i++) { Clazz.longReverseMasks[i] = Clazz.longReverseMasks[i - 1] + arr[i]; } }) (); Clazz.longLeftShift = function (l, o) { // 64bit if (o == 0) return l; if (o >= 64) return 0; if (o > 52) { error ("[Java2Script] Error : JavaScript does not support long shift!"); return l; } if ((l & Clazz.longMasks[o - 1]) != 0) { error ("[Java2Script] Error : Such shift operator results in wrong calculation!"); return l; } var high = l & Clazz.longMasks[52 - 32 + o]; if (high != 0) { return high * Clazz.longBits[o] + (l & Clazz.longReverseMasks[32 - o]) << 0; } else { return l << o; } }; Clazz.intLeftShift = function (n, o) { // 32bit return (n << o) & 0xffffffff; }; Clazz.longRightShift = function (l, o) { // 64bit if ((l & Clazz.longMasks[52 - 32]) != 0) { return Math.round((l & Clazz.longMasks[52 - 32]) / Clazz.longBits[32 - o]) + (l & Clazz.longReverseMasks[o]) >> o; } else { return l >> o; } }; Clazz.intRightShift = function (n, o) { // 32bit return n >> o; // no needs for this shifting wrapper }; Clazz.long0RightShift = function (l, o) { // 64bit return l >>> o; }; Clazz.int0RightShift = function (n, o) { // 64bit return n >>> o; // no needs for this shifting wrapper }; */ // Compress the common public API method in shorter name //$_L=Clazz.load; //$_W=Clazz.declareAnonymous;$_T=Clazz.declareType; //$_J=Clazz.declarePackage;$_C=Clazz.decorateAsClass; //$_Z=Clazz.instantialize;$_I=Clazz.declareInterface;$_D=Clazz.isClassDefined; //$_H=Clazz.pu$h;$_P=Clazz.p0p;$_B=Clazz.prepareCallback; //$_N=Clazz.innerTypeInstance;$_K=Clazz.makeConstructor;$_U=Clazz.superCall;$_R=Clazz.superConstructor; //$_M=Clazz.defineMethod;$_V=Clazz.overrideMethod;$_S=Clazz.defineStatics; //$_E=Clazz.defineEnumConstant; //$_F=Clazz.cloneFinals; //$_Y=Clazz.prepareFields;$_A=Clazz.newArray;$_O=Clazz.instanceOf; //$_G=Clazz.inheritArgs;$_X=Clazz.checkPrivateMethod;$_Q=Clazz.makeFunction; //$_s=Clazz.registerSerializableFields; //$_k=Clazz.overrideConstructor; /////////////////////// inner function support ///////////////////////////////// /* public */ Clazz.innerFunctionNames = Clazz.innerFunctionNames.concat ([ "getSuperclass", "isAssignableFrom", "getConstructor", "getDeclaredMethod", "getDeclaredMethods", "getMethod", "getMethods", "getModifiers", /*"isArray",*/ "newInstance"]); /* public */ Clazz._innerFunctions.getSuperclass = function () { return this.superClazz; }; /* public */ Clazz._innerFunctions.isAssignableFrom = function (clazz) { return Clazz.getInheritedLevel (clazz, this) >= 0; }; /* public */ Clazz._innerFunctions.getConstructor = function () { return new java.lang.reflect.Constructor (this, [], [], java.lang.reflect.Modifier.PUBLIC); }; /** * TODO: fix bug for polymorphic methods! */ /* public */ Clazz._innerFunctions.getDeclaredMethods = Clazz._innerFunctions.getMethods = function () { var ms = []; var p = this.prototype; for (var attr in p) { if (typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) { /* there are polynormical methods. */ ms.push(new java.lang.reflect.Method (this, attr, [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC)); } } p = this; for (var attr in p) { if (typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) { ms.push(new java.lang.reflect.Method (this, attr, [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC | java.lang.reflect.Modifier.STATIC)); } } return ms; }; /* public */ Clazz._innerFunctions.getDeclaredMethod = Clazz._innerFunctions.getMethod = function (name, clazzes) { var p = this.prototype; for (var attr in p) { if (name == attr && typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) { /* there are polynormical methods. */ return new java.lang.reflect.Method (this, attr, [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC); } } p = this; for (var attr in p) { if (name == attr && typeof p[attr] == "function" && !p[attr].__CLASS_NAME__) { return new java.lang.reflect.Method (this, attr, [], java.lang.Void, [], java.lang.reflect.Modifier.PUBLIC | java.lang.reflect.Modifier.STATIC); } } return null; }; /* public */ Clazz._innerFunctions.getModifiers = function () { return java.lang.reflect.Modifier.PUBLIC; }; Clazz._innerFunctions.newInstance = function (a) { var clz = this; switch(a == null ? 0 : a.length) { case 0: return new clz(); case 1: return new clz(a[0]); case 2: return new clz(a[0], a[1]); case 3: return new clz(a[0], a[1], a[2]); case 4: return new clz(a[0], a[1], a[2], a[3]); default: var x = "new " + clz.__CLASS_NAME__ + "("; for (var i = 0; i < a.length; i++) x += (i == 0 ? "" : ",") + "a[" + i + "]"; x += ")"; return eval(x); } }; //Object.newInstance = Clazz._innerFunctions.newInstance; ;(function(){ // BH added wrapper here var inF = Clazz.innerFunctionNames; for (var i = 0; i < inF.length; i++) { Clazz._O[inF[i]] = Clazz._innerFunctions[inF[i]]; Array[inF[i]] = Clazz._innerFunctions[inF[i]]; } //Array["isArray"] = function () { // return true; //}; })(); //////////////////////////// hotspot and unloading ///////////////////////////// /* For hotspot and unloading */ if (window["Clazz"] && !window["Clazz"].unloadClass) { /* public */ Clazz.unloadClass = function (qClazzName) { var cc = Clazz.evalType (qClazzName); if (cc) { Clazz.unloadedClasses[qClazzName] = cc; var clazzName = qClazzName; var pkgFrags = clazzName.split (/\./); var pkg = null; for (var i = 0; i < pkgFrags.length - 1; i++) pkg = (pkg ? pkg[pkgFrags[i]] : Clazz.allPackage[pkgFrags[0]]); if (!pkg) { Clazz.allPackage[pkgFrags[0]] = null; window[pkgFrags[0]] = null; // also try to unload inner or anonymous classes for (var c in window) { if (c.indexOf (qClazzName + "$") == 0) { Clazz.unloadClass (c); window[c] = null; } } } else { pkg[pkgFrags[pkgFrags.length - 1]] = null; // also try to unload inner or anonymous classes for (var c in pkg) { if (c.indexOf (pkgFrags[pkgFrags.length - 1] + "$") == 0) { Clazz.unloadClass (pkg.__PKG_NAME__ + "." + c); pkg[c] = null; } } } if (Clazz.allClasses[qClazzName]) { Clazz.allClasses[qClazzName] = false; // also try to unload inner or anonymous classes for (var c in Clazz.allClasses) { if (c.indexOf (qClazzName + "$") == 0) { Clazz.allClasses[c] = false; } } } for (var m in cc) { cleanDelegateMethod (cc[m]); } for (var m in cc.prototype) { cleanDelegateMethod (cc.prototype[m]); } if (Clazz._Loader) { Clazz._Loader.unloadClassExt(qClazzName); } return true; } return false; }; /* private */ var cleanDelegateMethod = function (m) { if (!m) return; if (typeof m == "function" && m.lastMethod && m.lastParams && m.lastClaxxRef) { m.lastMethod = null; m.lastParams = null; m.lastClaxxRef = null; } }; } // if (window["Clazz"] && !window["Clazz"].unloadClass) /****************************************************************************** * Copyright (c) 2007 java2script.org and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhou Renjian - initial API and implementation *****************************************************************************/ /******* * @author zhou renjian * @create July 10, 2006 *******/ //if (window["ClazzNode"] == null) { /** * TODO: * Make optimization over class dependency tree. */ /* * ClassLoader Summary * * ClassLoader creates SCRIPT elements and setup class path and onload * callback to continue class loading. * * In the onload callbacks, _Loader will try to calculate the next-to-be- * load *.js and load it. In *.js, it will contains some codes like * Clazz.load (..., "$wt.widgets.Control", ...); * to provide information to build up the class dependency tree. * * Some known problems of different browsers: * 1. In IE, loading *.js through SCRIPT will first triggers onreadstatechange * event, and then executes inner *.js source. * 2. In Firefox, loading *.js will first executes *.js source and then * triggers onload event. * 3. In Opera, similar to IE, but trigger onload event. (TODO: More details * should be studied. Currently, Opera supports no multiple-thread-loading) * * For class dependency tree, actually, it is not a tree. It is a reference * net with nodes have n parents and n children. There is a root, which * ClassLoader knows where to start searching and loading classes, for such * a net. Each node is a class. Each class may require a set of must-classes, * which must be loaded before itself getting initialized, and also need a set * of optional classes, which also be loaded before being called. * * The class loading status will be in 6 stages. * 1. Unknown, the class is newly introduced by other class. * 2. Known, the class is already mentioned by other class. * 3. Loaded, *.js source is in memory, but may not be initialized yet. It * requires all its must-classes be intiailized, which is in the next stage. * 4. Musts loaded, all must classes is already loaded and declared. * 5. Delcared, the class is already declared (_Loader#isClassDefined). * 6. Optionals loaded, all optional classes is loaded and declared. * * The ClassLoader tries to load all necessary classes in order, and intialize * them in order. For such job, it will traverse the dependency tree, and try * to next class to-be-loaded. Sometime, the class dependencies may be in one * or more cycles, which must be broken down so classes is loaded in correct * order. * * Loading order and intializing order is very important for the ClassLoader. * The following technical options are considered: * 1. SCRIPT is loading asynchronously, which means controling order must use * callback methods to continue. * 2. Multiple loading threads are later introduced, which requires the * ClassLoader should use variables to record the class status. * 3. Different browsers have different loading orders, which means extra tests * should be tested to make sure loading order won't be broken. * 4. Java2Script simulator itself have some loading orders that must be * honored, which means it should be integrated seamlessly to Clazz system. * 5. Packed *.z.js is introduced to avoid lots of small *.js which requires * lots of HTTP connections, which means that packed *.z.js should be treated * specially (There will be mappings for such packed classes). * 6. *.js or *.css loading may fail according to network status, which means * another loading try should be performed, so _Loader is more robust. * 7. SWT lazy loading is later introduced, which means that class loading * process may be paused and should be resumed later. * * Some known bugs: * $_L(["$wt.graphics.Drawable","$wt.widgets.Widget"], * "$wt.widgets.Control", ... * has errors while must classes in different order such as * $_L(["$wt.widgets.Widget", "$wt.graphics.Drawable"], * "$wt.widgets.Control", ... * has no error. * * Other maybe bug scenarios: * 1. In _Loader.maxLoadingThreads = 1; single loading thread * mode, there are no errors, but in default multiple thread loading mode, * there are errors. * 2. No errors in one browser, but has errors on other browsers (Browser * script loading order differences). * 3. First time loading has errors, but reloading it gets no errors (Maybe * HTTP connections timeout, but should not accur in local file system, or it * is a loading bug by using JavaScript timeout thread). */ /* * The following comments with "#" are special configurations for a much * smaller *.js file size. * * @see net.sf.j2s.lib/src/net/sf/j2s/lib/build/SmartJSCompressor.java */ /** * Static class loader class */ Clazz._Loader = Clazz.ClazzLoader = function () {}; /** * Class dependency tree node */ /* private */ var Node = function () { this.parents = []; this.musts = []; this.optionals = []; this.declaration = null; this.name = null; // id this.path = null; // this.requires = null; // this.requiresMap = null; this.onLoaded = null; this.status = 0; this.random = 0.13412; }; ;(function(Clazz, _Loader) { _Loader._checkLoad = Jmol._checkLoad; _Loader.updateNodeForFunctionDecoration = function(qName) { var node = findNode(qName); if (node && node.status == Node.STATUS_KNOWN) { window.setTimeout((function(nnn) { return function() { updateNode(nnn); }; })(node), 1); } } Node.prototype.toString = function() { return this.name || this.path || "ClazzNode"; } Node.STATUS_UNKNOWN = 0; Node.STATUS_KNOWN = 1; Node.STATUS_CONTENT_LOADED = 2; Node.STATUS_MUSTS_LOADED = 3; Node.STATUS_DECLARED = 4; Node.STATUS_LOAD_COMPLETE = 5; var loaders = []; /* public */ _Loader.requireLoaderByBase = function (base) { for (var i = 0; i < loaders.length; i++) { if (loaders[i].base == base) { return loaders[i]; } } var loader = new _Loader (); loader.base = base; loaders.push(loader); return loader; }; /** * Class dependency tree */ var clazzTreeRoot = new Node(); /** * Used to keep the status whether a given *.js path is loaded or not. */ /* private */ var loadedScripts = {}; /** * Multiple threads are used to speed up *.js loading. */ /* private */ var inLoadingThreads = 0; /** * Maximum of loading threads */ /* private */ var maxLoadingThreads = 6; var userAgent = navigator.userAgent.toLowerCase (); var isOpera = (userAgent.indexOf ("opera") != -1); var isIE = (userAgent.indexOf ("msie") != -1) && !isOpera; var isGecko = (userAgent.indexOf ("gecko") != -1); /* * Opera has different loading order which will result in performance degrade! * So just return to single thread loading in Opera! * * FIXME: This different loading order also causes bugs in single thread! */ if (isOpera) { maxLoadingThreads = 1; var index = userAgent.indexOf ("opera/"); if (index != -1) { var verNumber = 9.0; try { verNumber = parseFloat(userAgent.subString (index + 6)); } catch (e) {} if (verNumber >= 9.6) { maxLoadingThreads = 6; } } } /** * Try to be compatiable with Clazz system. * In original design _Loader and Clazz are independent! * -- zhourenjian @ December 23, 2006 */ var isClassdefined; var definedClasses; if (self.Clazz && Clazz.isClassDefined) { isClassDefined = Clazz.isClassDefined; } else { definedClasses = {}; isClassDefined = function (clazzName) { return definedClasses[clazzName] == true; }; } /** * Expand the shortened list of class names. * For example: * JU.Log, $.Display, $.Decorations * will be expanded to * JU.Log, JU.Display, JU.Decorations * where "$." stands for the previous class name's package. * * This method will be used to unwrap the required/optional classes list and * the ignored classes list. */ /* private */ var unwrapArray = function (arr) { if (!arr || arr.length == 0) return []; var last = null; for (var i = 0; i < arr.length; i++) { if (!arr[i]) continue; if (arr[i].charAt (0) == '$') { if (arr[i].charAt (1) == '.') { if (!last) continue; var idx = last.lastIndexOf ("."); if (idx != -1) { var prefix = last.substring (0, idx); arr[i] = prefix + arr[i].substring (1); } } else { arr[i] = "org.eclipse.s" + arr[i].substring (1); } } last = arr[i]; } return arr; }; /** * Used to keep to-be-loaded classes. */ /* private */ var classQueue = []; /* private */ var classpathMap = {}; /* private */ var pkgRefCount = 0; /* public */ _Loader.loadPackageClasspath = function (pkg, base, isIndex, fSuccess, mode, pt) { var map = classpathMap; mode || (mode = 0); fSuccess || (fSuccess = null); pt || (pt = 0); /* * In some situation, maybe, * _Loader.packageClasspath ("java", ..., true); * is called after other _Loader#packageClasspath, e.g. * * _Loader.packageClasspath ("org.eclipse.swt", "...", true); * _Loader.packageClasspath ("java", "...", true); * * which is not recommended. But _Loader should try to adjust orders * which requires "java" to be declared before normal _Loader * #packageClasspath call before that line! And later that line * should never initialize "java/package.js" again! */ var isPkgDeclared = (isIndex && map["@" + pkg]); if (mode == 0 && isIndex && !map["@java"] && pkg.indexOf ("java") != 0 && needPackage("java")) { _Loader.loadPackage("java", fSuccess ? function(_package){_Loader.loadPackageClasspath(pkg, base, isIndex, fSuccess, 1)} : null); if (fSuccess) return; } if (pkg instanceof Array) { unwrapArray(pkg); if (fSuccess) { if (pt < pkg.length) _Loader.loadPackageClasspath(pkg[pt], base, isIndex, function(_loadPackageClassPath){_Loader.loadPackageClasspath(pkg, base, isIndex, fSuccess, 1, pt + 1)}, 1); else fSuccess(); } else { for (var i = 0; i < pkg.length; i++) _Loader.loadPackageClasspath(pkg[i], base, isIndex, null); } return; } switch (pkg) { case "java.*": pkg = "java"; // fall through case "java": if (base) { // support ajax for default var key = "@net.sf.j2s.ajax"; if (!map[key]) map[key] = base; key = "@net.sf.j2s"; if (!map[key]) map[key] = base; } break; case "swt": pkg = "org.eclipse.swt"; break; case "ajax": pkg = "net.sf.j2s.ajax"; break; case "j2s": pkg = "net.sf.j2s"; break; default: if (pkg.lastIndexOf(".*") == pkg.length - 2) pkg = pkg.substring(0, pkg.length - 2); break; } if (base) // critical for multiple applets map["@" + pkg] = base; if (isIndex && !isPkgDeclared && !window[pkg + ".registered"]) { pkgRefCount++; if (pkg == "java") pkg = "core" // JSmol -- moves java/package.js to core/package.js _Loader.loadClass(pkg + ".package", function () { if (--pkgRefCount == 0) runtimeLoaded(); //fSuccess && fSuccess(); }, true, true, 1); return; } fSuccess && fSuccess(); }; /** * BH: allows user/developer to load classes even though wrapping and Google * Closure Compiler has not been run on the class. * */ Clazz.loadClass = function (name, onLoaded, async) { if (!self.Class) { Class = Clazz; Class.forName = Clazz._4Name; JavaObject = Clazz._O; // maybe more here } return (name && _Loader.loadClass(name, onLoaded, true, async, 1)); } /** * Load the given class ant its related classes. */ /* public */ _Loader.loadClass = function (name, onLoaded, forced, async, mode) { mode || (mode = 0); // BH: not implemented (async == null) && (async = false); if (typeof onLoaded == "boolean") return Clazz.evalType(name); System.out.println("loadClass " + name) // Make sure that packageClasspath ("java", base, true); // is called before any _Loader#loadClass is called. if (needPackage("java")) _Loader.loadPackage("java"); if (needPackage("core")) _Loader.loadPackage("core"); // var swtPkg = "org.eclipse.swt"; // if (name.indexOf (swtPkg) == 0 || name.indexOf ("$wt") == 0) { // _Loader.assurePackageClasspath (swtPkg); // } // if (name.indexOf ("junit") == 0) { // _Loader.assurePackageClasspath ("junit"); // } // Any _Loader#loadClass calls will be queued until java.* core classes are loaded. _Loader.keepOnLoading = true; if (!forced && (pkgRefCount && name.lastIndexOf(".package") != name.length - 8 || name.indexOf("java.") != 0 && !isClassDefined(runtimeKeyClass) )) { queueBe4KeyClazz.push([name, onLoaded]); System.out.println("loadclass-queuing" + name+ runtimeKeyClass + " "+ isClassDefined(runtimeKeyClass)) return; } var b; if ((b = isClassDefined(name)) || isClassExcluded(name)) { if (b && onLoaded) { var nn = findNode(name); if (!nn || nn.status >= Node.STATUS_LOAD_COMPLETE) { if (async) { window.setTimeout(onLoaded, 25); } else { onLoaded(); } } } return; } var path = _Loader.getClasspathFor(name); var existed = loadedScripts[path]; var qq = classQueue; if (!existed) for (var i = qq.length; --i >= 0;) if (qq[i].path == path || qq[i].name == name) { existed = true; break; } if (existed) { if (onLoaded) { var n = findNode(name); if (n) { if (!n.onLoaded) { n.onLoaded = onLoaded; } else if (onLoaded != n.onLoaded) { n.onLoaded = (function (nF, oF) { return function () { nF(); oF() }; }) (n.onLoaded, onLoaded); } } } return; } var n = (Clazz.unloadedClasses[name] && findNode(name) || new Node()); n.name = name; n.path = path; n.isPackage = (path.lastIndexOf("package.js") == path.length - 10); mappingPathNameNode(path, name, n); n.onLoaded = onLoaded; n.status = Node.STATUS_KNOWN; var needBeingQueued = false; for (var i = qq.length; --i >= 0;) { if (qq[i].status != Node.STATUS_LOAD_COMPLETE) { needBeingQueued = true; break; } } if (n.isPackage) {//forced // push class to queue var pt = qq.length; for (; --pt >= 0;) { if (qq[pt].isPackage) break; qq[pt + 1] = qq[pt]; } qq[++pt] = n; } else if (needBeingQueued) { qq.push(n); } if (!needBeingQueued) { // can be loaded directly var bSave = false; if (onLoaded) { bSave = isLoadingEntryClass; isLoadingEntryClass = true; } if (forced)onLoaded = null; addChildClassNode(clazzTreeRoot, n, true); loadScript(n, n.path, n.requiredBy, false, onLoaded ? function(_loadClass){ isLoadingEntryClass = bSave; onLoaded()}: null); } }; /* * Check whether given package's classpath is setup or not. * Only "java" and "org.eclipse.swt" are accepted in argument. */ /* private */ var needPackage = function(pkg) { // note that false != null and true != null return (window[pkg + ".registered"] != null && !classpathMap["@" + pkg]); } /* private */ _Loader.loadPackage = function(pkg, fSuccess) { fSuccess || (fSuccess = null); window[pkg + ".registered"] = false; _Loader.loadPackageClasspath(pkg, (_Loader.J2SLibBase || (_Loader.J2SLibBase = (_Loader.getJ2SLibBase() || "j2s/"))), true, fSuccess); }; /** * Register classes to a given *.z.js path, so only a single *.z.js is loaded * for all those classes. */ /* public */ _Loader.jarClasspath = function (jar, clazzes) { if (!(clazzes instanceof Array)) clazzes = [classes]; unwrapArray(clazzes); for (var i = clazzes.length; --i >= 0;) classpathMap["#" + clazzes[i]] = jar; classpathMap["$" + jar] = clazzes; }; /** * Usually be used in .../package.js. All given packages will be registered * to the same classpath of given prefix package. */ /* public */ _Loader.registerPackages = function (prefix, pkgs) { //_Loader.checkInteractive (); var base = _Loader.getClasspathFor (prefix + ".*", true); for (var i = 0; i < pkgs.length; i++) { if (window["Clazz"]) { Clazz.declarePackage (prefix + "." + pkgs[i]); } _Loader.loadPackageClasspath (prefix + "." + pkgs[i], base); } }; /** * Using multiple sites to load *.js in multiple threads. Using multiple * sites may avoid 2 HTTP 1.1 connections recommendation limit. * Here is a default implementation for http://archive.java2script.org. * In site archive.java2script.org, there are 6 sites: * 1. http://archive.java2script.org or http://a.java2script.org * 2. http://erchive.java2script.org or http://e.java2script.org * 3. http://irchive.java2script.org or http://i.java2script.org * 4. http://orchive.java2script.org or http://o.java2script.org * 5. http://urchive.java2script.org or http://u.java2script.org * 6. http://yrchive.java2script.org or http://y.java2script.org */ /* protected */ /* _Loader.multipleSites = function (path) { var deltas = window["j2s.update.delta"]; if (deltas && deltas instanceof Array && deltas.length >= 3) { var lastOldVersion = null; var lastNewVersion = null; for (var i = 0; i < deltas.length / 3; i++) { var oldVersion = deltas[i + i + i]; if (oldVersion != "$") { lastOldVersion = oldVersion; } var newVersion = deltas[i + i + i + 1]; if (newVersion != "$") { lastNewVersion = newVersion; } var relativePath = deltas[i + i + i + 2]; var key = lastOldVersion + "/" + relativePath; var idx = path.indexOf (key); if (idx != -1 && idx == path.length - key.length) { path = path.substring (0, idx) + lastNewVersion + "/" + relativePath; break; } } } var length = path.length; if (maxLoadingThreads > 1 && ((length > 15 && path.substring (0, 15) == "http://archive.") || (length > 9 && path.substring (0, 9) == "http://a."))) { var index = path.lastIndexOf("/"); if (index < length - 3) { var arr = ['a', 'e', 'i', 'o', 'u', 'y']; var c1 = path.charCodeAt (index + 1); var c2 = path.charCodeAt (index + 2); var idx = (length - index) * 3 + c1 * 5 + c2 * 7; // Hash return path.substring (0, 7) + arr[idx % 6] + path.substring (8); } } return path; }; */ /** * Return the *.js path of the given class. Maybe the class is contained * in a *.z.js jar file. * @param clazz Given class that the path is to be calculated for. May * be java.package, or java.lang.String * @param forRoot Optional argument, if true, the return path will be root * of the given classs' package root path. * @param ext Optional argument, if given, it will replace the default ".js" * extension. */ /* public */ _Loader.getClasspathFor = function (clazz, forRoot, ext) { var path = classpathMap["#" + clazz]; if (!path || forRoot || ext) { var base; var idx; if (path) { clazz = clazz.replace(/\./g, "/"); if ((idx = path.lastIndexOf(clazz)) >= 0 || (idx = clazz.lastIndexOf("/")) >= 0 && (idx = path.lastIndexOf(clazz.substring(0, idx))) >= 0) base = path.substring(0, idx); } else { idx = clazz.length + 2; while ((idx = clazz.lastIndexOf(".", idx - 2)) >= 0) if ((base = classpathMap["@" + clazz.substring(0, idx)])) break; if (!forRoot) clazz = clazz.replace (/\./g, "/"); } if (base == null) { var bins = "binaryFolders"; base = (window["Clazz"] && Clazz[bins] && Clazz[bins].length ? Clazz[bins][0] : _Loader[bins] && _Loader[bins].length ? _Loader[bins][0] : "j2s"); } path = (base.lastIndexOf("/") == base.length - 1 ? base : base + "/") + (forRoot ? "" : clazz.lastIndexOf("/*") == clazz.length - 2 ? clazz.substring(0, idx + 1) : clazz + (!ext ? ".js" : ext.charAt(0) != '.' ? "." + ext : ext)); } return path;//_Loader.multipleSites(path); }; /** * To ignore some classes. */ /* public */ _Loader.ignore = function () { var clazzes = (arguments.length == 1 && arguments[0] instanceof Array ? clazzes = arguments[0] : null); var n = (clazzes ? clazzes.length : arguments.length); if (!clazzes) { clazzes = new Array(n); for (var i = 0; i < n; i++) clazzes[i] = arguments[i]; } unwrapArray(clazzes); for (var i = 0; i < n; i++) excludeClassMap["@" + clazzes[i]] = 1; }; /** * The following *.script* can be overriden to indicate the * status of classes loading. * * TODO: There should be a Java interface with name like INativeLoaderStatus */ /* public */ _Loader.onScriptLoading = function (file){}; /* public */ _Loader.onScriptLoaded = function (file, isError){}; /* public */ _Loader.onScriptInitialized = function (file){}; /* public */ _Loader.onScriptCompleted = function (file){}; /* public */ _Loader.onClassUnloaded = function (clazz){}; /** * After all the classes are loaded, this method will be called. * Should be overriden to run *.main([]). */ /* public */ _Loader.onGlobalLoaded = function () {}; /* public */ _Loader.keepOnLoading = true; // never set false in this code /* private */ var mapPath2ClassNode = {}; /* private */ var isClassExcluded = function (clazz) { return excludeClassMap["@" + clazz]; }; /* Used to keep ignored classes */ /* private */ var excludeClassMap = {}; /* private */ var evaluate = function(file, file0, js) { try { eval(js + ";//# sourceURL="+file); } catch (e) { if (Clazz._isQuiet) return; var s = "[Java2Script] The required class file \n\n" + file + (js.indexOf("[Exception") == 0 && js.indexOf("data: no") ? "\nwas not found.\n" : "\ncould not be loaded. Script error: " + e.message + " \n\ndata:\n\n" + js) + "\n\n" + Clazz.getStackTrace(); alert(s) Clazz.alert(s); throw e; } _Loader.onScriptLoaded(file, false); tryToLoadNext(file0); } /* private */ var failedHandles = {}; /* private */ var generateRemovingFunction = function (node) { return function () { if (node.readyState != "interactive") { try { if (node.parentNode) node.parentNode.removeChild (node); } catch (e) { } node = null; } }; }; /* private */ var removeScriptNode = function (n) { if (window["j2s.script.debugging"]) { return; } // lazily remove script nodes. window.setTimeout (generateRemovingFunction (n), 1); }; /* public */ Clazz._4Name = function(clazzName, applet, state) { if (Clazz.isClassDefined(clazzName)) return Clazz.evalType(clazzName); var f = (Jmol._isAsync && applet ? applet._restoreState(clazzName, state) : null); if (f == 1) return null; // must be already being created if (_Loader.setLoadingMode(f ? _Loader.MODE_SCRIPT : "xhr.sync")) { _Loader.loadClass(clazzName, f, false, true, 1); return null; // this will surely throw an error, but that is OK } //alert ("Using Java reflection: " + clazzName + " for " + applet._id + " \n"+ Clazz.getStackTrace()); _Loader.loadClass(clazzName); return Clazz.evalType(clazzName); }; /** * BH: possibly useful for debugging */ Clazz.currentPath= ""; /** * Load *.js by adding script elements into head. Hook the onload event to * load the next class in dependency tree. */ /* private */ var loadScript = function (node, file, why, ignoreOnload, fSuccess, _loadScript) { Clazz.currentPath = file; if (ignoreOnload)alert("WHY>>") //BH removed // maybe some scripts are to be loaded without needs to know onload event. // if (!ignoreOnload && loadedScripts[file]) { // _Loader.tryToLoadNext(file); // return; // } loadedScripts[file] = true; // also remove from queue removeArrayItem(classQueue, file); // forces not-found message isUsingXMLHttpRequest = true; isAsynchronousLoading = false; if (_Loader._checkLoad) { System.out.println("\t" + file + (why ? "\n -- required by " + why : "") + " ajax=" + isUsingXMLHttpRequest + " async=" + isAsynchronousLoading) } var file0 = file; if (Clazz._debugging) { file = file.replace(/\.z\.js/,".js"); } _Loader.onScriptLoading(file); if (isUsingXMLHttpRequest && !isAsynchronousLoading) { // alert("\t" + file + (why ? "\n -- required by " + why : "") + " ajax=" + isUsingXMLHttpRequest + " async=" + isAsynchronousLoading + " " + Clazz.getStackTrace()) // synchronous loading // works in MSIE locally unless a binary file :) // from Jmol.api.Interface only var data = Jmol._getFileData(file); try{ evaluate(file, file0, data); }catch(e) { alert(e + " loading file " + file + " " + node.name + " " + Clazz.getStackTrace()); } if (fSuccess) { // System.out.println("firing in loadScript " + file + " " + (fSuccess && fSuccess.toString())) fSuccess(); } return; } System.out.println("for file " + file +" fSuccess = " + (fSuccess ? fSuccess.toString() : "")) var info = { dataType:"script", async:true, type:"GET", url:file, success:W3CScriptOnCallback(file, false, fSuccess), error:W3CScriptOnCallback(file, true, fSuccess) }; inLoadingThreads++; Jmol.$ajax(info); }; /* private */ var W3CScriptOnCallback = function (path, forError, fSuccess) { var s = Clazz.getStackTrace(); // if (!fSuccess)alert("why no fSuccess?" + s) return function () { //System.out.println("returning " + (fSuccess ? fSuccess.toString() : "no function ") + s) if (forError && __debuggingBH)Clazz.alert ("############ forError=" + forError + " path=" + path + " ####" + (forError ? "NOT" : "") + "LOADED###"); if (isGecko && this.timeoutHandle) window.clearTimeout(this.timeoutHandle), this.timeoutHandle = null; if (inLoadingThreads > 0) inLoadingThreads--; //System.out.println("w3ccalback for " + path + " " + inLoadingThreads + " threads") this.onload = null; this.onerror = null; if (forError) alert ("There was a problem loading " + path); _Loader.onScriptLoaded(path, true); var node = this; var f; if (fSuccess) f = function(_W3scriptFS){removeScriptNode(node);tryToLoadNext(path, fSuccess); }; else f = function(_W3script){removeScriptNode(node);tryToLoadNext(path)}; if (loadingTimeLag >= 0) window.setTimeout(function() { tryToLoadNext(path, f); }, loadingTimeLag); else tryToLoadNext(path, f); }; }; /* private */ var isLoadingEntryClass = true; /* private */ var besidesJavaPackage = false; /** * After class is loaded, this method will be executed to check whether there * are classes in the dependency tree that need to be loaded. */ /* private */ var tryToLoadNext = function (file, fSuccess) { var node = mapPath2ClassNode["@" + file]; if (!node) // maybe class tree root return; var n; // check for content loaded var clazzes = classpathMap["$" + file]; if (clazzes) { for (var i = 0; i < clazzes.length; i++) { var name = clazzes[i]; if (name != node.name && (n = findNode(name))) { if (n.status < Node.STATUS_CONTENT_LOADED) { n.status = Node.STATUS_CONTENT_LOADED; updateNode(n); } } else { n = new Node(); n.name = name; var pp = classpathMap["#" + name]; if (!pp) { alert (name + " J2S error in tryToLoadNext"); error("Java2Script implementation error! Please report this bug!"); } n.path = pp; mappingPathNameNode (n.path, name, n); n.status = Node.STATUS_CONTENT_LOADED; addChildClassNode(clazzTreeRoot, n, false); updateNode(n); } } } if (node instanceof Array) { for (var i = 0; i < node.length; i++) { if (node[i].status < Node.STATUS_CONTENT_LOADED) { node[i].status = Node.STATUS_CONTENT_LOADED; updateNode(node[i]); } } } else if (node.status < Node.STATUS_CONTENT_LOADED) { var stillLoading = false; var ss = document.getElementsByTagName ("SCRIPT"); for (var i = 0; i < ss.length; i++) { if (isIE) { if (ss[i].onreadystatechange && ss[i].onreadystatechange.path == node.path && ss[i].readyState == "interactive") { stillLoading = true; break; } } else if (ss[i].onload && ss[i].onload.path == node.path) { stillLoading = true; break; } } if (!stillLoading) { node.status = Node.STATUS_CONTENT_LOADED; updateNode(node); } } /* * Maybe in #optinalLoaded inside above _Loader#updateNode calls, * _Loader.keepOnLoading is set false (Already loaded the wanted * classes), so here check to stop. */ if (!_Loader.keepOnLoading) // set externally return; // check for a "must" class that has content and load it var cq; var working = true; if ((n = findNextMustClass(Node.STATUS_KNOWN))) { loadClassNode(n); while (inLoadingThreads < maxLoadingThreads) { if (!(n = findNextMustClass(Node.STATUS_KNOWN))) break; loadClassNode(n); // will increase inLoadingThreads! } } else if ((cq = classQueue).length != 0) { /* queue must be loaded in order! */ n = cq.shift(); if (!loadedScripts[n.path] || cq.length != 0 || !isLoadingEntryClass || n.musts.length || n.optionals.length) { addChildClassNode(clazzTreeRoot, n, true); loadScript(n, n.path, n.requiredBy, false); } else if (isLoadingEntryClass) { /* * The first time reaching here is the time when ClassLoader * is trying to load entry class. Class with #main method and * is to be executed is called Entry Class. * * Here when loading entry class, ClassLoader should not call * the next following loading script. This is because, those * scripts will try to mark the class as loaded directly and * then continue to call #onLoaded callback method, * which results in an script error! */ isLoadingEntryClass = false; } } else if ((n = findNextRequiredClass(Node.STATUS_KNOWN))) { loadClassNode(n); while (inLoadingThreads < maxLoadingThreads) { if (!(n = findNextRequiredClass(Node.STATUS_KNOWN))) break; loadClassNode(n); // will increase inLoadingThreads! } } else { working = false; } if (working || inLoadingThreads > 0) return; // // now check all classes that MUST be loaded prior to initialization // of some other class (static calls, extends, implements) // and all classes REQUIRED somewhere in that class, possibly by the constructor // (that is, "new xxxx()" called somewhere in code) and update them // that have content but are not declared already var f = [findNextMustClass,findNextRequiredClass]; var lastNode = null; for (var i = 0; i < 2; i++) while ((n = f[i](Node.STATUS_CONTENT_LOADED))) { if (i == 1 && lastNode === n) // Already existed cycle ? n.status = Node.STATUS_LOAD_COMPLETE; updateNode(n); lastNode = n; } // check for load cycles while (true) { tracks = []; if (!checkCycle(clazzTreeRoot, file)) break; } // and update all MUST and REQUIRED classes that are declared already for (var i = 0; i < 2; i++) { lastNode = null; while ((n = f[i](Node.STATUS_DECLARED))) { if (lastNode === n) break; updateNode(lastNode = n); } } var done = []; for (var i = 0; i < 2; i++) while ((n = f[i](Node.STATUS_DECLARED))) done.push(n), n.status = Node.STATUS_LOAD_COMPLETE; if (done.length) { for (var i = 0; i < done.length; i++) destroyClassNode(done[i]); for (var i = 0; i < done.length; i++) if ((f = done[i].onLoaded)) done[i].onLoaded = null, f(); } //System.out.println(node.name + " loaded completely" + _Loader.onGlobalLoaded + "\n\n") if (fSuccess) { //System.out.println("tryToLoadNext firing " + _Loader._classCountOK + "/" + _Loader._classCountPending + " " + fSuccess.toString() + " " + Clazz.getStackTrace()) fSuccess(); } else if (_Loader._classCountPending) { for (var name in _Loader._classPending) { var n = findNode(name); System.out.println("class left pending " + name + " " + n); if (n) { updateNode(n); break; } } } else { // System.out.println("I think I'm done " // + _Loader._classCountOK + "/" + _Loader._classCountPending + " " //+ _Loader.onGlobalLoaded.toString() + " " + Clazz.getStackTrace() // ) if (_Loader._checkLoad) { System.out.println("I think I'm done: SAEM call count: " + SAEMid); Clazz.showDuplicates(true); } } _Loader.onGlobalLoaded(); }; var tracks = []; /* * There are classes reference cycles. Try to detect and break those cycles. */ /* private */ var checkCycle = function (node, file) { var ts = tracks; var len = ts.length; // add this node to tracks ts.push(node); var i = len; for (; --i >= 0;) if (ts[i] === node && ts[i].status >= Node.STATUS_DECLARED) break; if (i >= 0) { // this node is already in tracks, and it has been declared already // for each node in tracks, set its status to "LOAD_COMPLETE" // update all parents, remove all parents, and fire its onLoaded function // then clear tracks and return true (keep checking) if (_Loader._checkLoad) { var msg = "cycle found loading " + file + " for " + node; System.out.println(msg) } for (; i < len; i++) { var n = ts[i]; n.status = Node.STATUS_LOAD_COMPLETE; destroyClassNode(n); // Same as above for (var k = 0; k < n.parents.length; k++) updateNode(n.parents[k]); n.parents = []; var f = n.onLoaded; if (_Loader._checkLoad) { var msg = "cycle setting status to LOAD_COMPLETE for " + n.name + (f ? " firing " + f.toString() : ""); System.out.println(msg) } if (f) n.onLoaded = null, f(); } ts.length = 0; return true; } var a = [node.musts, node.optionals]; for (var j = 0; j < 2; j++) for (var r = a[j], i = r.length; --i >= 0;) if (r[i].status == Node.STATUS_DECLARED && checkCycle(r[i], file)) return true; // reset _tracks to its original length ts.length = len; return false; // done }; _Loader._classCountPending = 0; _Loader._classCountOK = 0; _Loader._classPending = {}; _Loader.showPending = function() { var a = []; for (var name in _Loader._classPending) { var n = findNode(name); if (!n) { alert("No node for " + name); continue; } a.push(n); System.out.println(showNode("", "", n, "", 0)); } return a; } var showNode = function(s, names, node, inset, level) { names += "--" + node.name; s += names + "\n"; if (level > 5) { s += inset + " ...\n"; return s; } inset += "\t"; s += inset + "status: " + node.status + "\n"; if (node.parents && node.parents.length && node.parents[0] && node.parents[0].name) { s += inset + "parents: " + node.parents.length + "\n"; for (var i = 0; i < node.parents.length; i++) { s = showNode(s, names, node.parents[i], inset + "\t", level+1); } s += "\n"; } // if (node.requiredBy) { // s += inset + "requiredBy:\n"; // s = showNode(s, names, node.requiredBy, inset + "\t", level+1); // s += "\n"; // } return s; } /** * Update the dependency tree nodes recursively. */ /* private */ updateNode = function(node, _updateNode) { if (!node.name || node.status >= Node.STATUS_LOAD_COMPLETE) { destroyClassNode(node); return; } var ready = true; // check for declared and also having MUSTS if (node.musts.length && node.declaration) { for (var mustLength = node.musts.length, i = mustLength; --i >= 0;) { var n = node.musts[i]; n.requiredBy = node; if (n.status < Node.STATUS_DECLARED && isClassDefined (n.name)) { var nns = []; // a stack for onLoaded events n.status = Node.STATUS_LOAD_COMPLETE; destroyClassNode(n); // Same as above if (n.declaration && n.declaration.clazzList) { // For those classes within one *.js file, update them synchronously. for (var j = 0, list = n.declaration.clazzList, l = list.length; j < l; j++) { var nn = findNode (list[j]); if (nn && nn.status != Node.STATUS_LOAD_COMPLETE && nn !== n) { nn.status = n.status; nn.declaration = null; destroyClassNode(nn); nn.onLoaded && nns.push(nn); } } n.declaration = null; } // fire all onLoaded events if (n.onLoaded) nns.push(n); for (var j = 0; j < nns.length; j++) { var onLoaded = nns[j].onLoaded; if (onLoaded) { nns[j].onLoaded = null; onLoaded(); } } } else { (n.status == Node.STATUS_CONTENT_LOADED) && updateNode(n); // musts may be changed if (n.status < Node.STATUS_DECLARED) ready = false; } if (node.musts.length != mustLength) { // length changed -- restart! i = mustLength = node.musts.length; ready = true; } } } if (!ready) return; if (node.status < Node.STATUS_DECLARED) { var decl = node.declaration; if (decl) decl(), decl.executed = true; if(_Loader._checkLoad) { if (_Loader._classPending[node.name]) { delete _Loader._classPending[node.name]; _Loader._classCountOK; _Loader._classCountPending--; // System.out.println("OK " + (_Loader._classCountOK) + " FOR " + node.name) } } node.status = Node.STATUS_DECLARED; if (definedClasses) definedClasses[node.name] = true; _Loader.onScriptInitialized(node.path); if (node.declaration && node.declaration.clazzList) { // For those classes within one *.js file, update them synchronously. for (var j = 0, list = node.declaration.clazzList, l = list.length; j < l; j++) { var nn = findNode(list[j]); if (nn && nn.status != Node.STATUS_DECLARED && nn !== node) { nn.status = Node.STATUS_DECLARED; if (definedClasses) definedClasses[nn.name] = true; _Loader.onScriptInitialized(nn.path); } } } } var level = Node.STATUS_DECLARED; if (node.optionals.length == 0 && node.musts.length == 0 || node.status > Node.STATUS_KNOWN && !node.declaration || checkStatusIs(node.musts, Node.STATUS_LOAD_COMPLETE) && checkStatusIs(node.optionals, Node.STATUS_LOAD_COMPLETE)) { level = Node.STATUS_LOAD_COMPLETE; if (!doneLoading(node, level)) return false; // For those classes within one *.js file, update them synchronously. if (node.declaration && node.declaration.clazzList) { for (var j = 0, list = node.declaration.clazzList, l = list.length; j < l; j++) { var nn = findNode(list[j]); if (nn && nn.status != level && nn !== node) { nn.declaration = null; if (!doneLoading(nn, level)) return false; } } } } // _Loader.updateParents = function (node, level, _updateParents) if (node.parents && node.parents.length) { for (var i = 0; i < node.parents.length; i++) { var p = node.parents[i]; if (p.status < level) updateNode(p, p.name); } if (level == Node.STATUS_LOAD_COMPLETE) node.parents = []; } }; /* private */ var checkStatusIs = function(arr, status){ for (var i = arr.length; --i >= 0;) if (arr[i].status < status) return false; return true; } /* private */ var doneLoading = function(node, level, _doneLoading) { node.status = level; _Loader.onScriptCompleted(node.path); var onLoaded = node.onLoaded; if (onLoaded) { node.onLoaded = null; onLoaded(); if (!_Loader.keepOnLoading) return false; } destroyClassNode(node); return true; } /* * Be used to record already used random numbers. And next new random * number should not be in the property set. */ /* private */ var usedRandoms = { "r0.13412" : 1 }; /* private */ var getRnd = function() { while (true) { // get a unique random number var rnd = Math.random(); var s = "r" + rnd; if (!usedRandoms[s]) return (usedRandoms[s] = 1, clazzTreeRoot.random = rnd); } } /* protected */ var findNode = function(clazzName) { getRnd(); return findNodeUnderNode(clazzName, clazzTreeRoot); }; /* private */ var findNextRequiredClass = function(status) { getRnd(); return findNextRequiredNode(clazzTreeRoot, status); }; /* private */ var findNextMustClass = function(status) { return findNextMustNode(clazzTreeRoot, status); }; /* private */ var findNodeUnderNode = function(clazzName, node) { var n; // node, then musts then optionals return (node.name == clazzName ? node : (n = findNodeWithin(clazzName, node.musts)) || (n = findNodeWithin(clazzName, node.optionals)) ? n : null); }; /* private */ var findNodeWithin = function(name, arr) { var rnd = clazzTreeRoot.random; for (var i = arr.length; --i >= 0;) { var n = arr[i]; if (n.name == name) return n; if (n.random != rnd) { n.random = rnd; if ((n = findNodeUnderNode(name, n))) return n; } } return null; } /* private */ var checkStatus = function(n, status) { return (n.status == status && (status != Node.STATUS_KNOWN || !loadedScripts[n.path]) && (status == Node.STATUS_DECLARED || !isClassDefined (n.name))); } /* private */ var findNextMustNode = function(node, status) { for (var i = node.musts.length; --i >= 0;) { var n = node.musts[i]; if (checkStatus(n, status) || (n = findNextMustNode(n, status))) return n; } return (checkStatus(node, status) ? node : null); }; /* private */ var findNextRequiredNode = function (node, status) { // search musts first // search optionals second // search itself last var n; return ((n = searchClassArray(node.musts, status)) || (n = searchClassArray(node.optionals, status)) || checkStatus(n = node, status) ? n : null); }; /* private */ var searchClassArray = function (arr, status) { if (arr) { var rnd = clazzTreeRoot.random; for (var i = 0; i < arr.length; i++) { var n = arr[i]; if (checkStatus(n, status)) return n; if (n.random != rnd) { n.random = rnd; // mark as visited! if ((n = findNextRequiredNode(n, status))) return n; } } } return null; }; /** * This map variable is used to mark that *.js is correctly loaded. * In IE, _Loader has defects to detect whether a *.js is correctly * loaded or not, so inner loading mark is used for detecting. */ /* private */ var innerLoadedScripts = {}; /** * This method will be called in almost every *.js generated by Java2Script * compiler. */ /* public */ var load = function (musts, name, optionals, declaration) { // called as name.load in Jmol if (name instanceof Array) { unwrapArray(name); for (var i = 0; i < name.length; i++) load(musts, name[i], optionals, declaration, name); return; } if (_Loader._checkLoad) { if (_Loader._classPending[name]) { //alert("duplicate load for " + name) } else { _Loader._classPending[name] = 1; if (_Loader._classCountPending++ == 0) _Loader._classCountOK = 0; System.out.println("Loading class " + name); } } // if (clazz.charAt (0) == '$') // clazz = "org.eclipse.s" + clazz.substring (1); var node = mapPath2ClassNode["#" + name]; if (!node) { // load called inside *.z.js? var n = findNode(name); node = (n ? n : new Node()); node.name = name; node.path = classpathMap["#" + name] || "unknown"; mappingPathNameNode(node.path, name, node); node.status = Node.STATUS_KNOWN; addChildClassNode(clazzTreeRoot, node, false); } processRequired(node, musts, true); if (arguments.length == 5 && declaration) { declaration.status = node.status; declaration.clazzList = arguments[4]; } node.declaration = declaration; if (declaration) node.status = Node.STATUS_CONTENT_LOADED; processRequired(node, optionals, false); }; /* private */ var processRequired = function(node, arr, isMust) { if (arr && arr.length) { unwrapArray(arr); for (var i = 0; i < arr.length; i++) { var name = arr[i]; if (!name) continue; if (isClassDefined(name) || isClassExcluded(name)) continue; var n = findNode(name); if (!n) { n = new Node(); n.name = name; n.status = Node.STATUS_KNOWN; } n.requiredBy = node; addChildClassNode(node, n, isMust); } } } /* * Try to be compatiable of Clazz */ if (window["Clazz"]) { Clazz.load = load; } else { _Loader.load = load; } /** * Map different class to the same path! Many classes may be packed into * a *.z.js already. * * @path *.js path * @name class name * @node Node object */ /* private */ var mappingPathNameNode = function (path, name, node) { var map = mapPath2ClassNode; var keyPath = "@" + path; var v = map[keyPath]; if (v) { if (v instanceof Array) { var existed = false; for (var i = 0; i < v.length; i++) { if (v[i].name == name) { existed = true; break; } } if (!existed) v.push(node); } else { map[keyPath] = [v, node]; } } else { map[keyPath] = node; } map["#" + name] = node; }; /* protected */ var loadClassNode = function (node) { var name = node.name; if (!isClassDefined (name) && !isClassExcluded (name)) { var path = _Loader.getClasspathFor (name/*, true*/); node.path = path; mappingPathNameNode (path, name, node); if (!loadedScripts[path]) { loadScript(node, path, node.requiredBy, false); return true; } } return false; }; /** * Used in package /* public */ var runtimeKeyClass = _Loader.runtimeKeyClass = "java.lang.String"; /** * Queue used to store classes before key class is loaded. */ /* private */ var queueBe4KeyClazz = []; /* private */ var J2sLibBase; /** * Return J2SLib base path from existed SCRIPT src attribute. */ /* public */ _Loader.getJ2SLibBase = function () { var o = window["j2s.lib"]; return (o ? o.base + (o.alias == "." ? "" : (o.alias ? o.alias : (o.version ? o.version : "1.0.0")) + "/") : null); }; /** * Indicate whether _Loader is loading script synchronously or * asynchronously. */ /* private */ var isAsynchronousLoading = true; /* private */ var isUsingXMLHttpRequest = false; /* private */ var loadingTimeLag = -1; _Loader.MODE_SCRIPT = 4; _Loader.MODE_XHR = 2; _Loader.MODE_SYNC = 1; /** * String mode: * asynchronous modes: * async(...).script, async(...).xhr, async(...).xmlhttprequest, * script.async(...), xhr.async(...), xmlhttprequest.async(...), * script * * synchronous modes: * sync(...).xhr, sync(...).xmlhttprequest, * xhr.sync(...), xmlhttprequest.sync(...), * xmlhttprequest, xhr * * Integer mode: * Script 4; XHR 2; SYNC bit 1; */ /* public */ _Loader.setLoadingMode = function (mode, timeLag) { var async = true; var ajax = true; if (typeof mode == "string") { mode = mode.toLowerCase(); if (mode.indexOf("script") >= 0) ajax = false; else async = (mode.indexOf("async") >=0); async = false; // BH } else { if (mode & _Loader.MODE_SCRIPT) ajax = false; else async = !(mode & _Loader.MODE_SYNC); } isUsingXMLHttpRequest = ajax; isAsynchronousLoading = async; loadingTimeLag = (async && timeLag >= 0 ? timeLag: -1); return async; }; /* private */ var runtimeLoaded = function () { if (pkgRefCount || !isClassDefined(runtimeKeyClass)) return; var qbs = queueBe4KeyClazz; for (var i = 0; i < qbs.length; i++) _Loader.loadClass(qbs[i][0], qbs[i][1]); queueBe4KeyClazz = []; }; /* * Load those key *.z.js. This *.z.js will be surely loaded before other * queued *.js. */ /* public */ _Loader.loadZJar = function (zjarPath, keyClass) { // used only by package.js for core.z.js var f = null; var isArr = (keyClass instanceof Array); if (isArr) keyClass = keyClass[keyClass.length - 1]; else f = (keyClass == runtimeKeyClass ? runtimeLoaded : null); _Loader.jarClasspath(zjarPath, isArr ? keyClass : [keyClass]); // BH note: runtimeKeyClass is java.lang.String _Loader.loadClass(keyClass, f, true); }; var NodeMap = {}; var _allNodes = []; /** * The method help constructing the multiple-binary class dependency tree. */ /* private */ var addChildClassNode = function (parent, child, isMust) { var existed = false; var arr; if (isMust) { arr = parent.musts; if (!child.requiredBy) child.requiredBy = parent; // if (!parent.requiresMap){ // parent.requires = []; // parent.requiresMap = {}; // } // if (!parent.requiresMap[child.name]) { // parent.requiresMap[child.name] = 1; // parent.requires.push[child]; // } } else { arr = parent.optionals; } if (!NodeMap[child.name]) { _allNodes.push(child) NodeMap[child.name]=child } for (var i = 0; i < arr.length; i++) { if (arr[i].name == child.name) { existed = true; break; } } if (!existed) { arr.push(child); if (isLoadingEntryClass && child.name.indexOf("java") != 0 && child.name.indexOf("net.sf.j2s.ajax") != 0) { if (besidesJavaPackage) isLoadingEntryClass = false; besidesJavaPackage = true; // } else if (child.name.indexOf("org.eclipse.swt") == 0 // || child.name.indexOf("$wt") == 0) { // window["swt.lazy.loading.callback"] = swtLazyLoading; // if (needPackage("org.eclipse.swt")) // return _Loader.loadPackage("org.eclipse.swt", function() {addParentClassNode(child, parent)}); } } addParentClassNode(child, parent); }; /* private */ var addParentClassNode = function(child, parent) { if (parent.name && parent != clazzTreeRoot && parent != child) for (var i = 0; i < child.parents.length; i++) if (child.parents[i].name == parent.name) return; child.parents.push(parent); } /* private */ var destroyClassNode = function (node) { var parents = node.parents; if (parents) for (var k = parents.length; --k >= 0;) removeArrayItem(parents[k].musts, node) || removeArrayItem(parents[k].optionals, node); }; /* public */ _Loader.unloadClassExt = function (qClazzName) { if (definedClasses) definedClasses[qClazzName] = false; if (classpathMap["#" + qClazzName]) { var pp = classpathMap["#" + qClazzName]; classpathMap["#" + qClazzName] = null; var arr = classpathMap["$" + pp]; removeArrayItem(arr, qClazzName) && (classpathMap["$" + pp] = arr); } var n = findNode(qClazzName); if (n) { n.status = Node.STATUS_KNOWN; loadedScripts[n.path] = false; } var path = _Loader.getClasspathFor (qClazzName); loadedScripts[path] = false; innerLoadedScripts[path] && (innerLoadedScripts[path] = false); _Loader.onClassUnloaded(qClazzName); }; /* private */ var assureInnerClass = function (clzz, fun) { clzz = clzz.__CLASS_NAME__; if (Clazz.unloadedClasses[clzz]) { if (clzz.indexOf("$") >= 0) return; var list = []; var key = clzz + "$"; for (var s in Clazz.unloadedClasses) if (Clazz.unloadedClasses[s] && s.indexOf(key) == 0) list.push(s); if (!list.length) return; fun = "" + fun; var idx1, idx2; if ((idx1 = fun.indexOf(key)) < 0 || (idx2 = fun.indexOf("\"", idx1 + key.length)) < 0) return; clzz = fun.substring(idx1, idx2); if (!Clazz.unloadedClasses[clzz] || (idx1 = fun.indexOf("{", idx2) + 1) == 0) return; if ((idx2 = fun.indexOf("(" + clzz + ",", idx1 + 3)) < 0 || (idx2 = fun.lastIndexOf("}", idx2 - 1)) < 0) return; eval(fun.substring(idx1, idx2)); Clazz.unloadedClasses[clzz] = null; } }; Clazz.binaryFolders = _Loader.binaryFolders = [ _Loader.getJ2SLibBase() ]; })(Clazz, Clazz._Loader); //} /****************************************************************************** * Copyright (c) 2007 java2script.org and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhou Renjian - initial API and implementation *****************************************************************************/ /******* * @author zhou renjian * @create Jan 11, 2007 *******/ Clazz._LoaderProgressMonitor = {}; ;(function(CLPM, Jmol) { var fadeOutTimer = null; var fadeAlpha = 0; var monitorEl = null; var lastScrollTop = 0; var bindingParent = null; CLPM.DEFAULT_OPACITY = (Jmol && Jmol._j2sLoadMonitorOpacity ? Jmol._j2sLoadMonitorOpacity : 55); /* public */ /*CLPM.initialize = function (parent) { bindingParent = parent; if (parent && !attached) { attached = true; //Clazz.addEvent (window, "unload", cleanup); // window.attachEvent ("onunload", cleanup); } }; */ /* public */ CLPM.hideMonitor = function () { monitorEl.style.display = "none"; } /* public */ CLPM.showStatus = function (msg, fading) { if (!monitorEl) { createHandle (); if (!attached) { attached = true; //Clazz.addEvent (window, "unload", cleanup); // window.attachEvent ("onunload", cleanup); } } clearChildren(monitorEl); if (msg == null) { if (fading) { fadeOut(); } else { CLPM.hideMonitor(); } return; } monitorEl.appendChild(document.createTextNode ("" + msg)); if (monitorEl.style.display == "none") { monitorEl.style.display = ""; } setAlpha(CLPM.DEFAULT_OPACITY); var offTop = getFixedOffsetTop(); if (lastScrollTop != offTop) { lastScrollTop = offTop; monitorEl.style.bottom = (lastScrollTop + 4) + "px"; } if (fading) { fadeOut(); } }; /* private static */ var clearChildren = function (el) { if (!el) return; for (var i = el.childNodes.length; --i >= 0;) { var child = el.childNodes[i]; if (!child) continue; if (child.childNodes && child.childNodes.length) clearChildren (child); try { el.removeChild (child); } catch (e) {}; } }; /* private */ var setAlpha = function (alpha) { if (fadeOutTimer && alpha == CLPM.DEFAULT_OPACITY) { window.clearTimeout (fadeOutTimer); fadeOutTimer = null; } fadeAlpha = alpha; var ua = navigator.userAgent.toLowerCase(); monitorEl.style.filter = "Alpha(Opacity=" + alpha + ")"; monitorEl.style.opacity = alpha / 100.0; }; /* private */ var hidingOnMouseOver = function () { CLPM.hideMonitor(); }; /* private */ var attached = false; /* private */ var cleanup = function () { //if (monitorEl) { // monitorEl.onmouseover = null; //} monitorEl = null; bindingParent = null; //Clazz.removeEvent (window, "unload", cleanup); //window.detachEvent ("onunload", cleanup); attached = false; }; /* private */ var createHandle = function () { var div = document.createElement ("DIV"); div.id = "_Loader-status"; div.style.cssText = "position:absolute;bottom:4px;left:4px;padding:2px 8px;" + "z-index:" + (window["j2s.lib"].monitorZIndex || 10000) + ";background-color:#8e0000;color:yellow;" + "font-family:Arial, sans-serif;font-size:10pt;white-space:nowrap;"; div.onmouseover = hidingOnMouseOver; monitorEl = div; if (bindingParent) { bindingParent.appendChild(div); } else { document.body.appendChild(div); } return div; }; /* private */ var fadeOut = function () { if (monitorEl.style.display == "none") return; if (fadeAlpha == CLPM.DEFAULT_OPACITY) { fadeOutTimer = window.setTimeout(function () { fadeOut(); }, 750); fadeAlpha -= 5; } else if (fadeAlpha - 10 >= 0) { setAlpha(fadeAlpha - 10); fadeOutTimer = window.setTimeout(function () { fadeOut(); }, 40); } else { monitorEl.style.display = "none"; } }; /* private */ var getFixedOffsetTop = function (){ if (bindingParent) { var b = bindingParent; return b.scrollTop; } var dua = navigator.userAgent; var b = document.body; var p = b.parentNode; var pcHeight = p.clientHeight; var bcScrollTop = b.scrollTop + b.offsetTop; var pcScrollTop = p.scrollTop + p.offsetTop; return (dua.indexOf("Opera") < 0 && document.all ? (pcHeight == 0 ? bcScrollTop : pcScrollTop) : dua.indexOf("Gecko") < 0 ? (pcHeight == p.offsetHeight && pcHeight == p.scrollHeight ? bcScrollTop : pcScrollTop) : bcScrollTop); }; /* not used in Jmol if (window["ClazzLoader"]) { _Loader.onScriptLoading = function(file) { CLPM.showStatus("Loading " + file + "..."); }; _Loader.onScriptLoaded = function(file, isError) { CLPM.showStatus(file + (isError ? " loading failed." : " loaded."), true); }; _Loader.onGlobalLoaded = function(file) { CLPM.showStatus("Application loaded.", true); }; _Loader.onClassUnloaded = function(clazz) { CLPM.showStatus("Class " + clazz + " is unloaded.", true); }; } */ })(Clazz._LoaderProgressMonitor, Jmol); //} /****************************************************************************** * Copyright (c) 2007 java2script.org and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Zhou Renjian - initial API and implementation *****************************************************************************/ /******* * @author zhou renjian * @create Nov 5, 2005 *******/ ;(function(Con, Sys) { /** * Setting maxTotalLines to -1 will not limit the console result */ /* protected */ Con.maxTotalLines = 10000; /* protected */ Con.setMaxTotalLines = function (lines) { Con.maxTotalLines = (lines > 0 ? lines : 999999); } /* protected */ Con.maxLatency = 40; /* protected */ Con.setMaxLatency = function (latency) { Con.maxLatency = (latency > 0 ? latency : 40); }; /* protected */ Con.pinning = false; /* protected */ Con.enablePinning = function (enabled) { Con.pinning = enabled; }; /* private */ Con.linesCount = 0; /* private */ Con.metLineBreak = false; /* * Give an extension point so external script can create and bind the console * themself. * * TODO: provide more template of binding console window to browser. */ /* protected */ Con.createConsoleWindow = function (parentEl) { var console = document.createElement ("DIV"); console.style.cssText = "font-family:monospace, Arial, sans-serif;"; document.body.appendChild (console); return console; }; var c160 = String.fromCharCode(160); //nbsp; c160 += c160+c160+c160; /* protected */ Con.consoleOutput = function (s, color) { var o = window["j2s.lib"]; var console = (o && o.console); if (console && typeof console == "string") console = document.getElementById(console) if (!console) return false; // BH this just means we have turned off all console action if (Con.linesCount > Con.maxTotalLines) { for (var i = 0; i < Con.linesCount - Con.maxTotalLines; i++) { if (console && console.childNodes.length > 0) { console.removeChild (console.childNodes[0]); } } Con.linesCount = Con.maxTotalLines; } var willMeetLineBreak = false; s = (typeof s == "undefined" ? "" : s == null ? "null" : "" + s); s = s.replace (/\t/g, c160); if (s.length > 0) switch (s.charAt(s.length - 1)) { case '\n': case '\r': s = (s.length > 1 ? s.substring (0, s.length - (s.charAt (s.length - 2) == '\r' ? 2 : 1)) : ""); willMeetLineBreak = true; break; } var lines = null; s = s.replace (/\t/g, c160); lines = s.split(/\r\n|\r|\n/g); for (var i = 0, last = lines.length - 1; i <= last; i++) { var lastLineEl = null; if (Con.metLineBreak || Con.linesCount == 0 || console.childNodes.length < 1) { lastLineEl = document.createElement ("DIV"); console.appendChild (lastLineEl); lastLineEl.style.whiteSpace = "nowrap"; Con.linesCount++; } else { try { lastLineEl = console.childNodes[console.childNodes.length - 1]; } catch (e) { lastLineEl = document.createElement ("DIV"); console.appendChild (lastLineEl); lastLineEl.style.whiteSpace = "nowrap"; Con.linesCount++; } } var el = document.createElement ("SPAN"); lastLineEl.appendChild (el); el.style.whiteSpace = "nowrap"; if (color) el.style.color = color; var l = lines[i] if (l.length == 0) l = c160; el.appendChild(document.createTextNode(l)); if (!Con.pinning) console.scrollTop += 100; Con.metLineBreak = (i != last || willMeetLineBreak); } var cssClazzName = console.parentNode.className; if (!Con.pinning && cssClazzName && cssClazzName.indexOf ("composite") != -1) { console.parentNode.scrollTop = console.parentNode.scrollHeight; } Con.lastOutputTime = new Date ().getTime (); }; /* * Clear all contents inside the console. */ /* public */ Con.clear = function () { try { Con.metLineBreak = true; var o = window["j2s.lib"]; var console = o && o.console; if (!console || !(console = document.getElementById (console))) return; var childNodes = console.childNodes; for (var i = childNodes.length; --i >= 0;) console.removeChild (childNodes[i]); Con.linesCount = 0; } catch(e){}; }; /* public */ Clazz.alert = function (s) { Con.consoleOutput (s + "\r\n"); }; /* public */ Sys.out.print = function (s) { Con.consoleOutput (s); }; /* public */ Sys.out.println = function(s) { Con.consoleOutput(typeof s == "undefined" ? "\r\n" : s == null ? s = "null\r\n" : s + "\r\n"); }; Sys.out.write = function (buf, offset, len) { Sys.out.print(String.instantialize(buf).substring(offset, offset+len)); }; /* public */ Sys.err.__CLASS_NAME__ = "java.io.PrintStream"; /* public */ Sys.err.print = function (s) { Con.consoleOutput (s, "red"); }; /* public */ Sys.err.println = function (s) { Con.consoleOutput (typeof s == "undefined" ? "\r\n" : s == null ? s = "null\r\n" : s + "\r\n", "red"); }; Sys.err.write = function (buf, offset, len) { Sys.err.print(String.instantialize(buf).substring(offset, offset+len)); }; })(Clazz.Console, System); })(Clazz, Jmol); // requires JSmolCore.js }; // called by external application