Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/net/www/MimeTable.java
38830 views
/*1* Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.net.www;26import java.io.*;27import java.net.FileNameMap;28import java.util.Hashtable;29import java.util.Enumeration;30import java.util.Properties;31import java.util.StringTokenizer;3233public class MimeTable implements FileNameMap {34/** Keyed by content type, returns MimeEntries */35private Hashtable<String, MimeEntry> entries36= new Hashtable<String, MimeEntry>();3738/** Keyed by file extension (with the .), returns MimeEntries */39private Hashtable<String, MimeEntry> extensionMap40= new Hashtable<String, MimeEntry>();4142// Will be reset if in the platform-specific data file43private static String tempFileTemplate;4445static {46java.security.AccessController.doPrivileged(47new java.security.PrivilegedAction<Void>() {48public Void run() {49tempFileTemplate =50System.getProperty("content.types.temp.file.template",51"/tmp/%s");5253mailcapLocations = new String[] {54System.getProperty("user.mailcap"),55System.getProperty("user.home") + "/.mailcap",56"/etc/mailcap",57"/usr/etc/mailcap",58"/usr/local/etc/mailcap",59System.getProperty("hotjava.home",60"/usr/local/hotjava")61+ "/lib/mailcap",62};63return null;64}65});66}676869private static final String filePreamble = "sun.net.www MIME content-types table";70private static final String fileMagic = "#" + filePreamble;7172MimeTable() {73load();74}7576private static class DefaultInstanceHolder {77static final MimeTable defaultInstance = getDefaultInstance();7879static MimeTable getDefaultInstance() {80return java.security.AccessController.doPrivileged(81new java.security.PrivilegedAction<MimeTable>() {82public MimeTable run() {83MimeTable instance = new MimeTable();84URLConnection.setFileNameMap(instance);85return instance;86}87});88}89}9091/**92* Get the single instance of this class. First use will load the93* table from a data file.94*/95public static MimeTable getDefaultTable() {96return DefaultInstanceHolder.defaultInstance;97}9899/**100*101*/102public static FileNameMap loadTable() {103MimeTable mt = getDefaultTable();104return (FileNameMap)mt;105}106107public synchronized int getSize() {108return entries.size();109}110111public synchronized String getContentTypeFor(String fileName) {112MimeEntry entry = findByFileName(fileName);113if (entry != null) {114return entry.getType();115} else {116return null;117}118}119120public synchronized void add(MimeEntry m) {121entries.put(m.getType(), m);122123String exts[] = m.getExtensions();124if (exts == null) {125return;126}127128for (int i = 0; i < exts.length; i++) {129extensionMap.put(exts[i], m);130}131}132133public synchronized MimeEntry remove(String type) {134MimeEntry entry = entries.get(type);135return remove(entry);136}137138public synchronized MimeEntry remove(MimeEntry entry) {139String[] extensionKeys = entry.getExtensions();140if (extensionKeys != null) {141for (int i = 0; i < extensionKeys.length; i++) {142extensionMap.remove(extensionKeys[i]);143}144}145146return entries.remove(entry.getType());147}148149public synchronized MimeEntry find(String type) {150MimeEntry entry = entries.get(type);151if (entry == null) {152// try a wildcard lookup153Enumeration<MimeEntry> e = entries.elements();154while (e.hasMoreElements()) {155MimeEntry wild = e.nextElement();156if (wild.matches(type)) {157return wild;158}159}160}161162return entry;163}164165/**166* Locate a MimeEntry by the file extension that has been associated167* with it. Parses general file names, and URLs.168*/169public MimeEntry findByFileName(String fname) {170String ext = "";171172int i = fname.lastIndexOf('#');173174if (i > 0) {175fname = fname.substring(0, i - 1);176}177178i = fname.lastIndexOf('.');179// REMIND: OS specific delimters appear here180i = Math.max(i, fname.lastIndexOf('/'));181i = Math.max(i, fname.lastIndexOf('?'));182183if (i != -1 && fname.charAt(i) == '.') {184ext = fname.substring(i).toLowerCase();185}186187return findByExt(ext);188}189190/**191* Locate a MimeEntry by the file extension that has been associated192* with it.193*/194public synchronized MimeEntry findByExt(String fileExtension) {195return extensionMap.get(fileExtension);196}197198public synchronized MimeEntry findByDescription(String description) {199Enumeration<MimeEntry> e = elements();200while (e.hasMoreElements()) {201MimeEntry entry = e.nextElement();202if (description.equals(entry.getDescription())) {203return entry;204}205}206207// We failed, now try treating description as type208return find(description);209}210211String getTempFileTemplate() {212return tempFileTemplate;213}214215public synchronized Enumeration<MimeEntry> elements() {216return entries.elements();217}218219// For backward compatibility -- mailcap format files220// This is not currently used, but may in the future when we add ability221// to read BOTH the properties format and the mailcap format.222protected static String[] mailcapLocations;223224public synchronized void load() {225Properties entries = new Properties();226File file = null;227try {228InputStream is;229// First try to load the user-specific table, if it exists230String userTablePath =231System.getProperty("content.types.user.table");232if (userTablePath != null) {233file = new File(userTablePath);234if (!file.exists()) {235// No user-table, try to load the default built-in table.236file = new File(System.getProperty("java.home") +237File.separator +238"lib" +239File.separator +240"content-types.properties");241}242}243else {244// No user table, try to load the default built-in table.245file = new File(System.getProperty("java.home") +246File.separator +247"lib" +248File.separator +249"content-types.properties");250}251252is = new BufferedInputStream(new FileInputStream(file));253entries.load(is);254is.close();255}256catch (IOException e) {257System.err.println("Warning: default mime table not found: " +258file.getPath());259return;260}261parse(entries);262}263264void parse(Properties entries) {265// first, strip out the platform-specific temp file template266String tempFileTemplate = (String)entries.get("temp.file.template");267if (tempFileTemplate != null) {268entries.remove("temp.file.template");269MimeTable.tempFileTemplate = tempFileTemplate;270}271272// now, parse the mime-type spec's273Enumeration<?> types = entries.propertyNames();274while (types.hasMoreElements()) {275String type = (String)types.nextElement();276String attrs = entries.getProperty(type);277parse(type, attrs);278}279}280281//282// Table format:283//284// <entry> ::= <table_tag> | <type_entry>285//286// <table_tag> ::= <table_format_version> | <temp_file_template>287//288// <type_entry> ::= <type_subtype_pair> '=' <type_attrs_list>289//290// <type_subtype_pair> ::= <type> '/' <subtype>291//292// <type_attrs_list> ::= <attr_value_pair> [ ';' <attr_value_pair> ]*293// | [ <attr_value_pair> ]+294//295// <attr_value_pair> ::= <attr_name> '=' <attr_value>296//297// <attr_name> ::= 'description' | 'action' | 'application'298// | 'file_extensions' | 'icon'299//300// <attr_value> ::= <legal_char>*301//302// Embedded ';' in an <attr_value> are quoted with leading '\' .303//304// Interpretation of <attr_value> depends on the <attr_name> it is305// associated with.306//307308void parse(String type, String attrs) {309MimeEntry newEntry = new MimeEntry(type);310311// REMIND handle embedded ';' and '|' and literal '"'312StringTokenizer tokenizer = new StringTokenizer(attrs, ";");313while (tokenizer.hasMoreTokens()) {314String pair = tokenizer.nextToken();315parse(pair, newEntry);316}317318add(newEntry);319}320321void parse(String pair, MimeEntry entry) {322// REMIND add exception handling...323String name = null;324String value = null;325326boolean gotName = false;327StringTokenizer tokenizer = new StringTokenizer(pair, "=");328while (tokenizer.hasMoreTokens()) {329if (gotName) {330value = tokenizer.nextToken().trim();331}332else {333name = tokenizer.nextToken().trim();334gotName = true;335}336}337338fill(entry, name, value);339}340341void fill(MimeEntry entry, String name, String value) {342if ("description".equalsIgnoreCase(name)) {343entry.setDescription(value);344}345else if ("action".equalsIgnoreCase(name)) {346entry.setAction(getActionCode(value));347}348else if ("application".equalsIgnoreCase(name)) {349entry.setCommand(value);350}351else if ("icon".equalsIgnoreCase(name)) {352entry.setImageFileName(value);353}354else if ("file_extensions".equalsIgnoreCase(name)) {355entry.setExtensions(value);356}357358// else illegal name exception359}360361String[] getExtensions(String list) {362StringTokenizer tokenizer = new StringTokenizer(list, ",");363int n = tokenizer.countTokens();364String[] extensions = new String[n];365for (int i = 0; i < n; i++) {366extensions[i] = tokenizer.nextToken();367}368369return extensions;370}371372int getActionCode(String action) {373for (int i = 0; i < MimeEntry.actionKeywords.length; i++) {374if (action.equalsIgnoreCase(MimeEntry.actionKeywords[i])) {375return i;376}377}378379return MimeEntry.UNKNOWN;380}381382public synchronized boolean save(String filename) {383if (filename == null) {384filename = System.getProperty("user.home" +385File.separator +386"lib" +387File.separator +388"content-types.properties");389}390391return saveAsProperties(new File(filename));392}393394public Properties getAsProperties() {395Properties properties = new Properties();396Enumeration<MimeEntry> e = elements();397while (e.hasMoreElements()) {398MimeEntry entry = e.nextElement();399properties.put(entry.getType(), entry.toProperty());400}401402return properties;403}404405protected boolean saveAsProperties(File file) {406FileOutputStream os = null;407try {408os = new FileOutputStream(file);409Properties properties = getAsProperties();410properties.put("temp.file.template", tempFileTemplate);411String tag;412String user = System.getProperty("user.name");413if (user != null) {414tag = "; customized for " + user;415properties.store(os, filePreamble + tag);416}417else {418properties.store(os, filePreamble);419}420}421catch (IOException e) {422e.printStackTrace();423return false;424}425finally {426if (os != null) {427try { os.close(); } catch (IOException e) {}428}429}430431return true;432}433/*434* Debugging utilities435*436public void list(PrintStream out) {437Enumeration keys = entries.keys();438while (keys.hasMoreElements()) {439String key = (String)keys.nextElement();440MimeEntry entry = (MimeEntry)entries.get(key);441out.println(key + ": " + entry);442}443}444445public static void main(String[] args) {446MimeTable testTable = MimeTable.getDefaultTable();447448Enumeration e = testTable.elements();449while (e.hasMoreElements()) {450MimeEntry entry = (MimeEntry)e.nextElement();451System.out.println(entry);452}453454testTable.save(File.separator + "tmp" +455File.separator + "mime_table.save");456}457*/458}459460461