/**
* Copyright (C) 2012-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.mangoo.build;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* This is a refactored version of
* DelayedRestartTrigger.java from the Ninja Web Framework
*
* Original source code can be found here:
* https://github.com/ninjaframework/ninja/blob/develop/ninja-maven-plugin/src/main/java/ninja/build/DelayedRestartTrigger.java
*
* @author svenkubiak
*
*/
public class Trigger extends Thread {
private static final Logger LOG = LogManager.getLogger(Trigger.class);
private boolean shutdown;
private final AtomicInteger restartCount;
private final AtomicInteger triggerCount;
private final ReentrantLock restartLock;
private final Condition restartRequested;
private final Runner runner;
private long settleDownMillis = 500; //NOSONAR
public Trigger(Runner runner) {
this.shutdown = false;
this.setDaemon(true);
this.setName("DelayedRestartTrigger");
this.restartCount = new AtomicInteger(0);
this.triggerCount = new AtomicInteger(0);
this.restartLock = new ReentrantLock();
this.restartRequested = this.restartLock.newCondition();
this.runner = runner;
}
public void doShutdown() {
this.shutdown = true;
this.interrupt();
}
public int getRestartCount() {
return restartCount.get();
}
public int getAccumulatedTriggerCount() {
return triggerCount.get();
}
public long getSettleDownMillis() {
return settleDownMillis;
}
public void setSettleDownMillis(long settleDownMillis) {
this.settleDownMillis = settleDownMillis;
}
@Override
@SuppressWarnings("all")
public void run() {
while (!shutdown) {
try {
this.restartLock.lock();
try {
if (this.triggerCount.get() <= 0) {
this.restartRequested.await();
}
this.restartCount.incrementAndGet();
} finally {
this.restartLock.unlock();
}
LOG.info("------------------------------------------------------------------------");
LOG.info("Restart process...");
int totalTriggerCount = 0;
do {
LOG.info("Delaying restart for " + settleDownMillis + " ms to wait for file changes to settle");
totalTriggerCount += this.triggerCount.getAndSet(0);
sleep();
} while (this.triggerCount.get() != 0);
LOG.info("Restarting dev mode (" + totalTriggerCount + " file change(s) detected)");
LOG.info("------------------------------------------------------------------------");
runner.restart();
} catch (InterruptedException e) {
if (!shutdown) {
LOG.error("Unexpected thread interrupt (maybe you are shutting down Maven?)", e);
}
break;
}
}
}
@SuppressWarnings("all")
private void sleep() {
try {
Thread.sleep(settleDownMillis);
} catch (InterruptedException e) {
//intentionally left blank
}
}
public void trigger() {
this.restartLock.lock();
try {
triggerCount.incrementAndGet();
this.restartRequested.signalAll();
} finally {
this.restartLock.unlock();
}
}
}