001: // ServletWrapperFrame.java
002: // $Id: ServletWrapperFrame.java,v 1.24 2004/10/06 09:54:12 ylafon Exp $
003: // (c) COPYRIGHT MIT and INRIA, 1996.
004: // Please first read the full copyright statement in file COPYRIGHT.html
005:
006: package org.w3c.jigsaw.servlet;
007:
008: import javax.servlet.ServletException;
009: import javax.servlet.UnavailableException;
010:
011: import java.io.IOException;
012: import java.io.PipedInputStream;
013: import java.io.PipedOutputStream;
014:
015: import org.w3c.www.mime.MimeType;
016:
017: import org.w3c.www.http.HTTP;
018: import org.w3c.www.http.HttpEntityMessage;
019: import org.w3c.www.http.HttpMessage;
020: import org.w3c.www.http.HttpReplyMessage;
021:
022: import org.w3c.jigsaw.http.httpd;
023: import org.w3c.jigsaw.http.HTTPException;
024: import org.w3c.jigsaw.http.Reply;
025: import org.w3c.jigsaw.http.Request;
026:
027: import org.w3c.jigsaw.frames.HTTPFrame;
028:
029: import org.w3c.tools.resources.FramedResource;
030: import org.w3c.tools.resources.LookupResult;
031: import org.w3c.tools.resources.LookupState;
032: import org.w3c.tools.resources.ProtocolException;
033: import org.w3c.tools.resources.ReplyInterface;
034: import org.w3c.tools.resources.RequestInterface;
035: import org.w3c.tools.resources.Resource;
036: import org.w3c.tools.resources.ResourceException;
037: import org.w3c.tools.resources.ResourceFrame;
038: import org.w3c.tools.resources.ServerInterface;
039:
040: import org.w3c.tools.resources.ProtocolException;
041: import org.w3c.tools.resources.ResourceException;
042:
043: /**
044: * @author Alexandre Rafalovitch <alex@access.com.au>
045: * @author Anselm Baird-Smith <abaird@w3.org>
046: * @author Benoit Mahe <bmahe@w3.org>
047: */
048:
049: public class ServletWrapperFrame extends HTTPFrame {
050:
051: protected ServletWrapper wrapper = null;
052:
053: /**
054: * Register our resource. Must be an instance of ServletWrapper.
055: */
056: public void registerResource(FramedResource resource) {
057: super .registerOtherResource(resource);
058: if (resource instanceof ServletWrapper)
059: wrapper = (ServletWrapper) resource;
060: }
061:
062: /**
063: * Create a reply to answer to request on this file.
064: * This method will create a suitable reply (matching the given request)
065: * and will set all its default header values to the appropriate
066: * values. The reply will not have LastModified field setted.
067: * @param request The request to make a reply for.
068: * @return An instance of Reply, suited to answer this request.
069: */
070:
071: public Reply createDefaultReply(Request request, int status) {
072: Reply reply = super .createDefaultReply(request, status);
073: reply.setLastModified(-1);
074: return reply;
075: }
076:
077: /**
078: * Dispatch the give request to our servlet.
079: * <p>If the servlet cannot be inititalized, we just throw an error message
080: * otherwise, we just delegate that request processing to the underlying
081: * servlet instance.
082: * @param request The request to be processed.
083: * @exception ProtocolException If the wrapped servlet is not initialized.
084: * @exception ResourceException If the resource got a fatal error.
085: */
086:
087: public ReplyInterface perform(RequestInterface req)
088: throws ProtocolException, ResourceException {
089: ReplyInterface repi = performFrames(req);
090: if (repi != null)
091: return repi;
092:
093: if (!checkRequest(req))
094: return null;
095:
096: Request request = (Request) req;
097: PipedInputStream pis = null;
098:
099: if (wrapper == null) {
100: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
101: reply
102: .setContent("Servlet Wrapper Frame not configured properly: "
103: + "must be attached to a ServletWrapper.");
104: throw new HTTPException(reply);
105: }
106:
107: try {
108: wrapper.checkServlet();
109: } catch (ClassNotFoundException ex) {
110: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
111: reply.setContent("The server was unable to find the "
112: + "servlet class : " + ex.getMessage());
113: if (wrapper.debug)
114: ex.printStackTrace();
115: throw new HTTPException(reply);
116: } catch (ServletException ex) {
117: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
118: reply.setContent("The server was unable to initialize the "
119: + "servlet : " + ex.getMessage());
120: if (wrapper.debug)
121: ex.printStackTrace();
122: throw new HTTPException(reply);
123: }
124:
125: // Check that the servlet has been initialized properly:
126: if (!wrapper.isInited()) {
127: Reply reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
128: reply.setContent("Servlet not configured properly");
129: throw new HTTPException(reply);
130: }
131: // Dispatch the request:
132: Reply reply = createDefaultReply(request, HTTP.OK);
133: reply.setContentType(MimeType.TEXT_HTML);
134: try {
135: if (request.hasState(JigsawHttpServletResponse.INCLUDED)) {
136: wrapper.service(request, reply);
137: } else {
138: pis = new PipedInputStream();
139: request.setState(JigsawHttpServletResponse.STREAM, pis);
140: PipedOutputStream pos = new PipedOutputStream(pis);
141: reply.setState(JigsawHttpServletResponse.STREAM, pos);
142: reply.setStream(pis);
143: Object o = new Object();
144: reply.setState(JigsawHttpServletResponse.MONITOR, o);
145: // wait until the reply is constructed by the processing thread
146: ServerInterface server = getServer();
147: if (server instanceof httpd) {
148: synchronized (o) {
149: wrapper.service(request, reply);
150: o.wait((long) ((httpd) server)
151: .getRequestTimeOut());
152: }
153: Object strm;
154: strm = reply
155: .getState(JigsawHttpServletResponse.STREAM);
156: if (strm != null) {
157: // it is a timeout
158: try {
159: pis.close();
160: pos.close();
161: } catch (IOException ex) {
162: }
163: ;
164: if (strm instanceof PipedOutputStream) {
165: ServletWrapper.ServletRunner r;
166: r = (ServletWrapper.ServletRunner) reply
167: .getState(ServletWrapper.RUNNER);
168: if (r != null) {
169: r.signalTimeout();
170: }
171: throw new ServletException("Timed out");
172: }
173: }
174: } else {
175: synchronized (o) {
176: wrapper.service(request, reply);
177: o.wait();
178: }
179: }
180: }
181: } catch (UnavailableException uex) {
182: reply = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
183: if (uex.isPermanent()) {
184: reply.setContent("<h2>The servlet is permanently "
185: + "unavailable :</h2>" + "Details: <b>"
186: + uex.getMessage() + "</b>");
187: } else {
188: int delay = uex.getUnavailableSeconds();
189: if (delay > 0) {
190: reply.setRetryAfter(delay);
191: reply.setContent("<h2>The servlet is temporarily "
192: + "unavailable :</h2>" + "Delay : " + delay
193: + " seconds<br><br>Details: <b>"
194: + uex.getMessage() + "</b>");
195: } else {
196: reply.setContent("<h2>The servlet is temporarily "
197: + "unavailable :</h2>" + "Details: <b>"
198: + uex.getMessage() + "</b>");
199: }
200: }
201: if (pis != null) {
202: try {
203: pis.close();
204: } catch (IOException ioex) {
205: }
206: }
207: } catch (Exception ex) {
208: if (wrapper.debug)
209: ex.printStackTrace();
210: reply = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
211: reply.setContent("Servlet has thrown exception:"
212: + ex.toString());
213: if (pis != null) {
214: try {
215: pis.close();
216: } catch (IOException ioex) {
217: }
218: }
219: }
220: if (reply != null) {
221: reply.setDynamic(true);
222: }
223: return reply;
224: }
225:
226: /**
227: * Jigsaw's lookup on servlets.
228: * Once here, we have reached a leaf servlet (or at least the remaining
229: * lookup is to be done at the servlet itself). We keep track of the
230: * <em>path info</em> and mark that servlet as the target of request.
231: * @param ls The lookup state.
232: * @param lr The lookup result.
233: * @exception ProtocolException If some error occurs.
234: */
235:
236: protected boolean lookupOther(LookupState ls, LookupResult lr)
237: throws ProtocolException {
238: // Get the extra path information:
239: String extraPath = ls.getRemainingPath(true);
240: if ((extraPath == null) || extraPath.equals(""))
241: extraPath = "/";
242: // Keep this path info into the request, if possible:
243: Request request = (Request) ls.getRequest();
244: if (request != null) {
245: if (request.getState(JigsawRequestDispatcher.PATH_INFO_P) == null)
246: request.setState(JigsawRequestDispatcher.PATH_INFO_P,
247: extraPath);
248: }
249: lr.setTarget(resource.getResourceReference());
250: return super.lookupOther(ls, lr);
251: }
252:
253: }
|