Commit | Line | Data |
---|---|---|
13e578b1 FT |
1 | package dolda.jsvc.scgi; |
2 | ||
3 | import java.io.*; | |
4 | import java.net.*; | |
5 | import java.util.*; | |
a13bfa2c | 6 | import java.util.logging.*; |
13e578b1 FT |
7 | import dolda.jsvc.*; |
8 | import dolda.jsvc.util.*; | |
9 | import dolda.jsvc.j2ee.PosixArgs; | |
10 | ||
11 | public class DirServer extends Server { | |
12 | private final Map<File, DSContext> contexts = new HashMap<File, DSContext>(); | |
22779185 | 13 | private final Environment env; |
a13bfa2c | 14 | private final Logger logger = Logger.getLogger("dolda.jsvc.scgi.dirserver"); |
48d0e295 | 15 | private Thread sdhook = null, main = null; |
13e578b1 | 16 | |
22779185 | 17 | public DirServer(ServerSocket sk, Environment env) { |
13e578b1 | 18 | super(sk); |
22779185 | 19 | this.env = env; |
13e578b1 FT |
20 | } |
21 | ||
22 | private DSContext context(File file) throws ThreadContext.CreateException { | |
23 | synchronized(contexts) { | |
24 | DSContext ctx = contexts.get(file); | |
a13bfa2c | 25 | String act = "loaded %s as %s"; |
13e578b1 FT |
26 | if(ctx != null) { |
27 | if(ctx.mtime < file.lastModified()) { | |
ecbf3777 | 28 | ctx.tg.shutdown(); |
13e578b1 FT |
29 | contexts.remove(file); |
30 | ctx = null; | |
a13bfa2c | 31 | act = "reloaded %s as %s"; |
13e578b1 FT |
32 | } |
33 | } | |
34 | if(ctx == null) { | |
22779185 | 35 | ctx = new DSContext(file, env); |
13e578b1 | 36 | contexts.put(file, ctx); |
a13bfa2c | 37 | logger.config(String.format(act, file, ctx.name())); |
13e578b1 FT |
38 | } |
39 | return(ctx); | |
40 | } | |
41 | } | |
42 | ||
43 | public void handle(Map<String, String> head, Socket sk) throws Exception { | |
44 | String filename = head.get("SCRIPT_FILENAME"); | |
45 | if(filename == null) | |
46 | throw(new Exception("Request for DirServer must contain SCRIPT_FILENAME")); | |
47 | File file = new File(filename); | |
48 | if(!file.exists() || !file.canRead()) | |
49 | throw(new Exception("Cannot access the requested JSvc file " + file.toString())); | |
50 | DSContext ctx = context(file); | |
51 | Request req = new ScgiRequest(sk, head); | |
52 | RequestThread w = ctx.tg.respond(req); | |
53 | w.start(); | |
54 | } | |
0de51374 | 55 | |
48d0e295 FT |
56 | private class ShutdownHandler extends Thread { |
57 | public void run() { | |
58 | sdhook = null; | |
59 | DirServer.this.stop(); | |
60 | try { | |
61 | main.join(); | |
62 | } catch(InterruptedException e) {} | |
63 | } | |
64 | } | |
65 | ||
0de51374 | 66 | protected void shutdown() { |
48d0e295 FT |
67 | try { |
68 | if(sdhook != null) | |
69 | Runtime.getRuntime().removeShutdownHook(sdhook); | |
70 | } catch(Exception e) {} | |
0de51374 FT |
71 | synchronized(contexts) { |
72 | for(Iterator<Map.Entry<File, DSContext>> i = contexts.entrySet().iterator(); i.hasNext();) { | |
73 | Map.Entry<File, DSContext> e = i.next(); | |
74 | DSContext ctx = e.getValue(); | |
75 | i.remove(); | |
76 | ctx.tg.shutdown(); | |
77 | } | |
78 | } | |
48d0e295 | 79 | super.shutdown(); |
0de51374 | 80 | } |
13e578b1 FT |
81 | |
82 | private static void usage(PrintStream out) { | |
83 | out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-e CHARSET] [-d DATADIR] PORT"); | |
84 | } | |
85 | ||
86 | public static void main(String[] args) { | |
87 | PosixArgs opt = PosixArgs.getopt(args, "h"); | |
88 | if(opt == null) { | |
89 | usage(System.err); | |
90 | System.exit(1); | |
91 | } | |
92 | String charset = null; | |
93 | File datroot = null; | |
94 | for(char c : opt.parsed()) { | |
95 | switch(c) { | |
96 | case 'e': | |
97 | charset = opt.arg; | |
98 | break; | |
99 | case 'd': | |
100 | datroot = new File(opt.arg); | |
101 | if(!datroot.exists() || !datroot.isDirectory()) { | |
102 | System.err.println(opt.arg + ": no such directory"); | |
103 | System.exit(1); | |
104 | } | |
105 | break; | |
106 | case 'h': | |
107 | usage(System.out); | |
108 | return; | |
109 | } | |
110 | } | |
111 | if(opt.rest.length < 1) { | |
112 | usage(System.err); | |
113 | System.exit(1); | |
114 | } | |
22779185 FT |
115 | Environment env = (datroot == null)?new Environment():new Environment(datroot); |
116 | env.initvm(); | |
13e578b1 FT |
117 | int port = Integer.parseInt(opt.rest[0]); |
118 | ServerSocket sk; | |
119 | try { | |
120 | sk = new ServerSocket(port); | |
121 | } catch(IOException e) { | |
122 | System.err.println("could not bind to port " + port + ": " + e.getMessage()); | |
123 | System.exit(1); | |
124 | return; /* Because javac is stupid. :-/ */ | |
125 | } | |
22779185 | 126 | DirServer s = new DirServer(sk, env); |
13e578b1 FT |
127 | if(charset != null) |
128 | s.headcs = charset; | |
129 | ||
48d0e295 FT |
130 | Runtime.getRuntime().addShutdownHook(s.sdhook = s.new ShutdownHandler()); |
131 | s.main = new Thread(s, "SCGI server thread"); | |
132 | s.main.start(); | |
13e578b1 FT |
133 | } |
134 | } |