typemgr.updatePrototype("root"); typemgr.updatePrototype("global");   RequestEvaluator eval = getEvaluator(); try { eval.invokeInternal(null, "onStart", new Object[0]); } catch (Exception ignore) { logEvent("Error in " + name + "/onStart(): " + ignore); } finally { if (!stopped) { releaseEvaluator(eval); } }
    public void run() {        // interval between session cleanups        long sessionCleanupInterval = 60000;        long lastSessionCleanup = System.currentTimeMillis();        // logEvent ("Starting scheduler for "+name);        // read in standard prototypes to make first request go faster        typemgr.updatePrototype("root");        typemgr.updatePrototype("global");        // as first thing, invoke function onStart in the root object        RequestEvaluator eval = getEvaluator();        try {            eval.invokeInternal(null, "onStart", new Object[0]);        } catch (Exception ignore) {            logEvent("Error in " + name + "/onStart(): " + ignore);        } finally {            if (!stopped) {                releaseEvaluator(eval);            }        }        // loop-local cron job data        List cronJobs = null;        long lastCronParse = 0;        while (Thread.currentThread() == worker) {            long now = System.currentTimeMillis();            // check if we should clean up user sessions            if ((now - lastSessionCleanup) > sessionCleanupInterval) {                lastSessionCleanup = now;                // get session timeout                int sessionTimeout = 30;                try {                    sessionTimeout = Math.max(0,                            Integer.parseInt(props.getProperty("sessionTimeout",                                                               "30")));                } catch (Exception ignore) {}                try {                    Hashtable cloned = (Hashtable) sessions.clone();                    for (Enumeration e = cloned.elements(); e.hasMoreElements();) {                        Session session = (Session) e.nextElement();                        if ((now - session.lastTouched()) > (sessionTimeout * 60000)) {                            NodeHandle userhandle = session.userHandle;                            if (userhandle != null) {                                try {                                    Object[] param = { session.getSessionID() };                                    eval.invokeInternal(userhandle, "onLogout", param);                                } catch (Exception ignore) {                                }                            }                            destroySession(session);                        }                    }                } catch (Exception cx) {                    logEvent("Error cleaning up sessions: " + cx);                    cx.printStackTrace();                }            }            if ((cronJobs == null) || (props.lastModified() > lastCronParse)) {                updateProperties();                cronJobs = CronJob.parse(props);                lastCronParse = props.lastModified();            }            Date d = new Date();            List jobs = new ArrayList(cronJobs);            jobs.addAll(customCronJobs.values());            CronJob.sort(jobs);            for (Iterator i = jobs.iterator(); i.hasNext();) {                CronJob j = (CronJob) i.next();                if (j.appliesToDate(d)) {                    // check if the job is already active ...                    if (activeCronJobs.containsKey(j.getName())) {                        logEvent(j + " is still active, skipped in this minute");                        continue;                    }                    RequestEvaluator thisEvaluator;                    try {                        thisEvaluator = getEvaluator();                    } catch (RuntimeException rt) {                        if (!stopped) {                            logEvent("couldn't execute " + j +                                     ", maximum thread count reached");                            continue;                        } else {                            break;                        }                    }                    // if the job has a long timeout or we're already late during this minute                    // the job is run from an extra thread                    if ((j.getTimeout() > 20000) ||                            (CronJob.millisToNextFullMinute() < 30000)) {                        CronRunner r = new CronRunner(thisEvaluator, j);                        activeCronJobs.put(j.getName(), r);                        r.start();                    } else {                        try {                            thisEvaluator.invokeInternal(null, j.getFunction(),                                                         new Object[0], j.getTimeout());                        } catch (Exception ex) {                            logEvent("error running " + j + ": " + ex.toString());                        } finally {                            if (!stopped) {                                releaseEvaluator(thisEvaluator);                            }                        }                    }                }            }            long sleepInterval = CronJob.millisToNextFullMinute();            try {                String sleepProp = props.getProperty("schedulerInterval");                if (sleepProp != null) {                    sleepInterval = Math.max(1000, Integer.parseInt(sleepProp)*1000);                }            } catch (Exception ignore) {}            // sleep until the next full minute            try {                Thread.sleep(sleepInterval);            } catch (InterruptedException x) {                worker = null;                break;            }        }        // when interrupted, shutdown running cron jobs        synchronized (activeCronJobs) {            for (Iterator i = activeCronJobs.keySet().iterator(); i.hasNext();) {                String jobname = (String) i.next();                ((CronRunner) activeCronJobs.get(jobname)).interrupt();                activeCronJobs.remove(jobname);            }        }        logEvent("Scheduler for " + name + " exiting");    }