1 package dolda.jsvc.scgi;
6 import java.util.logging.*;
8 import dolda.jsvc.util.*;
9 import dolda.jsvc.j2ee.PosixArgs;
10 import java.lang.management.ManagementFactory;
11 import javax.management.*;
13 public class DirServer extends Server {
14 private final Map<File, DSContext> contexts = new HashMap<File, DSContext>();
15 public final Environment env;
16 private final Logger logger = Logger.getLogger("dolda.jsvc.scgi.dirserver");
17 private Thread sdhook = null, main = null;
19 public DirServer(ServerSocket sk, Environment env) {
24 private DSContext context(File file) throws ThreadContext.CreateException {
25 synchronized(contexts) {
26 DSContext ctx = contexts.get(file);
27 String act = "loaded %s as %s";
29 if(ctx.mtime < file.lastModified()) {
32 ManagementFactory.getPlatformMBeanServer().unregisterMBean(ctx.mbean.name);
33 } catch(InstanceNotFoundException e) {
34 } catch(MBeanRegistrationException e) {
36 contexts.remove(file);
38 act = "reloaded %s as %s";
42 ctx = new DSContext(file, env);
44 ManagementFactory.getPlatformMBeanServer().registerMBean(ctx.mbean, ctx.mbean.name);
45 } catch(InstanceAlreadyExistsException e) {
46 } catch(MBeanRegistrationException e) {
47 } catch(NotCompliantMBeanException e) {
49 contexts.put(file, ctx);
50 logger.config(String.format(act, file, ctx.name()));
56 public void handle(Map<String, String> head, Socket sk) throws Exception {
57 String filename = head.get("SCRIPT_FILENAME");
59 throw(new Exception("Request for DirServer must contain SCRIPT_FILENAME"));
60 File file = new File(filename);
61 if(!file.exists() || !file.canRead())
62 throw(new Exception("Cannot access the requested JSvc file " + file.toString()));
63 DSContext ctx = context(file);
64 Request req = new ScgiRequest(sk, head);
65 RequestThread w = ctx.tg.respond(req);
69 private class ShutdownHandler extends Thread {
72 DirServer.this.stop();
75 } catch(InterruptedException e) {}
79 protected void shutdown() {
82 Runtime.getRuntime().removeShutdownHook(sdhook);
83 } catch(Exception e) {}
84 synchronized(contexts) {
85 for(Iterator<Map.Entry<File, DSContext>> i = contexts.entrySet().iterator(); i.hasNext();) {
86 Map.Entry<File, DSContext> e = i.next();
87 DSContext ctx = e.getValue();
94 ManagementFactory.getPlatformMBeanServer().unregisterMBean(dolda.jsvc.scgi.jmx.Server.name);
95 } catch(InstanceNotFoundException e) {
96 } catch(MBeanRegistrationException e) {
100 private static void usage(PrintStream out) {
101 out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-B BINDADDR] [-e CHARSET] [-d DATADIR] PORT");
104 public static void main(String[] args) {
105 PosixArgs opt = PosixArgs.getopt(args, "he:d:B:");
110 String charset = null;
112 InetAddress bindaddr;
114 bindaddr = InetAddress.getByName(null);
115 } catch(UnknownHostException e) {
118 for(char c : opt.parsed()) {
124 datroot = new File(opt.arg);
125 if(!datroot.exists() || !datroot.isDirectory()) {
126 System.err.println(opt.arg + ": no such directory");
132 bindaddr = InetAddress.getByName(opt.arg);
133 } catch(UnknownHostException e) {
134 System.err.println(opt.arg + ": no such host");
143 if(opt.rest.length < 1) {
147 Environment env = (datroot == null)?new Environment():new Environment(datroot);
149 int port = Integer.parseInt(opt.rest[0]);
151 SocketAddress saddr = new InetSocketAddress(bindaddr, port);
153 sk = new ServerSocket();
155 } catch(IOException e) {
156 System.err.println("could not bind to " + saddr + ": " + e.getMessage());
158 return; /* Because javac is stupid. :-/ */
160 DirServer s = new DirServer(sk, env);
162 ManagementFactory.getPlatformMBeanServer().registerMBean(new dolda.jsvc.scgi.jmx.Server(s), dolda.jsvc.scgi.jmx.Server.name);
163 } catch(InstanceAlreadyExistsException e) {
164 } catch(MBeanRegistrationException e) {
165 } catch(NotCompliantMBeanException e) {
170 Runtime.getRuntime().addShutdownHook(s.sdhook = s.new ShutdownHandler());
171 s.main = new Thread(s, "SCGI server thread");