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

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

Webmaster