1 /* MimeTypeMapper.java -- A class for mapping file names to MIME types
2    Copyright (C) 1998 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 package java.net;
39 
40 import gnu.classpath.SystemProperties;
41 
42 import java.io.FileReader;
43 import java.io.IOException;
44 import java.io.LineNumberReader;
45 import java.util.Hashtable;
46 import java.util.Iterator;
47 import java.util.Map;
48 import java.util.NoSuchElementException;
49 import java.util.StringTokenizer;
50 import java.util.TreeMap;
51 
52 
53 /**
54  * This non-public class is used to implement the FileNameMap interface
55  * which defines a mechanism for mapping filenames to MIME types.
56  *
57  * @version 0.5
58  *
59  * @author Aaron M. Renn (arenn@urbanophile.com)
60  */
61 class MimeTypeMapper implements FileNameMap
62 {
63   /**
64    * This array of strings is used to identify a MIME type based on a file
65    * extension.  This is list is based on the Apache mime.types file.
66    */
67   protected static final String[][] mime_strings =
68     {
69        { "ai", "application/postscript" }
70      , { "aif", "audio/x-aiff" }
71      , { "aifc", "audio/x-aiff" }
72      , { "aiff", "audio/x-aiff" }
73      , { "asc", "text/plain" }
74      , { "au", "audio/basic" }
75      , { "avi", "video/x-msvideo" }
76      , { "bcpio", "application/x-bcpio" }
77      , { "bin", "application/octet-stream" }
78      , { "bmp", "image/bmp" }
79      , { "bz2", "application/x-bzip2" }
80      , { "cdf", "application/x-netcdf" }
81      , { "chrt", "application/x-kchart" }
82      , { "class", "application/octet-stream" }
83      , { "cpio", "application/x-cpio" }
84      , { "cpt", "application/mac-compactpro" }
85      , { "csh", "application/x-csh" }
86      , { "css", "text/css" }
87      , { "dcr", "application/x-director" }
88      , { "dir", "application/x-director" }
89      , { "djv", "image/vnd.djvu" }
90      , { "djvu", "image/vnd.djvu" }
91      , { "dll", "application/octet-stream" }
92      , { "dms", "application/octet-stream" }
93      , { "doc", "application/msword" }
94      , { "dvi", "application/x-dvi" }
95      , { "dxr", "application/x-director" }
96      , { "eps", "application/postscript" }
97      , { "etx", "text/x-setext" }
98      , { "exe", "application/octet-stream" }
99      , { "ez", "application/andrew-inset" }
100      , { "gif", "image/gif" }
101      , { "gtar", "application/x-gtar" }
102      , { "gz", "application/x-gzip" }
103      , { "hdf", "application/x-hdf" }
104      , { "hqx", "application/mac-binhex40" }
105      , { "htm", "text/html" }
106      , { "html", "text/html" }
107      , { "ice", "x-conference/x-cooltalk" }
108      , { "ief", "image/ief" }
109      , { "iges", "model/iges" }
110      , { "igs", "model/iges" }
111      , { "img", "application/octet-stream" }
112      , { "iso", "application/octet-stream" }
113      , { "jpe", "image/jpeg" }
114      , { "jpeg", "image/jpeg" }
115      , { "jpg", "image/jpeg" }
116      , { "js", "application/x-javascript" }
117      , { "kar", "audio/midi" }
118      , { "kil", "application/x-killustrator" }
119      , { "kpr", "application/x-kpresenter" }
120      , { "kpt", "application/x-kpresenter" }
121      , { "ksp", "application/x-kspread" }
122      , { "kwd", "application/x-kword" }
123      , { "kwt", "application/x-kword" }
124      , { "latex", "application/x-latex" }
125      , { "lha", "application/octet-stream" }
126      , { "lzh", "application/octet-stream" }
127      , { "m3u", "audio/x-mpegurl" }
128      , { "man", "application/x-troff-man" }
129      , { "me", "application/x-troff-me" }
130      , { "mesh", "model/mesh" }
131      , { "mid", "audio/midi" }
132      , { "midi", "audio/midi" }
133      , { "mif", "application/vnd.mif" }
134      , { "mov", "video/quicktime" }
135      , { "movie", "video/x-sgi-movie" }
136      , { "mp2", "audio/mpeg" }
137      , { "mp3", "audio/mpeg" }
138      , { "mpe", "video/mpeg" }
139      , { "mpeg", "video/mpeg" }
140      , { "mpg", "video/mpeg" }
141      , { "mpga", "audio/mpeg" }
142      , { "ms", "application/x-troff-ms" }
143      , { "msh", "model/mesh" }
144      , { "mxu", "video/vnd.mpegurl" }
145      , { "nc", "application/x-netcdf" }
146      , { "ogg", "application/ogg" }
147      , { "pbm", "image/x-portable-bitmap" }
148      , { "pdb", "chemical/x-pdb" }
149      , { "pdf", "application/pdf" }
150      , { "pgm", "image/x-portable-graymap" }
151      , { "pgn", "application/x-chess-pgn" }
152      , { "png", "image/png" }
153      , { "pnm", "image/x-portable-anymap" }
154      , { "ppm", "image/x-portable-pixmap" }
155      , { "ppt", "application/vnd.ms-powerpoint" }
156      , { "ps", "application/postscript" }
157      , { "qt", "video/quicktime" }
158      , { "ra", "audio/x-realaudio" }
159      , { "ram", "audio/x-pn-realaudio" }
160      , { "ras", "image/x-cmu-raster" }
161      , { "rgb", "image/x-rgb" }
162      , { "rm", "audio/x-pn-realaudio" }
163      , { "roff", "application/x-troff" }
164      , { "rpm", "application/x-rpm" }
165      , { "rtf", "text/rtf" }
166      , { "rtx", "text/richtext" }
167      , { "sgm", "text/sgml" }
168      , { "sgml", "text/sgml" }
169      , { "sh", "application/x-sh" }
170      , { "shar", "application/x-shar" }
171      , { "silo", "model/mesh" }
172      , { "sit", "application/x-stuffit" }
173      , { "skd", "application/x-koan" }
174      , { "skm", "application/x-koan" }
175      , { "skp", "application/x-koan" }
176      , { "skt", "application/x-koan" }
177      , { "smi", "application/smil" }
178      , { "smil", "application/smil" }
179      , { "snd", "audio/basic" }
180      , { "so", "application/octet-stream" }
181      , { "spl", "application/x-futuresplash" }
182      , { "src", "application/x-wais-source" }
183      , { "stc", "application/vnd.sun.xml.calc.template" }
184      , { "std", "application/vnd.sun.xml.draw.template" }
185      , { "sti", "application/vnd.sun.xml.impress.template" }
186      , { "stw", "application/vnd.sun.xml.writer.template" }
187      , { "sv4cpio", "application/x-sv4cpio" }
188      , { "sv4crc", "application/x-sv4crc" }
189      , { "swf", "application/x-shockwave-flash" }
190      , { "sxc", "application/vnd.sun.xml.calc" }
191      , { "sxd", "application/vnd.sun.xml.draw" }
192      , { "sxg", "application/vnd.sun.xml.writer.global" }
193      , { "sxi", "application/vnd.sun.xml.impress" }
194      , { "sxm", "application/vnd.sun.xml.math" }
195      , { "sxw", "application/vnd.sun.xml.writer" }
196      , { "t", "application/x-troff" }
197      , { "tar", "application/x-tar" }
198      , { "tcl", "application/x-tcl" }
199      , { "tex", "application/x-tex" }
200      , { "texi", "application/x-texinfo" }
201      , { "texinfo", "application/x-texinfo" }
202      , { "tgz", "application/x-gzip" }
203      , { "tif", "image/tiff" }
204      , { "tiff", "image/tiff" }
205      , { "torrent", "application/x-bittorrent" }
206      , { "tr", "application/x-troff" }
207      , { "tsv", "text/tab-separated-values" }
208      , { "txt", "text/plain" }
209      , { "ustar", "application/x-ustar" }
210      , { "vcd", "application/x-cdlink" }
211      , { "vrml", "model/vrml" }
212      , { "wav", "audio/x-wav" }
213      , { "wbmp", "image/vnd.wap.wbmp" }
214      , { "wbxml", "application/vnd.wap.wbxml" }
215      , { "wml", "text/vnd.wap.wml" }
216      , { "wmlc", "application/vnd.wap.wmlc" }
217      , { "wmls", "text/vnd.wap.wmlscript" }
218      , { "wmlsc", "application/vnd.wap.wmlscriptc" }
219      , { "wrl", "model/vrml" }
220      , { "xbm", "image/x-xbitmap" }
221      , { "xht", "application/xhtml+xml" }
222      , { "xhtml", "application/xhtml+xml" }
223      , { "xls", "application/vnd.ms-excel" }
224      , { "xml", "text/xml" }
225      , { "xpm", "image/x-xpixmap" }
226      , { "xsl", "text/xml" }
227      , { "xwd", "image/x-xwindowdump" }
228      , { "xyz", "chemical/x-xyz" }
229      , { "zip", "application/zip" }
230     };
231 
232   /**
233    * The MIME types above are put into this Hashtable for faster lookup.
234    */
235   private Hashtable<String, String> mime_types
236     = new Hashtable<String, String>(150);
237 
238   /**
239    * Create a new <code>MimeTypeMapper</code> object.
240    */
MimeTypeMapper()241   public MimeTypeMapper()
242   {
243     for (int i = 0; i < mime_strings.length; i++)
244       mime_types.put(mime_strings[i][0], mime_strings[i][1]);
245 
246     // Now read from the system mime database, if it exists.  Entries found
247     // here override our internal ones.
248     try
249       {
250         // On Linux this usually means /etc/mime.types.
251         String file
252           = SystemProperties.getProperty("gnu.classpath.mime.types.file");
253         if (file != null)
254           fillFromFile(mime_types, file);
255       }
256     catch (IOException ignore)
257       {
258       }
259   }
260 
fillFromFile(Map<String, String> table, String fname)261   public static void fillFromFile (Map<String, String> table, String fname)
262     throws IOException
263   {
264     LineNumberReader reader =
265       new LineNumberReader (new FileReader (fname));
266 
267     while (reader.ready ())
268       {
269         StringTokenizer tokenizer =
270           new StringTokenizer (reader.readLine ());
271 
272         try
273           {
274             String t = tokenizer.nextToken ();
275 
276             if (! t.startsWith ("#"))
277               {
278                 while (true)
279                   {
280                     // Read the next extension
281                     String e = tokenizer.nextToken ();
282                     if ((e != null) && (! e.startsWith ("#")))
283                       table.put (e, t);
284                     else
285                       break;
286                   }
287               }
288           }
289         catch (NoSuchElementException ex)
290           {
291             // Do nothing.
292           }
293       }
294   }
295 
296   /**
297    * The method returns the MIME type of the filename passed as an argument.
298    * The value returned is based on the extension of the filename.  The
299    * default content type returned if this method cannot determine the
300    * actual content type is "application/octet-stream"
301    *
302    * @param filename The name of the file to return the MIME type for
303    *
304    * @return The MIME type
305    */
getContentTypeFor(String filename)306   public String getContentTypeFor(String filename)
307   {
308     int index = filename.lastIndexOf(".");
309     if (index != -1)
310       {
311         if (index == filename.length())
312           return "application/octet-stream";
313         else
314           filename = filename.substring(index + 1);
315       }
316 
317     String type = (String) mime_types.get(filename);
318     if (type == null)
319       return "application/octet-stream";
320     else
321       return type;
322   }
323 
324   /**
325    * Run this class as a program to create a new mime_strings table.
326    */
main(String[] args)327   public static void main(String[] args) throws IOException
328   {
329     TreeMap<String, String> map = new TreeMap<String, String>();
330     // It is fine to hard-code the name here.  This is only ever
331     // used by maintainers, who can hack it if they need to re-run
332     // it.
333     fillFromFile(map, "/etc/mime.types");
334     Iterator<String> it = map.keySet().iterator();
335     boolean first = true;
336     while (it.hasNext())
337       {
338         String key = it.next();
339         String value = map.get(key);
340         // Put the "," first since it is easier to make correct syntax this way.
341         System.out.println("      " + (first ? "  " : ", ")
342                            + "{ \"" + key + "\", \"" + value + "\" }");
343         first = false;
344       }
345   }
346 }
347