Thread th = Thread.currentThread();
if(perthr.containsKey(th))
return(perthr.get(th));
- ThreadContext ctx = getctx();
+ ThreadContext ctx = ThreadContext.current();
if(perctx.containsKey(ctx))
return(perctx.get(ctx));
if(!bound)
}
public synchronized T ctxset(T val) {
- ThreadContext ctx = getctx();
+ ThreadContext ctx = ThreadContext.current();
return(perctx.put(ctx, val));
}
- private static ThreadContext getctx() {
- for(ThreadGroup tg = Thread.currentThread().getThreadGroup(); tg != null; tg = tg.getParent()) {
- if(tg instanceof ThreadContext)
- return((ThreadContext)tg);
- }
- return(null);
- }
-
public static Responder let(final Responder next, Object... params) {
final Map<ContextParam, Object> values = new HashMap<ContextParam, Object>();
if((params.length % 2) != 0)
public interface Request {
/* Input */
public URL url();
+ public URL rooturl();
public String method();
public String path();
public InputStream input();
}
}
- public static ServerContext context() {
- return(((RequestThread)Thread.currentThread()).req.ctx());
- }
-
public static Request request() {
return(((RequestThread)Thread.currentThread()).req);
}
}
public URL url() {return(bk.url());}
+ public URL rooturl() {return(bk.rooturl());}
public String method() {return(bk.method());}
public String path() {return(bk.path());}
public InputStream input() {return(bk.input());}
package dolda.jsvc;
public interface ServerContext {
- public String rootpath();
public long starttime();
}
private Logger logger = Logger.getLogger("dolda.jsvc.context");
private ThreadGroup workers;
private long reqs = 0;
+ private final ServerContext ctx;
public final Responder root;
- public ThreadContext(ThreadGroup parent, String name, Class<?> bootclass) {
+ public ThreadContext(ThreadGroup parent, String name, ServerContext ctx, Class<?> bootclass) {
super((parent == null)?(Thread.currentThread().getThreadGroup()):parent, name);
+ this.ctx = ctx;
workers = new ThreadGroup(this, "Worker threads") {
public void uncaughtException(Thread t, Throwable e) {
logger.log(Level.SEVERE, "Worker thread terminated with an uncaught exception", e);
logger.log(Level.SEVERE, "Service thread " + t.toString() + " terminated with an uncaught exception", e);
}
+ public ServerContext server() {
+ return(ctx);
+ }
+
public void shutdown() {
if(root instanceof ContextResponder)
((ContextResponder)root).destroy();
}
return(res[0]);
}
+
+ public static ThreadContext current() {
+ for(ThreadGroup tg = Thread.currentThread().getThreadGroup(); tg != null; tg = tg.getParent()) {
+ if(tg instanceof ThreadContext)
+ return((ThreadContext)tg);
+ }
+ return(null);
+ }
}
public class J2eeContext implements ServerContext {
private ServletConfig cfg;
- private HttpServletRequest req;
- private HttpServletResponse resp;
+ private long ctime;
- J2eeContext(ServletConfig cfg, HttpServletRequest req, HttpServletResponse resp) {
+ J2eeContext(ServletConfig cfg) {
this.cfg = cfg;
- this.req = req;
- this.resp = resp;
- }
-
- public String rootpath() {
- return("/" + Misc.stripslashes(req.getContextPath(), true, true));
+ this.ctime = System.currentTimeMillis();
}
public long starttime() {
- return((Long)cfg.getServletContext().getAttribute("jsvc.starttime"));
+ return(ctime);
}
}
private HttpServletRequest req;
private HttpServletResponse resp;
private String method, path;
- private URL url;
+ private URL url, context;
private MultiMap<String, String> params = null;
private Map<Object, Object> props = new HashMap<Object, Object>();
q = "";
try {
url = new URL(scheme, host, port, req.getContextPath() + req.getServletPath() + pi + q);
+ context = new URL(scheme, host, port, req.getContextPath());
} catch(MalformedURLException e) {
throw(new Error(e));
}
return(props);
}
- public ServerContext ctx() {
- return(new J2eeContext(cfg, req, resp));
- }
-
public SocketAddress remoteaddr() {
try {
return(new InetSocketAddress(InetAddress.getByName(req.getRemoteAddr()), req.getRemotePort()));
return(url);
}
+ public URL rooturl() {
+ return(context);
+ }
+
+ public ServerContext ctx() {
+ return(ThreadContext.current().server());
+ }
+
public String method() {
return(method);
}
public class Servlet extends HttpServlet {
private ThreadContext tg;
- public void init() throws ServletException {
+ public void init(ServletConfig cfg) throws ServletException {
Properties sprop = new Properties();
try {
InputStream pi = Servlet.class.getClassLoader().getResourceAsStream("jsvc.properties");
} catch(ClassNotFoundException e) {
throw(new ServletException("Invalid JSvc bootstrapper specified", e));
}
- tg = new ThreadContext(null, "JSvc service", bc);
- ServletContext ctx = getServletContext();
- ctx.setAttribute("jsvc.starttime", System.currentTimeMillis());
+ tg = new ThreadContext(null, "JSvc service", new J2eeContext(cfg), bc);
}
public void destroy() {
public void respond(Request req) {
req.status(303);
URL url;
- String rel = req.ctx().rootpath() + "/" + Misc.stripslashes(path, true, false);
try {
- url = new URL(req.url(), rel);
+ url = new URL(req.rooturl(), Misc.stripslashes(path, true, false));
} catch(MalformedURLException e) {
- throw(new RuntimeException("Bad relative URL: + " + rel, e));
+ throw(new RuntimeException("Bad relative URL: + " + path, e));
}
req.outheaders().put("Location", url.toString());
}