// ServletDirectoryFrame.java
// $Id: ServletDirectoryFrame.java,v 1.2 1998/02/09 17:03:21 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.servlet;

import java.io.*;
import java.net.*;
import java.util.*;

import javax.servlet.*;

import org.w3c.tools.resources.store.*;
import org.w3c.tools.resources.*;
import org.w3c.jigsaw.frames.*;

/**
 *  @author Alexandre Rafalovitch <alex@access.com.au>
 *  @author Anselm Baird-Smith <abaird@w3.org>
 */

public class ServletDirectoryFrame extends HTTPFrame
    implements ServletContext 
{
  /**
   * A useful utility routine that tries to guess the content-type
   * of an object based upon its extension.
   */
  protected static String guessContentTypeFromName(String fname) {
    String ext = "";
    int i = fname.lastIndexOf('#');

    if (i != -1)
      fname = fname.substring(0, i - 1);
    i = fname.lastIndexOf('.');
    i = Math.max(i, fname.lastIndexOf('/'));
    i = Math.max(i, fname.lastIndexOf('?'));

    if (i != -1 && fname.charAt(i) == '.') {
      ext = fname.substring(i).toLowerCase();
    }
    return (String) extension_map.get(ext);
  }

  static Hashtable extension_map = new Hashtable();

  static {
    setSuffix("", "content/unknown");
    setSuffix(".uu", "application/octet-stream");
    setSuffix(".saveme", "application/octet-stream");
    setSuffix(".dump", "application/octet-stream");
    setSuffix(".hqx", "application/octet-stream");
    setSuffix(".arc", "application/octet-stream");
    setSuffix(".o", "application/octet-stream");
    setSuffix(".a", "application/octet-stream");
    setSuffix(".bin", "application/octet-stream");
    setSuffix(".exe", "application/octet-stream");
    /* Temporary only. */
    setSuffix(".z", "application/octet-stream");
    setSuffix(".gz", "application/octet-stream");

    setSuffix(".oda", "application/oda");
    setSuffix(".pdf", "application/pdf");
    setSuffix(".eps", "application/postscript");
    setSuffix(".ai", "application/postscript");
    setSuffix(".ps", "application/postscript");
    setSuffix(".rtf", "application/rtf");
    setSuffix(".dvi", "application/x-dvi");
    setSuffix(".hdf", "application/x-hdf");
    setSuffix(".latex", "application/x-latex");
    setSuffix(".cdf", "application/x-netcdf");
    setSuffix(".nc", "application/x-netcdf");
    setSuffix(".tex", "application/x-tex");
    setSuffix(".texinfo", "application/x-texinfo");
    setSuffix(".texi", "application/x-texinfo");
    setSuffix(".t", "application/x-troff");
    setSuffix(".tr", "application/x-troff");
    setSuffix(".roff", "application/x-troff");
    setSuffix(".man", "application/x-troff-man");
    setSuffix(".me", "application/x-troff-me");
    setSuffix(".ms", "application/x-troff-ms");
    setSuffix(".src", "application/x-wais-source");
    setSuffix(".wsrc", "application/x-wais-source");
    setSuffix(".zip", "application/zip");
    setSuffix(".bcpio", "application/x-bcpio");
    setSuffix(".cpio", "application/x-cpio");
    setSuffix(".gtar", "application/x-gtar");
    setSuffix(".shar", "application/x-shar");
    setSuffix(".sh", "application/x-shar");
    setSuffix(".sv4cpio", "application/x-sv4cpio");
    setSuffix(".sv4crc", "application/x-sv4crc");
    setSuffix(".tar", "application/x-tar");
    setSuffix(".ustar", "application/x-ustar");
    setSuffix(".snd", "audio/basic");
    setSuffix(".au", "audio/basic");
    setSuffix(".aifc", "audio/x-aiff");
    setSuffix(".aif", "audio/x-aiff");
    setSuffix(".aiff", "audio/x-aiff");
    setSuffix(".wav", "audio/x-wav");
    setSuffix(".gif", "image/gif");
    setSuffix(".ief", "image/ief");
    setSuffix(".jfif", "image/jpeg");
    setSuffix(".jfif-tbnl", "image/jpeg");
    setSuffix(".jpe", "image/jpeg");
    setSuffix(".jpg", "image/jpeg");
    setSuffix(".jpeg", "image/jpeg");
    setSuffix(".tif", "image/tiff");
    setSuffix(".tiff", "image/tiff");
    setSuffix(".ras", "image/x-cmu-rast");
    setSuffix(".pnm", "image/x-portable-anymap");
    setSuffix(".pbm", "image/x-portable-bitmap");
    setSuffix(".pgm", "image/x-portable-graymap");
    setSuffix(".ppm", "image/x-portable-pixmap");
    setSuffix(".rgb", "image/x-rgb");
    setSuffix(".xbm", "image/x-xbitmap");
    setSuffix(".xpm", "image/x-xpixmap");
    setSuffix(".xwd", "image/x-xwindowdump");
    setSuffix(".htm", "text/html");
    setSuffix(".html", "text/html");
    setSuffix(".text", "text/plain");
    setSuffix(".c", "text/plain");
    setSuffix(".cc", "text/plain");
    setSuffix(".c++", "text/plain");
    setSuffix(".h", "text/plain");
    setSuffix(".pl", "text/plain");
    setSuffix(".txt", "text/plain");
    setSuffix(".java", "text/plain");
    setSuffix(".rtx", "application/rtf");
    setSuffix(".tsv", "text/tab-separated-values");
    setSuffix(".etx", "text/x-setext");
    setSuffix(".mpg", "video/mpeg");
    setSuffix(".mpe", "video/mpeg");
    setSuffix(".mpeg", "video/mpeg");
    setSuffix(".mov", "video/quicktime");
    setSuffix(".qt", "video/quicktime");
    setSuffix(".avi", "application/x-troff-msvideo");
    setSuffix(".movie", "video/x-sgi-movie");
    setSuffix(".mv", "video/x-sgi-movie");
    setSuffix(".mime", "message/rfc822");
  }

  static private void setSuffix(String ext, String ct) {
    extension_map.put(ext, ct);
  }


  /**
   * ServletContext implementation - Get the MIME type for given file.
   */

  public String getMimeType(String filename) {
    return guessContentTypeFromName(filename);
  }

  public File getDirectory() {
    if (dresource != null)
      return dresource.getDirectory();
    return null;
  }

  /**
   * ServletContext implementation - Lookup a given servlet.
   */

  public Servlet getServlet(String name) {
    if (dresource != null) {
      ResourceReference rr = dresource.lookup(name);
      try {
	Resource resource = rr.lock();
	if (resource instanceof ServletWrapper)
	  return ((ServletWrapper) resource).getServlet();
      } catch (InvalidResourceException ex) {
	return null;
      } finally {
	rr.unlock();
      }
    }
    return null;
  }

  /**
   * ServletContext implementation - Enumerate all servlets within context.
   */

  public Enumeration getServlets() {
    if (dresource != null)
      return new ServletEnumeration(this, 
				    dresource.enumerateResourceIdentifiers());
    else
      return new ServletEnumeration(this, null);
  }

  public Enumeration getServletNames() {
    return getServlets();
  }

  /**
   * ServletContext implementation - Log a message.
   */

  public void log(String msg) {
    System.out.println(msg);
  }

  public void log(Exception ex, String msg) {
    log(msg+" : "+ex.getMessage());
  }

  /**
   * ServletContext implementation - Translate a piece of path.
   */

  public String getRealPath(String path) {
    return path;
  }

  /**
   * ServletContext implementation - Get server informations.
   */

  public String getServerInfo() {
    return resource.getServer().getSoftware();
  }

  /**
   * ServletContext implementation - Get an attribute value.
   * We map this into the ServletWrapper attributes, without
   * support for name clashes though.
   * @param name The attribute name.
   */

  public Object getAttribute(String name) {
    if ( definesAttribute(name) )
      return getValue(name, null);
    else if (resource.definesAttribute(name))
      return resource.getValue(name, null);
    return null;
  }

  /**
   * We add a <em>context</em> attribute to all our children.
   * The <em>context</em> attribute is any object implementing the
   * ServletContext interface.
   */

  protected void updateDefaultChildAttributes(Hashtable attrs) {
    attrs.put("servlet-context", this);
  }

}
