Implemented removing of compiled functions that no longer exist as
proposed by Stefan Matthias Aust. General refactoring of the class.
This commit is contained in:
		
							parent
							
								
									28c6810fb0
								
							
						
					
					
						commit
						260cca8971
					
				
					 1 changed files with 220 additions and 262 deletions
				
			
		| 
						 | 
					@ -42,7 +42,7 @@ public final class RhinoCore {
 | 
				
			||||||
    public final Application app;
 | 
					    public final Application app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // the global object
 | 
					    // the global object
 | 
				
			||||||
    Scriptable global;
 | 
					    GlobalObject global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // caching table for JavaScript object wrappers
 | 
					    // caching table for JavaScript object wrappers
 | 
				
			||||||
    WeakHashMap wrappercache;
 | 
					    WeakHashMap wrappercache;
 | 
				
			||||||
| 
						 | 
					@ -82,7 +82,7 @@ public final class RhinoCore {
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            GlobalObject g = new GlobalObject(this, app, context);
 | 
					            GlobalObject g = new GlobalObject(this, app, context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            global = context.initStandardObjects(g);
 | 
					            global = (GlobalObject) context.initStandardObjects(g);
 | 
				
			||||||
            ScriptableObject.defineClass(global, HopObject.class);
 | 
					            ScriptableObject.defineClass(global, HopObject.class);
 | 
				
			||||||
            ScriptableObject.defineClass(global, FileObject.class);
 | 
					            ScriptableObject.defineClass(global, FileObject.class);
 | 
				
			||||||
            ScriptableObject.defineClass(global, FtpObject.class);
 | 
					            ScriptableObject.defineClass(global, FtpObject.class);
 | 
				
			||||||
| 
						 | 
					@ -90,7 +90,8 @@ public final class RhinoCore {
 | 
				
			||||||
            XmlRpcObject.init(global);
 | 
					            XmlRpcObject.init(global);
 | 
				
			||||||
            MailObject.init(global, app.getProperties());
 | 
					            MailObject.init(global, app.getProperties());
 | 
				
			||||||
            putPrototype("hopobject",
 | 
					            putPrototype("hopobject",
 | 
				
			||||||
                         ScriptableObject.getClassPrototype(global, "HopObject"));
 | 
					                    (ScriptableObject) ScriptableObject
 | 
				
			||||||
 | 
					                    .getClassPrototype(global, "HopObject"));
 | 
				
			||||||
            putPrototype("global", global);
 | 
					            putPrototype("global", global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // add some convenience functions to string, date and number prototypes
 | 
					            // add some convenience functions to string, date and number prototypes
 | 
				
			||||||
| 
						 | 
					@ -135,53 +136,28 @@ public final class RhinoCore {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     *   Initialize a prototype without fully parsing its script files.
 | 
					     *   Initialize a prototype without fully parsing its script files.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param prototype the prototype to be created
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    synchronized void initPrototype(Prototype prototype) {
 | 
					    synchronized void initPrototype(Prototype prototype) {
 | 
				
			||||||
        // System.err.println ("FESI INIT PROTO "+prototype);
 | 
					
 | 
				
			||||||
        Scriptable op = null;
 | 
					 | 
				
			||||||
        String name = prototype.getName();
 | 
					        String name = prototype.getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // get the prototype's prototype if possible and necessary
 | 
					        // check if the prototype info exists already
 | 
				
			||||||
        Scriptable opp = null;
 | 
					        ScriptableObject op = getRawPrototype(name);
 | 
				
			||||||
        Prototype parent = prototype.getParentPrototype();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (parent != null) {
 | 
					 | 
				
			||||||
            // see if parent prototype is already registered. if not, register it
 | 
					 | 
				
			||||||
            opp = getRawPrototype(parent.getName());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (opp == null) {
 | 
					 | 
				
			||||||
                initPrototype(parent);
 | 
					 | 
				
			||||||
                opp = getRawPrototype(parent.getName());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
 | 
					 | 
				
			||||||
                (opp == null)) {
 | 
					 | 
				
			||||||
            if (app.isJavaPrototype(name)) {
 | 
					 | 
				
			||||||
                opp = null;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                opp = getRawPrototype("hopobject");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // if prototype doesn't exist (i.e. is a standard prototype built by HopExtension), create it.
 | 
					 | 
				
			||||||
        op = getRawPrototype(name);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // if prototype info doesn't exist (i.e. is a standard prototype
 | 
				
			||||||
 | 
					        // built by HopExtension), create it.
 | 
				
			||||||
        if (op == null) {
 | 
					        if (op == null) {
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                op = new HopObject(name); // context.newObject (global /*, "HopObject" */);
 | 
					                op = new HopObject(name);
 | 
				
			||||||
                op.setPrototype(opp);
 | 
					 | 
				
			||||||
                op.setParentScope(global);
 | 
					                op.setParentScope(global);
 | 
				
			||||||
                op.put("prototypename", op, name);
 | 
					                // op.put("prototypename", op, name);
 | 
				
			||||||
            } catch (Exception ignore) {
 | 
					            } catch (Exception ignore) {
 | 
				
			||||||
                System.err.println("Error creating prototype: " + ignore);
 | 
					                System.err.println("Error creating prototype: " + ignore);
 | 
				
			||||||
                ignore.printStackTrace();
 | 
					                ignore.printStackTrace();
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					 | 
				
			||||||
            putPrototype(name, op);
 | 
					            putPrototype(name, op);
 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // set parent prototype just in case it has been changed
 | 
					 | 
				
			||||||
            op.setPrototype(opp);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Register a constructor for all types except global.
 | 
					        // Register a constructor for all types except global.
 | 
				
			||||||
| 
						 | 
					@ -201,69 +177,92 @@ public final class RhinoCore {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     *   Set up a prototype, parsing and compiling all its script files.
 | 
					     *   Set up a prototype, parsing and compiling all its script files.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param prototype the prototype to update/evaluate/compile
 | 
				
			||||||
 | 
					     *  @param info the info, containing the object proto, last update time and
 | 
				
			||||||
 | 
					     *         the set of compiled functions properties
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    synchronized void evaluatePrototype(Prototype prototype) {
 | 
					    synchronized void evaluatePrototype(Prototype prototype, TypeInfo info) {
 | 
				
			||||||
        // System.err.println ("FESI EVALUATE PROTO "+prototype+" FOR "+this);
 | 
					        // System.err.println("EVALUATING PROTO: "+prototype);
 | 
				
			||||||
        Scriptable op = null;
 | 
					        Scriptable op = info.objectPrototype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // get the prototype's prototype if possible and necessary
 | 
					        // set the parent prototype in case it hasn't been done before
 | 
				
			||||||
        Scriptable opp = null;
 | 
					        // or it has changed...
 | 
				
			||||||
        Prototype parent = prototype.getParentPrototype();
 | 
					        setParentPrototype(prototype, op);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (parent != null) {
 | 
					 | 
				
			||||||
            // see if parent prototype is already registered. if not, register it
 | 
					 | 
				
			||||||
            opp = getPrototype(parent.getName());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (opp == null) {
 | 
					 | 
				
			||||||
                evaluatePrototype(parent);
 | 
					 | 
				
			||||||
                opp = getPrototype(parent.getName());
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        String name = prototype.getName();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name) &&
 | 
					 | 
				
			||||||
                (opp == null)) {
 | 
					 | 
				
			||||||
            if (app.isJavaPrototype(name)) {
 | 
					 | 
				
			||||||
                opp = null;
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                opp = getPrototype("hopobject");
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // if prototype doesn't exist (i.e. is a standard prototype built by HopExtension), create it.
 | 
					 | 
				
			||||||
        op = getPrototype(name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (op == null) {
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                op = new HopObject(name); // context.newObject (global /*, "HopObject" */);
 | 
					 | 
				
			||||||
                op.setPrototype(opp);
 | 
					 | 
				
			||||||
                op.setParentScope(global);
 | 
					 | 
				
			||||||
                op.put("prototypename", op, name);
 | 
					 | 
				
			||||||
            } catch (Exception ignore) {
 | 
					 | 
				
			||||||
                System.err.println("Error creating prototype: " + ignore);
 | 
					 | 
				
			||||||
                ignore.printStackTrace();
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            putPrototype(name, op);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            // reset prototype to original state
 | 
					 | 
				
			||||||
            resetPrototype(op);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            // set parent prototype just in case it has been changed
 | 
					 | 
				
			||||||
            op.setPrototype(opp);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // loop through the prototype's code elements and evaluate them
 | 
				
			||||||
 | 
					        // first the zipped ones ...
 | 
				
			||||||
        for (Iterator it = prototype.getZippedCode().values().iterator(); it.hasNext();) {
 | 
					        for (Iterator it = prototype.getZippedCode().values().iterator(); it.hasNext();) {
 | 
				
			||||||
            Object code = it.next();
 | 
					            Object code = it.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            evaluate(prototype, code);
 | 
					            evaluate(prototype, op, code);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // then the unzipped ones (this is to make sure unzipped code overwrites zipped code)
 | 
				
			||||||
        for (Iterator it = prototype.getCode().values().iterator(); it.hasNext();) {
 | 
					        for (Iterator it = prototype.getCode().values().iterator(); it.hasNext();) {
 | 
				
			||||||
            Object code = it.next();
 | 
					            Object code = it.next();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            evaluate(prototype, code);
 | 
					            evaluate(prototype, op, code);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // loop through function properties defined for this proto and
 | 
				
			||||||
 | 
					        // remove those which are left over from the previous generation
 | 
				
			||||||
 | 
					        // and haven't been renewed in this pass.
 | 
				
			||||||
 | 
					        Set oldFunctions = info.compiledFunctions;
 | 
				
			||||||
 | 
					        Set newFunctions = new HashSet();
 | 
				
			||||||
 | 
					        Object[] keys = ((ScriptableObject) op).getAllIds();
 | 
				
			||||||
 | 
					        for (int i = 0; i < keys.length; i++) {
 | 
				
			||||||
 | 
					            String key = keys[i].toString();
 | 
				
			||||||
 | 
					            if (info.predefinedProperties.contains(key)) {
 | 
				
			||||||
 | 
					                // don't mess with properties we didn't set
 | 
				
			||||||
 | 
					                continue;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            Object prop = op.get(key, op);
 | 
				
			||||||
 | 
					            if (oldFunctions.contains(prop) && prop instanceof NativeFunction) {
 | 
				
			||||||
 | 
					                // if this is a function compiled from script, it's from the
 | 
				
			||||||
 | 
					                // old generation and wasn't renewed -- delete it.
 | 
				
			||||||
 | 
					                System.err.println("DELETING OLD FUNC: "+key);
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    ((ScriptableObject) op).setAttributes(key, op, 0);
 | 
				
			||||||
 | 
					                    op.delete(key);
 | 
				
			||||||
 | 
					                } catch (PropertyException px) {
 | 
				
			||||||
 | 
					                    System.err.println("Error unsetting property "+key+" on "+prototype);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                newFunctions.add(prop);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        info.compiledFunctions = newFunctions;
 | 
				
			||||||
 | 
					        info.lastUpdate = prototype.getLastUpdate();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  Set the parent prototype on the ObjectPrototype.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     *  @param prototype the prototype spec
 | 
				
			||||||
 | 
					     *  @param op the prototype object
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void setParentPrototype(Prototype prototype, Scriptable op) {
 | 
				
			||||||
 | 
					        String name = prototype.getName();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!"global".equalsIgnoreCase(name) && !"hopobject".equalsIgnoreCase(name)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // get the prototype's prototype if possible and necessary
 | 
				
			||||||
 | 
					            Scriptable opp = null;
 | 
				
			||||||
 | 
					            Prototype parent = prototype.getParentPrototype();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (parent != null) {
 | 
				
			||||||
 | 
					                // see if parent prototype is already registered. if not, register it
 | 
				
			||||||
 | 
					                opp = getPrototype(parent.getName());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (opp == null && !app.isJavaPrototype(name)) {
 | 
				
			||||||
 | 
					                // FIXME: does this ever occur?
 | 
				
			||||||
 | 
					                opp = getPrototype("hopobject");
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            op.setPrototype(opp);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -271,40 +270,28 @@ public final class RhinoCore {
 | 
				
			||||||
     *  This is a version of org.mozilla.javascript.FunctionObject.addAsConstructor()
 | 
					     *  This is a version of org.mozilla.javascript.FunctionObject.addAsConstructor()
 | 
				
			||||||
     *  that does not set the constructor property in the prototype. This is because
 | 
					     *  that does not set the constructor property in the prototype. This is because
 | 
				
			||||||
     *  we want our own scripted constructor function to prevail, if it is defined.
 | 
					     *  we want our own scripted constructor function to prevail, if it is defined.
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param name the name of the constructor
 | 
				
			||||||
 | 
					     * @param op the object prototype
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    private void installConstructor(String name, Scriptable prototype) {
 | 
					    private void installConstructor(String name, Scriptable op) {
 | 
				
			||||||
        FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global);
 | 
					        FunctionObject fo = new FunctionObject(name, HopObject.hopObjCtor, global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ScriptRuntime.setFunctionProtoAndParent(global, fo);
 | 
					        ScriptRuntime.setFunctionProtoAndParent(global, fo);
 | 
				
			||||||
        fo.setImmunePrototypeProperty(prototype);
 | 
					        fo.setImmunePrototypeProperty(op);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        prototype.setParentScope(fo);
 | 
					        op.setParentScope(fo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        ScriptableObject.defineProperty(global, name, fo, ScriptableObject.DONTENUM);
 | 
					        ScriptableObject.defineProperty(global, name, fo, ScriptableObject.DONTENUM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fo.setParentScope(global);
 | 
					        fo.setParentScope(global);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     *  Return an object prototype to its initial state, removing all application specific
 | 
					 | 
				
			||||||
     *  functions.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    synchronized void resetPrototype(Scriptable op) {
 | 
					 | 
				
			||||||
        Object[] ids = op.getIds();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for (int i = 0; i < ids.length; i++) {
 | 
					 | 
				
			||||||
            /* String prop = en.nextElement ().toString ();
 | 
					 | 
				
			||||||
               try {
 | 
					 | 
				
			||||||
                   ESValue esv = op.getProperty (prop, prop.hashCode ());
 | 
					 | 
				
			||||||
                   if (esv instanceof ConstructedFunctionObject || esv instanceof FesiActionAdapter.ThrowException)
 | 
					 | 
				
			||||||
                       op.deleteProperty (prop, prop.hashCode());
 | 
					 | 
				
			||||||
               } catch (Exception x) {} */
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     *  This method is called before an execution context is entered to let the
 | 
					     *  This method is called before an execution context is entered to let the
 | 
				
			||||||
     *  engine know it should update its prototype information.
 | 
					     *  engine know it should update its prototype information. The update policy
 | 
				
			||||||
 | 
					     *  here is to check for update those prototypes which already have been compiled
 | 
				
			||||||
 | 
					     *  before. Others will be updated/compiled on demand.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    public synchronized void updatePrototypes() {
 | 
					    public synchronized void updatePrototypes() {
 | 
				
			||||||
        if ((System.currentTimeMillis() - lastUpdate) < 1000L) {
 | 
					        if ((System.currentTimeMillis() - lastUpdate) < 1000L) {
 | 
				
			||||||
| 
						 | 
					@ -334,8 +321,7 @@ public final class RhinoCore {
 | 
				
			||||||
                    app.typemgr.updatePrototype(p);
 | 
					                    app.typemgr.updatePrototype(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    if (p.getLastUpdate() > info.lastUpdate) {
 | 
					                    if (p.getLastUpdate() > info.lastUpdate) {
 | 
				
			||||||
                        evaluatePrototype(p);
 | 
					                        evaluatePrototype(p, info);
 | 
				
			||||||
                        info.lastUpdate = p.getLastUpdate();
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					@ -344,6 +330,64 @@ public final class RhinoCore {
 | 
				
			||||||
        lastUpdate = System.currentTimeMillis();
 | 
					        lastUpdate = System.currentTimeMillis();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Get a raw prototype, i.e. in potentially unfinished state
 | 
				
			||||||
 | 
					     * without checking if it needs to be updated.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private ScriptableObject getRawPrototype(String protoName) {
 | 
				
			||||||
 | 
					        if (protoName == null) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TypeInfo info = (TypeInfo) prototypes.get(protoName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (info == null) ? null : info.objectPrototype;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     *  Get the object prototype for a prototype name and initialize/update it
 | 
				
			||||||
 | 
					     *  if necessary. The policy here is to update the prototype only if it
 | 
				
			||||||
 | 
					     *  hasn't been updated before, otherwise we assume it already was updated
 | 
				
			||||||
 | 
					     *  by updatePrototypes(), which is called for each request.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    public Scriptable getPrototype(String protoName) {
 | 
				
			||||||
 | 
					        if (protoName == null) {
 | 
				
			||||||
 | 
					            return null;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TypeInfo info = (TypeInfo) prototypes.get(protoName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((info != null) && (info.lastUpdate == 0)) {
 | 
				
			||||||
 | 
					            Prototype p = app.typemgr.getPrototype(protoName);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (p != null) {
 | 
				
			||||||
 | 
					                app.typemgr.updatePrototype(p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (p.getLastUpdate() > info.lastUpdate) {
 | 
				
			||||||
 | 
					                    evaluatePrototype(p, info);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                // set info.lastUpdate to 1 if it is 0 so we know we
 | 
				
			||||||
 | 
					                // have initialized this prototype already, even if
 | 
				
			||||||
 | 
					                // it is empty (i.e. doesn't contain any scripts/skins/actions)
 | 
				
			||||||
 | 
					                if (info.lastUpdate == 0) {
 | 
				
			||||||
 | 
					                    info.lastUpdate = 1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return (info == null) ? null : info.objectPrototype;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Register an object prototype for a prototype name.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    private void putPrototype(String protoName, ScriptableObject op) {
 | 
				
			||||||
 | 
					        if ((protoName != null) && (op != null)) {
 | 
				
			||||||
 | 
					            prototypes.put(protoName, new TypeInfo(op, protoName));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Check if an object has a function property (public method if it
 | 
					     * Check if an object has a function property (public method if it
 | 
				
			||||||
     * is a java object) with that name.
 | 
					     * is a java object) with that name.
 | 
				
			||||||
| 
						 | 
					@ -375,7 +419,6 @@ public final class RhinoCore {
 | 
				
			||||||
     *  Convert an input argument from Java to the scripting runtime
 | 
					     *  Convert an input argument from Java to the scripting runtime
 | 
				
			||||||
     *  representation.
 | 
					     *  representation.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Object processXmlRpcArgument (Object what) throws Exception {
 | 
					    public Object processXmlRpcArgument (Object what) throws Exception {
 | 
				
			||||||
        if (what == null)
 | 
					        if (what == null)
 | 
				
			||||||
            return null;
 | 
					            return null;
 | 
				
			||||||
| 
						 | 
					@ -412,7 +455,6 @@ public final class RhinoCore {
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * convert a JavaScript Object object to a generic Java object stucture.
 | 
					     * convert a JavaScript Object object to a generic Java object stucture.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public Object processXmlRpcResponse (Object what) throws Exception {
 | 
					    public Object processXmlRpcResponse (Object what) throws Exception {
 | 
				
			||||||
        if (what instanceof NativeJavaObject) {
 | 
					        if (what instanceof NativeJavaObject) {
 | 
				
			||||||
            what = ((NativeJavaObject) what).unwrap();
 | 
					            what = ((NativeJavaObject) what).unwrap();
 | 
				
			||||||
| 
						 | 
					@ -454,51 +496,6 @@ public final class RhinoCore {
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return what;
 | 
					        return what;
 | 
				
			||||||
       /* if (what == null || what instanceof ESNull)
 | 
					 | 
				
			||||||
           return null;
 | 
					 | 
				
			||||||
       if (what instanceof ArrayPrototype) {
 | 
					 | 
				
			||||||
           ArrayPrototype a = (ArrayPrototype) what;
 | 
					 | 
				
			||||||
           int l = a.size ();
 | 
					 | 
				
			||||||
           Vector v = new Vector ();
 | 
					 | 
				
			||||||
           for (int i=0; i<l; i++) {
 | 
					 | 
				
			||||||
               Object nj = processXmlRpcResponse (a.getProperty (i));
 | 
					 | 
				
			||||||
               v.addElement (nj);
 | 
					 | 
				
			||||||
           }
 | 
					 | 
				
			||||||
           return v;
 | 
					 | 
				
			||||||
       }
 | 
					 | 
				
			||||||
       if (what instanceof ObjectPrototype) {
 | 
					 | 
				
			||||||
           ObjectPrototype o = (ObjectPrototype) what;
 | 
					 | 
				
			||||||
           Hashtable t = new Hashtable ();
 | 
					 | 
				
			||||||
           for (Enumeration e=o.getProperties (); e.hasMoreElements (); ) {
 | 
					 | 
				
			||||||
               String next = (String) e.nextElement ();
 | 
					 | 
				
			||||||
               // We don't do deep serialization of HopObjects to avoid
 | 
					 | 
				
			||||||
               // that the whole web site structure is sucked out with one
 | 
					 | 
				
			||||||
               // object. Instead we return some kind of "proxy" objects
 | 
					 | 
				
			||||||
               // that only contain the prototype and id of the HopObject property.
 | 
					 | 
				
			||||||
               Object nj = null;
 | 
					 | 
				
			||||||
               ESValue esv = o.getProperty (next, next.hashCode ());
 | 
					 | 
				
			||||||
               if (esv instanceof ESNode) {
 | 
					 | 
				
			||||||
                   INode node = ((ESNode) esv).getNode ();
 | 
					 | 
				
			||||||
                   if (node != null) {
 | 
					 | 
				
			||||||
                       Hashtable nt = new Hashtable ();
 | 
					 | 
				
			||||||
                       nt.put ("id", node.getID());
 | 
					 | 
				
			||||||
                       if (node.getPrototype() != null)
 | 
					 | 
				
			||||||
                           nt.put ("prototype", node.getPrototype ());
 | 
					 | 
				
			||||||
                       nj = nt;
 | 
					 | 
				
			||||||
                   }
 | 
					 | 
				
			||||||
               } else
 | 
					 | 
				
			||||||
                   nj = processXmlRpcResponse (esv);
 | 
					 | 
				
			||||||
               if (nj != null)  // can't put null as value in hashtable
 | 
					 | 
				
			||||||
                   t.put (next, nj);
 | 
					 | 
				
			||||||
           }
 | 
					 | 
				
			||||||
           return t;
 | 
					 | 
				
			||||||
       }
 | 
					 | 
				
			||||||
       if (what instanceof ESUndefined || what instanceof ESNull)
 | 
					 | 
				
			||||||
           return null;
 | 
					 | 
				
			||||||
       Object jval = what.toJavaObject ();
 | 
					 | 
				
			||||||
       if (jval instanceof Byte || jval instanceof Short)
 | 
					 | 
				
			||||||
           jval = new Integer (jval.toString ());
 | 
					 | 
				
			||||||
       return jval; */
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -509,63 +506,6 @@ public final class RhinoCore {
 | 
				
			||||||
        return app;
 | 
					        return app;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Get a raw prototype, i.e. in potentially unfinished state
 | 
					 | 
				
			||||||
     * without checking if it needs to be updated.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private Scriptable getRawPrototype(String protoName) {
 | 
					 | 
				
			||||||
        if (protoName == null) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        TypeInfo info = (TypeInfo) prototypes.get(protoName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (info == null) ? null : info.objectPrototype;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     *  Get the object prototype for a prototype name and initialize/update it
 | 
					 | 
				
			||||||
     *  if necessary.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    public Scriptable getPrototype(String protoName) {
 | 
					 | 
				
			||||||
        if (protoName == null) {
 | 
					 | 
				
			||||||
            return null;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        TypeInfo info = (TypeInfo) prototypes.get(protoName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ((info != null) && (info.lastUpdate == 0)) {
 | 
					 | 
				
			||||||
            Prototype p = app.typemgr.getPrototype(protoName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (p != null) {
 | 
					 | 
				
			||||||
                app.typemgr.updatePrototype(p);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if (p.getLastUpdate() > info.lastUpdate) {
 | 
					 | 
				
			||||||
                    info.lastUpdate = p.getLastUpdate();
 | 
					 | 
				
			||||||
                    evaluatePrototype(p);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // set info.lastUpdate to 1 if it is 0 so we know we 
 | 
					 | 
				
			||||||
                // have initialized this prototype already, even if 
 | 
					 | 
				
			||||||
                // it is empty (i.e. doesn't contain any scripts/skins/actoins
 | 
					 | 
				
			||||||
                if (info.lastUpdate == 0) {
 | 
					 | 
				
			||||||
                    info.lastUpdate = 1;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        return (info == null) ? null : info.objectPrototype;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /**
 | 
					 | 
				
			||||||
     * Register an object prototype for a certain prototype name.
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    private void putPrototype(String protoName, Scriptable op) {
 | 
					 | 
				
			||||||
        if ((protoName != null) && (op != null)) {
 | 
					 | 
				
			||||||
            prototypes.put(protoName, new TypeInfo(op, protoName));
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     *  Get a Script wrapper for any given object. If the object implements the IPathElement
 | 
					     *  Get a Script wrapper for any given object. If the object implements the IPathElement
 | 
				
			||||||
| 
						 | 
					@ -645,44 +585,9 @@ public final class RhinoCore {
 | 
				
			||||||
        return esn;
 | 
					        return esn;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /////////////////////////////////////////////
 | 
				
			||||||
     *  Register a new Node wrapper with the wrapper cache. This is used by the
 | 
					    // skin related methods
 | 
				
			||||||
     * Node constructor.
 | 
					    /////////////////////////////////////////////
 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    /* public void putNodeWrapper(INode n, Scriptable esn) {
 | 
					 | 
				
			||||||
        wrappercache.put(n, esn);
 | 
					 | 
				
			||||||
    } */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    private synchronized void evaluate(Prototype prototype, Object code) {
 | 
					 | 
				
			||||||
        if (code instanceof FunctionFile) {
 | 
					 | 
				
			||||||
            FunctionFile funcfile = (FunctionFile) code;
 | 
					 | 
				
			||||||
            File file = funcfile.getFile();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (file != null) {
 | 
					 | 
				
			||||||
                try {
 | 
					 | 
				
			||||||
                    FileReader fr = new FileReader(file);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    updateEvaluator(prototype, fr, funcfile.getSourceName(), 1);
 | 
					 | 
				
			||||||
                } catch (IOException iox) {
 | 
					 | 
				
			||||||
                    app.logEvent("Error updating function file: " + iox);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                StringReader reader = new StringReader(funcfile.getContent());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                updateEvaluator(prototype, reader, funcfile.getSourceName(), 1);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else if (code instanceof ActionFile) {
 | 
					 | 
				
			||||||
            ActionFile action = (ActionFile) code;
 | 
					 | 
				
			||||||
            RhinoActionAdapter fa = new RhinoActionAdapter(action);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            try {
 | 
					 | 
				
			||||||
                updateEvaluator(prototype, new StringReader(fa.function),
 | 
					 | 
				
			||||||
                                action.getSourceName(), 0);
 | 
					 | 
				
			||||||
            } catch (Exception esx) {
 | 
					 | 
				
			||||||
                app.logEvent("Error parsing " + action + ": " + esx);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected static Object[] unwrapSkinpath(Object[] skinpath) {
 | 
					    protected static Object[] unwrapSkinpath(Object[] skinpath) {
 | 
				
			||||||
        if (skinpath != null) {
 | 
					        if (skinpath != null) {
 | 
				
			||||||
| 
						 | 
					@ -721,25 +626,64 @@ public final class RhinoCore {
 | 
				
			||||||
        return param;
 | 
					        return param;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private synchronized void updateEvaluator(Prototype prototype, Reader reader,
 | 
					    ////////////////////////////////////////////////
 | 
				
			||||||
                                              String sourceName, int firstline) {
 | 
					    // private evaluation/compilation methods
 | 
				
			||||||
        // context = Context.enter(context);
 | 
					    ////////////////////////////////////////////////
 | 
				
			||||||
        try {
 | 
					 | 
				
			||||||
            Scriptable op = getPrototype(prototype.getName());
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private synchronized void evaluate(Prototype prototype, Scriptable op, Object code) {
 | 
				
			||||||
 | 
					        if (code instanceof FunctionFile) {
 | 
				
			||||||
 | 
					            FunctionFile funcfile = (FunctionFile) code;
 | 
				
			||||||
 | 
					            File file = funcfile.getFile();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (file != null) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    FileReader fr = new FileReader(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    updateEvaluator(prototype, op, fr, funcfile.getSourceName(), 1);
 | 
				
			||||||
 | 
					                } catch (IOException iox) {
 | 
				
			||||||
 | 
					                    app.logEvent("Error updating function file: " + iox);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                StringReader reader = new StringReader(funcfile.getContent());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                updateEvaluator(prototype, op, reader, funcfile.getSourceName(), 1);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        } else if (code instanceof ActionFile) {
 | 
				
			||||||
 | 
					            ActionFile action = (ActionFile) code;
 | 
				
			||||||
 | 
					            RhinoActionAdapter fa = new RhinoActionAdapter(action);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                updateEvaluator(prototype, op, new StringReader(fa.function),
 | 
				
			||||||
 | 
					                                action.getSourceName(), 0);
 | 
				
			||||||
 | 
					            } catch (Exception esx) {
 | 
				
			||||||
 | 
					                app.logEvent("Error parsing " + action + ": " + esx);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private synchronized void updateEvaluator(Prototype prototype, Scriptable op,
 | 
				
			||||||
 | 
					                                        Reader reader, String sourceName, int firstline) {
 | 
				
			||||||
 | 
					        // System.err.println("UPDATE EVALUATOR: "+prototype+" - "+sourceName);
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
            // get the current context
 | 
					            // get the current context
 | 
				
			||||||
            Context cx = Context.getCurrentContext();
 | 
					            Context cx = Context.getCurrentContext();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // do the update, evaluating the file
 | 
					            // do the update, evaluating the file
 | 
				
			||||||
            cx.evaluateReader(op, reader, sourceName, firstline, null);
 | 
					            cx.evaluateReader(op, reader, sourceName, firstline, null);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        } catch (Throwable e) {
 | 
					        } catch (Throwable e) {
 | 
				
			||||||
            app.logEvent("Error parsing function file " + sourceName + ": " + e);
 | 
					            app.logEvent("Error parsing file " + sourceName + ": " + e);
 | 
				
			||||||
 | 
					            // also write to standard out unless we're logging to it anyway
 | 
				
			||||||
 | 
					            if (!"console".equalsIgnoreCase(app.getProperty("logDir"))) {
 | 
				
			||||||
 | 
					                System.err.println("Error parsing file " + sourceName + ": " + e);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            // e.printStackTrace();
 | 
					            // e.printStackTrace();
 | 
				
			||||||
        } finally {
 | 
					        } finally {
 | 
				
			||||||
            if (reader != null) {
 | 
					            if (reader != null) {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    reader.close();
 | 
					                    reader.close();
 | 
				
			||||||
                } catch (IOException ignore) {
 | 
					                } catch (IOException ignore) {
 | 
				
			||||||
 | 
					                    // shouldn't happen
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					@ -756,13 +700,27 @@ public final class RhinoCore {
 | 
				
			||||||
     *  TypeInfo helper class
 | 
					     *  TypeInfo helper class
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    class TypeInfo {
 | 
					    class TypeInfo {
 | 
				
			||||||
        Scriptable objectPrototype;
 | 
					        // the object prototype for this type
 | 
				
			||||||
 | 
					        ScriptableObject objectPrototype;
 | 
				
			||||||
 | 
					        // timestamp of last update
 | 
				
			||||||
        long lastUpdate = 0;
 | 
					        long lastUpdate = 0;
 | 
				
			||||||
 | 
					        // the prototype name
 | 
				
			||||||
        String protoName;
 | 
					        String protoName;
 | 
				
			||||||
 | 
					        // a set of property values that were defined in last script compliation
 | 
				
			||||||
 | 
					        Set compiledFunctions;
 | 
				
			||||||
 | 
					        // a set of property keys that were present before first script compilation
 | 
				
			||||||
 | 
					        final Set predefinedProperties;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public TypeInfo(Scriptable op, String name) {
 | 
					        public TypeInfo(ScriptableObject op, String name) {
 | 
				
			||||||
            objectPrototype = op;
 | 
					            objectPrototype = op;
 | 
				
			||||||
            protoName = name;
 | 
					            protoName = name;
 | 
				
			||||||
 | 
					            compiledFunctions = new HashSet(0);
 | 
				
			||||||
 | 
					            // remember properties already defined on this object prototype
 | 
				
			||||||
 | 
					            predefinedProperties = new HashSet();
 | 
				
			||||||
 | 
					            Object[] keys = op.getAllIds();
 | 
				
			||||||
 | 
					            for (int i = 0; i < keys.length; i++) {
 | 
				
			||||||
 | 
					                predefinedProperties.add(keys[i].toString());
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        public String toString() {
 | 
					        public String toString() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue