package hyperscout;


import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.Locale;

import scone.netobjects.DBTableAdapter;
import scone.netobjects.HtmlNode;
import scone.netobjects.HtmlNodeCache;
import scone.netobjects.Link;
import scone.netobjects.LinkCache;
import scone.netobjects.NetNode;
import scone.netobjects.NetNodeCache;
import scone.netobjects.Server;
import scone.netobjects.ServerCache;

import com.ibm.wbi.RequestEvent;
import com.ibm.wbi.RequestRejectedException;
import com.ibm.wbi.protocol.http.DocumentInfo;
import com.ibm.wbi.protocol.http.HttpGenerator;
import com.ibm.wbi.protocol.http.HttpRequest;
import com.ibm.wbi.protocol.http.HttpResponse;
import com.ibm.wbi.protocol.http.beans.StaticHtmlGenerator;


/**
 * This Generator creates the HyperScout popupt windows.<P>
 */
public class PopupGenerator extends HttpGenerator {

    public static final String COPYRIGHT = "(C) Harald Weinreich & Volkert Buchmann";
    private String hyperScoutBaseUrl = "http://_hyperscout.scone.de/res/";

    private DocumentInfo documentInfo;
    private String 		file;
    private HttpRequest  request;
    private HttpResponse response;
    private String baseNodeId;
    private NetNode baseNode;
    private HtmlNode baseDoc;
    private String query;
    private String popups;
   
    // different for every link...
    private Link link;
    private NetNode toNode;
    private HtmlNode doc;

    public void handleRequest(RequestEvent e) throws RequestRejectedException {
        documentInfo = (DocumentInfo) e.getRequestInfo(); // get RequestInfo
        file = documentInfo.getPath();           // get Path+File of the URL
        query = documentInfo.getQuery();          // get Query Parameter from URL
        request = new HttpRequest(e, true);          // Get the request header
        popups = new String("");

        if (query.startsWith("?baseNodeId="))  // Is the Querystring what we expected?
        {
            int endOfNodeId = (query.indexOf("&") > 0)
                    ? query.indexOf("&")
                    : query.length();      // where does the baseNodeId end?

            baseNodeId = query.substring(query.indexOf("=") + 1, endOfNodeId);                     // extract basenodeId
            System.out.println("Creating popups for " + baseNodeId);
            query = query.substring(endOfNodeId);  // remove baseNodeId from query
        } else { 
            throw new RequestRejectedException();
        }

        // get the baseNodeId
        baseNode = NetNodeCache.getById(baseNodeId);
        // GethtmlNode object only if Document is html, what it should be in any case...
        if (baseNode.getMimeType().equals("text/html")
                && Integer.parseInt(baseNode.getSize()) > 0) {       
            baseDoc = HtmlNodeCache.get(baseNode);
        }
      
        // Extract the link IDs...
        while (query.length() > 0) {
            StringBuffer popupString = new StringBuffer(1024);

            query = query.substring(1);  // remove leading "&"
            int endOfLinkId = (query.indexOf("&") > 0)
                    ? query.indexOf("&")
                    : query.length();   // find end..
            String linkId = query.substring(0, endOfLinkId);            // extract linkId

            // System.out.println(linkId);                             
            query = query.substring(endOfLinkId);                      // remove the string from the query...

            // Get link and tonode
            link = LinkCache.getById(linkId);
         
            toNode = link.getToNode();

            // GethtmlNode object only if Document is html, what it should be in any case...
            doc = null;
            if (toNode.getMimeType().equals("text/html")
                    && Integer.parseInt(toNode.getSize()) > 0) {       // Get htmlNode object only if referenced Document is html...
                doc = HtmlNodeCache.get(toNode);
            }
      
            addAccessInfo(popupString);
            addContentInfo(popupString);
            addUsageInfo(popupString);
            addTopologicalInfo(popupString);
            addActionInfo(popupString);
            addFormatInfo(popupString);

            // No Information available...
            if (popupString.length() == 0) {
                // popupString.append(tableLine("Sorry:","No information available."));
                popups += "hs_newMouseIcon('linkid" + link.getLinkId() + "','"
                        + hyperScoutBaseUrl + "quest.gif');\n";
                // Show a questionmark mouse pointer instead
                popups += "hs_noPopup('linkid" + link.getLinkId() + "');\n";
            } else {
                // Now creating the JavaScript code for the new popup
                popups += "hs_newPopup('linkid" + link.getLinkId() + "','"
                        + popupString.toString() + "');\n";
            }
        }
      
        StaticHtmlGenerator sg = new StaticHtmlGenerator(); // Return generated document to the client

        response = sg.getHttpResponse();                    // Get http response header
        // response.setCache(false);  // doesn't work!!!
        response.add("Pragma", "no-cache");
        sg.setStaticHtml(popups);                           // Set dummy text
        sg.setContentType("application/x-javascript");      // Set type to javascript
        // Send Response to Browser
        try {
            forwardRequest(sg, e);
        } catch (java.io.IOException ex) {
            System.out.println("Error sending response in PopupGenerator!");
        }

    }

    // END of handleRequest: And now for the subroutines...
    // ------------------------------------------------------------------------------------

    /**
     * Add information about the content of the referenced object.
     */
    private void addContentInfo(StringBuffer popupString) {
        if (baseNode.toDocString().equals(toNode.toDocString())) { 
            return;  // Same Document: No Content Information to be displayed...
        }
      
        // Display title of target object
        if (doc != null && doc.getTitle().length() > 0) {
            popupString.append(tableLine("Title", DBTableAdapter.escape(new StringBuffer(doc.getTitle())), "info.gif"));
        }

        // display description
        if (doc != null && doc.getDescription().length() > 0) {
            popupString.append(tableLine("Description", doc.getDescription(), "colors/blank.gif"));
        } 

        // Display first lines of Text of Document...
        if (doc != null && doc.getBodyText().length() > 20
                && doc.getNumberOfWords().length() > 0) {
            int bodylength = doc.getBodyText().length();

            popupString.append(tableLine("Content", doc.getBodyText().substring(0, Math.min(200, bodylength - 1)), "colors/blank.gif"));
        }
      
        // display language
        if (doc != null && !doc.getLanguage().equals("")) {
            String lang = doc.getLanguage();

            if (!lang.equals("?")) {
                if (lang.equals("en")) {
                    lang = "English";
                }
                if (lang.equals("de")) {
                    lang = "German";
                }
                if (lang.equals("es")) {
                    lang = "Spanish";
                }
                if (lang.equals("fr")) {
                    lang = "French";
                }
                popupString.append(tableLine("Language", lang, "language.gif"));
            }
        }

        // display author
        if (doc != null && doc.getAuthor().length() > 0) {
            popupString.append(tableLine("Author", doc.getAuthor(), "author.gif"));
        } 

        // display last-modified-info
        if (doc != null && doc.getLastModified() != -1) {
            // popupString.append(tableLine("Last visit",String.valueOf(toNode.getLastAccess()),"clock.gif"));
            long now = (new Date()).getTime();
            long lastModified = toNode.getLastModified();

            if (now - lastModified < 1000 * 60 * 60) { // less than one hour ago!
                popupString.append(tableLine("Updated", String.valueOf((now - lastModified) / 1000 / 60) + " minutes ago", "clock.gif"));
            } else {
                Date lastModifiedDate = new Date(lastModified);
                // SimpleDateFormat formatter = new SimpleDateFormat ("EEE, dd-MMM-yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
                SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd.MMM.yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
                String dateString = formatter.format(lastModifiedDate);

                popupString.append(tableLine("Updated", dateString, "clock.gif"));
            }
        }

        // Display length of referenced object
        if (doc != null && doc.getNumberOfParagraphs().length() > 0) {
            popupString.append(tableLine2("Paragraphs", DBTableAdapter.escape(new StringBuffer(doc.getNumberOfParagraphs())), "colors/blank.gif"));
        }

        // Display length of referenced object
        if (doc != null && doc.getNumberOfWords().length() > 0) {
            popupString.append(tableLine2("Wörter", DBTableAdapter.escape(new StringBuffer(doc.getNumberOfWords())), "colors/blank.gif"));
        }

        // Display length of referenced object
        if (doc != null && doc.getNumberOfImages().length() > 0) {
            popupString.append(tableLine2("Bilder", DBTableAdapter.escape(new StringBuffer(doc.getNumberOfImages())), "colors/blank.gif"));
        }

        // Display Space of Images
        if (doc != null && doc.getSpaceOfImages().length() > 0) {
            popupString.append(tableLine2("Space", DBTableAdapter.escape(new StringBuffer(doc.getSpaceOfImages())), "colors/blank.gif"));
        }

        // Display Space / Word Ratio
        if (doc != null && doc.getSpaceOfImages().length() > 2
                && doc.getNumberOfWords().length() > 0) {
            popupString.append(tableLine2("Graphical?", "Space / Words:" + String.valueOf(Long.parseLong(doc.getSpaceOfImages()) / Integer.parseInt(doc.getNumberOfWords())), "colors/blank.gif"));
        }

    }

    /**
     * Add information about the Usage of the referenced object.
     */
    private void addUsageInfo(StringBuffer popupString) {
        // Wann habe ich das Objekt bereits besucht?
        // Wie oft, in welchen Zeiträumen
        // War ich schon mal “in der Nähe” dieser Seite, also z.B. auf Seiten, die auf diese Verweisen.
        // Bookmarks
        // Anmerkungen

        if (baseNode.toDocString().equals(toNode.toDocString())) { 
            return;  // Same Document: No usage Information to be displayed...
        }
      
        // display last visit
        if (toNode.getLastAccess() > 0L) {
            // popupString.append(tableLine("Last visit",String.valueOf(toNode.getLastAccess()),"clock.gif"));
            long now = (new Date()).getTime();
            long lastAccess = toNode.getLastAccess();

            if (now - lastAccess < 1000 * 60 * 60) { // less than one hour ago!
                popupString.append(tableLine("Last visit", String.valueOf((now - lastAccess) / 1000 / 60) + " minutes ago", "clock.gif"));
            } else {
                Date lastAccessDate = new Date(lastAccess);
                // SimpleDateFormat formatter = new SimpleDateFormat ("EEE, dd-MMM-yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
                SimpleDateFormat formatter = new SimpleDateFormat("EEE, dd.MMM.yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
                String dateString = formatter.format(lastAccessDate);

                popupString.append(tableLine("Last visit", dateString, "clock.gif"));
            }
        } // Display first visit
        // if (toNode.getFirstAccess() > 0L)
        {// popupString.append(tableLine("Last visit",String.valueOf(toNode.getLastAccess()),"clock.gif"));
            // Date firstAccess = new Date(toNode.getFirstAccess());
            // SimpleDateFormat formatter = new SimpleDateFormat ("EEE, dd.MMM.yyyy HH:mm:ss", Locale.US); // 09-Nov-2030 23:59:00 GMT;
            // String dateString = formatter.format(firstAccess);
            // popupString.append(tableLine("First visit",dateString,"clock.gif"));
        }
       
        // häufig zugegriffen?
        if (toNode.getAccessCounter() > 1) {
            popupString.append(tableLine("Frequency", String.valueOf(toNode.getAccessCounter()) + " times accessed", "colors/blank.gif"));
        }

        // -> Balken für Zugriffe??
        // popupString.append(tableLine("Last visit","blabla","clock.gif","colors/yellow2brown.gif"));
        // display dummy-bookmark
        // popupString.append(tableLine("bookmarked:","July,4.,1999","bookmark.gif"));

    }

    /**
     * Add information about the toplology
     */
    private void addTopologicalInfo(StringBuffer popupString) {

        // Lokaler oder entfernter Link
        // Dead End/ Sackgasse (Objekte ohne Hyperlinks)
        // Typ des Links:
        // Navigation: Zur Homepage, Landmark etc.
        // Assoziativ
        // Hierarchisch
        // Anzahl ein-/ ausgehender Links


        // display whether it leads to the same doc, ref
        if (baseNode.toDocString().equals(toNode.toDocString())) {
            if (link.getFragment().length() > 0) {
                popupString.append(tableLine("Reference ", link.getFragment(), "updown.gif"));
            } else {
                popupString.append(tableLine("Identical", "Pointing to this document", "back.gif"));
            }
            return;  // No more topological Information to be displayed...
        }

        // display remote server info
        if ((toNode.getProtocol().equals("http")
                        || toNode.getProtocol().equals("ftp"))
                &&  // Only for http and ftp!
                        !baseNode.toHostString().equals(toNode.toHostString()))  // Other Server?
        {
            popupString.append(tableLine("External", toNode.toHostString(), "out.gif"));
            Server remoteServer = ServerCache.get(toNode.toHostString());

            if (remoteServer.getAccessStatus().equals("err")) {
                popupString.append(tableLine("Status", "Server is propably unreachable!", "flash.gif"));
            } else {
                if (remoteServer.getAccessStatus().length() > 0
                        && !remoteServer.getDelay().equals("0")) {
                    popupString.append(tableLine("server title", DBTableAdapter.escape(new StringBuffer(remoteServer.getTitle()))));
                    popupString.append(tableLine("mean delay", "medium", "clock.gif"));
                }
            }
        }
      
        // more or less details?
        // Fist check if it's the same Server...
        if (baseNode.toHostString().equals(toNode.toHostString())) {

            // File in the same path?
            if (baseNode.getPath().equals(toNode.getPath())) {// popupString.append(tableLine("Cluster","Same cluster","same.gif"));
            } // path shorter
            else if (baseNode.getPath().startsWith(toNode.getPath())
                    || (toNode.getPath().startsWith(baseNode.getPath())
                            && toNode.getPath().endsWith("/../"))) {
                popupString.append(tableLine("Survey", "Path: " + toNode.getPath(), "higher.gif"));
            } // path longer
            else if (toNode.getPath().startsWith(baseNode.getPath())) {
                popupString.append(tableLine("Detail", "Subdirectory: " + toNode.getPath().substring(baseNode.getPath().length()), "deeper.gif"));
            } else {
                popupString.append(tableLine("Associative", "Subdirectory: " + toNode.getPath(), "same.gif"));
            }
        }

        if (toNode.getQuery().length() > 0) {
            popupString.append(tableLine("Query", toNode.getQuery(), "questionmark.gif"));
        }

        // Link to Homepage of Server?
        if (toNode.getPath().equals("/") && toNode.getFile().equals("")) {
            popupString.append(tableLine("Home", "To homepage of server", "home.gif"));
        }

        // Is ref. document a dead end?
        if (doc != null && doc.getNumberOfLinks().equals("0")) {
            popupString.append(tableLine3("Links", "Dead End: No Links!", "deadend.gif"));
        }

        // Has ref. document loads of links?
        // Many external links?
        if (doc != null && Integer.parseInt(doc.getNumberOfExternalLinks()) > 10) {
            popupString.append(tableLine3("Hub page", "External Links: " + doc.getNumberOfExternalLinks(), "multilink.gif"));
        }
        // Many overall Links?
        if (doc != null && Integer.parseInt(doc.getNumberOfLinks()) > 20) {
            popupString.append(tableLine3("Link page", "Many Links: " + doc.getNumberOfLinks(), "multilink.gif"));
        }

    }

    /**
     * Add information about the Access to the referenced object.
     */
    private void addAccessInfo(StringBuffer popupString) {
        // Status:
        // Objekt erhältlich?
        // Authentifizierung notwendig?
        // Zugriffszeit als Schätzung aus
        // Größe des Dokumentes 
        // Bandbreite (über Testdaten oder Ping ermittelt

        // Display Status of target object
        String status = statusDescription(toNode.getAccessStatus());

        if (status != null && status.length() != 0 && !status.equals("200")
                && status.equals("304")) {
            popupString.append(tableLine("Status", statusDescription(toNode.getAccessStatus()), "flash.gif"));
        }

        // Display size of target object
        int size;

        try {
            size = ((new Integer(toNode.getSize())).intValue());
        } catch (Exception ex) {
            size = 0;
        }

        if (size > 30000) { 
            size /= 1024;  // Display KBytes!
            popupString.append(tableLine("Big Size", (new Integer(size)).toString() + " kByte", "size.gif"));
        }
    }

    /**
     * Add information about the Action of the link.
     */
    private void addActionInfo(StringBuffer popupString) {
        // Display email
        if (toNode.getProtocol().equals("mailto")) {
            popupString.append(tableLine("eMail to", toNode.getOpaquePart(), "e-mail.gif"));
        }

        // Link opens a new Window
        if (link.getTarget() != null && link.getTarget().length() != 0) {
            if (link.getTarget().equalsIgnoreCase("_blank")) {
                popupString.append(tableLine2("Action", "Opens new window", "new.gif"));
            } else if (link.getTarget().equalsIgnoreCase("_parent")
                    || link.getTarget().equalsIgnoreCase("_top")) {
                popupString.append(tableLine2("Action", "Removes Frames", "colors/blank.gif"));
            } else if (link.getTarget().toLowerCase().startsWith("JavaScript:")) {
                popupString.append(tableLine2("Action", "JavaScript!", "colors/blank.gif"));
            } else { 
                popupString.append(tableLine2("Action", "Controls other frame", "colors/blank.gif"));
            }
        }

    }

    /**
     * Add information about the Action of the link.
     */
    private void addFormatInfo(StringBuffer popupString) {
        // Display file type of target object
        String mimeType = toNode.getMimeType();

        if (mimeType != null && !mimeType.equals("null") && // mimeType not defined
                mimeTypeDescription(mimeType).length() != 0 &&  // Description not available
                mimeType.indexOf("text/html") == -1) {  // text/html  is linktool...
            popupString.append(tableLine("Type", mimeTypeDescription(mimeType), "eye.gif"));
        }

    }

    // -----------------------
    // Die Tabelle wird bereits in der Datei popup.js geöffnet und dann wieder geschlossen.
    // Hier werden die einzelnen Zeilen erstellt

    // five parameters: title, info, icon, backgroundimage)
    private String tableLine(String name, String value, String icon, String bgImage) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt1\" width=\"4%\"><IMG src=\""
                + hyperScoutBaseUrl + icon
                + "\" width=12 height=12></TD><TD class=\"hs-tt1\" width=\"17%\">"
                + name + "</TD><TD class=\"hs-td1\" background=\""
                + hyperScoutBaseUrl + bgImage + "\">" + value
                + "&nbsp;</TD></TR>";
    }

    // Three parameters: title, info and icon
    private String tableLine(String name, String value, String icon) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt1\" width=\"4%\"><IMG src=\""
                + hyperScoutBaseUrl + icon
                + "\" width=12 height=12></TD><TD class=\"hs-tt1\" width=\"17%\">"
                + name + "</TD><TD class=\"hs-td1\">" + value
                + "&nbsp;</TD></TR>";
    }

    // Three parameters: title, info and icon
    private String tableLine2(String name, String value, String icon) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt2\" width=\"4%\"><IMG src=\""
                + hyperScoutBaseUrl + icon
                + "\" width=12 height=12></TD><TD class=\"hs-tt2\" width=\"17%\">"
                + name + "</TD><TD class=\"hs-td2\">" + value
                + "&nbsp;</TD></TR>";
    }

    // Three parameters: title, info and icon
    private String tableLine3(String name, String value, String icon) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt3\" width=\"4%\"><IMG src=\""
                + hyperScoutBaseUrl + icon
                + "\" width=12 height=12></TD><TD class=\"hs-tt3\" width=\"17%\">"
                + name + "</TD><TD class=\"hs-td3\">" + value
                + "&nbsp;</TD></TR>";
    }

    // Only two parameters: Title and Info
    private String tableLine(String name, String value) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt1\" width=\"21%\" colspan=\"2\">" + name
                + "</TD><TD class=\"hs-td1\">" + value + "&nbsp;</TD></TR>";
    }

    // Only one parameters: The URL
    private String tableLine(String value) {
        value = escapeForJavaScript(value);
        return "<TR><TD class=\"hs-tt1\" width=\"4%\"><IMG src=\""
                + hyperScoutBaseUrl
                + "url.gif\" width=12 height=12></TD><TD class=\"hs-td1\"  colspan=\"2\">"
                + value + "&nbsp;</TD></TR>";
    }

    /**
     * Calls escape(StringBuffer s)
     */
    private String escapeForJavaScript(String s) {
        return escapeForJavaScript(new StringBuffer(s));
    }
   
    /**
     * escapeForJavaScript is used to escape characters that 
     * may cause problems with JavaScript
     * <UL>
     * <LI> null (0) -> SPACE 
     * <LI> Backspace (8) -> \b
     * <LI> New line (10) -> \n
     * <LI> CR (13) -> \r
     * <LI> Double qoutes " (34) -> \"
     * <LI> Single quote ' (39) -> \'
     * <LI> Backslash (39) -> \\
     * </UL> 
     */
    public String escapeForJavaScript(StringBuffer s) {
        StringBuffer t = new StringBuffer(s.length() + 100);

        for (int i = 0; i < s.length(); i++) {
            char test = s.charAt(i);

            switch (test) {
            case 0:  // null
                {
                    t.append(' ');
                    break;
                }

            case 10: // newline
                {
                    t.append('\\');
                    t.append('n');
                    break;
                }

            case 13: // carriage return
                {
                    t.append('\\');
                    t.append('r');
                    break;
                }

            case 8:  // backspace
                {
                    t.append('\\');
                    t.append('b');
                    break;
                }

            case 39: // '
                {
                    t.append('\\');
                    t.append('\'');
                    break;
                }     

            case 34: // "
                {
                    t.append('\\');
                    t.append('\"');
                    break;
                }

            case 92: // backslash \
                {
                    t.append('\\');
                    t.append('\\');
                    break;
                }

            default:
                t.append(test);
            }
        }
        return t.toString();
    }

    // -----------------------
    private String mimeTypeDescription(String type) {
        String description = "";

        if (type != null) {
            description = (String) mimeTypeTable.get(type);
        }
        if (description == null) {
            description = "";
        }
        return description;
    }

    private String statusDescription(String status) {
        String description = "";

        if (status != null) {
            description = (String) statusTable.get(status);
        }
        if (description == null) {
            description = "Unknown status of page!";
        }
        return description;
    }

    private static Hashtable mimeTypeTable = new Hashtable();
    static {
        mimeTypeTable.put(new String("application/excel"), new String("Microsoft Excel Table"));
        mimeTypeTable.put(new String("application/mac-binhex40"), new String("Macintosh Compressed File (Binhex)"));
        mimeTypeTable.put(new String("application/pdf"), new String("Adobe Acrobat Document (pdf)"));
        mimeTypeTable.put(new String("application/zip"), new String("ZIP Compressed file"));
        mimeTypeTable.put(new String("image/gif"), new String("Graphics (gif)"));
        mimeTypeTable.put(new String("image/jpeg"), new String("Graphics (jpeg)"));
        mimeTypeTable.put(new String("image/png"), new String("Graphics (png)"));
        mimeTypeTable.put(new String("application/msword"), new String("Microsoft Word Document"));
        mimeTypeTable.put(new String("application/octet-stream"), new String(""));
        mimeTypeTable.put(new String("application/java-vm"), new String("Java Program"));
        mimeTypeTable.put(new String("application/pgp"), new String("Pretty Good Privacy Key"));
        mimeTypeTable.put(new String("application/postscript"), new String("Postscript File"));
        mimeTypeTable.put(new String("application/powerpoint"), new String("Microsoft Powerpoint Presentation"));
        mimeTypeTable.put(new String("application/rtf"), new String("Rich Text Format File (rtf)"));
   
        mimeTypeTable.put(new String("application/wordperfect5.1"), new String("Word Perfect Document"));
        mimeTypeTable.put(new String("application/x-cdlink"), new String(""));
        mimeTypeTable.put(new String("application/x-compress"), new String("Unix Compressed File"));
        mimeTypeTable.put(new String("application/x-cpio"), new String(""));
        mimeTypeTable.put(new String("application/x-csh"), new String(""));
        mimeTypeTable.put(new String("application/x-debian-package"), new String(""));
        mimeTypeTable.put(new String("application/x-director"), new String(""));
        mimeTypeTable.put(new String("application/x-dvi"), new String(""));
        mimeTypeTable.put(new String("application/x-gtar"), new String("Unix compressed archive"));
        mimeTypeTable.put(new String("application/x-gzip"), new String("Unix comressed file (gzip)"));
        mimeTypeTable.put(new String("application/x-hdf"), new String(""));
        mimeTypeTable.put(new String("application/x-httpd-php"), new String("Dynamic World Wide Web Document"));
        mimeTypeTable.put(new String("application/x-JavaScript"), new String("JavaScript Program Definition"));
        mimeTypeTable.put(new String("application/x-latex"), new String("Latex Document"));
        // mimeTypeTable.put(new String("frm maker frame fm fb book fbdoc"), new String("application/x-maker"));
        mimeTypeTable.put(new String("application/x-mif"), new String(""));
        mimeTypeTable.put(new String("application/x-msdos-program"), new String("Executeable programme for PCs"));
        mimeTypeTable.put(new String("application/x-netcdf"), new String(""));
        mimeTypeTable.put(new String("application/x-netcdf"), new String(""));
        mimeTypeTable.put(new String("application/x-perl"), new String("Perl program"));
        mimeTypeTable.put(new String("application/x-sh"), new String("Unix shell script"));
        mimeTypeTable.put(new String("application/x-stuffit"), new String(""));
        mimeTypeTable.put(new String("application/x-tar"), new String("Unix Archive (tar)"));
        mimeTypeTable.put(new String("application/x-tcl"), new String("TCL program file"));
        mimeTypeTable.put(new String("application/x-tex"), new String("TEX Document"));
        mimeTypeTable.put(new String("application/x-texinfo"), new String(""));
        mimeTypeTable.put(new String("application/x-troff-man"), new String("Unix manual pages file"));
        mimeTypeTable.put(new String("application/x-troff-me"), new String(""));
        mimeTypeTable.put(new String("application/x-troff-ms"), new String(""));
        mimeTypeTable.put(new String("application/x-ustar"), new String(""));
        mimeTypeTable.put(new String("application/x-wais-source"), new String("Source File"));
        mimeTypeTable.put(new String("audio/basic"), new String("Audio file"));
        mimeTypeTable.put(new String("audio/midi"), new String("Audio file (midi)"));
        mimeTypeTable.put(new String("audio/mpeg"), new String("Audio file (mp3)"));
        mimeTypeTable.put(new String("audio/x-aiff"), new String("Audio file"));
        mimeTypeTable.put(new String("audio/x-pn-realaudio"), new String("Realaudio file"));
        mimeTypeTable.put(new String("audio/x-wav"), new String("Audio file (wav)"));
        mimeTypeTable.put(new String("image/ief"), new String("Graphics (ief)"));
        mimeTypeTable.put(new String("image/tiff"), new String("Graphics (tiff)"));
        mimeTypeTable.put(new String("image/x-cmu-raster"), new String(""));
        mimeTypeTable.put(new String("image/x-portable-anymap"), new String(""));
        mimeTypeTable.put(new String("image/x-portable-bitmap"), new String(""));
        mimeTypeTable.put(new String("image/x-portable-graymap"), new String(""));
        mimeTypeTable.put(new String("image/x-portable-pixmap"), new String(""));
        mimeTypeTable.put(new String("image/x-rgb"), new String(""));
        mimeTypeTable.put(new String("image/x-xbitmap"), new String(""));
        mimeTypeTable.put(new String("image/x-xpixmap"), new String(""));
        mimeTypeTable.put(new String("image/x-xwindowdump"), new String(""));
        mimeTypeTable.put(new String("model/iges"), new String(""));
        mimeTypeTable.put(new String("model/iges"), new String(""));
        mimeTypeTable.put(new String("model/mesh"), new String(""));
        mimeTypeTable.put(new String("model/vrml"), new String("3D world (VRML)"));
        mimeTypeTable.put(new String("text/css"), new String("Style Definition (CSS)"));
        mimeTypeTable.put(new String("text/html"), new String("Wold Wide Web Document"));
        mimeTypeTable.put(new String("text/plain"), new String("Plain Text Document"));
        mimeTypeTable.put(new String("text/richtext"), new String("Rich Text Format"));
        mimeTypeTable.put(new String("text/tab-separated-values"), new String("Text file"));
        mimeTypeTable.put(new String("text/x-setext"), new String(""));
        mimeTypeTable.put(new String("text/x-sgml"), new String("SGML file"));
        mimeTypeTable.put(new String("text/x-vCalendar"), new String(""));
        mimeTypeTable.put(new String("text/x-vCard"), new String(""));
        mimeTypeTable.put(new String("text/xml"), new String("XML file"));
        mimeTypeTable.put(new String("video/dl"), new String("Video file"));
        mimeTypeTable.put(new String("video/fli"), new String("Video file"));
        mimeTypeTable.put(new String("video/gl"), new String("Video file"));
        mimeTypeTable.put(new String("video/mpeg"), new String("Video file (mpeg)"));
        mimeTypeTable.put(new String("video/quicktime"), new String(""));
        mimeTypeTable.put(new String("video/x-msvideo"), new String("Microsoft video file"));
        mimeTypeTable.put(new String("video/x-sgi-movie"), new String(""));
        mimeTypeTable.put(new String("x-conference/x-cooltalk"), new String(""));
    }

    private static Hashtable statusTable = new Hashtable();
    static {
        statusTable.put(new String(""), new String(""));
        statusTable.put(new String("-1"), new String(""));
        statusTable.put(new String("100"), new String(""));
        statusTable.put(new String("101"), new String(""));
        statusTable.put(new String("200"), new String(""));
        statusTable.put(new String("201"), new String(""));
        statusTable.put(new String("202"), new String(""));
        statusTable.put(new String("203"), new String(""));
        statusTable.put(new String("204"), new String(""));
        statusTable.put(new String("205"), new String(""));
        statusTable.put(new String("206"), new String(""));
        statusTable.put(new String("300"), new String(""));
        statusTable.put(new String("301"), new String("Document at new address"));
        statusTable.put(new String("302"), new String(""));
        statusTable.put(new String("303"), new String(""));
        statusTable.put(new String("304"), new String("Document was not modified since last visit"));
        statusTable.put(new String("305"), new String(""));
        statusTable.put(new String("400"), new String("Unable to resolve server name"));
        statusTable.put(new String("401"), new String("Error"));
        statusTable.put(new String("402"), new String("Error"));
        statusTable.put(new String("403"), new String("Access to document denied"));
        statusTable.put(new String("404"), new String("Document does NOT exist!"));
        statusTable.put(new String("405"), new String("Error"));
        statusTable.put(new String("406"), new String("Error"));
        statusTable.put(new String("407"), new String("Error"));
        statusTable.put(new String("408"), new String("Error"));
        statusTable.put(new String("409"), new String("Error"));
        statusTable.put(new String("410"), new String("Error"));
        statusTable.put(new String("411"), new String("Error"));
        statusTable.put(new String("412"), new String("Error"));
        statusTable.put(new String("500"), new String("Server error"));
        statusTable.put(new String("501"), new String("Error"));
        statusTable.put(new String("502"), new String("Error"));
        statusTable.put(new String("503"), new String("Error"));
        statusTable.put(new String("504"), new String("Error"));
    }

    /* 100 Continue
     101 Switching Protocols
     200 OK
     201 Created
     202 Accepted
     203 Non-Authoritative Information
     204 No Content
     205 Reset Content
     206 Partial Content
     300 Multiple Choices
     301 Moved Permanently
     302 Moved Temporarily
     303 See Other
     304 Not Modified
     305 Use Proxy
     400 Bad Request
     401 Unauthorized
     402 Payment Required
     403 Forbidden
     404 Not Found
     405 Method Not Allowed
     406 None Acceptable
     407 Proxy Authentication Required
     408 Request Timeout
     409 Conflict
     410 Gone
     411 Length Required
     412 Unless True
     500 Internal Server Error
     501 Not Implemented
     502 Bad Gateway
     503 Service Unavailable
     504 Gateway Timeout
     */
}
