Coverage Report - org.apache.fulcrum.mimetype.util.MimeTypeMap
 
Classes in this File Line Coverage Branch Coverage Complexity
MimeTypeMap
66%
55/83
61%
17/28
2,412
 
 1  
 package org.apache.fulcrum.mimetype.util;
 2  
 
 3  
 
 4  
 /*
 5  
  * Licensed to the Apache Software Foundation (ASF) under one
 6  
  * or more contributor license agreements.  See the NOTICE file
 7  
  * distributed with this work for additional information
 8  
  * regarding copyright ownership.  The ASF licenses this file
 9  
  * to you under the Apache License, Version 2.0 (the
 10  
  * "License"); you may not use this file except in compliance
 11  
  * with the License.  You may obtain a copy of the License at
 12  
  *
 13  
  *   http://www.apache.org/licenses/LICENSE-2.0
 14  
  *
 15  
  * Unless required by applicable law or agreed to in writing,
 16  
  * software distributed under the License is distributed on an
 17  
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 18  
  * KIND, either express or implied.  See the License for the
 19  
  * specific language governing permissions and limitations
 20  
  * under the License.
 21  
  */
 22  
 
 23  
 
 24  
 import java.io.File;
 25  
 import java.io.InputStream;
 26  
 import java.io.IOException;
 27  
 
 28  
 /**
 29  
  * This class maintains a set of mappers defining mappings
 30  
  * between MIME types and the corresponding file name extensions.
 31  
  * The mappings are defined as lines formed by a MIME type name
 32  
  * followed by a list of extensions separated by a whitespace.
 33  
  * The definitions can be listed in MIME type files located in user's
 34  
  * home directory, Java home directory or the current class jar.
 35  
  * In addition, this class maintains static default mappings
 36  
  * and constructors support application specific mappings.
 37  
  *
 38  
  * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
 39  
  * @author Daniel Rall
 40  
  * @version $Id: MimeTypeMap.java 826489 2009-10-18 18:54:59Z tv $
 41  
  */
 42  
 public class MimeTypeMap
 43  
 {
 44  
     /**
 45  
      * The default MIME type when nothing else is applicable.
 46  
      */
 47  3
     public static final MimeType DEFAULT_MIMETYPE =
 48  
         MimeType.APPLICATION_OCTET_STREAM;
 49  
 
 50  
     /**
 51  
      * The default MIME type as a string.
 52  
      */
 53  3
     public static final String DEFAULT_TYPE = DEFAULT_MIMETYPE.toString();
 54  
 
 55  
     /**
 56  
      * The name for MIME type mapper resources.
 57  
      */
 58  
     public static final String MIMETYPE_RESOURCE = "mime.types";
 59  
 
 60  
     /**
 61  
      * Common MIME type extensions.
 62  
      */
 63  
     public static final String EXT_HTML = "html";
 64  
     public static final String EXT_HTM = "htm";
 65  
     public static final String EXT_WML = "wml";
 66  
     public static final String EXT_HDML = "hdml";
 67  
     public static final String EXT_HDM = "hdm";
 68  
     public static final String EXT_CHTML = "chtml";
 69  
     public static final String EXT_TEXT = "txt";
 70  
     public static final String EXT_GIF = "gif";
 71  
     public static final String EXT_JPEG = "jpeg";
 72  
     public static final String EXT_JPG = "jpg";
 73  
     public static final String EXT_WBMP = "wbmp";
 74  
 
 75  
     /**
 76  
      * Priorities of available mappers.
 77  
      */
 78  
     private static final int MAP_PROG = 0;
 79  
     private static final int MAP_HOME = 1;
 80  
     private static final int MAP_SYS = 2;
 81  
     private static final int MAP_JAR = 3;
 82  
     private static final int MAP_COM = 4;
 83  
 
 84  
     /**
 85  
      * A common MIME type mapper.
 86  
      */
 87  3
     private static MimeTypeMapper commonMapper = new MimeTypeMapper();
 88  
     static
 89  
     {
 90  3
         commonMapper.setContentType(
 91  
             MimeType.TEXT_HTML.toString() + " " + EXT_HTML + " " + EXT_HTM);
 92  3
         commonMapper.setContentType(
 93  
             MimeType.TEXT_WML.toString() + " " + EXT_WML);
 94  3
         commonMapper.setContentType(
 95  
             MimeType.TEXT_HDML.toString() + " " + EXT_HDML + " " + EXT_HDM);
 96  3
         commonMapper.setContentType(
 97  
             MimeType.TEXT_CHTML.toString() + " " + EXT_CHTML);
 98  3
         commonMapper.setContentType(
 99  
             MimeType.TEXT_PLAIN.toString() + " " + EXT_TEXT);
 100  3
         commonMapper.setContentType(
 101  
             MimeType.IMAGE_GIF.toString() + " " + EXT_GIF);
 102  3
         commonMapper.setContentType(
 103  
             MimeType.IMAGE_JPEG.toString() + " " + EXT_JPEG + " " + EXT_JPG);
 104  3
         commonMapper.setContentType(
 105  
             MimeType.IMAGE_WBMP.toString() + " " + EXT_WBMP);
 106  3
     }
 107  
 
 108  
     /**
 109  
      * An array of available MIME type mappers.
 110  
      */
 111  9
     private MimeTypeMapper mappers[] = new MimeTypeMapper[5];
 112  
 
 113  
     /**
 114  
      * Loads mappings from a file path.
 115  
      *
 116  
      * @param path a file path.
 117  
      * @return the mappings.
 118  
      * @throws IOException for an incorrect file.
 119  
      */
 120  
     protected static MimeTypeMapper loadPath(String path)
 121  
         throws IOException
 122  
     {
 123  18
         return new MimeTypeMapper(path);
 124  
     }
 125  
 
 126  
     /**
 127  
      * Loads mappings from a resource.
 128  
      *
 129  
      * @param name a resource name.
 130  
      * @return the mappings.
 131  
      */
 132  
     protected static MimeTypeMapper loadResource(String name)
 133  
     {
 134  12
         InputStream input = MimeTypeMap.class.getResourceAsStream(name);
 135  9
         if (input != null)
 136  
         {
 137  
             try
 138  
             {
 139  0
                 return new MimeTypeMapper(input);
 140  
             }
 141  0
             catch (IOException x)
 142  
             {
 143  0
                 return null;
 144  
             }
 145  
         }
 146  
         else
 147  
         {
 148  9
             return null;
 149  
         }
 150  
     }
 151  
 
 152  
     /**
 153  
      * Constructs a new MIME type map with default mappers.
 154  
      */
 155  
     public MimeTypeMap()
 156  9
     {
 157  
         String path;
 158  
         try
 159  
         {
 160  
             // Check whether the user directory contains mappings.
 161  9
             path = System.getProperty("user.home");
 162  9
             if (path != null)
 163  
             {
 164  9
                 path = path + File.separator + MIMETYPE_RESOURCE;
 165  9
                 mappers[MAP_HOME] = loadPath(path);
 166  
             }
 167  
         }
 168  9
         catch (IOException x)
 169  
         {
 170  
             // ignore
 171  0
         }
 172  
 
 173  
         try
 174  
         {
 175  
             // Check whether the system directory contains mappings.
 176  9
             path = System.getProperty("java.home") +
 177  
                 File.separator + "lib" + File.separator + MIMETYPE_RESOURCE;
 178  9
             mappers[MAP_SYS] = loadPath(path);
 179  
         }
 180  9
         catch (IOException x)
 181  
         {
 182  
             // ignore
 183  0
         }
 184  
 
 185  
         // Check whether the current class jar contains mappings.
 186  9
         mappers[MAP_JAR] = loadResource("/META-INF/" + MIMETYPE_RESOURCE);
 187  
 
 188  
         // Set the common mapper to have the lowest priority.
 189  9
         mappers[MAP_COM] = commonMapper;
 190  9
     }
 191  
 
 192  
     /**
 193  
      * Contructs a MIME type map read from a stream.
 194  
      *
 195  
      * @param input an input stream.
 196  
      * @throws IOException for an incorrect stream.
 197  
      */
 198  
     public MimeTypeMap(InputStream input)
 199  
         throws IOException
 200  
     {
 201  0
         this();
 202  0
         mappers[MAP_PROG] = new MimeTypeMapper(input);
 203  0
     }
 204  
 
 205  
     /**
 206  
      * Contructs a MIME type map read from a file.
 207  
      *
 208  
      * @param file an input file.
 209  
      * @throws IOException for an incorrect input file.
 210  
      */
 211  
     public MimeTypeMap(File file)
 212  
         throws IOException
 213  
     {
 214  0
         this();
 215  0
         mappers[MAP_PROG] = new MimeTypeMapper(file);
 216  0
     }
 217  
 
 218  
     /**
 219  
      * Contructs a MIME type map read from a file path.
 220  
      *
 221  
      * @param path an input file path.
 222  
      * @throws IOException for an incorrect input file.
 223  
      */
 224  
     public MimeTypeMap(String path)
 225  
         throws IOException
 226  
     {
 227  0
         this();
 228  0
         mappers[MAP_PROG] = new MimeTypeMapper(path);
 229  0
     }
 230  
 
 231  
     /**
 232  
      * Sets a MIME content type mapping to extensions.
 233  
      *
 234  
      * @param spec a MIME type extension specification to set.
 235  
      */
 236  
     public synchronized void setContentType(String spec)
 237  
     {
 238  9
         if (mappers[MAP_PROG] == null)
 239  
         {
 240  9
             mappers[MAP_PROG] = new MimeTypeMapper();
 241  
         }
 242  9
         mappers[MAP_PROG].setContentType(spec);
 243  9
     }
 244  
 
 245  
     /**
 246  
      * Gets the MIME content type for a file as a string.
 247  
      *
 248  
      * @param file The file to look up a MIME type mapping for.
 249  
      * @return The MIME type, or {@link #DEFAULT_TYPE} if unmapped.
 250  
      */
 251  
     public String getContentType(File file)
 252  
     {
 253  15
         return getContentType(file.getName());
 254  
     }
 255  
 
 256  
     /**
 257  
      * Gets the MIME content type for a named file as a string.
 258  
      *
 259  
      * @param fileName The name of the file to look up a MIME type
 260  
      * mapping for.
 261  
      * @return The MIME type, or {@link #DEFAULT_TYPE} if unmapped.
 262  
      */
 263  
     public String getContentType(String fileName)
 264  
     {
 265  15
         return getContentType(fileName, DEFAULT_TYPE);
 266  
     }
 267  
 
 268  
     /**
 269  
      * Gets the MIME content type for a file name extension as a string.
 270  
      *
 271  
      * @param fileName The name of the file to look up a MIME type
 272  
      * mapping for.
 273  
      * @param def The default MIME type to use if no mapping exists.
 274  
      * @return The MIME type, or <code>def</code> if unmapped.
 275  
      */
 276  
     public String getContentType(String fileName, String def)
 277  
     {
 278  15
         String ext = parseFileExtension(fileName);
 279  15
         if (ext != null)
 280  
         {
 281  
             String mimeType;
 282  
             MimeTypeMapper mapper;
 283  15
             for (int i = 0; i < mappers.length; i++)
 284  
             {
 285  15
                 mapper = mappers[i];
 286  15
                 if (mapper != null)
 287  
                 {
 288  15
                     mimeType = mapper.getContentType(ext);
 289  15
                     if (mimeType != null)
 290  
                     {
 291  15
                         return mimeType;
 292  
                     }
 293  
                 }
 294  
             }
 295  
         }
 296  0
         return def;
 297  
     }
 298  
 
 299  
     /**
 300  
      * @param fileName The name of the file to parse the extension
 301  
      * from.  Must be non-<code>null</code>.
 302  
      * @return The file extension parsed from <code>fileName</code>
 303  
      * (if present), or <code>null</code> if not found.
 304  
      */
 305  
     private static String parseFileExtension(String fileName)
 306  
     {
 307  15
         int i = fileName.lastIndexOf('.');
 308  15
         return (i >= 0 && i + 2 < fileName.length() ?
 309  
                 fileName.substring(i + 1) : null);
 310  
     }
 311  
 
 312  
     /**
 313  
      * Gets the MIME content type for a file.
 314  
      *
 315  
      * @param file the file.
 316  
      * @return the MIME type.
 317  
      */
 318  
     public MimeType getMimeContentType(File file)
 319  
     {
 320  
         try
 321  
         {
 322  0
             return new MimeType(getContentType(file));
 323  
         }
 324  0
         catch (Exception x)
 325  
         {
 326  0
             return DEFAULT_MIMETYPE;
 327  
         }
 328  
     }
 329  
 
 330  
     /**
 331  
      * Gets the MIME content type for a named file.
 332  
      *
 333  
      * @param name the name of the file.
 334  
      * @return the MIME type.
 335  
      */
 336  
     public MimeType getMimeContentType(String name)
 337  
     {
 338  
         try
 339  
         {
 340  0
             return new MimeType(getContentType(name));
 341  
         }
 342  0
         catch (Exception x)
 343  
         {
 344  0
             return DEFAULT_MIMETYPE;
 345  
         }
 346  
     }
 347  
 
 348  
     /**
 349  
      * Gets the MIME content type for a file name extension.
 350  
      *
 351  
      * @param ext the file name extension.
 352  
      * @param def the default type if none is found.
 353  
      * @return the MIME type.
 354  
      */
 355  
     public MimeType getMimeContentType(String ext,
 356  
                                        String def)
 357  
     {
 358  
         try
 359  
         {
 360  0
             return new MimeType(getContentType(ext,def));
 361  
         }
 362  0
         catch (Exception x)
 363  
         {
 364  0
             return DEFAULT_MIMETYPE;
 365  
         }
 366  
     }
 367  
 
 368  
     /**
 369  
      * Gets the default file name extension for a MIME type.
 370  
      * Note that the mappers are called in the reverse order.
 371  
      *
 372  
      * @param type the MIME type as a string.
 373  
      * @return the file name extension or null.
 374  
      */
 375  
     public String getDefaultExtension(String type)
 376  
     {
 377  
         String ext;
 378  
         MimeTypeMapper mapper;
 379  6
         int i = type.indexOf(';');
 380  6
         if (i >= 0)
 381  
         {
 382  0
             type = type.substring(0,i);
 383  
         }
 384  6
         type = type.trim();
 385  30
         for (i = mappers.length - 1; i >= 0; i--)
 386  
         {
 387  30
             mapper = mappers[i];
 388  30
             if (mapper != null)
 389  
             {
 390  12
                 ext = mapper.getExtension(type);
 391  12
                 if (ext != null)
 392  
                 {
 393  6
                     return ext;
 394  
                 }
 395  
             }
 396  
         }
 397  0
         return null;
 398  
     }
 399  
 
 400  
     /**
 401  
      * Gets the default file name extension for a MIME type.
 402  
      * Note that the mappers are called in the reverse order.
 403  
      *
 404  
      * @param mime the MIME type.
 405  
      * @return the file name extension or null.
 406  
      */
 407  
     public String getDefaultExtension(MimeType mime)
 408  
     {
 409  3
         return getDefaultExtension(mime.getTypes());
 410  
     }
 411  
 
 412  
     /**
 413  
      * Sets a common MIME content type mapping to extensions.
 414  
      *
 415  
      * @param spec a MIME type extension specification to set.
 416  
      */
 417  
     protected synchronized void setCommonContentType(String spec)
 418  
     {
 419  0
         mappers[MAP_COM].setContentType(spec);
 420  0
     }
 421  
 }