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