import java.io.*;
import java.net.*;
import java.util.*;
+import java.util.logging.*;
import dolda.jsvc.*;
import dolda.jsvc.util.*;
import dolda.jsvc.j2ee.PosixArgs;
+import java.lang.management.ManagementFactory;
+import javax.management.*;
public class DirServer extends Server {
private final Map<File, DSContext> contexts = new HashMap<File, DSContext>();
- private final File datroot;
+ public final Environment env;
+ private final Logger logger = Logger.getLogger("dolda.jsvc.scgi.dirserver");
+ private Thread sdhook = null, main = null;
- public DirServer(ServerSocket sk, File datroot) {
+ public DirServer(ServerSocket sk, Environment env) {
super(sk);
- this.datroot = datroot;
+ this.env = env;
}
private DSContext context(File file) throws ThreadContext.CreateException {
synchronized(contexts) {
DSContext ctx = contexts.get(file);
+ String act = "loaded %s as %s";
if(ctx != null) {
if(ctx.mtime < file.lastModified()) {
- ctx.tg.destroy();
+ ctx.tg.shutdown();
+ try {
+ ManagementFactory.getPlatformMBeanServer().unregisterMBean(ctx.mbean.name);
+ } catch(InstanceNotFoundException e) {
+ } catch(MBeanRegistrationException e) {
+ }
contexts.remove(file);
ctx = null;
+ act = "reloaded %s as %s";
}
}
if(ctx == null) {
- ctx = new DSContext(file, datroot);
+ ctx = new DSContext(file, env);
+ try {
+ ManagementFactory.getPlatformMBeanServer().registerMBean(ctx.mbean, ctx.mbean.name);
+ } catch(InstanceAlreadyExistsException e) {
+ } catch(MBeanRegistrationException e) {
+ } catch(NotCompliantMBeanException e) {
+ }
contexts.put(file, ctx);
+ logger.config(String.format(act, file, ctx.name()));
}
return(ctx);
}
RequestThread w = ctx.tg.respond(req);
w.start();
}
+
+ private class ShutdownHandler extends Thread {
+ public void run() {
+ sdhook = null;
+ DirServer.this.stop();
+ try {
+ main.join();
+ } catch(InterruptedException e) {}
+ }
+ }
+
+ protected void shutdown() {
+ try {
+ if(sdhook != null)
+ Runtime.getRuntime().removeShutdownHook(sdhook);
+ } catch(Exception e) {}
+ synchronized(contexts) {
+ for(Iterator<Map.Entry<File, DSContext>> i = contexts.entrySet().iterator(); i.hasNext();) {
+ Map.Entry<File, DSContext> e = i.next();
+ DSContext ctx = e.getValue();
+ i.remove();
+ ctx.tg.shutdown();
+ }
+ }
+ super.shutdown();
+ try {
+ ManagementFactory.getPlatformMBeanServer().unregisterMBean(dolda.jsvc.scgi.jmx.Server.name);
+ } catch(InstanceNotFoundException e) {
+ } catch(MBeanRegistrationException e) {
+ }
+ }
private static void usage(PrintStream out) {
- out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-e CHARSET] [-d DATADIR] PORT");
+ out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-B BINDADDR] [-e CHARSET] [-d DATADIR] PORT");
}
public static void main(String[] args) {
- PosixArgs opt = PosixArgs.getopt(args, "h");
+ PosixArgs opt = PosixArgs.getopt(args, "he:d:B:");
if(opt == null) {
usage(System.err);
System.exit(1);
}
String charset = null;
File datroot = null;
+ InetAddress bindaddr;
+ try {
+ bindaddr = InetAddress.getByName(null);
+ } catch(UnknownHostException e) {
+ throw(new Error(e));
+ }
for(char c : opt.parsed()) {
switch(c) {
case 'e':
System.exit(1);
}
break;
+ case 'B':
+ try {
+ bindaddr = InetAddress.getByName(opt.arg);
+ } catch(UnknownHostException e) {
+ System.err.println(opt.arg + ": no such host");
+ System.exit(1);
+ }
+ break;
case 'h':
usage(System.out);
return;
usage(System.err);
System.exit(1);
}
- if(datroot == null) {
- datroot = new File(System.getProperty("user.home"), ".jsvc");
- if(!datroot.exists() || !datroot.isDirectory())
- datroot = null;
- }
+ Environment env = (datroot == null)?new Environment():new Environment(datroot);
+ env.initvm();
int port = Integer.parseInt(opt.rest[0]);
ServerSocket sk;
+ SocketAddress saddr = new InetSocketAddress(bindaddr, port);
try {
- sk = new ServerSocket(port);
+ sk = new ServerSocket();
+ sk.bind(saddr);
} catch(IOException e) {
- System.err.println("could not bind to port " + port + ": " + e.getMessage());
+ System.err.println("could not bind to " + saddr + ": " + e.getMessage());
System.exit(1);
return; /* Because javac is stupid. :-/ */
}
- DirServer s = new DirServer(sk, datroot);
+ DirServer s = new DirServer(sk, env);
+ try {
+ ManagementFactory.getPlatformMBeanServer().registerMBean(new dolda.jsvc.scgi.jmx.Server(s), dolda.jsvc.scgi.jmx.Server.name);
+ } catch(InstanceAlreadyExistsException e) {
+ } catch(MBeanRegistrationException e) {
+ } catch(NotCompliantMBeanException e) {
+ }
if(charset != null)
s.headcs = charset;
- new Thread(s, "SCGI server thread").start();
+ Runtime.getRuntime().addShutdownHook(s.sdhook = s.new ShutdownHandler());
+ s.main = new Thread(s, "SCGI server thread");
+ s.main.start();
}
}