1. /*
  2. * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
  3. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  4. */
  5. package javax.activation;
  6. import java.io.*;
  7. import com.sun.activation.registries.MimeTypeFile;
  8. /**
  9. * This class extends FileTypeMap and provides data typing of files
  10. * via their file extension. It uses the <code>.mime.types</code> format. <p>
  11. *
  12. * <b>MIME types file search order:</b><p>
  13. * The MimetypesFileTypeMap looks in various places in the user's
  14. * system for MIME types file entries. When requests are made
  15. * to search for MIME types in the MimetypesFileTypeMap, it searches
  16. * MIME types files in the following order:
  17. * <p>
  18. * <ol>
  19. * <li> Programmatically added entries to the MimetypesFileTypeMap instance.
  20. * <li> The file <code>.mime.types</code> in the user's home directory.
  21. * <li> The file <<i>java.home</i>><code>/lib/mime.types</code>.
  22. * <li> The file or resource named <code>META-INF/mime.types</code>.
  23. * <li> The file or resource named <code>META-INF/mimetypes.default</code>
  24. * (usually found only in the <code>activation.jar</code> file).
  25. * </ol>
  26. * <p>
  27. * <b>MIME types file format:</b><p>
  28. *
  29. * <code>
  30. * # comments begin with a '#'<br>
  31. * # the format is <mime type> <space separated file extensions><br>
  32. * # for example:<br>
  33. * text/plain txt text TXT<br>
  34. * # this would map file.txt, file.text, and file.TXT to<br>
  35. * # the mime type "text/plain"<br>
  36. * </code>
  37. *
  38. * @author Bart Calder
  39. * @author Bill Shannon
  40. */
  41. public class MimetypesFileTypeMap extends FileTypeMap {
  42. /*
  43. * We manage up to 5 databases, searched in order.
  44. * The default database is shared between all instances
  45. * of this class.
  46. * XXX - Can we safely share more databases between instances?
  47. */
  48. private static MimeTypeFile defDB = null;
  49. private MimeTypeFile[] DB = new MimeTypeFile[5];
  50. private static final int PROG = 0; // programmatically added entries
  51. private static final int HOME = 1; // the user's home directory
  52. private static final int SYS = 2; // the system file
  53. private static final int JAR = 3; // the app's entry in the jar file
  54. private static final int DEF = 4; // the default entry in our jar file
  55. private static String defaultType = "application/octet-stream";
  56. /**
  57. * The default constructor.
  58. */
  59. public MimetypesFileTypeMap() {
  60. try {
  61. String user_home = System.getProperty("user.home");
  62. if (user_home != null) {
  63. String path = user_home + File.separator + ".mime.types";
  64. DB[HOME] = loadFile(path);
  65. }
  66. } catch (SecurityException ex) {}
  67. try {
  68. // check system's home
  69. String system_mimetypes = System.getProperty("java.home") +
  70. File.separator + "lib" + File.separator + "mime.types";
  71. DB[SYS] = loadFile(system_mimetypes);
  72. } catch (SecurityException ex) {}
  73. // load from the app's jar file
  74. DB[JAR] = loadResource("/META-INF/mime.types");
  75. synchronized (MimetypesFileTypeMap.class) {
  76. // see if another instance has created this yet.
  77. if (defDB == null)
  78. defDB = loadResource("/META-INF/mimetypes.default");
  79. }
  80. DB[DEF] = defDB;
  81. }
  82. /**
  83. * Load the named resource.
  84. */
  85. private MimeTypeFile loadResource(String name) {
  86. try {
  87. InputStream clis = this.getClass().getResourceAsStream(name);
  88. if (clis != null)
  89. return new MimeTypeFile(clis);
  90. } catch (IOException e) {
  91. // e.printStackTrace();
  92. }
  93. return null;
  94. }
  95. /**
  96. * Load the named file.
  97. */
  98. private MimeTypeFile loadFile(String name) {
  99. MimeTypeFile mtf = null;
  100. try {
  101. mtf = new MimeTypeFile(name);
  102. } catch (IOException e) {
  103. // e.printStackTrace();
  104. }
  105. return mtf;
  106. }
  107. /**
  108. * Construct a MimetypesFileTypeMap with programmatic entries
  109. * added from the named file.
  110. *
  111. * @param mimeTypeFileName the file name
  112. */
  113. public MimetypesFileTypeMap(String mimeTypeFileName) throws IOException {
  114. this();
  115. DB[PROG] = new MimeTypeFile(mimeTypeFileName);
  116. }
  117. /**
  118. * Construct a MimetypesFileTypeMap with programmatic entries
  119. * added from the InputStream.
  120. *
  121. * @param is the input stream to read from
  122. */
  123. public MimetypesFileTypeMap(InputStream is) {
  124. this();
  125. try {
  126. DB[PROG] = new MimeTypeFile(is);
  127. } catch (IOException ex) {
  128. // XXX - really should throw it
  129. }
  130. }
  131. /**
  132. * Prepend the MIME type values to the registry.
  133. *
  134. * @param mime_types A .mime.types formatted string of entries.
  135. */
  136. public synchronized void addMimeTypes(String mime_types) {
  137. // check to see if we have created the registry
  138. if (DB[PROG] == null)
  139. DB[PROG] = new MimeTypeFile(); // make one
  140. DB[PROG].appendToRegistry(mime_types);
  141. }
  142. /**
  143. * Return the MIME type of the file object.
  144. * The implementation in this class calls
  145. * <code>getContentType(f.getName())</code>.
  146. *
  147. * @param f the file
  148. * @return the file's MIME type
  149. */
  150. public String getContentType(File f) {
  151. return this.getContentType(f.getName());
  152. }
  153. /**
  154. * Return the MIME type based on the specified file name.
  155. * The MIME type entries are searched as described above under
  156. * <i>MIME types file search order</i>.
  157. * If no entry is found, the type "application/octet-stream" is returned.
  158. *
  159. * @param filename the file name
  160. * @return the file's MIME type
  161. */
  162. public synchronized String getContentType(String filename) {
  163. int dot_pos = filename.lastIndexOf("."); // period index
  164. if (dot_pos < 0)
  165. return defaultType;
  166. String file_ext = filename.substring(dot_pos + 1);
  167. if (file_ext.length() == 0)
  168. return defaultType;
  169. for (int i = 0; i < DB.length; i++) {
  170. if (DB[i] == null)
  171. continue;
  172. String result = DB[i].getMIMETypeString(file_ext);
  173. if (result != null)
  174. return result;
  175. }
  176. return defaultType;
  177. }
  178. /**
  179. * for debugging...
  180. *
  181. public static void main(String[] argv) throws Exception {
  182. MimetypesFileTypeMap map = new MimetypesFileTypeMap();
  183. System.out.println("File " + argv[0] + " has MIME type " +
  184. map.getContentType(argv[0]));
  185. System.exit(0);
  186. }
  187. */
  188. }