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"); |
13e578b1 | 15 | |
22779185 | 16 | public DirServer(ServerSocket sk, Environment env) { |
13e578b1 | 17 | super(sk); |
22779185 | 18 | this.env = env; |
13e578b1 FT |
19 | } |
20 | ||
21 | private DSContext context(File file) throws ThreadContext.CreateException { | |
22 | synchronized(contexts) { | |
23 | DSContext ctx = contexts.get(file); | |
a13bfa2c | 24 | String act = "loaded %s as %s"; |
13e578b1 FT |
25 | if(ctx != null) { |
26 | if(ctx.mtime < file.lastModified()) { | |
ecbf3777 | 27 | ctx.tg.shutdown(); |
13e578b1 FT |
28 | contexts.remove(file); |
29 | ctx = null; | |
a13bfa2c | 30 | act = "reloaded %s as %s"; |
13e578b1 FT |
31 | } |
32 | } | |
33 | if(ctx == null) { | |
22779185 | 34 | ctx = new DSContext(file, env); |
13e578b1 | 35 | contexts.put(file, ctx); |
a13bfa2c | 36 | logger.config(String.format(act, file, ctx.name())); |
13e578b1 FT |
37 | } |
38 | return(ctx); | |
39 | } | |
40 | } | |
41 | ||
42 | public void handle(Map<String, String> head, Socket sk) throws Exception { | |
43 | String filename = head.get("SCRIPT_FILENAME"); | |
44 | if(filename == null) | |
45 | throw(new Exception("Request for DirServer must contain SCRIPT_FILENAME")); | |
46 | File file = new File(filename); | |
47 | if(!file.exists() || !file.canRead()) | |
48 | throw(new Exception("Cannot access the requested JSvc file " + file.toString())); | |
49 | DSContext ctx = context(file); | |
50 | Request req = new ScgiRequest(sk, head); | |
51 | RequestThread w = ctx.tg.respond(req); | |
52 | w.start(); | |
53 | } | |
54 | ||
55 | private static void usage(PrintStream out) { | |
56 | out.println("usage: dolda.jsvc.scgi.DirServer [-h] [-e CHARSET] [-d DATADIR] PORT"); | |
57 | } | |
58 | ||
59 | public static void main(String[] args) { | |
60 | PosixArgs opt = PosixArgs.getopt(args, "h"); | |
61 | if(opt == null) { | |
62 | usage(System.err); | |
63 | System.exit(1); | |
64 | } | |
65 | String charset = null; | |
66 | File datroot = null; | |
67 | for(char c : opt.parsed()) { | |
68 | switch(c) { | |
69 | case 'e': | |
70 | charset = opt.arg; | |
71 | break; | |
72 | case 'd': | |
73 | datroot = new File(opt.arg); | |
74 | if(!datroot.exists() || !datroot.isDirectory()) { | |
75 | System.err.println(opt.arg + ": no such directory"); | |
76 | System.exit(1); | |
77 | } | |
78 | break; | |
79 | case 'h': | |
80 | usage(System.out); | |
81 | return; | |
82 | } | |
83 | } | |
84 | if(opt.rest.length < 1) { | |
85 | usage(System.err); | |
86 | System.exit(1); | |
87 | } | |
22779185 FT |
88 | Environment env = (datroot == null)?new Environment():new Environment(datroot); |
89 | env.initvm(); | |
13e578b1 FT |
90 | int port = Integer.parseInt(opt.rest[0]); |
91 | ServerSocket sk; | |
92 | try { | |
93 | sk = new ServerSocket(port); | |
94 | } catch(IOException e) { | |
95 | System.err.println("could not bind to port " + port + ": " + e.getMessage()); | |
96 | System.exit(1); | |
97 | return; /* Because javac is stupid. :-/ */ | |
98 | } | |
22779185 | 99 | DirServer s = new DirServer(sk, env); |
13e578b1 FT |
100 | if(charset != null) |
101 | s.headcs = charset; | |
102 | ||
103 | new Thread(s, "SCGI server thread").start(); | |
104 | } | |
105 | } |