package org.openntf.domino.xots; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.concurrent.TimeUnit; import org.openntf.domino.thread.AbstractDominoExecutor; import org.openntf.domino.thread.AbstractDominoExecutor.DominoFutureTask; import org.openntf.domino.thread.XotsExecutorService; import org.openntf.domino.utils.Factory; /* * This class and package is intended to become the space for the XPages implementation * of IBM's DOTS. Except it will use modern thread management instead of acting like it was * written in Java 1.1 */ public class Xots { ; public static Comparator<DominoFutureTask<?>> TASKS_BY_ID = new Comparator<DominoFutureTask<?>>() { @Override public int compare(final DominoFutureTask<?> o1, final DominoFutureTask<?> o2) { if (o1.sequenceNumber < o2.sequenceNumber) { return -1; } else if (o1.sequenceNumber == o2.sequenceNumber) { return 0; } else { return 1; } } }; //private Set<TaskletDefinition> tasklets_ = new HashSet<TaskletDefinition>(); // This is our Threadpool that will execute all Runnables private static AbstractDominoExecutor executor_; // public void addListener(final IDominoListener listener) { // executor_.addListener(listener); // } // // public IDominoListener removeListener(final IDominoListener listener) { // return executor_.removeListener(listener); // } private Xots() { super(); } public static XotsExecutorService getService() { if (!isStarted()) { throw new IllegalStateException("Xots is not started"); } return executor_; } public static List<DominoFutureTask<?>> getTasks(final Comparator<DominoFutureTask<?>> comparator) { if (!isStarted()) return Collections.emptyList(); return executor_.getTasks(comparator); } /** * Start the XOTS with the given Executor */ public static synchronized void start(final AbstractDominoExecutor executor) throws IllegalStateException { if (isStarted()) throw new IllegalStateException("XotsDaemon is already started"); Factory.println(Xots.class, "Starting XPages OSGi Tasklet Service with " + executor.getCorePoolSize() + " core threads."); executor_ = executor; } /** * Tests if the XotsDaemon is started * */ public static synchronized boolean isStarted() { return executor_ != null; } public static synchronized void stop(int wait) { if (isStarted()) { Factory.println(Xots.class, "Stopping XPages OSGi Tasklet Service..."); executor_.shutdown(); long running; try { while ((running = executor_.getActiveCount()) > 0 && wait-- > 0) { Factory.println(Xots.class, "There are " + running + " tasks running... waiting " + wait + " seconds."); Thread.sleep(1000); } } catch (InterruptedException e) { } if (executor_.getActiveCount() > 0) { Factory.println(Xots.class, "he following Threads did not terminate gracefully:"); for (DominoFutureTask<?> task : executor_.getTasks(null)) { Factory.println(Xots.class, "* " + task); } } try { for (int i = 60; i > 0; i -= 10) { if (executor_.getActiveCount() > 0) { Factory.println(Xots.class, "Trying to interrupt them and waiting again " + i + " seconds."); executor_.shutdownNow(); } if (executor_.awaitTermination(10, TimeUnit.SECONDS)) { executor_ = null; Factory.println(Xots.class, " XPages OSGi Tasklet Service stopped."); return; } } } catch (InterruptedException e) { } Factory.println(Xots.class, "WARNING: Could not stop XPages OSGi Tasklet Service!"); } else { Factory.println(Xots.class, " XPages OSGi Tasklet Service not running"); } } // // // ---- delegate methods // ///** // * Registers a new tasklet for periodic execution // * @param moduleName // * the ModuleName (i.e. DatabaseName) // * @param className // * the ClassName. (Must be annotated with {@link XotsTasklet // * @param onEvent // * String array with events // * @return // */ // public static Future<?> registerTasklet(final String moduleName, final String className, final String... cron) { // return executor_.registerTasklet(moduleName, className, cron); // // } }