|
Java example source code file (hat.js)
The hat.js Java example source code/* * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * The Original Code is HAT. The Initial Developer of the * Original Code is Bill Foote, with contributions from others * at JavaSoft/Sun. */ var hatPkg = Packages.com.sun.tools.hat.internal; /** * This is JavaScript interface for heap analysis using HAT * (Heap Analysis Tool). HAT classes are referred from * this file. In particular, refer to classes in hat.model * package. * * HAT model objects are wrapped as convenient script objects so that * fields may be accessed in natural syntax. For eg. Java fields can be * accessed with obj.field_name syntax and array elements can be accessed * with array[index] syntax. */ // returns an enumeration that wraps elements of // the input enumeration elements. function wrapperEnumeration(e) { return new java.util.Enumeration() { hasMoreElements: function() { return e.hasMoreElements(); }, nextElement: function() { return wrapJavaValue(e.nextElement()); } }; } // returns an enumeration that filters out elements // of input enumeration using the filter function. function filterEnumeration(e, func, wrap) { var next = undefined; var index = 0; function findNext() { var tmp; while (e.hasMoreElements()) { tmp = e.nextElement(); index++; if (wrap) { tmp = wrapJavaValue(tmp); } if (func(tmp, index, e)) { next = tmp; return; } } } return new java.util.Enumeration() { hasMoreElements: function() { findNext(); return next != undefined; }, nextElement: function() { if (next == undefined) { // user may not have called hasMoreElements? findNext(); } if (next == undefined) { throw "NoSuchElementException"; } var res = next; next = undefined; return res; } }; } // enumeration that has no elements .. var emptyEnumeration = new java.util.Enumeration() { hasMoreElements: function() { return false; }, nextElement: function() { throw "NoSuchElementException"; } }; function wrapRoot(root) { if (root) { return { id: root.idString, description: root.description, referrer: wrapJavaValue(root.referer), type: root.typeName }; } else { return null; } } function JavaClassProto() { function jclass(obj) { return obj['wrapped-object']; } // return whether given class is subclass of this class or not this.isSubclassOf = function(other) { var tmp = jclass(this); var otherid = objectid(other); while (tmp != null) { if (otherid.equals(tmp.idString)) { return true; } tmp = tmp.superclass; } return false; } // return whether given class is superclass of this class or not this.isSuperclassOf = function(other) { return other.isSubclassOf(this); } // includes direct and indirect superclasses this.superclasses = function() { var res = new Array(); var tmp = this.superclass; while (tmp != null) { res[res.length] = tmp; tmp = tmp.superclass; } return res; } /** * Returns an array containing subclasses of this class. * * @param indirect should include indirect subclasses or not. * default is true. */ this.subclasses = function(indirect) { if (indirect == undefined) indirect = true; var classes = jclass(this).subclasses; var res = new Array(); for (var i in classes) { var subclass = wrapJavaValue(classes[i]); res[res.length] = subclass; if (indirect) { res = res.concat(subclass.subclasses()); } } return res; } this.toString = function() { return jclass(this).toString(); } } var theJavaClassProto = new JavaClassProto(); // Script wrapper for HAT model objects, values. // wraps a Java value as appropriate for script object function wrapJavaValue(thing) { if (thing == null || thing == undefined || thing instanceof hatPkg.model.HackJavaValue) { return null; } if (thing instanceof hatPkg.model.JavaValue) { // map primitive values to closest JavaScript primitives if (thing instanceof hatPkg.model.JavaBoolean) { return thing.toString() == "true"; } else if (thing instanceof hatPkg.model.JavaChar) { return thing.toString() + ''; } else { return java.lang.Double.parseDouble(thing.toString()); } } else { // wrap Java object as script object return wrapJavaObject(thing); } } // wrap Java object with appropriate script object function wrapJavaObject(thing) { // HAT Java model object wrapper. Handles all cases // (instance, object/primitive array and Class objects) function javaObject(jobject) { // FIXME: Do I need this? or can I assume that these would // have been resolved already? if (jobject instanceof hatPkg.model.JavaObjectRef) { jobject = jobject.dereference(); if (jobject instanceof hatPkg.model.HackJavaValue) { print(jobject); return null; } } if (jobject instanceof hatPkg.model.JavaObject) { return new JavaObjectWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaClass) { return new JavaClassWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaObjectArray) { return new JavaObjectArrayWrapper(jobject); } else if (jobject instanceof hatPkg.model.JavaValueArray) { return new JavaValueArrayWrapper(jobject); } else { print("unknown heap object type: " + jobject.getClass()); return jobject; } } // returns wrapper for Java instances function JavaObjectWrapper(instance) { var things = instance.fields; var fields = instance.clazz.fieldsForInstance; // instance fields can be accessed in natural syntax return new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].name) return true; } return name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { for (var i in fields) { if(fields[i].name == name) { return wrapJavaValue(things[i]); } } if (name == 'class') { return wrapJavaValue(instance.clazz); } else if (name == 'wrapped-object') { return instance; } return undefined; }, __call__: function(name) { if (name == 'toString') { return instance.toString(); } else { return undefined; } } } } // return wrapper for Java Class objects function JavaClassWrapper(jclass) { var fields = jclass.statics; // to access static fields of given Class cl, use // cl.statics.<static-field-name> syntax this.statics = new JSAdapter() { __getIds__ : function() { var res = new Array(fields.length); for (var i in fields) { res[i] = fields[i].field.name; } return res; }, __has__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return true; } } return false; }, __get__ : function(name) { for (var i in fields) { if (name == fields[i].field.name) { return wrapJavaValue(fields[i].value); } } return undefined; } } if (jclass.superclass != null) { this.superclass = wrapJavaValue(jclass.superclass); } else { this.superclass = null; } this.loader = wrapJavaValue(jclass.getLoader()); this.signers = wrapJavaValue(jclass.getSigners()); this.protectionDomain = wrapJavaValue(jclass.getProtectionDomain()); this.instanceSize = jclass.instanceSize; this.name = jclass.name; this.fields = jclass.fields; this['wrapped-object'] = jclass; } for (var i in theJavaClassProto) { if (typeof theJavaClassProto[i] == 'function') { JavaClassWrapper.prototype[i] = theJavaClassProto[i]; } } // returns wrapper for Java object arrays function JavaObjectArrayWrapper(array) { var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var res = new Array(elements.length); for (var i = 0; i < elements.length; i++) { res[i] = String(i); } return res; }, __has__: function(name) { return (name >= 0 && name < elements.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__ : function(name) { if (name >= 0 && name < elements.length) { return wrapJavaValue(elements[name]); } else if (name == 'length') { return elements.length; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else if (name == 'wrapped-object') { return array; } else { return undefined; } }, __call__: function(name) { if (name == 'toString') { return array.toString(); } else { return undefined; } } } } // returns wrapper for Java primitive arrays function JavaValueArrayWrapper(array) { var type = String(java.lang.Character.toString(array.elementType)); var elements = array.elements; // array elements can be accessed in natural syntax // also, 'length' property is supported. return new JSAdapter() { __getIds__ : function() { var r = new Array(array.length); for (var i = 0; i < array.length; i++) { r[i] = String(i); } return r; }, __has__: function(name) { return (name >= 0 && name < array.length) || name == 'length' || name == 'class' || name == 'toString' || name == 'wrapped-object'; }, __get__: function(name) { if (name >= 0 && name < array.length) { return elements[name]; } if (name == 'length') { return array.length; } else if (name == 'wrapped-object') { return array; } else if (name == 'class') { return wrapJavaValue(array.clazz); } else { return undefined; } }, __call__: function(name) { if (name == 'toString') { return array.valueString(true); } else { return undefined; } } } } return javaObject(thing); } // unwrap a script object to corresponding HAT object function unwrapJavaObject(jobject) { if (!(jobject instanceof hatPkg.model.JavaHeapObject)) { try { jobject = jobject["wrapped-object"]; } catch (e) { print("unwrapJavaObject: " + jobject + ", " + e); jobject = undefined; } } return jobject; } /** * readHeapDump parses a heap dump file and returns script wrapper object. * * @param file Heap dump file name * @param stack flag to tell if allocation site traces are available * @param refs flag to tell if backward references are needed or not * @param debug debug level for HAT * @return heap as a JavaScript object */ function readHeapDump(file, stack, refs, debug) { // default value of debug is 0 if (!debug) debug = 0; // by default, we assume no stack traces if (!stack) stack = false; // by default, backward references are resolved if (!refs) refs = true; // read the heap dump var heap = hatPkg.parser.HprofReader.readFile(file, stack, debug); // resolve it heap.resolve(refs); // wrap Snapshot as convenient script object return wrapHeapSnapshot(heap); } /** * The result object supports the following methods: * * forEachClass -- calls a callback for each Java Class * forEachObject -- calls a callback for each Java object * findClass -- finds Java Class of given name * findObject -- finds object from given object id * objects -- returns all objects of given class as an enumeration * classes -- returns all classes in the heap as an enumeration * reachables -- returns all objects reachable from a given object * livepaths -- returns an array of live paths because of which an * object alive. * describeRef -- returns description for a reference from a 'from' * object to a 'to' object. */ function wrapHeapSnapshot(heap) { function getClazz(clazz) { if (clazz == undefined) clazz = "java.lang.Object"; var type = typeof(clazz); if (type == "string") { clazz = heap.findClass(clazz); } else if (type == "object") { clazz = unwrapJavaObject(clazz); } else { throw "class expected";; } return clazz; } // return heap as a script object with useful methods. return { snapshot: heap, /** * Class iteration: Calls callback function for each * Java Class in the heap. Default callback function * is 'print'. If callback returns true, the iteration * is stopped. * * @param callback function to be called. */ forEachClass: function(callback) { if (callback == undefined) callback = print; var classes = this.snapshot.classes; while (classes.hasMoreElements()) { if (callback(wrapJavaValue(classes.nextElement()))) return; } }, /** * Returns an Enumeration of all roots. */ roots: function() { var e = this.snapshot.roots; return new java.util.Enumeration() { hasMoreElements: function() { return e.hasMoreElements(); }, nextElement: function() { return wrapRoot(e.nextElement()); } }; }, /** * Returns an Enumeration for all Java classes. */ classes: function() { return wrapIterator(this.snapshot.classes, true); }, /** * Object iteration: Calls callback function for each * Java Object in the heap. Default callback function * is 'print'.If callback returns true, the iteration * is stopped. * * @param callback function to be called. * @param clazz Class whose objects are retrieved. * Optional, default is 'java.lang.Object' * @param includeSubtypes flag to tell if objects of subtypes * are included or not. optional, default is true. */ forEachObject: function(callback, clazz, includeSubtypes) { if (includeSubtypes == undefined) includeSubtypes = true; if (callback == undefined) callback = print; clazz = getClazz(clazz); if (clazz) { var instances = clazz.getInstances(includeSubtypes); while (instances.hasNextElements()) { if (callback(wrapJavaValue(instances.nextElement()))) return; } } }, /** * Returns an enumeration of Java objects in the heap. * * @param clazz Class whose objects are retrieved. * Optional, default is 'java.lang.Object' * @param includeSubtypes flag to tell if objects of subtypes * are included or not. optional, default is true. * @param where (optional) filter expression or function to * filter the objects. The expression has to return true * to include object passed to it in the result array. * Built-in variable 'it' refers to the current object in * filter expression. */ objects: function(clazz, includeSubtypes, where) { if (includeSubtypes == undefined) includeSubtypes = true; if (where) { if (typeof(where) == 'string') { where = new Function("it", "return " + where); } } clazz = getClazz(clazz); if (clazz) { var instances = clazz.getInstances(includeSubtypes); if (where) { return filterEnumeration(instances, where, true); } else { return wrapperEnumeration(instances); } } else { return emptyEnumeration; } }, /** * Find Java Class of given name. * * @param name class name */ findClass: function(name) { var clazz = this.snapshot.findClass(name + ''); return wrapJavaValue(clazz); }, /** * Find Java Object from given object id * * @param id object id as string */ findObject: function(id) { return wrapJavaValue(this.snapshot.findThing(id)); }, /** * Returns an enumeration of objects in the finalizer * queue waiting to be finalized. */ finalizables: function() { var tmp = this.snapshot.getFinalizerObjects(); return wrapperEnumeration(tmp); }, /** * Returns an array that contains objects referred from the * given Java object directly or indirectly (i.e., all * transitively referred objects are returned). * * @param jobject Java object whose reachables are returned. */ reachables: function (jobject) { return reachables(jobject, this.snapshot.reachableExcludes); }, /** * Returns array of paths of references by which the given * Java object is live. Each path itself is an array of * objects in the chain of references. Each path supports * toHtml method that returns html description of the path. * * @param jobject Java object whose live paths are returned * @param weak flag to indicate whether to include paths with * weak references or not. default is false. */ livepaths: function (jobject, weak) { if (weak == undefined) { weak = false; } function wrapRefChain(refChain) { var path = new Array(); // compute path array from refChain var tmp = refChain; while (tmp != null) { var obj = tmp.obj; path[path.length] = wrapJavaValue(obj); tmp = tmp.next; } function computeDescription(html) { var root = refChain.obj.root; var desc = root.description; if (root.referer) { var ref = root.referer; desc += " (from " + (html? toHtml(ref) : ref.toString()) + ')'; } desc += '->'; var tmp = refChain; while (tmp != null) { var next = tmp.next; var obj = tmp.obj; desc += html? toHtml(obj) : obj.toString(); if (next != null) { desc += " (" + obj.describeReferenceTo(next.obj, heap) + ") ->"; } tmp = next; } return desc; } return new JSAdapter() { __getIds__ : function() { var res = new Array(path.length); for (var i = 0; i < path.length; i++) { res[i] = String(i); } return res; }, __has__ : function (name) { return (name >= 0 && name < path.length) || name == 'length' || name == 'toHtml' || name == 'toString'; }, __get__ : function(name) { if (name >= 0 && name < path.length) { return path[name]; } else if (name == 'length') { return path.length; } else { return undefined; } }, __call__: function(name) { if (name == 'toHtml') { return computeDescription(true); } else if (name == 'toString') { return computeDescription(false); } else { return undefined; } } }; } jobject = unwrapJavaObject(jobject); var refChains = this.snapshot.rootsetReferencesTo(jobject, weak); var paths = new Array(refChains.length); for (var i in refChains) { paths[i] = wrapRefChain(refChains[i]); } return paths; }, /** * Return description string for reference from 'from' object * to 'to' Java object. * * @param from source Java object * @param to destination Java object */ describeRef: function (from, to) { from = unwrapJavaObject(from); to = unwrapJavaObject(to); return from.describeReferenceTo(to, this.snapshot); }, }; } // per-object functions /** * Returns allocation site trace (if available) of a Java object * * @param jobject object whose allocation site trace is returned */ function allocTrace(jobject) { try { jobject = unwrapJavaObject(jobject); var trace = jobject.allocatedFrom; return (trace != null) ? trace.frames : null; } catch (e) { print("allocTrace: " + jobject + ", " + e); return null; } } /** * Returns Class object for given Java object * * @param jobject object whose Class object is returned */ function classof(jobject) { jobject = unwrapJavaObject(jobject); return wrapJavaValue(jobject.clazz); } /** * Find referers (a.k.a in-coming references). Calls callback * for each referrer of the given Java object. If the callback * returns true, the iteration is stopped. * * @param callback function to call for each referer * @param jobject object whose referers are retrieved */ function forEachReferrer(callback, jobject) { jobject = unwrapJavaObject(jobject); var refs = jobject.referers; while (refs.hasMoreElements()) { if (callback(wrapJavaValue(refs.nextElement()))) { return; } } } /** * Compares two Java objects for object identity. * * @param o1, o2 objects to compare for identity */ function identical(o1, o2) { return objectid(o1) == objectid(o2); } /** * Returns Java object id as string * * @param jobject object whose id is returned */ function objectid(jobject) { try { jobject = unwrapJavaObject(jobject); return String(jobject.idString); } catch (e) { print("objectid: " + jobject + ", " + e); return null; } } /** * Prints allocation site trace of given object * * @param jobject object whose allocation site trace is returned */ function printAllocTrace(jobject) { var frames = this.allocTrace(jobject); if (frames == null || frames.length == 0) { print("allocation site trace unavailable for " + objectid(jobject)); return; } print(objectid(jobject) + " was allocated at .."); for (var i in frames) { var frame = frames[i]; var src = frame.sourceFileName; if (src == null) src = '<unknown source>'; print('\t' + frame.className + "." + frame.methodName + '(' + frame.methodSignature + ') [' + src + ':' + frame.lineNumber + ']'); } } /** * Returns an enumeration of referrers of the given Java object. * * @param jobject Java object whose referrers are returned. */ function referrers(jobject) { try { jobject = unwrapJavaObject(jobject); return wrapperEnumeration(jobject.referers); } catch (e) { print("referrers: " + jobject + ", " + e); return emptyEnumeration; } } /** * Returns an array that contains objects referred from the * given Java object. * * @param jobject Java object whose referees are returned. */ function referees(jobject) { var res = new Array(); jobject = unwrapJavaObject(jobject); if (jobject != undefined) { try { jobject.visitReferencedObjects( new hatPkg.model.JavaHeapObjectVisitor() { visit: function(other) { res[res.length] = wrapJavaValue(other); }, exclude: function(clazz, field) { return false; }, mightExclude: function() { return false; } }); } catch (e) { print("referees: " + jobject + ", " + e); } } return res; } /** * Returns an array that contains objects referred from the * given Java object directly or indirectly (i.e., all * transitively referred objects are returned). * * @param jobject Java object whose reachables are returned. * @param excludes optional comma separated list of fields to be * removed in reachables computation. Fields are * written as class_name.field_name form. */ function reachables(jobject, excludes) { if (excludes == undefined) { excludes = null; } else if (typeof(excludes) == 'string') { var st = new java.util.StringTokenizer(excludes, ","); var excludedFields = new Array(); while (st.hasMoreTokens()) { excludedFields[excludedFields.length] = st.nextToken().trim(); } if (excludedFields.length > 0) { excludes = new hatPkg.model.ReachableExcludes() { isExcluded: function (field) { for (var index in excludedFields) { if (field.equals(excludedFields[index])) { return true; } } return false; } }; } else { // nothing to filter... excludes = null; } } else if (! (excludes instanceof hatPkg.model.ReachableExcludes)) { excludes = null; } jobject = unwrapJavaObject(jobject); var ro = new hatPkg.model.ReachableObjects(jobject, excludes); var tmp = ro.reachables; var res = new Array(tmp.length); for (var i in tmp) { res[i] = wrapJavaValue(tmp[i]); } return res; } /** * Returns whether 'from' object refers to 'to' object or not. * * @param from Java object that is source of the reference. * @param to Java object that is destination of the reference. */ function refers(from, to) { try { var tmp = unwrapJavaObject(from); if (tmp instanceof hatPkg.model.JavaClass) { from = from.statics; } else if (tmp instanceof hatPkg.model.JavaValueArray) { return false; } for (var i in from) { if (identical(from[i], to)) { return true; } } } catch (e) { print("refers: " + from + ", " + e); } return false; } /** * If rootset includes given jobject, return Root * object explanining the reason why it is a root. * * @param jobject object whose Root is returned */ function root(jobject) { try { jobject = unwrapJavaObject(jobject); return wrapRoot(jobject.root); } catch (e) { return null; } } /** * Returns size of the given Java object * * @param jobject object whose size is returned */ function sizeof(jobject) { try { jobject = unwrapJavaObject(jobject); return jobject.size; } catch (e) { print("sizeof: " + jobject + ", " + e); return null; } } /** * Returns String by replacing Unicode chars and * HTML special chars (such as '<') with entities. * * @param str string to be encoded */ function encodeHtml(str) { return hatPkg.util.Misc.encodeHtml(str); } /** * Returns HTML string for the given object. * * @param obj object for which HTML string is returned. */ function toHtml(obj) { if (obj == null) { return "null"; } if (obj == undefined) { return "undefined"; } var tmp = unwrapJavaObject(obj); if (tmp != undefined) { var id = tmp.idString; if (tmp instanceof Packages.com.sun.tools.hat.internal.model.JavaClass) { var name = tmp.name; return "<a href='/class/" + id + "'>class " + name + ""; } else { var name = tmp.clazz.name; return "<a href='/object/" + id + "'>" + name + "@" + id + "</a>"; } } else if (obj instanceof Object) { if (Array.isArray(obj)) { // script array var res = "[ "; for (var i in obj) { res += toHtml(obj[i]); if (i != obj.length - 1) { res += ", "; } } res += " ]"; return res; } else { // if the object has a toHtml function property // just use that... if (typeof(obj.toHtml) == 'function') { return obj.toHtml(); } else { // script object var res = "{ "; for (var i in obj) { res += i + ":" + toHtml(obj[i]) + ", "; } res += "}"; return res; } } } else { // a Java object obj = wrapIterator(obj); // special case for enumeration if (obj instanceof java.util.Enumeration) { var res = "[ "; while (obj.hasMoreElements()) { res += toHtml(obj.nextElement()) + ", "; } res += "]"; return res; } else { return obj; } } } /* * Generic array/iterator/enumeration [or even object!] manipulation * functions. These functions accept an array/iteration/enumeration * and expression String or function. These functions iterate each * element of array and apply the expression/function on each element. */ // private function to wrap an Iterator as an Enumeration function wrapIterator(itr, wrap) { if (itr instanceof java.util.Iterator) { return new java.util.Enumeration() { hasMoreElements: function() { return itr.hasNext(); }, nextElement: function() { return wrap? wrapJavaValue(itr.next()) : itr.next(); } }; } else { return itr; } } /** * Converts an enumeration/iterator/object into an array * * @param obj enumeration/iterator/object * @return array that contains values of enumeration/iterator/object */ function toArray(obj) { obj = wrapIterator(obj); if (obj instanceof java.util.Enumeration) { var res = new Array(); while (obj.hasMoreElements()) { res[res.length] = obj.nextElement(); } return res; } else if (obj instanceof Array) { return obj; } else { var res = new Array(); for (var index in obj) { res[res.length] = obj[index]; } return res; } } /** * Returns whether the given array/iterator/enumeration contains * an element that satisfies the given boolean expression specified * in code. * * @param array input array/iterator/enumeration that is iterated * @param code expression string or function * @return boolean result * * The code evaluated can refer to the following built-in variables. * * 'it' -> currently visited element * 'index' -> index of the current element * 'array' -> array that is being iterated */ function contains(array, code) { array = wrapIterator(array); var func = code; if (typeof(func) != 'function') { func = new Function("it", "index", "array", "return " + code); } if (array instanceof java.util.Enumeration) { var index = 0; while (array.hasMoreElements()) { var it = array.nextElement(); if (func(it, index, array)) { return true; } index++; } } else { for (var index in array) { var it = array[index]; if (func(it, String(index), array)) { return true; } } } return false; } /** * concatenates two arrays/iterators/enumerators. * * @param array1 array/iterator/enumeration * @param array2 array/iterator/enumeration * * @return concatenated array or composite enumeration */ function concat(array1, array2) { array1 = wrapIterator(array1); array2 = wrapIterator(array2); if (array1 instanceof Array && array2 instanceof Array) { return array1.concat(array2); } else if (array1 instanceof java.util.Enumeration && array2 instanceof java.util.Enumeration) { return new Packages.com.sun.tools.hat.internal.util.CompositeEnumeration(array1, array2); } else { return undefined; } } /** * Returns the number of array/iterator/enumeration elements * that satisfy the given boolean expression specified in code. * The code evaluated can refer to the following built-in variables. * * @param array input array/iterator/enumeration that is iterated * @param code expression string or function * @return number of elements * * 'it' -> currently visited element * 'index' -> index of the current element * 'array' -> array that is being iterated */ function count(array, code) { if (code == undefined) { return length(array); } array = wrapIterator(array); var func = code; if (typeof(func) != 'function') { func = new Function("it", "index", "array", "return " + code); } var result = 0; if (array instanceof java.util.Enumeration) { var index = 0; while (array.hasMoreElements()) { var it = array.nextElement(); if (func(it, index, array)) { result++; } index++; } } else { for (var index in array) { var it = array[index]; if (func(it, index, array)) { result++; } } } return result; } /** * filter function returns an array/enumeration that contains * elements of the input array/iterator/enumeration that satisfy * the given boolean expression. The boolean expression code can * refer to the following built-in variables. * * @param array input array/iterator/enumeration that is iterated * @param code expression string or function * @return array/enumeration that contains the filtered elements * * 'it' -> currently visited element * 'index' -> index of the current element * 'array' -> array that is being iterated * 'result' -> result array */ function filter(array, code) { array = wrapIterator(array); var func = code; if (typeof(code) != 'function') { func = new Function("it", "index", "array", "result", "return " + code); } if (array instanceof java.util.Enumeration) { return filterEnumeration(array, func, false); } else { var result = new Array(); for (var index in array) { var it = array[index]; if (func(it, String(index), array, result)) { result[result.length] = it; } } return result; } } /** * Returns the number of elements of array/iterator/enumeration. * * @param array input array/iterator/enumeration that is iterated */ function length(array) { array = wrapIterator(array); if (array instanceof Array) { return array.length; } else if (array instanceof java.util.Enumeration) { var cnt = 0; while (array.hasMoreElements()) { array.nextElement(); cnt++; } return cnt; } else { var cnt = 0; for (var index in array) { cnt++; } return cnt; } } /** * Transforms the given object or array by evaluating given code * on each element of the object or array. The code evaluated * can refer to the following built-in variables. * * @param array input array/iterator/enumeration that is iterated * @param code expression string or function * @return array/enumeration that contains mapped values * * 'it' -> currently visited element * 'index' -> index of the current element * 'array' -> array that is being iterated * 'result' -> result array * * map function returns an array/enumeration of values created * by repeatedly calling code on each element of the input * array/iterator/enumeration. */ function map(array, code) { array = wrapIterator(array); var func = code; if(typeof(code) != 'function') { func = new Function("it", "index", "array", "result", "return " + code); } if (array instanceof java.util.Enumeration) { var index = 0; var result = new java.util.Enumeration() { hasMoreElements: function() { return array.hasMoreElements(); }, nextElement: function() { return func(array.nextElement(), index++, array, result); } }; return result; } else { var result = new Array(); for (var index in array) { var it = array[index]; result[result.length] = func(it, String(index), array, result); } return result; } } // private function used by min, max functions function minmax(array, code) { if (typeof(code) == 'string') { code = new Function("lhs", "rhs", "return " + code); } array = wrapIterator(array); if (array instanceof java.util.Enumeration) { if (! array.hasMoreElements()) { return undefined; } var res = array.nextElement(); while (array.hasMoreElements()) { var next = array.nextElement(); if (code(next, res)) { res = next; } } return res; } else { if (array.length == 0) { return undefined; } var res = array[0]; for (var index = 1; index < array.length; index++) { if (code(array[index], res)) { res = array[index]; } } return res; } } /** * Returns the maximum element of the array/iterator/enumeration * * @param array input array/iterator/enumeration that is iterated * @param code (optional) comparision expression or function * by default numerical maximum is computed. */ function max(array, code) { if (code == undefined) { code = function (lhs, rhs) { return lhs > rhs; } } return minmax(array, code); } /** * Returns the minimum element of the array/iterator/enumeration * * @param array input array/iterator/enumeration that is iterated * @param code (optional) comparision expression or function * by default numerical minimum is computed. */ function min(array, code) { if (code == undefined) { code = function (lhs, rhs) { return lhs < rhs; } } return minmax(array, code); } /** * sort function sorts the input array. optionally accepts * code to compare the elements. If code is not supplied, * numerical sort is done. * * @param array input array/iterator/enumeration that is sorted * @param code expression string or function * @return sorted array * * The comparison expression can refer to the following * built-in variables: * * 'lhs' -> 'left side' element * 'rhs' -> 'right side' element */ function sort(array, code) { // we need an array to sort, so convert non-arrays array = toArray(array); // by default use numerical comparison var func = code; if (code == undefined) { func = function(lhs, rhs) { return lhs - rhs; }; } else if (typeof(code) == 'string') { func = new Function("lhs", "rhs", "return " + code); } return array.sort(func); } /** * Returns the sum of the elements of the array * * @param array input array that is summed. * @param code optional expression used to map * input elements before sum. */ function sum(array, code) { array = wrapIterator(array); if (code != undefined) { array = map(array, code); } var result = 0; if (array instanceof java.util.Enumeration) { while (array.hasMoreElements()) { result += Number(array.nextElement()); } } else { for (var index in array) { result += Number(array[index]); } } return result; } /** * Returns array of unique elements from the given input * array/iterator/enumeration. * * @param array from which unique elements are returned. * @param code optional expression (or function) giving unique * attribute/property for each element. * by default, objectid is used for uniqueness. */ function unique(array, code) { array = wrapIterator(array); if (code == undefined) { code = new Function("it", "return objectid(it);"); } else if (typeof(code) == 'string') { code = new Function("it", "return " + code); } var tmp = new Object(); if (array instanceof java.util.Enumeration) { while (array.hasMoreElements()) { var it = array.nextElement(); tmp[code(it)] = it; } } else { for (var index in array) { var it = array[index]; tmp[code(it)] = it; } } var res = new Array(); for (var index in tmp) { res[res.length] = tmp[index]; } return res; } Other Java examples (source code examples)Here is a short list of links related to this Java hat.js source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.