Annotation of java/classes/org/w3c/jigsaw/servlet/JigsawServletContext.java, revision 1.24.4.6
1.1 bmahe 1: // JigsawServletContext.java
1.24.4.6! bmahe 2: // $Id: JigsawServletContext.java,v 1.28 2000/03/09 17:02:07 bmahe Exp $
1.1 bmahe 3: // (c) COPYRIGHT MIT and INRIA, 1998.
4: // Please first read the full copyright statement in file COPYRIGHT.html
5:
6: package org.w3c.jigsaw.servlet;
7:
8: import java.io.*;
9: import java.net.*;
10: import java.util.*;
11:
12: import javax.servlet.*;
13:
1.11 bmahe 14: import org.w3c.util.*;
1.1 bmahe 15: import org.w3c.tools.resources.store.*;
1.5 bmahe 16: import org.w3c.tools.resources.event.*;
1.1 bmahe 17: import org.w3c.tools.resources.*;
18: import org.w3c.jigsaw.frames.*;
1.24.4.3 bmahe 19: import org.w3c.jigsaw.proxy.ForwardFrame;
1.22 bmahe 20: import org.w3c.jigsaw.resources.VirtualHostResource;
1.20 bmahe 21: import org.w3c.jigsaw.http.httpd;
1.1 bmahe 22:
23: /**
1.24.4.6! bmahe 24: * @version $Revision: 1.28 $
1.1 bmahe 25: * @author Benoît Mahé (bmahe@w3.org)
26: */
1.5 bmahe 27: public class JigsawServletContext extends StructureChangedAdapter
28: implements ServletContext,
1.11 bmahe 29: PropertyMonitoring
1.5 bmahe 30: {
31:
1.24.4.2 bmahe 32: public static final String TEMPDIR_P = "javax.servlet.context.tempdir";
33:
1.5 bmahe 34: class Logger {
35: File logfile = null;
36: RandomAccessFile log = null ;
37: byte msgbuf[] = null ;
38: boolean closed = true;
39:
40: private final String monthnames[] = {
41: "Jan", "Feb", "Mar", "Apr", "May", "Jun",
1.18 bmahe 42: "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
1.5 bmahe 43: };
44:
45: String getDate() {
46: Date now = new Date();
47: return (now.getDate()
48: + "/" + monthnames[now.getMonth()]
49: + "/" + (now.getYear() + 1900)
50: + ((now.getHours() < 10)
51: ? (":0" + now.getHours())
52: : (":" + now.getHours()))
53: + ((now.getMinutes() < 10)
54: ? (":0" + now.getMinutes())
55: : (":" + now.getMinutes()))
56: + ((now.getSeconds() < 10)
57: ? (":0" + now.getSeconds())
58: : (":" + now.getSeconds()))
59: + ((now.getTimezoneOffset() < 0)
60: ? " " + (now.getTimezoneOffset() / 60)
61: : " +" + (now.getTimezoneOffset() / 60)));
62: }
63:
64: void log(String msg) {
65: msg = "["+getDate()+"] "+msg+"\n";
66: try {
67: if ( log == null || closed)
68: openLogFile();
69: if ( log != null ) {
70: int len = msg.length() ;
71: if ( len > msgbuf.length )
72: msgbuf = new byte[len] ;
73: msg.getBytes (0, len, msgbuf, 0) ;
74: log.write (msgbuf, 0, len) ;
75: }
76: } catch (IOException ex) {
1.7 bmahe 77: System.out.println("Can't write ("+
78: msg+") to logfile ["+
79: logfile+"] : "+ex.getMessage());
1.5 bmahe 80: }
81: }
82:
83: void log(Exception ex, String msg) {
1.15 bmahe 84: log(msg+" : "+ex.getClass().getName()+" ("+ex.getMessage()+")");
1.5 bmahe 85: }
86:
1.20 bmahe 87: void log(Throwable throwable, String msg) {
88: ByteArrayOutputStream out = new ByteArrayOutputStream();
89: PrintWriter writer = new PrintWriter(out);
90: throwable.printStackTrace(writer);
91: writer.close();
92: String stacktrace = out.toString();
93: log(msg+" "+stacktrace);
94: }
95:
1.5 bmahe 96: void openLogFile()
97: throws IOException
98: {
99: RandomAccessFile old = log ;
100: log = new RandomAccessFile (logfile, "rw") ;
101: log.seek (log.length()) ;
102: closed = false;
103: if ( old != null )
104: old.close () ;
105: }
106:
107: void close() {
108: try {
109: if (log != null)
110: log.close();
111: closed = true;
112: } catch (IOException ex) {
113: ex.printStackTrace();
114: }
115: }
116:
117: Logger(File logfile) {
118: this.logfile = logfile;
119: this.msgbuf = new byte[128] ;
120: log("Servlet Logger started");
121: }
122: }
1.9 bmahe 123:
1.1 bmahe 124: private ResourceReference reference = null;
125:
1.5 bmahe 126: private Logger logger = null;
127:
1.11 bmahe 128: private ObservableProperties props = null;
129:
1.15 bmahe 130: private File directory = null;
131:
1.20 bmahe 132: private Hashtable attributes = null;
133:
1.12 bmahe 134: protected static String logdir = "logs" ;
135:
136: protected static String deflogfile = "servlets";
137:
1.11 bmahe 138: public boolean propertyChanged (String name) {
1.13 bmahe 139: if (name.equals(ServletProps.SERVLET_LOG_FILE_P)) {
1.5 bmahe 140: if (logger != null) {
141: logger.close();
1.24.4.3 bmahe 142: File newlogfile = new File((String)
143: props.get(ServletProps.SERVLET_LOG_FILE_P));
1.11 bmahe 144: if (newlogfile.getPath().length() < 1)
1.7 bmahe 145: newlogfile = getServletLogFile();
146: logger = new Logger(newlogfile);
1.5 bmahe 147: }
148: }
1.11 bmahe 149: return true;
1.5 bmahe 150: }
151:
152: public void resourceUnloaded(StructureChangedEvent evt){
153: if (logger != null) {
154: logger.close();
155: }
1.21 bmahe 156: }
157:
158: protected long getServletTimeout() {
1.23 bmahe 159: return props.getLong(ServletProps.SERVLET_TIMEOUT, -1);
1.5 bmahe 160: }
161:
1.1 bmahe 162: /**
163: * A useful utility routine that tries to guess the content-type
164: * of an object based upon its extension.
165: */
166: protected static String guessContentTypeFromName(String fname) {
1.17 bmahe 167: return org.w3c.www.mime.Utils.guessContentTypeFromName(fname);
1.1 bmahe 168: }
169:
170: /**
171: * ServletContext implementation - Get the MIME type for given file.
172: */
173:
174: public String getMimeType(String filename) {
175: return guessContentTypeFromName(filename);
1.7 bmahe 176: }
177:
1.19 bmahe 178: public ServerInterface getServer() {
1.7 bmahe 179: try {
180: Resource res = reference.lock();
1.11 bmahe 181: return ((ServletDirectoryFrame)res).getServer();
1.7 bmahe 182: } catch(InvalidResourceException ex) {
183: ex.printStackTrace();
184: return null;
185: } finally {
186: reference.unlock();
187: }
1.1 bmahe 188: }
189:
1.11 bmahe 190: public File getServletLogFile() {
191: ServerInterface server = getServer();
192: File logfile = null;
193: String file = (String)
1.14 bmahe 194: server.getProperties().getString(ServletProps.SERVLET_LOG_FILE_P,
195: null);
1.11 bmahe 196: if (file != null)
197: logfile = new File(file);
198: if ((logfile != null) && (logfile.getPath().length() < 1))
199: logfile = null;
200: if (logfile == null) {
201: File root_dir = server.getRootDirectory();
202: if (root_dir == null) {
203: throw new RuntimeException("unable to build a default "+
204: "value for the servlet log file.");
205: }
206: logfile = new File(new File(root_dir, logdir), deflogfile);
1.16 bmahe 207: server.getProperties().putValue(ServletProps.SERVLET_LOG_FILE_P,
208: logfile.getAbsolutePath());
1.11 bmahe 209: }
210: return logfile;
211: }
212:
1.1 bmahe 213: /**
214: * ServletContext implementation - Lookup a given servlet.
1.20 bmahe 215: * @deprecated since jsdk2.1
1.1 bmahe 216: */
217:
218: public Servlet getServlet(String name) {
219: try {
220: Resource res = reference.lock();
221: return ((ServletDirectoryFrame)res).getServlet(name);
222: } catch(InvalidResourceException ex) {
223: ex.printStackTrace();
224: return null;
225: } finally {
226: reference.unlock();
227: }
228: }
229:
230: /**
231: * ServletContext implementation - Enumerate all servlets within context.
1.20 bmahe 232: * @deprecated since jsdk2.1
1.1 bmahe 233: */
234:
235: public Enumeration getServlets() {
236: try {
237: Resource res = reference.lock();
238: return ((ServletDirectoryFrame)res).getServlets();
239: } catch(InvalidResourceException ex) {
240: ex.printStackTrace();
241: return null;
242: } finally {
243: reference.unlock();
244: }
245: }
1.4 bmahe 246:
247: /**
248: * ServletContext implementation - Enumerate all servlets names
249: * within context.
1.20 bmahe 250: * @deprecated since jsdk2.1
1.4 bmahe 251: */
1.1 bmahe 252:
253: public Enumeration getServletNames() {
1.2 bmahe 254: try {
255: Resource res = reference.lock();
256: return ((ServletDirectoryFrame)res).getServletNames();
257: } catch(InvalidResourceException ex) {
258: ex.printStackTrace();
259: return null;
260: } finally {
261: reference.unlock();
262: }
1.1 bmahe 263: }
264:
265: /**
266: * ServletContext implementation - Log a message.
267: */
268:
269: public void log(String msg) {
1.5 bmahe 270: logger.log(msg);
1.1 bmahe 271: }
272:
1.20 bmahe 273: /**
274: * @deprecated since jsdk2.1
275: */
1.1 bmahe 276: public void log(Exception ex, String msg) {
1.5 bmahe 277: logger.log(ex,msg);
1.1 bmahe 278: }
279:
1.20 bmahe 280: public void log(String message, Throwable throwable) {
281: logger.log(throwable, message);
282: }
283:
1.1 bmahe 284: /**
285: * ServletContext implementation - Translate a piece of path.
1.24.4.4 bmahe 286: * @param path the virtual path to translate
287: * @param rr_root the Root ResourceReference
288: * @param rr the target ResourceReference
289: * @return the real path
290: */
291: protected static String getRealPath(String path,
292: ResourceReference rr_root,
293: ResourceReference rr)
294: {
295: ResourceReference local_root = getLocalRoot(rr_root, rr);
296: try {
297: FramedResource root = (FramedResource)local_root.lock();
298: LookupState ls = new LookupState(path);
299: LookupResult lr = new LookupResult(local_root);
300: if (root.lookup(ls,lr)) {
301: ResourceReference target = lr.getTarget();
302: if (target != null) {
303: try {
304: FramedResource res = (FramedResource)target.lock();
305: if (res instanceof FileResource) {
306: File file = ((FileResource)res).getFile();
307: return file.getAbsolutePath();
308: } else if (res instanceof DirectoryResource) {
309: DirectoryResource dir = (DirectoryResource) res;
310: return dir.getDirectory().getAbsolutePath();
311: //return getFilePath(dir);
312: }
313: } finally {
314: target.unlock();
315: }
316: }
317: }
318: return null;
319: } catch (InvalidResourceException ex) {
320: return null;
321: } catch (org.w3c.tools.resources.ProtocolException pex) {
322: return null;
323: } finally {
324: local_root.unlock();
325: }
326: }
1.1 bmahe 327:
1.24.4.4 bmahe 328: /**
329: * ServletContext implementation - Translate a piece of path.
330: * @param path the virtual path to translate
331: * @return the real path
332: */
1.1 bmahe 333: public String getRealPath(String path) {
1.24.4.4 bmahe 334: ResourceReference rr_root = ((httpd) getServer()).getRootReference();
335: return getRealPath(path, rr_root, reference);
336: }
337:
338: protected static String getFilePath(DirectoryResource dir) {
339: HTTPFrame frame =
340: (HTTPFrame)dir.getFrame("org.w3c.jigsaw.frames.HTTPFrame");
341: String indexes[] = frame.getIndexes();
342: if (indexes != null) {
343: for (int i = 0 ; i < indexes.length ; i++) {
344: String index = indexes[i];
345: if ( index != null && index.length() > 0) {
346: ResourceReference rr = dir.lookup(index);
347: if (rr != null) {
348: try {
349: FramedResource ri = (FramedResource) rr.lock();
350: if (ri instanceof FileResource) {
351: FileResource fr = (FileResource) ri;
352: File file = fr.getFile();
353: return file.getAbsolutePath();
354: } else {
355: // we don't know
356: return null;
357: }
358: } catch (InvalidResourceException ex) {
359: } finally {
360: rr.unlock();
361: }
362: }
363: }
364: }
365: return dir.getDirectory().getAbsolutePath();
366: } else {
367: return dir.getDirectory().getAbsolutePath();
1.24.4.3 bmahe 368: }
369: }
370:
1.24.4.4 bmahe 371: protected static ResourceReference getLocalRoot(ResourceReference rr_root,
372: ResourceReference ref)
373: {
1.22 bmahe 374: try {
375: FramedResource root = (FramedResource)rr_root.lock();
376: if (root instanceof VirtualHostResource) {
377: //backward to the virtual host resource
378: ResourceReference rr = null;
379: ResourceReference rrp = null;
380: FramedResource res = null;
381: try {
1.24.4.3 bmahe 382: res = (FramedResource)ref.lock();
383: if (res instanceof ResourceFrame) {
384: ResourceFrame fr = (ResourceFrame)res;
385: rr = fr.getResource().getResourceReference();
386: } else {
387: rr = ref;
388: }
1.22 bmahe 389: } catch (InvalidResourceException ex) {
1.24.4.4 bmahe 390: return rr_root;
1.22 bmahe 391: } finally {
1.24.4.3 bmahe 392: ref.unlock();
1.22 bmahe 393: }
394:
395: while (true) {
396: try {
397: res = (FramedResource)rr.lock();
398: rrp = res.getParent();
399: if ((rrp == rr_root) || (rrp == null)) {
1.24.4.4 bmahe 400: return getLocalRoot(rr, ref);
1.22 bmahe 401: }
402: } catch (InvalidResourceException ex) {
1.24.4.4 bmahe 403: return rr_root;
1.22 bmahe 404: } finally {
405: rr.unlock();
406: }
407: rr = rrp;
408: }
1.24.4.3 bmahe 409: } else {
1.24.4.4 bmahe 410: try {
411: FramedResource res = (FramedResource)rr_root.lock();
412: ForwardFrame ffr = (ForwardFrame)
413: res.getFrame("org.w3c.jigsaw.proxy.ForwardFrame");
414: if (ffr == null) {
415: return rr_root;
416: } else {
417: ResourceReference rr = ffr.getLocalRootResource();
418: return getLocalRoot(rr, ref);
419: }
420: } catch (InvalidResourceException ex) {
421: return rr_root;
422: }
1.22 bmahe 423: }
424: } catch (InvalidResourceException ex) {
1.24.4.4 bmahe 425: return rr_root;
1.22 bmahe 426: } finally {
427: rr_root.unlock();
428: }
1.1 bmahe 429: }
430:
431: /**
432: * ServletContext implementation - Get server informations.
433: */
434:
435: public String getServerInfo() {
436: try {
437: Resource res = reference.lock();
438: return ((ServletDirectoryFrame)res).getServerInfo();
439: } catch(InvalidResourceException ex) {
440: ex.printStackTrace();
441: return null;
442: } finally {
443: reference.unlock();
444: }
445: }
446:
447: /**
448: * ServletContext implementation - Get an attribute value.
449: * We map this into the ServletWrapper attributes, without
450: * support for name clashes though.
451: * @param name The attribute name.
452: */
453:
454: public Object getAttribute(String name) {
1.20 bmahe 455: Object attribute = attributes.get(name);
456: if (attribute != null) {
457: return attribute;
458: } else {
459: try {
460: Resource res = reference.lock();
461: return ((ServletDirectoryFrame)res).getAttribute(name);
462: } catch(InvalidResourceException ex) {
463: ex.printStackTrace();
464: return null;
465: } finally {
466: reference.unlock();
467: }
1.1 bmahe 468: }
469: }
470:
1.20 bmahe 471: public void setAttribute(String name, Object object) {
472: attributes.put(name, object);
473: }
474:
475: public void removeAttribute(String name) {
476: attributes.remove(name);
477: }
478:
479: public Enumeration getAttributeNames() {
480: return attributes.keys();
481: }
482:
1.24.4.1 bmahe 483: /**
484: * Returns a <code>String</code> containing the value of the named
485: * context-wide initialization parameter, or <code>null</code> if the
486: * parameter does not exist.
487: *
488: * <p>This method can make available configuration information useful
489: * to an entire "web application". For example, it can provide a
490: * webmaster's email address or the name of a system that holds
491: * critical data.
492: *
493: * @param name a <code>String</code> containing the name of the
494: * parameter whose value is requested
495: * @return a <code>String</code> containing at least the
496: * servlet container name and version number
497: * @see ServletConfig#getInitParameter
498: */
499: public String getInitParameter(String name) {
1.24.4.2 bmahe 500: // @@ not implemented @@
1.24.4.1 bmahe 501: return null;
502: }
503:
504:
505:
506:
507: /**
508: * Returns the names of the context's initialization parameters as an
509: * <code>Enumeration</code> of <code>String</code> objects, or an
510: * empty <code>Enumeration</code> if the context has no initialization
511: * parameters.
512: *
513: * @return an <code>Enumeration</code> of <code>String</code>
514: * objects containing the names of the context's initialization parameters
515: * @see ServletConfig#getInitParameter
516: */
517: public Enumeration getInitParameterNames() {
1.24.4.2 bmahe 518: // @@ not implemented @@
519: return new EmptyEnumeration();
1.24.4.1 bmahe 520: }
521:
1.15 bmahe 522: private AutoReloadServletLoader loader = null;
523:
524: /**
525: * Get or create a suitable LocalServletLoader instance to load
526: * that servlet.
527: * @return A LocalServletLoader instance.
528: */
529: protected synchronized AutoReloadServletLoader getLocalServletLoader() {
530: if ( loader == null ) {
531: loader = new AutoReloadServletLoader(this);
532: }
533: return loader;
534: }
535:
536: protected synchronized
537: AutoReloadServletLoader createNewLocalServletLoader (boolean keepold)
538: {
539: if ((loader != null) && keepold)
540: loader = new AutoReloadServletLoader(loader);
541: else
542: loader = new AutoReloadServletLoader(this);
543: return loader;
544: }
545:
546: public File getServletDirectory() {
547: return directory;
548: }
549:
1.20 bmahe 550: //jsdk2.1
551:
552: /**
553: * Returns a RequestDispatcher object for the specified URL path if
554: * the context knows of an active source (such as a servlet, JSP page,
555: * CGI script, etc) of content for the particular path. This format of
556: * the URL path must be of the form /dir/dir/file.ext. The servlet
557: * engine is responsible for implementing whatever functionality is
558: * required to wrap the target source with an implementation of
559: * the RequestDispatcher interface.
560: * @param urlpath Path to use to look up the target server resource
561: */
562: public RequestDispatcher getRequestDispatcher(String urlpath) {
1.24.4.2 bmahe 563: return JigsawRequestDispatcher.getRequestDispatcher(urlpath,
1.24.4.6! bmahe 564: (httpd)getServer(),
! 565: reference);
1.24.4.1 bmahe 566: }
567:
568: /**
569: * Returns a {@link RequestDispatcher} object that acts
570: * as a wrapper for the named servlet.
571: *
572: * <p>Servlets (and JSP pages also) may be given names via server
573: * administration or via a web application deployment descriptor.
574: * A servlet instance can determine its name using
575: * {@link ServletConfig#getServletName}.
576: *
577: * <p>This method returns <code>null</code> if the
578: * <code>ServletContext</code>
579: * cannot return a <code>RequestDispatcher</code> for any reason.
580: *
581: * @param name a <code>String</code> specifying the name
582: * of a servlet to wrap
583: * @return a <code>RequestDispatcher</code> object
584: * that acts as a wrapper for the named servlet
585: * @see RequestDispatcher
586: * @see ServletContext#getContext
587: * @see ServletConfig#getServletName
588: */
589: public RequestDispatcher getNamedDispatcher(String name) {
1.24.4.2 bmahe 590: if (name == null) {
591: throw new IllegalArgumentException("null");
592: }
593: return JigsawRequestDispatcher.getRequestDispatcher(name,
594: reference,
595: (httpd)getServer());
1.20 bmahe 596: }
597:
598: public int getMajorVersion() {
599: return 2;
600: }
601:
602: public int getMinorVersion() {
1.24.4.2 bmahe 603: return 2;
1.20 bmahe 604: }
605:
606: public ServletContext getContext(String uripath) {
607: if (uripath == null)
608: return null;
609: //first, find the ServletDirectoryFrame.
610: // Prepare for lookup:
611: ResourceReference rr_root = null;
612: rr_root = ((httpd) getServer()).getRootReference();
613:
614: FramedResource root = null;
615: root = ((httpd) getServer()).getRoot();
616:
617: // Do the lookup:
618: ResourceReference r_target = null;
619: try {
620: LookupState ls = new LookupState(uripath);
621: LookupResult lr = new LookupResult(rr_root);
622: root.lookup(ls, lr);
623: r_target = lr.getTarget();
624: } catch (Exception ex) {
625: r_target = null;
626: }
627: //then return its context
628: if (r_target != null) {
629: try {
630: Resource target = r_target.lock();
631: if (target instanceof FramedResource) {
632: ServletDirectoryFrame frame = (ServletDirectoryFrame)
633: ((FramedResource) target).
634: getFrame("org.w3c.jigsaw.servlet.ServletDirectoryFrame");
635: if (frame != null)
636: return frame.getServletContext();
637: }
638: } catch (InvalidResourceException ex) {
639: // continue
640: } finally {
641: r_target.unlock();
642: }
643: }
644: return null;
645: }
646:
647: public URL getResource(String path)
1.24.4.3 bmahe 648: throws MalformedURLException
1.20 bmahe 649: {
1.24.4.4 bmahe 650: String realpath = getRealPath(path);
651: if (realpath != null) {
652: File file = new File(realpath);
653: if (file.exists()) {
654: return new URL("file", "", file.getAbsolutePath());
655: } else {
656: return null;
657: }
658: } else {
659: // it could be a virtual resource
660: // check that it exists (on server)
661: // FIXME (Virtual host)
662: return null;
1.24.4.3 bmahe 663: }
1.24 bmahe 664: }
1.24.4.3 bmahe 665:
1.20 bmahe 666: public InputStream getResourceAsStream(String path) {
667: try {
668: URL resource = getResource(path);
669: if (resource == null)
670: return null;
671: try {
672: URLConnection c = resource.openConnection();
673: return c.getInputStream();
674: } catch (IOException ex) {
675: return null;
676: }
677: } catch (MalformedURLException ex) {
678: return null;
679: }
680: }
681:
1.1 bmahe 682: /**
683: * Create a new ServletContext.
684: * @param ref a ResourceReference pointing on a ServletDirectoryFrame.
685: */
1.11 bmahe 686: protected JigsawServletContext(ResourceReference ref,
687: ObservableProperties props)
688: {
1.20 bmahe 689: this.reference = ref;
690: this.props = props;
691: this.attributes = new Hashtable(3);
692: this.logger = new Logger(getServletLogFile());
693: this.loader = new AutoReloadServletLoader(this);
694:
1.11 bmahe 695: props.registerObserver(this);
1.20 bmahe 696:
1.3 bmahe 697: try {
698: Resource res = reference.lock();
699: if (! (res instanceof ServletDirectoryFrame)) {
1.24.4.2 bmahe 700: throw new IllegalArgumentException("This reference is not "+
1.24.4.3 bmahe 701: "pointing on a ServletDirectoryFrame.");
1.5 bmahe 702: } else {
703: ServletDirectoryFrame sframe = (ServletDirectoryFrame)res;
704: FramedResource resource = (FramedResource)sframe.getResource();
705: resource.addStructureChangedListener(this);
1.15 bmahe 706: if (resource.definesAttribute("directory"))
707: this.directory =
708: (File) resource.getValue("directory", null);
1.3 bmahe 709: }
710: } catch(InvalidResourceException ex) {
1.24.4.2 bmahe 711: throw new IllegalArgumentException("This reference is pointing on"+
1.24.4.3 bmahe 712: " an Invalid ServletDirectoryFrame.");
1.3 bmahe 713: } finally {
714: reference.unlock();
715: }
1.1 bmahe 716: }
717:
718: }
Webmaster