package org.vaadin.mideaas.frontend;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.vaadin.mideaas.frontend.MavenTask.LogListener;
import org.vaadin.mideaas.model.SharedProject;
public class JettyUtil {
private static final List<String> GOAL_JETTY_RUN = Arrays
.asList(new String[] { "jetty:stop", "jetty:run" });
private static final List<String> GOAL_JETTY_STOP = Arrays
.asList(new String[] { "jetty:stop" });
private static final String STOP_KEY = "heilopeta";
// TODO: what if we run out of ports?
private static int PORT_FIRST;
private static int PORT_LAST;
private static int STOP_PORT_FIRST;
private static int STOP_PORT_LAST;
private static TreeSet<Integer> portsAvailable = new TreeSet<Integer>();
private static TreeSet<Integer> stopPortsAvailable = new TreeSet<Integer>();
public static void setPortRange(int first, int last) {
PORT_FIRST = first;
PORT_LAST = last;
for (int p=PORT_FIRST; p<=PORT_LAST; p++) {
portsAvailable.add(p);
}
}
public static void setStopPortRange(int first, int last) {
STOP_PORT_FIRST = first;
STOP_PORT_LAST = last;
for (int p=STOP_PORT_FIRST; p<=STOP_PORT_LAST; p++) {
stopPortsAvailable.add(p);
}
}
private static void setAllPortsOpen() {
setPortRange(PORT_FIRST, PORT_LAST);
setStopPortRange(STOP_PORT_FIRST, STOP_PORT_LAST);
}
/**
* key: port
* value: stopPort
*/
private static TreeMap<Integer, Integer> portsInUse =
new TreeMap<Integer, Integer>();
private static ExecutorService executor = Executors.newCachedThreadPool();
/**
*
* @param pomXml
* @param contextPath
* @return port
*/
synchronized public static int runJetty(File pomXml, String contextPath, String buildDir, LogListener listener) {
int port = getAvailablePort();
int stopPort = getAvailableStopPort();
portsAvailable.remove(port);
stopPortsAvailable.remove(stopPort);
portsInUse.put(port, stopPort);
Properties props = new Properties();
props.setProperty("jetty.port", "" + port);
// TODO: buildDir?
props.setProperty("alt.build.dir", buildDir);
props.setProperty("mideaas.jetty.stopPort", ""+stopPort);
props.setProperty("mideaas.jetty.stopKey", STOP_KEY);
props.setProperty("mideaas.jetty.contextPath", contextPath);
MavenTask task = new MavenTask(pomXml.getAbsoluteFile(), GOAL_JETTY_RUN, props, listener);
// task.setLoggingEnabled(true);
executor.submit(task);
return port;
}
synchronized public static void stopJetty(int port, File pomXml, String contextPath, LogListener listener) {
Integer stopPort = portsInUse.remove(port);
if (stopPort==null) {
throw new IllegalArgumentException("No Jetty running in port "+port+" (that I know of...)");
}
portsAvailable.add(port);
stopPortsAvailable.add(stopPort);
Properties props = new Properties();
props.setProperty("jetty.port", "" + port);
props.setProperty("mideaas.jetty.stopPort", ""+stopPort);
props.setProperty("mideaas.jetty.stopKey", STOP_KEY);
props.setProperty("mideaas.jetty.contextPath", contextPath);
executor.submit(new MavenTask(pomXml.getAbsoluteFile(), GOAL_JETTY_STOP, props, listener));
}
/**
* Stops all the Jetty instances, in a separate thread.
*
* Runs jetty:stop for each stop port, whether there was Jetty running or not.
* This is not the cleanest solution...
*/
synchronized public static void stopAllJettys() {
InputStream is = JettyUtil.class.getClassLoader().getResourceAsStream("jettyutil/pom.xml");
StringWriter writer = new StringWriter();
File temp;
try {
IOUtils.copy(is, writer);
String theString = writer.toString();
temp = File.createTempFile("mideaas", "pom.xml");
FileUtils.write(temp, theString);
}
catch (IOException e) {
e.printStackTrace();
return;
}
ExecutorService exer = Executors.newSingleThreadExecutor();
for (int p=STOP_PORT_FIRST; p<=STOP_PORT_LAST; p++) {
Properties props = new Properties();
props.setProperty("mideaas.jetty.stopPort", ""+p);
props.setProperty("mideaas.jetty.stopKey", STOP_KEY);
MavenTask task = new MavenTask(temp, GOAL_JETTY_STOP, props, null);
exer.submit(task);
}
exer.shutdown();
setAllPortsOpen();
}
private static int getAvailablePort() {
return portsAvailable.first();
}
private static int getAvailableStopPort() {
return stopPortsAvailable.first();
}
public static String contextPathFor(SharedProject project) {
return "/apps/"+project.getName();
}
}