package aQute.jpm.service;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketTimeoutException;
import java.util.Date;
import java.util.UUID;
import aQute.lib.io.IO;
import aQute.lib.io.IOConstants;
public class ServiceMain extends Thread {
static final int BUFFER_SIZE = IOConstants.PAGE_SIZE * 16;
static File lock;
Date last = new Date();
String message = "<>";
static DatagramSocket socket;
static Class< ? > mainClass;
static Method serviceMethod;
static Thread mainThread;
static final UUID uuid = UUID.randomUUID();
private boolean trace = false;
public static void main(String args[]) throws Exception, SecurityException, NoSuchMethodException {
System.out.println(args.length);
System.out.println(args[0]);
lock = new File(args[0]).getAbsoluteFile();
// lock.deleteOnExit();
if (!lock.exists())
throw new IllegalArgumentException("Must start with a valid lock file " + lock);
socket = new DatagramSocket();
ServiceMain main = new ServiceMain();
main.trace("Port " + socket.getLocalPort());
write(lock, socket.getLocalPort() + ":" + System.getProperty("pid") + ":" + uuid.toString());
main.start();
mainClass = ServiceMain.class.getClassLoader().loadClass(args[1]);
try {
serviceMethod = mainClass.getDeclaredMethod("daemon", boolean.class);
serviceMethod.invoke(null, true);
} catch (NoSuchMethodException e) {
String[] args2 = new String[args.length - 2];
System.arraycopy(args, 2, args2, 0, args2.length);
Method m = mainClass.getDeclaredMethod("main", String[].class);
m.invoke(null, (Object) args2);
}
}
ServiceMain() {
super("jpm main service thread");
}
@Override
public void run() {
try {
byte[] buffer = new byte[BUFFER_SIZE];
DatagramPacket dp = new DatagramPacket(buffer, BUFFER_SIZE);
boolean stopped = false;
socket.setSoTimeout(5000);
while (!isInterrupted() && !stopped) {
try {
trace("Listening for messages");
socket.receive(dp);
trace("Received message " + dp.getAddress());
if (dp.getAddress().isLoopbackAddress()) {
String s = new String(dp.getData(), dp.getOffset(), dp.getLength(), UTF_8);
trace("Received message " + s);
String parts[] = s.split(":");
String reply;
if (parts[0].equals("STOP")) {
stopped = true;
reply = "200 STOPPING";
if (serviceMethod != null) {
try {
serviceMethod.invoke(null, false);
} catch (Exception e) {
// Ignore
}
mainThread.interrupt();
mainThread.join(2000);
}
} else if (parts[0].equals("STATUS")) {
reply = "200 OK " + last + " " + message;
} else if (parts[0].equals("TRACE-ON")) {
trace = true;
reply = "200 Trace on";
} else if (parts[0].equals("TRACE-OFF")) {
trace = false;
reply = "200 Trace off";
} else
reply = "404 UNKNOWN REQUEST " + s;
byte data[] = reply.getBytes(UTF_8);
DatagramPacket p = new DatagramPacket(data, 0, data.length, dp.getAddress(), dp.getPort());
trace("Sending reply message " + reply);
socket.send(p);
} else
System.err.println("Received UDP from external source");
} catch (SocketTimeoutException stoe) {
trace("checking lock " + lock + " " + lock.exists());
if (!lock.exists())
break;
}
}
} catch (Throwable t) {
t.printStackTrace();
} finally {
try {
socket.close();
} finally {
try {
IO.delete(lock);
} finally {
System.exit(1);
}
}
}
}
private void trace(String string) {
if (trace)
System.err.println("JPM: " + string);
}
private static void write(File f, String response) throws IOException {
try (PrintWriter fw = IO.writer(f)) {
fw.append(response);
}
}
public synchronized void setMessage(String m) {
trace(m);
last = new Date();
message = m;
}
}