Skin skin = getSkin ((ESNode) sobj, sname);
Skin skin = getSkin ((ESObject) sobj, sname);  Object obj = sobj == null ? null : sobj.toJavaObject ();
    public void run () {        int txcount = 0;        // first, set a local variable to the current transactor thread so we know        // when it's time to quit because another thread took over.        Transactor localrtx = (Transactor) Thread.currentThread ();        try {	do {	    // long startCheck = System.currentTimeMillis ();	    app.typemgr.checkPrototypes ();	    // evaluators are only initialized as needed, so we need to check that here	    if (!initialized)	        app.typemgr.initRequestEvaluator (this);	    // System.err.println ("Type check overhead: "+(System.currentTimeMillis ()-startCheck)+" millis");		    // object refs to ressolve request path	    Object root, currentElement;		    // reset skinManager	    skinmanagers = null;	    skincache.clear ();	    switch (reqtype) {	    case HTTP:	        int tries = 0;	        boolean done = false;	        String error = null;	        while (!done) {	            current = null;	            currentElement = null;	            reqPath.setSize (0);	            // delete path objects-via-prototype	            for (Enumeration en=reqPath.getAllProperties(); en.hasMoreElements(); ) {	                String pn = (String) en.nextElement ();	                if (!"length".equalsIgnoreCase (pn)) try {	                    reqPath.deleteProperty (pn, pn.hashCode ());	                } catch (Exception ignore) {}	            }		            try {	                String requestPath = app.getName()+"/"+req.path;	                // set Timer to get some profiling data	                localrtx.timer.reset ();	                localrtx.timer.beginEvent (requestPath+" init");	                localrtx.begin (requestPath);	                Action action = null;	                root = app.getDataRoot ();	                ESUser esu = (ESUser) getNodeWrapper (user);	                // esu.setUser (user);	                global.putHiddenProperty ("root", getElementWrapper (root));	                global.putHiddenProperty("user", esu);	                global.putHiddenProperty ("req", new ESWrapper (req, evaluator));	                global.putHiddenProperty ("res", new ESWrapper (res, evaluator));	                if (error != null)	                    res.error = error;	                if (user.message != null) {	                    // bring over the message from a redirect	                    res.message = user.message;	                    user.message = null;	                }	                global.putHiddenProperty ("path", reqPath);	                global.putHiddenProperty ("app", appnode);	                // set and mount the request data object	                reqData.setData (req.getReqData());	                req.data = reqData;	                try {	                    if (error != null) {	                        // there was an error in the previous loop, call error handler	                        currentElement = root;	                        current = getElementWrapper (root);	                        reqPath.putProperty (0, current);	                        reqPath.putHiddenProperty ("root", current);	                        Prototype p = app.getPrototype (root);	                        String errorAction = app.props.getProperty ("error", "error");	                        action = p.getActionOrTemplate (errorAction);	                        if (action == null)	                            throw new RuntimeException (error);		                    } else if (req.path == null || "".equals (req.path.trim ())) {	                        currentElement = root;	                        current = getElementWrapper (root);	                        reqPath.putProperty (0, current);	                        reqPath.putHiddenProperty ("root", current);	                        Prototype p = app.getPrototype (root);	                        action = p.getActionOrTemplate (null);	                        if (action == null)	                            throw new FrameworkException ("Action not found");	                    } else {	                        // march down request path...		                        StringTokenizer st = new StringTokenizer (req.path, "/");	                        int ntokens = st.countTokens ();	                        // limit path to < 50 tokens	                        if (ntokens > 50)	                            throw new RuntimeException ("Path too long");	                        String[] pathItems = new String [ntokens];	                        for (int i=0; i<ntokens; i++)	                              pathItems[i] = st.nextToken ();		                        currentElement = root;	                        current = getElementWrapper (root);	                        reqPath.putProperty (0, current);	                        reqPath.putHiddenProperty ("root", current);	                        for (int i=0; i<ntokens; i++) {		                            if (currentElement == null)	                                throw new FrameworkException ("Object not found.");		                            // the first token in the path needs to be treated seprerately,	                            // because "/user" is a shortcut to the current user session, while "/users"	                            // is the mounting point for all users.	                            if (i == 0 && "user".equalsIgnoreCase (pathItems[i])) {	                                currentElement = user.getNode ();	                                if (currentElement != null) {	                                    current = getElementWrapper (currentElement);	                                    reqPath.putProperty (1, current);	                                    reqPath.putHiddenProperty ("user", current);	                                }		                            } else if (i == 0 && "users".equalsIgnoreCase (pathItems[i])) {	                                currentElement = app.getUserRoot ();	                                if (currentElement != null) {	                                    current = getElementWrapper (currentElement);	                                    reqPath.putProperty (1, current);	                                }		                            } else {	                                if (i == ntokens-1) {	                                    Prototype p = app.getPrototype (currentElement);	                                    if (p != null)	                                        action = p.getActionOrTemplate (pathItems[i]);	                                }		                                if (action == null) {		                                    if (pathItems[i].length () == 0)	                                        continue;		                                    currentElement = app.getChildElement (currentElement, pathItems[i]);	                                    // add object to request path if suitable	                                    if (currentElement != null) {	                                        // add to reqPath array	                                        current = getElementWrapper (currentElement);	                                        reqPath.putProperty (reqPath.size(), current);	                                        String pt = app.getPrototypeName (currentElement);	                                        if (pt != null) {	                                            // if a prototype exists, add also by prototype name	                                            reqPath.putHiddenProperty (pt, current);	                                        }	                                    }	                                }	                            }	                        }	                        if (currentElement == null)	                            throw new FrameworkException ("Object not found.");	                        else	                            current = getElementWrapper (currentElement);	                        if (action == null) {	                            Prototype p = app.getPrototype (currentElement);	                            if (p != null)	                                action = p.getActionOrTemplate (null);	                        }	                        if (action == null)	                            throw new FrameworkException ("Action not found");	                    }		                } catch (FrameworkException notfound) {	                    if (error != null)	                        // we already have an error and the error template wasn't found,	                        // display it instead of notfound message	                        throw new RuntimeException ();	                    // The path could not be resolved. Check if there is a "not found" action	                    // specified in the property file.	                    res.status = 404;	                    String notFoundAction = app.props.getProperty ("notFound", "notfound");	                    Prototype p = app.getPrototype (root);	                    action = p.getActionOrTemplate (notFoundAction);	                    if (action == null)	                        throw new FrameworkException (notfound.getMessage ());	                    current = getElementWrapper (root);	                }	                localrtx.timer.endEvent (requestPath+" init");	                try {	                    localrtx.timer.beginEvent (requestPath+" execute");	                    current.doIndirectCall (evaluator, current, action.getFunctionName (), new ESValue[0]);		                    // check if the script set the name of a skin to render in res.skin	                    if (res.skin != null) {	                        int dot = res.skin.indexOf (".");	                        ESValue sobj = null;	                        String sname = res.skin;	                        if (dot > -1) {	                            String soname = res.skin.substring (0, dot);	                            sobj = reqPath.getProperty (soname, soname.hashCode ());	                            if (sobj == null || sobj == ESUndefined.theUndefined)	                                throw new RuntimeException ("Skin "+res.skin+" not found in path.");	                            sname = res.skin.substring (dot+1);	                        }	                        Skin skin = getSkin ((ESNode) sobj, sname);	                        if (skin != null)	                            skin.render (this, (ESNode) sobj, null);	                        else	                            throw new RuntimeException ("Skin "+res.skin+" not found in path.");	                    }		                    localrtx.timer.endEvent (requestPath+" execute");	                } catch (RedirectException redirect) {	                    // res.redirect = redirect.getMessage ();	                    // if there is a message set, save it on the user object for the next request	                    if (res.message != null)	                        user.message = res.message;	                    done = true;	                }	                // check if we're still the one and only or if the waiting thread has given up on us already	                commitTransaction ();	                done = true;	            } catch (ConcurrencyException x) {	                res.reset ();	                if (++tries < 5) {	                    // try again after waiting some period	                    abortTransaction (true);	                    try {	                        // wait a bit longer with each try	                        int base = 500 * tries;	                        Thread.currentThread ().sleep ((long) (base + Math.random ()*base*2));	                    } catch (Exception ignore) {}	                    continue;	                } else {	                    abortTransaction (false);	                    if (error == null) {	                        app.errorCount += 1;	                        error = "Couldn't complete transaction due to heavy object traffic (tried "+tries+" times)";	                    } else {	                        // error in error action. use traditional minimal error message	                        res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>"+error+"</pre>");	                        done = true;	                    }	                }	            } catch (Exception x) {	                abortTransaction (false);	                app.logEvent ("### Exception in "+app.getName()+"/"+req.path+": "+x);	                // Dump the profiling data to System.err	                if (app.debug) {	                    ((Transactor) Thread.currentThread ()).timer.dump (System.err);	                    x.printStackTrace ();	                }	                // If the transactor thread has been killed by the invoker thread we don't have to	                // bother for the error message, just quit.	                if (localrtx != rtx)	                    break;	                res.reset ();	                if (error == null) {	                    app.errorCount += 1;	                    error = x.getMessage ();	                    if (error == null || error.length() == 0)	                        error = x.toString ();	                } else {	                    // error in error action. use traditional minimal error message	                    res.write ("<b>Error in application '"+app.getName()+"':</b> <br><br><pre>"+error+"</pre>");	                    done = true;	                }	            }	        }	        break;	    case XMLRPC:	        try {	            localrtx.begin (app.getName()+":xmlrpc/"+method);	            root = app.getDataRoot ();	            global.putHiddenProperty ("root", getElementWrapper (root));	            global.deleteProperty("user", "user".hashCode());	            global.deleteProperty ("req", "req".hashCode());	            global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator));	            global.deleteProperty ("path", "path".hashCode());	            global.putHiddenProperty ("app", appnode);	            // convert arguments	            int l = args.size ();	            current = getElementWrapper (root);	            if (method.indexOf (".") > -1) {	                StringTokenizer st = new StringTokenizer (method, ".");	                int cnt = st.countTokens ();	                for (int i=1; i<cnt; i++) {	                    String next = st.nextToken ();	                    try {	                        current = (ESObject) current.getProperty (next, next.hashCode ());	                    } catch (Exception x) {	                        throw new EcmaScriptException ("The property \""+next+"\" is not defined in the remote object.");	                    }	                }	                if (current == null)	                    throw new EcmaScriptException ("Method name \""+method+"\" could not be resolved.");	                method = st.nextToken ();	            }	            // check XML-RPC access permissions	            String proto = ((ESNode) current).getNode().getPrototype ();	            app.checkXmlRpcAccess (proto, method);	            ESValue esa[] = new ESValue[l];	            for (int i=0; i<l; i++) {    	                esa[i] = FesiRpcUtil.convertJ2E (args.elementAt (i), evaluator);	            }		            result = FesiRpcUtil.convertE2J (current.doIndirectCall (evaluator, current, method, esa));	            commitTransaction ();	        } catch (Exception wrong) {	            abortTransaction (false);	            // If the transactor thread has been killed by the invoker thread we don't have to	            // bother for the error message, just quit.	            if (localrtx != rtx) {	                return;	            }	            this.exception = wrong;	        }	        break;	    case INTERNAL:	        esresult = ESNull.theNull;	        // Just a human readable descriptor of this invocation	        String funcdesc = app.getName()+":internal/"+method;		        // avoid going into transaction if called function doesn't exist	        boolean functionexists = true;	        if (current != null) try {	            functionexists = global.getProperty (method, method.hashCode()) != ESUndefined.theUndefined;	        } catch (EcmaScriptException x) {}		        if (!functionexists)	            // global function doesn't exist, nothing to do here.	            reqtype = NONE;	        else try {	            localrtx.begin (funcdesc);	            root = app.getDataRoot ();	            global.putHiddenProperty ("root", getElementWrapper (root));	            global.deleteProperty("user", "user".hashCode());	            global.deleteProperty ("req", "req".hashCode());	            global.putHiddenProperty ("res", ESLoader.normalizeValue(res, evaluator));	            global.deleteProperty ("path", "path".hashCode());	            global.putHiddenProperty ("app", appnode);                         if (current == null) {	                if (user == null) {	                    current = global;	                } else {	                    ESUser esu = (ESUser) getNodeWrapper (user);	                    // esu.setUser (user);	                    current = esu;	                }	            }	            // call internal functions only if they're specified	            if (current.getProperty (method, method.hashCode()) != ESUndefined.theUndefined)	                esresult = current.doIndirectCall (evaluator, current, method, new ESValue[0]);	            commitTransaction ();	        } catch (Throwable wrong) {	            abortTransaction (false);	            // If the transactor thread has been killed by the invoker thread we don't have to	            // bother for the error message, just quit.	            if (localrtx != rtx) {	                return;	            }	            String msg = wrong.getMessage ();	            if (msg == null || msg.length () == 0)	                msg = wrong.toString ();	            app.logEvent ("Error executing "+funcdesc+": "+msg);	            if (app.debug)	                wrong.printStackTrace ();	            this.exception = new Exception (msg);	        }	        break;	    }	    // make sure there is only one thread running per instance of this class	    // if localrtx != rtx, the current thread has been aborted and there's no need to notify	    if (localrtx != rtx) {	        localrtx.closeConnections ();	        return;	    }	    notifyAndWait ();            }  while (localrtx == rtx);        } finally {            localrtx.closeConnections ();        }    }