package org.atomnuke; import java.util.UUID; import org.atomnuke.kernel.GenericKernelDelegate; import org.atomnuke.kernel.shutdown.ShutdownHook; import org.atomnuke.plugin.InstanceContext; import org.atomnuke.plugin.context.InstanceContextImpl; import org.atomnuke.source.AtomSource; import org.atomnuke.task.atom.AtomTask; import org.atomnuke.util.TimeValue; import org.atomnuke.lifecycle.InitializationException; import org.atomnuke.lifecycle.Reclaimable; import org.atomnuke.plugin.env.LocalInstanceEnvironment; import org.atomnuke.service.introspection.ServicesInterrogator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * @author zinic */ public abstract class AbstractNukeImpl implements Nuke { private static final Logger LOG = LoggerFactory.getLogger(AbstractNukeImpl.class); private static final long MAX_WAIT_TIME_FOR_SHUTDOWN = 15000; private final GenericKernelDelegate kernelDelegate; private final NukeEnvironment nukeEnvironment; private final ShutdownHook kernelShutdownHook; private final Thread controlThread; public AbstractNukeImpl(NukeEnvironment nukeEnvironment, ShutdownHook kernelShutdownHook, GenericKernelDelegate kernelDelegate) { this.nukeEnvironment = nukeEnvironment; this.kernelShutdownHook = kernelShutdownHook; this.kernelDelegate = kernelDelegate; this.controlThread = new Thread(kernelDelegate, "nuke-kernel-" + UUID.randomUUID().toString()); } @Override public NukeEnvironment nukeEnvironment() { return nukeEnvironment; } @Override public ShutdownHook shutdownHook() { return kernelShutdownHook; } /** * Helper method for following a given source at a defined polling interval. * This has the same effect as calling follow on the Tasker interface.This * calls the follow method by wrapping the given AtomSource in a * SimpleInstanceContext. * * @param source the AtomSource to be scheduled. * @param pollingInterval the desired polling interval for the source. * @return a new task instance for further interaction with the newly * scheduled source. * @throws InitializationException thrown when initializing the source fails * wit the current task context. */ public AtomTask follow(AtomSource source, TimeValue pollingInterval) { return follow(new InstanceContextImpl<AtomSource>(LocalInstanceEnvironment.getInstance(), source), pollingInterval); } /** * Helper method for following a given source at a defined polling interval. * This has the same effect as calling follow on the Tasker interface. * * @param source the instance context of the AtomSource to be scheduled. * @param pollingInterval the desired polling interval for the source. * @return a new task instance for further interaction with the newly * scheduled source. * @throws InitializationException thrown when initializing the source fails * wit the current task context. */ public AtomTask follow(InstanceContext<AtomSource> source, TimeValue pollingInterval) { return atomTasker().follow(source, pollingInterval); } @Override public void start() { if (controlThread.getState() != Thread.State.NEW) { throw new IllegalStateException("Crawler already started or destroyed."); } kernelShutdownHook.enlist(new Reclaimable() { @Override public void destroy() { kernelDelegate.cancellationRemote().cancel(); kernelDelegate.taskManager().destroy(); try { controlThread.join(MAX_WAIT_TIME_FOR_SHUTDOWN); } catch (InterruptedException ie) { LOG.info("Nuke kernel interrupted while shutting down. Killing thread now.", ie); controlThread.interrupt(); } } }); LOG.info("Nuke kernel: " + toString() + " starting."); controlThread.start(); } @Override public void destroy() { kernelShutdownHook.shutdown(); } }