Added some JMX support.
[jsvc.git] / src / dolda / jsvc / scgi / DirServer.java
CommitLineData
13e578b1
FT
1package dolda.jsvc.scgi;
2
3import java.io.*;
4import java.net.*;
5import java.util.*;
a13bfa2c 6import java.util.logging.*;
13e578b1
FT
7import dolda.jsvc.*;
8import dolda.jsvc.util.*;
9import dolda.jsvc.j2ee.PosixArgs;
32994173
FT
10import java.lang.management.ManagementFactory;
11import javax.management.*;
13e578b1
FT
12
13public class DirServer extends Server {
14 private final Map<File, DSContext> contexts = new HashMap<File, DSContext>();
32994173 15 public final Environment env;
a13bfa2c 16 private final Logger logger = Logger.getLogger("dolda.jsvc.scgi.dirserver");
48d0e295 17 private Thread sdhook = null, main = null;
13e578b1 18
22779185 19 public DirServer(ServerSocket sk, Environment env) {
13e578b1 20 super(sk);
22779185 21 this.env = env;
13e578b1
FT
22 }
23
24 private DSContext context(File file) throws ThreadContext.CreateException {
25 synchronized(contexts) {
26 DSContext ctx = contexts.get(file);
a13bfa2c 27 String act = "loaded %s as %s";
13e578b1
FT
28 if(ctx != null) {
29 if(ctx.mtime < file.lastModified()) {
ecbf3777 30 ctx.tg.shutdown();
32994173
FT
31 try {
32 ManagementFactory.getPlatformMBeanServer().unregisterMBean(ctx.mbean.name);
33 } catch(InstanceNotFoundException e) {
34 } catch(MBeanRegistrationException e) {
35 }
13e578b1
FT
36 contexts.remove(file);
37 ctx = null;
a13bfa2c 38 act = "reloaded %s as %s";
13e578b1
FT
39 }
40 }
41 if(ctx == null) {
22779185 42 ctx = new DSContext(file, env);
32994173
FT
43 try {
44 ManagementFactory.getPlatformMBeanServer().registerMBean(ctx.mbean, ctx.mbean.name);
45 } catch(InstanceAlreadyExistsException e) {
46 } catch(MBeanRegistrationException e) {
47 } catch(NotCompliantMBeanException e) {
48 }
13e578b1 49 contexts.put(file, ctx);
a13bfa2c 50 logger.config(String.format(act, file, ctx.name()));
13e578b1
FT
51 }
52 return(ctx);
53 }
54 }
55
56 public void handle(Map<String, String> head, Socket sk) throws Exception {
57 String filename = head.get("SCRIPT_FILENAME");
58 if(filename == null)
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);
66 w.start();
67 }
0de51374 68
48d0e295
FT
69 private class ShutdownHandler extends Thread {
70 public void run() {
71 sdhook = null;
72 DirServer.this.stop();
73 try {
74 main.join();
75 } catch(InterruptedException e) {}
76 }
77 }
78
0de51374 79 protected void shutdown() {
48d0e295
FT
80 try {
81 if(sdhook != null)
82 Runtime.getRuntime().removeShutdownHook(sdhook);
83 } catch(Exception e) {}
0de51374
FT
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();
88 i.remove();
89 ctx.tg.shutdown();
90 }
91 }
48d0e295 92 super.shutdown();
32994173
FT
93 try {
94 ManagementFactory.getPlatformMBeanServer().unregisterMBean(dolda.jsvc.scgi.jmx.Server.name);
95 } catch(InstanceNotFoundException e) {
96 } catch(MBeanRegistrationException e) {
97 }
0de51374 98 }
13e578b1
FT
99
100 private static void usage(PrintStream out) {
101 out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-e CHARSET] [-d DATADIR] PORT");
102 }
103
104 public static void main(String[] args) {
105 PosixArgs opt = PosixArgs.getopt(args, "h");
106 if(opt == null) {
107 usage(System.err);
108 System.exit(1);
109 }
110 String charset = null;
111 File datroot = null;
112 for(char c : opt.parsed()) {
113 switch(c) {
114 case 'e':
115 charset = opt.arg;
116 break;
117 case 'd':
118 datroot = new File(opt.arg);
119 if(!datroot.exists() || !datroot.isDirectory()) {
120 System.err.println(opt.arg + ": no such directory");
121 System.exit(1);
122 }
123 break;
124 case 'h':
125 usage(System.out);
126 return;
127 }
128 }
129 if(opt.rest.length < 1) {
130 usage(System.err);
131 System.exit(1);
132 }
22779185
FT
133 Environment env = (datroot == null)?new Environment():new Environment(datroot);
134 env.initvm();
13e578b1
FT
135 int port = Integer.parseInt(opt.rest[0]);
136 ServerSocket sk;
137 try {
138 sk = new ServerSocket(port);
139 } catch(IOException e) {
140 System.err.println("could not bind to port " + port + ": " + e.getMessage());
141 System.exit(1);
142 return; /* Because javac is stupid. :-/ */
143 }
22779185 144 DirServer s = new DirServer(sk, env);
32994173
FT
145 try {
146 ManagementFactory.getPlatformMBeanServer().registerMBean(new dolda.jsvc.scgi.jmx.Server(s), dolda.jsvc.scgi.jmx.Server.name);
147 } catch(InstanceAlreadyExistsException e) {
148 } catch(MBeanRegistrationException e) {
149 } catch(NotCompliantMBeanException e) {
150 }
13e578b1
FT
151 if(charset != null)
152 s.headcs = charset;
153
48d0e295
FT
154 Runtime.getRuntime().addShutdownHook(s.sdhook = s.new ShutdownHandler());
155 s.main = new Thread(s, "SCGI server thread");
156 s.main.start();
13e578b1
FT
157 }
158}