Annotation of java/classes/org/w3c/jigsaw/servlet/ServletWrapperFrame.java, revision 1.27
1.1 bmahe 1: // ServletWrapperFrame.java
1.27 ! ylafon 2: // $Id: ServletWrapperFrame.java,v 1.26 2012/06/16 15:48:46 ylafon Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT and INRIA, 1996.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5:
6: package org.w3c.jigsaw.servlet;
7:
1.26 ylafon 8: import org.w3c.jigsaw.frames.HTTPFrame;
1.15 ylafon 9: import org.w3c.jigsaw.http.HTTPException;
10: import org.w3c.jigsaw.http.Reply;
11: import org.w3c.jigsaw.http.Request;
1.26 ylafon 12: import org.w3c.jigsaw.http.httpd;
1.15 ylafon 13: import org.w3c.tools.resources.FramedResource;
14: import org.w3c.tools.resources.LookupResult;
15: import org.w3c.tools.resources.LookupState;
16: import org.w3c.tools.resources.ProtocolException;
17: import org.w3c.tools.resources.ReplyInterface;
18: import org.w3c.tools.resources.RequestInterface;
19: import org.w3c.tools.resources.ResourceException;
1.18 ylafon 20: import org.w3c.tools.resources.ServerInterface;
1.26 ylafon 21: import org.w3c.www.http.HTTP;
22: import org.w3c.www.mime.MimeType;
1.1 bmahe 23:
1.26 ylafon 24: import javax.servlet.ServletException;
25: import javax.servlet.UnavailableException;
26: import java.io.IOException;
27: import java.io.PipedInputStream;
28: import java.io.PipedOutputStream;
1.2 bmahe 29:
1.1 bmahe 30: /**
31: * @author Alexandre Rafalovitch <alex@access.com.au>
32: * @author Anselm Baird-Smith <abaird@w3.org>
33: * @author Benoit Mahe <bmahe@w3.org>
34: */
35:
36: public class ServletWrapperFrame extends HTTPFrame {
37:
1.5 ylafon 38: protected ServletWrapper wrapper = null;
1.1 bmahe 39:
1.9 bmahe 40: /**
41: * Register our resource. Must be an instance of ServletWrapper.
42: */
1.5 ylafon 43: public void registerResource(FramedResource resource) {
44: super.registerOtherResource(resource);
45: if (resource instanceof ServletWrapper)
46: wrapper = (ServletWrapper) resource;
1.1 bmahe 47: }
48:
1.5 ylafon 49: /**
50: * Create a reply to answer to request on this file.
51: * This method will create a suitable reply (matching the given request)
52: * and will set all its default header values to the appropriate
53: * values. The reply will not have LastModified field setted.
54: * @param request The request to make a reply for.
55: * @return An instance of Reply, suited to answer this request.
56: */
57:
58: public Reply createDefaultReply(Request request, int status) {
59: Reply reply = super.createDefaultReply(request, status);
60: reply.setLastModified( -1 );
61: return reply;
62: }
1.1 bmahe 63:
1.5 ylafon 64: /**
65: * Dispatch the give request to our servlet.
66: * <p>If the servlet cannot be inititalized, we just throw an error message
67: * otherwise, we just delegate that request processing to the underlying
68: * servlet instance.
1.26 ylafon 69: * @param req The request to be processed.
1.5 ylafon 70: * @exception ProtocolException If the wrapped servlet is not initialized.
1.11 bmahe 71: * @exception ResourceException If the resource got a fatal error.
1.5 ylafon 72: */
73:
74: public ReplyInterface perform(RequestInterface req)
1.11 bmahe 75: throws ProtocolException, ResourceException
1.5 ylafon 76: {
77: ReplyInterface repi = performFrames(req);
78: if (repi != null)
79: return repi;
80:
81: if (! checkRequest(req))
82: return null;
83:
84: Request request = (Request) req;
1.22 ylafon 85: PipedInputStream pis = null;
1.5 ylafon 86:
87: if (wrapper == null) {
88: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
89: reply.setContent("Servlet Wrapper Frame not configured properly: "+
90: "must be attached to a ServletWrapper.");
91: throw new HTTPException(reply);
92: }
93:
1.10 bmahe 94: try {
95: wrapper.checkServlet();
96: } catch (ClassNotFoundException ex) {
97: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
98: reply.setContent("The server was unable to find the "+
99: "servlet class : "+ex.getMessage());
1.27 ! ylafon 100: if (ServletWrapper.debug)
1.10 bmahe 101: ex.printStackTrace();
102: throw new HTTPException(reply);
103: } catch (ServletException ex) {
104: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
105: reply.setContent("The server was unable to initialize the "+
106: "servlet : "+ex.getMessage());
1.27 ! ylafon 107: if (ServletWrapper.debug)
1.10 bmahe 108: ex.printStackTrace();
109: throw new HTTPException(reply);
110: }
1.5 ylafon 111:
1.8 bmahe 112: // Check that the servlet has been initialized properly:
1.5 ylafon 113: if ( ! wrapper.isInited() ) {
114: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
115: reply.setContent("Servlet not configured properly");
116: throw new HTTPException(reply);
117: }
118: // Dispatch the request:
119: Reply reply = createDefaultReply(request, HTTP.OK);
120: reply.setContentType(MimeType.TEXT_HTML);
121: try {
1.17 ylafon 122: if (request.hasState(JigsawHttpServletResponse.INCLUDED)) {
1.16 ylafon 123: wrapper.service(request, reply);
1.17 ylafon 124: } else {
1.22 ylafon 125: pis = new PipedInputStream();
126: request.setState(JigsawHttpServletResponse.STREAM, pis);
1.17 ylafon 127: PipedOutputStream pos = new PipedOutputStream(pis);
128: reply.setState(JigsawHttpServletResponse.STREAM, pos);
129: reply.setStream(pis);
130: Object o = new Object();
131: reply.setState(JigsawHttpServletResponse.MONITOR, o);
132: // wait until the reply is constructed by the processing thread
1.18 ylafon 133: ServerInterface server = getServer();
134: if (server instanceof httpd) {
135: synchronized (o) {
136: wrapper.service(request, reply);
137: o.wait((long)((httpd)server).getRequestTimeOut());
138: }
139: Object strm;
140: strm = reply.getState(JigsawHttpServletResponse.STREAM);
141: if (strm != null) {
142: // it is a timeout
143: try {
1.19 ylafon 144: pis.close();
1.25 ylafon 145: } catch (IOException ex) {};
146: try {
1.18 ylafon 147: pos.close();
148: } catch (IOException ex) {};
1.21 ylafon 149: if (strm instanceof PipedOutputStream) {
1.24 ylafon 150: ServletWrapper.ServletRunner r;
151: r = (ServletWrapper.ServletRunner)
152: reply.getState(ServletWrapper.RUNNER);
1.21 ylafon 153: if (r != null) {
1.24 ylafon 154: r.signalTimeout();
1.21 ylafon 155: }
156: throw new ServletException("Timed out");
1.20 ylafon 157: }
1.19 ylafon 158: }
1.18 ylafon 159: } else {
160: synchronized (o) {
161: wrapper.service(request, reply);
162: o.wait();
163: }
1.17 ylafon 164: }
1.16 ylafon 165: }
1.6 bmahe 166: } catch (UnavailableException uex) {
1.13 ylafon 167: reply = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
1.6 bmahe 168: if (uex.isPermanent()) {
169: reply.setContent("<h2>The servlet is permanently "+
170: "unavailable :</h2>"+
171: "Details: <b>"+uex.getMessage()+"</b>");
172: } else {
173: int delay = uex.getUnavailableSeconds();
1.13 ylafon 174: if (delay > 0) {
175: reply.setRetryAfter(delay);
1.6 bmahe 176: reply.setContent("<h2>The servlet is temporarily "+
177: "unavailable :</h2>"+
1.7 bmahe 178: "Delay : "+delay+
1.6 bmahe 179: " seconds<br><br>Details: <b>"+
180: uex.getMessage()+"</b>");
1.13 ylafon 181: } else {
1.6 bmahe 182: reply.setContent("<h2>The servlet is temporarily "+
183: "unavailable :</h2>"+
184: "Details: <b>"+uex.getMessage()+"</b>");
1.13 ylafon 185: }
1.6 bmahe 186: }
1.22 ylafon 187: if (pis != null) {
188: try {
189: pis.close();
190: } catch (IOException ioex) {}
191: }
1.5 ylafon 192: } catch (Exception ex) {
1.27 ! ylafon 193: if (ServletWrapper.debug)
1.5 ylafon 194: ex.printStackTrace();
195: reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
196: reply.setContent("Servlet has thrown exception:" + ex.toString());
1.22 ylafon 197: if (pis != null) {
198: try {
199: pis.close();
200: } catch (IOException ioex) {}
201: }
1.23 ylafon 202: }
203: if (reply != null) {
204: reply.setDynamic(true);
1.5 ylafon 205: }
206: return reply;
1.1 bmahe 207: }
1.15 ylafon 208:
1.5 ylafon 209: /**
210: * Jigsaw's lookup on servlets.
211: * Once here, we have reached a leaf servlet (or at least the remaining
212: * lookup is to be done at the servlet itself). We keep track of the
213: * <em>path info</em> and mark that servlet as the target of request.
214: * @param ls The lookup state.
215: * @param lr The lookup result.
216: * @exception ProtocolException If some error occurs.
217: */
218:
219: protected boolean lookupOther(LookupState ls, LookupResult lr)
220: throws ProtocolException
221: {
222: // Get the extra path information:
223: String extraPath = ls.getRemainingPath(true);
224: if ((extraPath == null) || extraPath.equals(""))
225: extraPath = "/";
226: // Keep this path info into the request, if possible:
227: Request request = (Request) ls.getRequest();
1.12 bmahe 228: if ( request != null ) {
1.14 bmahe 229: if (request.getState(JigsawRequestDispatcher.PATH_INFO_P) == null)
230: request.setState(JigsawRequestDispatcher.PATH_INFO_P,
231: extraPath);
1.12 bmahe 232: }
1.5 ylafon 233: lr.setTarget(resource.getResourceReference());
234: return super.lookupOther(ls, lr);
235: }
1.1 bmahe 236:
237: }
Webmaster