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