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