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

1.1       abaird      1: // ServletWrapper.java
1.40    ! bmahe       2: // $Id: ServletWrapper.java,v 1.39 1999/03/18 14:37:26 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.40    ! bmahe     453:        timeoutManager.stop();
1.20      bmahe     454:        destroyServlet();
1.26      bmahe     455:     }
                    456: 
                    457:     /** 
                    458:      * Get or create a suitable LocalServletLoader instance to load 
                    459:      * that servlet.
                    460:      * @return A LocalServletLoader instance.
                    461:      */
                    462: 
1.34      bmahe     463:     protected synchronized AutoReloadServletLoader getLocalServletLoader() {
                    464:        JigsawServletContext ctxt = (JigsawServletContext) getServletContext();
                    465:        return ctxt.getLocalServletLoader();
1.26      bmahe     466:     }
                    467: 
1.34      bmahe     468:     protected 
                    469:        AutoReloadServletLoader createNewLocalServletLoader(boolean keepold) 
1.26      bmahe     470:     {
1.34      bmahe     471:        JigsawServletContext ctxt = (JigsawServletContext) getServletContext();
                    472:        return ctxt.createNewLocalServletLoader(keepold);
1.20      bmahe     473:     }
                    474: 
                    475:     /**
                    476:      * Initialize this servlet wrapper resource.
                    477:      * After the wrapper itself is inited, it performs the servlet 
                    478:      * initialzation.
                    479:      * @param values The default attribute values.
                    480:      */
                    481: 
                    482:     public void initialize(Object values[]) {
                    483:        super.initialize(values);
1.40    ! bmahe     484: 
        !           485:        timeoutManager = new TimeoutManager((httpd)getServer());
        !           486:        timeoutManager.start();
        !           487: 
1.20      bmahe     488:        // Initialize the wrapped servlet (is now the rigt time ?)
1.36      bmahe     489:        if ( getServletClass() != null ) {
                    490:            try {
                    491:                inited = launchServlet();
                    492:            } catch (Exception ex) {
                    493:                //this could be a "normal" exception.
                    494:            }
                    495:        }
1.20      bmahe     496:        try {
                    497:            registerFrameIfNone("org.w3c.jigsaw.servlet.ServletWrapperFrame",
                    498:                                "servlet-wrapper-frame");
                    499:        } catch (Exception ex) {
                    500:            ex.printStackTrace();
                    501:        }
1.40    ! bmahe     502:        
1.18      bmahe     503:     }
1.1       abaird    504: 
                    505: }
                    506: 
                    507: 
                    508: 
                    509: 
                    510: 
                    511: 
                    512: 
                    513: 

Webmaster