Annotation of java/classes/org/w3c/jigsaw/servlet/ServletWrapper.java, revision 1.45

1.1       abaird      1: // ServletWrapper.java
1.45    ! bmahe       2: // $Id: ServletWrapper.java,v 1.44 1999/05/05 12:01:47 bmahe Exp $
1.1       abaird      3: // (c) COPYRIGHT MIT and INRIA, 1996.
                      4: // Please first read the full copyright statement in file COPYRIGHT.html
                      5: 
1.18      bmahe       6: package org.w3c.jigsaw.servlet;
1.1       abaird      7: 
                      8: import java.io.* ;
                      9: import java.util.*;
                     10: 
1.9       bmahe      11: import javax.servlet.*;
1.1       abaird     12: 
1.18      bmahe      13: import org.w3c.tools.resources.store.*;
1.40      bmahe      14: import org.w3c.tools.timers.*;
1.18      bmahe      15: import org.w3c.util.*;
                     16: import org.w3c.www.mime.*;
                     17: import org.w3c.www.http.*;
                     18: import org.w3c.jigsaw.http.*;
                     19: import org.w3c.tools.resources.*;
1.1       abaird     20: 
1.2       abaird     21: /**
                     22:  * @author Alexandre Rafalovitch <alex@access.com.au>
                     23:  * @author Anselm Baird-Smith <abaird@w3.org>
1.18      bmahe      24:  * @author Benoit Mahe <bmahe@w3.org>
1.2       abaird     25:  */
                     26: 
1.40      bmahe      27: public class ServletWrapper extends FramedResource 
                     28:     implements ServletConfig
1.1       abaird     29: {
                     30: 
1.40      bmahe      31:     protected class TimeoutManager implements EventHandler {
                     32: 
                     33:        private Object timer     = null;
                     34:        private httpd  server    = null;
                     35: 
                     36:        /**
                     37:         * Handle timer events. 
                     38:         * @param data The timer closure.
                     39:         * @param time The absolute time at which the event was triggered.
                     40:         * @see org.w3c.tools.timers.EventManager
                     41:         * @see org.w3c.tools.timers.EventHandler
                     42:         */
                     43:        public synchronized void handleTimerEvent(Object data, long time) {
                     44:            timer = null;
                     45:            destroyServlet();
                     46:        }
                     47: 
                     48:        private synchronized void setTimer(long ms) {
                     49:            if ( timer != null ) {
                     50:                server.timer.recallTimer(timer) ;
                     51:                timer = null ;
                     52:            }
                     53:            timer = server.timer.registerTimer(ms, this, null);
                     54:        }
                     55: 
                     56:        protected void restart() {
                     57:            start();
                     58:        }
                     59: 
                     60:        protected void start() {
1.45    ! bmahe      61:            long timeout = getServletTimeout();
        !            62:            if (timeout != -1)
        !            63:                setTimer(getServletTimeout());
1.40      bmahe      64:        }
                     65: 
                     66:        protected synchronized void stop() {
                     67:            if ( timer != null ) {
                     68:                server.timer.recallTimer(timer) ;
                     69:                timer = null;
                     70:            }
                     71:        }
                     72:        
                     73:        TimeoutManager(httpd server) {
                     74:            this.server = server;
                     75:        }
                     76: 
                     77:     }
                     78: 
                     79:     protected TimeoutManager timeoutManager = null;
                     80: 
                     81:     protected final static boolean debug = false;
1.9       bmahe      82: 
1.20      bmahe      83:     /**
                     84:      * Attributes index - The servlet class name.
                     85:      */
                     86:     protected static int ATTR_SERVLET_CLASS = -1 ;
                     87:     /**
1.40      bmahe      88:      * Attributes index - The servlet timeout
                     89:      */
                     90:     protected static int ATTR_SERVLET_TIMEOUT = -1 ;
                     91:     /**
1.20      bmahe      92:      * Attribute index - The init parameters for that servlet.
                     93:      */
                     94:     protected static int ATTR_PARAMETERS = 1;
                     95:     /**
                     96:      * Attribute index - Our parent-inherited servlet context.
                     97:      */
                     98:     protected static int ATTR_SERVLET_CONTEXT = -1;
                     99:     /**
1.28      bmahe     100:      * Attribute index - Our parent-inherited session context.
                    101:      */
                    102:     protected static int ATTR_SESSION_CONTEXT = -1;
1.20      bmahe     103: 
                    104:     static {
                    105:        Attribute a   = null ;
                    106:        Class     cls = null ;
                    107:        try {
                    108:            cls = Class.forName("org.w3c.jigsaw.servlet.ServletWrapper") ;
                    109:        } catch (Exception ex) {
                    110:            ex.printStackTrace();
                    111:            System.exit(0);
                    112:        }
                    113:        // The servlet class attribute.
                    114:        a = new StringAttribute("servlet-class"
1.1       abaird    115:                                , null
1.20      bmahe     116:                                , Attribute.EDITABLE | Attribute.MANDATORY) ;
                    117:        ATTR_SERVLET_CLASS = AttributeRegistry.registerAttribute(cls, a) ;
                    118:        // This servlet init parameters
                    119:        a = new PropertiesAttribute("servlet-parameters"
                    120:                                    , null
                    121:                                    , Attribute.EDITABLE);
                    122:        ATTR_PARAMETERS = AttributeRegistry.registerAttribute(cls, a);
                    123:        // Our servlet context:
                    124:        a = new ObjectAttribute("servlet-context",
1.24      bmahe     125:                                "org.w3c.jigsaw.servlet.JigsawServletContext",
1.20      bmahe     126:                                null,
                    127:                                Attribute.DONTSAVE);
                    128:        ATTR_SERVLET_CONTEXT = AttributeRegistry.registerAttribute(cls, a);
1.28      bmahe     129:        // Our session context:
                    130:        a = new ObjectAttribute("session-context",
                    131:                                     "org.w3c.jigsaw.servlet.JigsawHttpSessionContext",
                    132:                             null,
                    133:                             Attribute.DONTSAVE);
                    134:        ATTR_SESSION_CONTEXT = AttributeRegistry.registerAttribute(cls, a);
1.40      bmahe     135:        // The servlet timeout:
                    136:        a = new LongAttribute("servlet-timeout",
                    137:                              null,
                    138:                              Attribute.EDITABLE);
                    139:        ATTR_SERVLET_TIMEOUT = AttributeRegistry.registerAttribute(cls, a);
                    140: 
1.20      bmahe     141:     }
1.1       abaird    142:     
1.20      bmahe     143:     /**
                    144:      * The servlet wrapped within that Jigsaw resource.
                    145:      */
                    146:     protected Servlet servlet = null;
                    147:     /**
                    148:      * Is out servler initialized ?
                    149:      */
                    150:     protected boolean inited = false;
                    151: 
                    152:     /**
                    153:      * The Path where we can find the servlet class file.
                    154:      */
                    155:     public File getServletDirectory() {
1.25      bmahe     156:        ResourceReference rr = getParent();
                    157:        if (rr != null) {
                    158:            try {
                    159:                Resource parent = rr.lock();
                    160:                if (parent.definesAttribute("directory"))
                    161:                    return (File) parent.getValue("directory", null);
                    162:            } catch(InvalidResourceException ex) {
                    163:                ex.printStackTrace();
                    164:            } finally {
                    165:                rr.unlock();
                    166:            }
                    167:        }
                    168:        return null;
1.20      bmahe     169:     }
                    170: 
                    171:     /**
                    172:      * Servlet stub implementation - Get an init parameter value.
                    173:      */
                    174: 
                    175:     public synchronized String getInitParameter(String string) {
                    176:        ArrayDictionary d = getServletParameters();
                    177:        String          v = (d != null) ? (String) d.get(string) : null;
                    178:        return v;
                    179:     }
                    180: 
                    181:     /**
                    182:      * Servlet stub implementation - Get all init parameters.
                    183:      */
                    184: 
                    185:     public synchronized Enumeration getInitParameterNames() {
                    186:        // Convert init parameters to hashtable:
                    187:        ArrayDictionary d = getServletParameters();
                    188:        return (d != null) ? d.keys() : new EmptyEnumeration();
                    189:     }
                    190: 
                    191:     /**
                    192:      * Servlet stub implementation - Get that servlet context.
                    193:      */
                    194: 
                    195:     public ServletContext getServletContext() { 
                    196:        return (ServletContext) getValue(ATTR_SERVLET_CONTEXT, null);
                    197:     }
                    198: 
1.28      bmahe     199:     public JigsawHttpSessionContext getSessionContext() {
                    200:        return (JigsawHttpSessionContext) getValue(ATTR_SESSION_CONTEXT, null);
                    201:     }
                    202: 
1.40      bmahe     203:     protected long getServletTimeout() {
1.45    ! bmahe     204:        long timeout = getLong(ATTR_SERVLET_TIMEOUT, 0);
        !           205:        if (timeout == 0) {
1.40      bmahe     206:            JigsawServletContext ctxt = 
                    207:                (JigsawServletContext) getServletContext();
                    208:            timeout = ctxt.getServletTimeout();
                    209:        }
                    210:        return timeout;
                    211:     }
                    212: 
1.36      bmahe     213:     protected void invalidateAllSession() {
                    214:        if (debug)
                    215:            System.out.println("Invalidate All Session...");
                    216:        JigsawHttpSessionContext ctxt = getSessionContext();
                    217:        Enumeration enum = ctxt.getIds();
                    218:        while (enum.hasMoreElements())
                    219:            ctxt.getSession((String)enum.nextElement()).invalidate();
                    220:     }
                    221: 
1.37      bmahe     222:     /**
                    223:      * Check the servlet class, ans try to initialize it.
                    224:      * @exception ClassNotFoundException if servlet class can't be found.
                    225:      * @exception ServletException if servlet can't be initialized.
                    226:      */
1.36      bmahe     227:     protected void checkServlet() 
                    228:        throws ClassNotFoundException, ServletException
                    229:     {
                    230:        boolean classmodified =
                    231:            getLocalServletLoader().classChanged(getServletClass());
                    232: 
                    233:        if (classmodified ||
                    234:            (servlet == null) ||
                    235:            (servlet.getClass() != 
                    236:             getLocalServletLoader().loadClass(getServletClass())))
                    237:            {
                    238:                inited = launchServlet();
                    239:            }
1.20      bmahe     240:     }
                    241: 
                    242:     protected boolean isInited() {
                    243:        return inited;
                    244:     }
                    245: 
                    246:     protected void service(Request request, Reply reply)
                    247:        throws ServletException, IOException
                    248:     {
1.23      bmahe     249:        JigsawHttpServletResponse jRes = null;
                    250:        JigsawHttpServletRequest jReq = null;
                    251:        if (servlet instanceof SingleThreadModel) {
                    252:            synchronized (this) {
                    253:                jRes = new JigsawHttpServletResponse(request, reply);
1.28      bmahe     254:                jReq = new JigsawHttpServletRequest(servlet, 
                    255:                                                    request, 
                    256:                                                    jRes,
                    257:                                                    getSessionContext());
                    258:                jRes.setServletRequest(jReq);
1.23      bmahe     259:                servlet.service(jReq , jRes);
1.39      bmahe     260:                jRes.flushStream(true);
1.23      bmahe     261:            }
                    262:        } else {
1.31      bmahe     263:            jRes = new JigsawHttpServletResponse(request, reply);
                    264:            jReq = new JigsawHttpServletRequest(servlet, 
                    265:                                                request, 
                    266:                                                jRes,
                    267:                                                getSessionContext());
                    268:            jRes.setServletRequest(jReq);
                    269:            servlet.service(jReq , jRes);
1.39      bmahe     270:            jRes.flushStream(true);
1.23      bmahe     271:        }
1.40      bmahe     272:        timeoutManager.restart();
1.20      bmahe     273:     }
                    274: 
                    275:     /**
                    276:      * Get the class name of the wrapped servlet.
                    277:      * @return The class name for the servlet if attribute is defined. 
                    278:      * Otherwise the class name is deduced from the resource identifier.
                    279:      */
                    280: 
                    281:     public String getServletClass()
                    282:     {
                    283:        String sclass =  getString(ATTR_SERVLET_CLASS, null);
                    284:        if (sclass == null) {
                    285:            String ident = getIdentifier();
                    286:            if (ident.endsWith(".class"))
                    287:                sclass = ident;
                    288:        }
                    289:        return sclass;
                    290:     }
                    291: 
                    292:     /**
                    293:      * Get the init parameters for our wrapped servlet.
                    294:      * @return An ArrayDictionary instance if the attribute is defined, 
                    295:      * <strong>false</strong> otherwise.
                    296:      */
                    297: 
                    298:     public ArrayDictionary getServletParameters() {
                    299:        return (ArrayDictionary) getValue(ATTR_PARAMETERS, null);
                    300:     }
                    301: 
1.26      bmahe     302:     protected void setValueOfSuperClass(int idx, Object value) {
                    303:        super.setValue(idx, value);
                    304:     }
                    305: 
1.20      bmahe     306:     /**
                    307:      * Catch assignements to the servlet class name attribute.
                    308:      * <p>When a change to that attribute is detected, the servlet is
                    309:      * automatically reinitialized.
                    310:      */
                    311: 
                    312:     public void setValue(int idx, Object value) {
                    313:        super.setValue(idx, value);
1.44      bmahe     314:        if (((idx == ATTR_SERVLET_CLASS) && (value != null)) ||
                    315:            (idx == ATTR_PARAMETERS)) {
1.36      bmahe     316:            try {
                    317:                inited = launchServlet();
                    318:            } catch (Exception ex) {
                    319:                String msg = ("unable to set servlet class \""+
                    320:                              getServletClass()+
                    321:                              "\" : "+
                    322:                              ex.getMessage());
                    323:                getServer().errlog(msg);
                    324:            }
1.40      bmahe     325:        } if (idx == ATTR_SERVLET_TIMEOUT) {
                    326:            timeoutManager.restart();
1.36      bmahe     327:        }
1.20      bmahe     328:     }
                    329: 
                    330:     /**
                    331:      * Destroy the servlet we are wrapping.
                    332:      */
                    333: 
                    334:     protected synchronized void destroyServlet() {
                    335:        if (servlet != null) {
                    336:            servlet.destroy();
                    337:            servlet = null;
                    338:        }
                    339:     }
                    340: 
                    341:     /**
                    342:      * Get the servlet we are wrapping.
                    343:      * @return A servlet instance, if the servlet is alredy running, 
                    344:      * <strong>null</strong> otherwise.
                    345:      */
                    346: 
1.34      bmahe     347:     public synchronized Servlet getServlet() {
1.36      bmahe     348:        try {
                    349:            checkServlet();
                    350:        } catch (Exception ex) {
                    351:            if (debug)
                    352:                ex.printStackTrace();
                    353:        }
1.20      bmahe     354:        return servlet;
                    355:     }
                    356: 
                    357:     /**
                    358:      * Initialize our servlet from the given (loaded) class.
                    359:      * @param cls The servlet loaded main class.
                    360:      * @return A boolean, <strong>true</strong> if servlet was successfully
                    361:      * initialised, <strong>false</strong> otherwise.
1.37      bmahe     362:      * @exception ServletException if servlet can't be initialized.
1.20      bmahe     363:      */
                    364: 
1.36      bmahe     365:     protected boolean launchServlet(Class cls) 
                    366:        throws ServletException
                    367:     {
1.20      bmahe     368:        try {
                    369:            servlet = (Servlet) cls.newInstance();
                    370:            servlet.init((ServletConfig) this);
1.40      bmahe     371:            timeoutManager.restart();
1.36      bmahe     372:        } catch (IllegalAccessException ex) {
                    373:            String msg = ("Illegal access during servlet instantiation, "+
1.34      bmahe     374:                          ex.getClass().getName()+": "+
1.20      bmahe     375:                          ex.getMessage());
                    376:            if ( debug )
                    377:                ex.printStackTrace();
                    378:            getServer().errlog(this, msg);
                    379:            return false;
1.36      bmahe     380:        } catch (InstantiationException iex) {
                    381:            String msg = ("unable to instantiate servlet, "+
                    382:                          iex.getClass().getName()+": "+
                    383:                          iex.getMessage());
                    384:            if ( debug )
                    385:                iex.printStackTrace();
                    386:            getServer().errlog(this, msg);
                    387:            return false;
1.20      bmahe     388:        }
                    389:        return (servlet != null) ;
1.32      bmahe     390:     }
                    391: 
                    392:     /**
                    393:      * Check if the Servletclass wrapped is a Servlet class without
1.36      bmahe     394:      * initializing it. (not the same than checkServlet).
1.33      bmahe     395:      * used by the ServletIndexer.
                    396:      * @see org.w3c.jigsaw.servlet.ServletIndexer
1.32      bmahe     397:      * @return A boolean.
                    398:      */
                    399:     protected boolean isWrappingAServlet() {
                    400:        String clsname = getServletClass();
                    401:        if ( clsname == null ) 
                    402:            return false;
                    403:        Class c = null;
                    404:        try {
1.34      bmahe     405:            c = getLocalServletLoader().loadClass(clsname, true);
1.32      bmahe     406:            Object o = c.newInstance();
                    407:            return (o instanceof Servlet);
                    408:        } catch (Exception ex) {
                    409:            return false;
                    410:        }
1.20      bmahe     411:     }
                    412: 
                    413:     /**
                    414:      * Launch the servlet we are wrapping.
                    415:      * <p>This method either succeed, or the wrapper resource itself will fail
                    416:      * to initialize, acting as transparently as possible (in some sense).
                    417:      * @return A boolean, <strong>true</strong> if servlet launched.
1.37      bmahe     418:      * @exception ClassNotFoundException if servlet class can't be found.
                    419:      * @exception ServletException if servlet can't be initialized.
1.20      bmahe     420:      */
                    421: 
1.36      bmahe     422:     protected boolean launchServlet() 
                    423:        throws ClassNotFoundException, ServletException
                    424:     {
1.20      bmahe     425:        // Get and check the servlet class:
                    426:        if ( servlet != null )
                    427:            destroyServlet();
                    428:        String clsname = getServletClass();
                    429:        if ( clsname == null ) {
                    430:            getServer().errlog(this, "no servlet class attribute defined.");
                    431:            return false;
                    432:        } else {
                    433:            Class c = null;
                    434:            try {
1.36      bmahe     435:                if (getLocalServletLoader().classChanged(clsname)) {
1.34      bmahe     436:                    createNewLocalServletLoader(true);
1.36      bmahe     437:                    invalidateAllSession();
                    438:                }
1.34      bmahe     439:                c = getLocalServletLoader().loadClass(clsname, true);
1.20      bmahe     440:            } catch (ClassNotFoundException ex) {
1.36      bmahe     441:                String msg = ("unable to find servlet class \""+
                    442:                              getServletClass()+"\"");
1.20      bmahe     443:                getServer().errlog(msg);
1.36      bmahe     444:                // re throw the exception
                    445:                throw ex;
1.20      bmahe     446:            }
                    447:            return (c != null) ? launchServlet(c) : false;
                    448:        }
                    449:     }
                    450: 
1.40      bmahe     451:     public boolean acceptUnload() {
                    452:        return (servlet == null);
                    453:     }
                    454: 
1.20      bmahe     455:     public void notifyUnload() {
1.42      bmahe     456:        if (timeoutManager != null)
                    457:            timeoutManager.stop();
1.20      bmahe     458:        destroyServlet();
1.26      bmahe     459:     }
                    460: 
                    461:     /** 
                    462:      * Get or create a suitable LocalServletLoader instance to load 
                    463:      * that servlet.
                    464:      * @return A LocalServletLoader instance.
                    465:      */
                    466: 
1.34      bmahe     467:     protected synchronized AutoReloadServletLoader getLocalServletLoader() {
                    468:        JigsawServletContext ctxt = (JigsawServletContext) getServletContext();
                    469:        return ctxt.getLocalServletLoader();
1.26      bmahe     470:     }
                    471: 
1.34      bmahe     472:     protected 
                    473:        AutoReloadServletLoader createNewLocalServletLoader(boolean keepold) 
1.26      bmahe     474:     {
1.34      bmahe     475:        JigsawServletContext ctxt = (JigsawServletContext) getServletContext();
                    476:        return ctxt.createNewLocalServletLoader(keepold);
1.20      bmahe     477:     }
                    478: 
                    479:     /**
                    480:      * Initialize this servlet wrapper resource.
                    481:      * After the wrapper itself is inited, it performs the servlet 
                    482:      * initialzation.
                    483:      * @param values The default attribute values.
                    484:      */
                    485: 
                    486:     public void initialize(Object values[]) {
                    487:        super.initialize(values);
1.40      bmahe     488: 
1.41      bmahe     489:        
                    490:        if (getServletContext() != null) {
                    491:            timeoutManager = new TimeoutManager((httpd)getServer());
                    492:            timeoutManager.start();
                    493:        }
1.40      bmahe     494: 
1.20      bmahe     495:        // Initialize the wrapped servlet (is now the rigt time ?)
1.36      bmahe     496:        if ( getServletClass() != null ) {
                    497:            try {
                    498:                inited = launchServlet();
1.43      bmahe     499:            } catch (ServletException ex) {
                    500:                System.err.println(ex.toString());
1.36      bmahe     501:            } catch (Exception ex) {
                    502:                //this could be a "normal" exception.
                    503:            }
                    504:        }
1.20      bmahe     505:        try {
                    506:            registerFrameIfNone("org.w3c.jigsaw.servlet.ServletWrapperFrame",
                    507:                                "servlet-wrapper-frame");
                    508:        } catch (Exception ex) {
                    509:            ex.printStackTrace();
                    510:        }
1.40      bmahe     511:        
1.18      bmahe     512:     }
1.1       abaird    513: 
                    514: }
                    515: 
                    516: 
                    517: 
                    518: 
                    519: 
                    520: 
                    521: 
                    522: 

Webmaster