case STOPPED :
return;
case STOPPING :
if (waitForStateChangeEx() != ServiceState.STOPPED)
throw new ServiceOperationException("stop operation in other thread failed");
return;
case STOP_FAILED :
throw new ServiceOperationException("previous stop operation failed");
case STARTING :
waitForStateChangeEx();
break;
case RUNNING :
int newRefCount = decrementRefCount();
if (newRefCount > 0)
return;
changeState(ServiceState.STOPPING);
done = true;
break;
}
}
// wait supplied grace period, then interrupt any threads working in the service
if (!serviceThreads.isEmpty())
{
// wait for threads to drain. < 0 means wait forever, 0 means don't wait, > 0 means number
// of milliseconds to wait
long now = System.currentTimeMillis();
long drainEnd = gracePeriod < 0 ? Long.MAX_VALUE : now + gracePeriod;
while (!serviceThreads.isEmpty() && (now < drainEnd))
{
try {
if (log.isDebugEnabled())
log.debug(logId + ": waiting " + (drainEnd - now) + "ms for worker threads to drain");
state.wait(drainEnd - now);
now = System.currentTimeMillis();
}
catch (InterruptedException e) {
interrupted = true;
error = new ServiceOperationException("stop operation thread interrupted", e);
break;
}
}
for (Thread serviceThread : serviceThreads)
{
if (log.isDebugEnabled())
log.debug(logId + ": interrupting worker thread " + ObjectUtils.getUniqueId(serviceThread));
serviceThread.interrupt();
}
}
}
// first call subclass onStop()
try {
onStop();
}
catch (InterruptedException e) {
interrupted = true;
// don't overwrite potential SOE from InterruptedException handler above
if (error == null)
error = new ServiceOperationException("stop operation thread interrupted", e);
}
catch (RuntimeException e)
{
// don't overwrite potential SOE from InterruptedException handler above
if (error == null)