429 lines · 11.3 KB · Java
RawDownload
/* * @(#)MimeTable.java	1.12 97/04/08 James Gosling *  * Copyright (c) 1994,1996 Sun Microsystems, Inc. All Rights Reserved. *  * Permission to use, copy, modify, and distribute this software and its * documentation for NON-COMMERCIAL purposes and without fee is hereby * granted provided that this copyright notice appears in all copies. Please * refer to the file "copyright.html" for further important copyright and * licensing information. *  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, * OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY * LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR * ITS DERIVATIVES. */ package sun.net.www;import java.io.*;import java.util.Calendar;import java.util.Date;import java.net.URL;import java.net.FileNameMap;import java.util.Hashtable;import java.util.Enumeration;import java.util.Properties;import java.util.StringTokenizer; public class MimeTable implements FileNameMap {    /** Keyed by content type, returns MimeEntries */    private Hashtable entries = new Hashtable();     /** Keyed by file extension (with the .), returns MimeEntries */    private Hashtable extensionMap = new Hashtable();     // Will be reset if in the platform-specific data file    private static String tempFileTemplate =        System.getProperty("content.types.temp.file.template", "/tmp/%s");     private static final String filePreamble = "sun.net.www MIME content-types table";    private static final String fileMagic = "#" + filePreamble;    private static MimeTable defaultInstance = null;     private MimeTable() {	load();    }     /**     * Get the single instance of this class.  First use will load the     * table from a data file.     */    public static MimeTable getDefaultTable() {	if (defaultInstance == null) {	    defaultInstance = new MimeTable();	    URLConnection.fileNameMap = defaultInstance;	}		return defaultInstance;    }     public synchronized int getSize() {	return entries.size();    }        public synchronized String getContentTypeFor(String fileName) {	MimeEntry entry = findByFileName(fileName);	if (entry != null) {	    return entry.getType();	} else {	    return null;	}    }     public synchronized void add(MimeEntry m) {	entries.put(m.getType(), m); 	String exts[] = m.getExtensions();	if (exts == null) {	    return;	}		for (int i = 0; i < exts.length; i++) {	    extensionMap.put(exts[i], m);	}    }     public synchronized MimeEntry remove(String type) {	MimeEntry entry = (MimeEntry)entries.get(type);	return remove(entry);    }     public synchronized MimeEntry remove(MimeEntry entry) {	String[] extensionKeys = entry.getExtensions();	if (extensionKeys != null) {	    for (int i = 0; i < extensionKeys.length; i++) {		extensionMap.remove(extensionKeys[i]);	    }	} 	return (MimeEntry)entries.remove(entry.getType());    }     public synchronized MimeEntry find(String type) {	MimeEntry entry = (MimeEntry)entries.get(type);	if (entry == null) {	    // try a wildcard lookup	    Enumeration e = entries.elements();	    while (e.hasMoreElements()) {		MimeEntry wild = (MimeEntry)e.nextElement();		if (wild.matches(type)) {		    return wild;		}	    }	} 	return entry;    }     /**     * Locate a MimeEntry by the file extension that has been associated     * with it. Parses general file names, and URLs.     */    public MimeEntry findByFileName(String fname) {	String ext = ""; 	int i = fname.lastIndexOf('#'); 	if (i > 0) {	    fname = fname.substring(0, i - 1);	} 	i = fname.lastIndexOf('.');	// REMIND: OS specific delimters appear here	i = Math.max(i, fname.lastIndexOf('/'));	i = Math.max(i, fname.lastIndexOf('?')); 	if (i != -1 && fname.charAt(i) == '.') {	    ext = fname.substring(i).toLowerCase();	} 	return findByExt(ext);    }     /**     * Locate a MimeEntry by the file extension that has been associated     * with it.     */    public synchronized MimeEntry findByExt(String fileExtension) {	return (MimeEntry)extensionMap.get(fileExtension);    }     public synchronized MimeEntry findByDescription(String description) {	Enumeration e = elements();	while (e.hasMoreElements()) {	    MimeEntry entry = (MimeEntry)e.nextElement();	    if (description.equals(entry.getDescription())) {		return entry;	    }	} 	// We failed, now try treating description as type	return find(description);    }     String getTempFileTemplate() {	return tempFileTemplate;    }     public synchronized Enumeration elements() {	return entries.elements();    }     // For backward compatibility -- mailcap format files    // This is not currently used, but may in the future when we add ability    // to read BOTH the properties format and the mailcap format.    protected static String[] mailcapLocations = {	System.getProperty("user.mailcap"),	System.getProperty("user.home") + "/.mailcap",	"/etc/mailcap",	"/usr/etc/mailcap",	"/usr/local/etc/mailcap",	System.getProperty("hotjava.home",			   "/usr/local/hotjava") + "/lib/mailcap",    };     public synchronized void load() {	Properties entries = new Properties();	File file = null;	try {	    InputStream is;	    // First try to load the user-specific table, if it exists	    String userTablePath =		System.getProperty("content.types.user.table");	    if (userTablePath != null) {		file = new File(userTablePath);		if (!file.exists()) {		    // No user-table, try to load the default built-in table.		    file = new File(System.getProperty("java.home") +				    File.separator +				    "lib" +				    File.separator +				    "content-types.properties");		}	    }	    else {		// No user table, try to load the default built-in table.		file = new File(System.getProperty("java.home") +				File.separator +				"lib" +				File.separator +				"content-types.properties");	    } 	    is = new BufferedInputStream(new FileInputStream(file));	    entries.load(is);	    is.close();	}	catch (IOException e) {	    // The default table file was not found?	    System.err.println("MimeTable.load: file = " +			       file.getPath() +			       ", " +			       e);	    e.printStackTrace();	    // The table will be empty since this is called from the	    // constructor.	    return;	} 	parse(entries);    }     void parse(Properties entries) {	// first, strip out the platform-specific temp file template	String tempFileTemplate = (String)entries.get("temp.file.template");	if (tempFileTemplate != null) {	    entries.remove("temp.file.template");	    this.tempFileTemplate = tempFileTemplate;	} 	// now, parse the mime-type spec's	Enumeration types = entries.propertyNames();	while (types.hasMoreElements()) {	    String type = (String)types.nextElement();	    String attrs = entries.getProperty(type);	    parse(type, attrs);	}    }     //    // Table format:    //    // <entry> ::= <table_tag> | <type_entry>    //    // <table_tag> ::= <table_format_version> | <temp_file_template>    //    // <type_entry> ::= <type_subtype_pair> '=' <type_attrs_list>    //    // <type_subtype_pair> ::= <type> '/' <subtype>    //    // <type_attrs_list> ::= <attr_value_pair> [ ';' <attr_value_pair> ]*    //                       | [ <attr_value_pair> ]+    //    // <attr_value_pair> ::= <attr_name> '=' <attr_value>    //    // <attr_name> ::= 'description' | 'action' | 'application'    //                 | 'file_extensions' | 'icon'    //    // <attr_value> ::= <legal_char>*    //    // Embedded ';' in an <attr_value> are quoted with leading '\' .    //    // Interpretation of <attr_value> depends on the <attr_name> it is    // associated with.    //     void parse(String type, String attrs) {	MimeEntry newEntry = new MimeEntry(type); 	// REMIND handle embedded ';' and '|' and literal '"'	StringTokenizer tokenizer = new StringTokenizer(attrs, ";");	while (tokenizer.hasMoreTokens()) {	    String pair = tokenizer.nextToken();	    parse(pair, newEntry);	} 	add(newEntry);    }     void parse(String pair, MimeEntry entry) {	// REMIND add exception handling...	String name = null;	String value = null;		boolean gotName = false;	StringTokenizer tokenizer = new StringTokenizer(pair, "=");	while (tokenizer.hasMoreTokens()) {	    if (gotName) {		value = tokenizer.nextToken().trim();	    }	    else {		name = tokenizer.nextToken().trim();		gotName = true;	    }	} 	fill(entry, name, value);    }     void fill(MimeEntry entry, String name, String value) {	if ("description".equalsIgnoreCase(name)) {	    entry.setDescription(value);	}	else if ("action".equalsIgnoreCase(name)) {	    entry.setAction(getActionCode(value));	}	else if ("application".equalsIgnoreCase(name)) {	    entry.setCommand(value);	}	else if ("icon".equalsIgnoreCase(name)) {	    entry.setImageFileName(value);	}	else if ("file_extensions".equalsIgnoreCase(name)) {	    entry.setExtensions(value);	} 	// else illegal name exception    }     String[] getExtensions(String list) {	StringTokenizer tokenizer = new StringTokenizer(list, ",");	int n = tokenizer.countTokens();	String[] extensions = new String[n];	for (int i = 0; i < n; i++) {	    extensions[i] = tokenizer.nextToken();	} 	return extensions;    }     int getActionCode(String action) {	for (int i = 0; i < MimeEntry.actionKeywords.length; i++) {	    if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) {		return i;	    }	}		return MimeEntry.UNKNOWN;    }     public synchronized boolean save(String filename) {	if (filename == null) {	    filename = System.getProperty("user.home" +					  File.separator +					  "lib" + 					  File.separator +					  "content-types.properties");	} 	return saveAsProperties(new File(filename));    }     public Properties getAsProperties() {	Properties properties = new Properties();	Enumeration e = elements();	while (e.hasMoreElements()) {	    MimeEntry entry = (MimeEntry)e.nextElement();	    properties.put(entry.getType(), entry.toProperty());	} 	return properties;    }     protected boolean saveAsProperties(File file) {	FileOutputStream os = null;	try {	    os = new FileOutputStream(file);	    Properties properties = getAsProperties();	    properties.put("temp.file.template", tempFileTemplate);	    String tag;	    String user = System.getProperty("user.name");	    if (user != null) {		tag = "; customized for " + user;		properties.save(os, filePreamble + tag);	    }	    else {		properties.save(os, filePreamble);	    }	}	catch (IOException e) {	    e.printStackTrace();	    return false;	}	finally {	    if (os != null) {		try { os.close(); } catch (IOException e) {}	    }	} 	return true;    }    /*     * Debugging utilities     *    public void list(PrintStream out) {	Enumeration keys = entries.keys();	while (keys.hasMoreElements()) {	    String key = (String)keys.nextElement();	    MimeEntry entry = (MimeEntry)entries.get(key);	    out.println(key + ": " + entry);	}    }        public static void main(String[] args) {	MimeTable testTable = MimeTable.getDefaultTable(); 	Enumeration e = testTable.elements();	while (e.hasMoreElements()) {	    MimeEntry entry = (MimeEntry)e.nextElement();	    System.out.println(entry);	} 	testTable.save(File.separator + "tmp" +		       File.separator + "mime_table.save");    }    */}