You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by ep...@apache.org on 2003/11/13 21:28:29 UTC

cvs commit: jakarta-turbine-fulcrum/mimetype/api/src/java/org/apache/fulcrum/mimetype/util MimeType.java

epugh       2003/11/13 12:28:29

  Added:       mimetype/impl/conf block.xml config.xml
               mimetype/impl .cvsignore maven.xml project.xml
               mimetype/impl/src/java/org/apache/fulcrum/mimetype
                        DefaultMimeTypeService.java
               mimetype/api/src/java/org/apache/fulcrum/mimetype
                        MimeTypeService.java
               mimetype/api .cvsignore project.xml
               mimetype/impl/src/java/org/apache/fulcrum/mimetype/util
                        MimeTypeMap.java CharSetMap.java
                        MimeTypeMapper.java
               mimetype/impl/src/test/org/apache/fulcrum/mimetype/util
                        MimeTypeMapperTest.java
               mimetype/impl/src/test/org/apache/fulcrum/mimetype
                        MimetypeTest.java
               mimetype/api/src/java/org/apache/fulcrum/mimetype/util
                        MimeType.java
  Removed:     mimetype project.properties LICENSE.txt project.xml
  Log:
  Moving code around for Merlinized Avalon component.
  
  Revision  Changes    Path
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/conf/block.xml
  
  Index: block.xml
  ===================================================================
  
  <container name="test">
  
     <classloader>
       <classpath>
         <repository>
           <resource id="fulcrum:fulcrum-mimetype-api" version="1.0-alpha-4"/>
         </repository>
       </classpath>
     </classloader>
  
     <component name="mimetype" 
       class="org.apache.fulcrum.mimetype.DefaultMimeTypeService"/>
  
  </container>
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/conf/config.xml
  
  Index: config.xml
  ===================================================================
  
  <targets>
  
    <target path="/test/mimetype">
      <categories priority="INFO"/>
    </target>
  
  </targets>
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  target
  *.log
  .classpath
  .project
  jcoverage.ser
  *.merlin
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/maven.xml
  
  Index: maven.xml
  ===================================================================
  <project default="jar:jar" xmlns:maven="jelly:maven" xmlns:j="jelly:core" xmlns:util="jelly:util">
  
    <preGoal name="java:compile">
      <attainGoal name="avalon:meta"/>
    </preGoal>
  
  </project>
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/project.xml
  
  Index: project.xml
  ===================================================================
  <?xml version="1.0"?>
  <project>
    <extend>${basedir}/../../project-merlin.xml</extend>
    <id>fulcrum-mimetype-impl</id>
    <name>Fulcrum Mimtype Component</name>
    <currentVersion>1.0-alpha-4</currentVersion>
  
    <dependencies>
  
      <dependency>
        <groupId>fulcrum</groupId>
        <artifactId>fulcrum-mimetype-api</artifactId>
        <version>1.0-alpha-4</version>
      </dependency>
  
      <!--  Needed only for testing -->
  
      <dependency>
        <groupId>merlin</groupId>
        <artifactId>merlin-unit</artifactId>
        <version>3.2.2-dev</version>
      </dependency>
  
    </dependencies>
  
  </project>
  
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/java/org/apache/fulcrum/mimetype/DefaultMimeTypeService.java
  
  Index: DefaultMimeTypeService.java
  ===================================================================
  package org.apache.fulcrum.mimetype;
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  import java.io.File;
  import java.io.IOException;
  import java.util.Locale;
  import org.apache.avalon.framework.activity.Initializable;
  import org.apache.avalon.framework.configuration.Configurable;
  import org.apache.avalon.framework.configuration.Configuration;
  import org.apache.avalon.framework.configuration.ConfigurationException;
  import org.apache.avalon.framework.context.Context;
  import org.apache.avalon.framework.context.ContextException;
  import org.apache.avalon.framework.context.Contextualizable;
  import org.apache.avalon.framework.logger.AbstractLogEnabled;
  import org.apache.fulcrum.mimetype.util.CharSetMap;
  import org.apache.fulcrum.mimetype.util.MimeType;
  import org.apache.fulcrum.mimetype.util.MimeTypeMap;
  /**
   * The MimeType Service maintains mappings between MIME types and
   * the corresponding file name extensions, and between locales and
   * character encodings.
   *
   * <p>The MIME type mappings can be defined in MIME type files
   * located in user's home directory, Java home directory or
   * the current class jar. The default mapping file is defined
   * with the mime.type.file property. In addition, the service maintains
   * a set of most common mappings.
   *
   * <p>The charset mappings can be defined in property files
   * located in user's home directory, Java home directory or
   * the current class jar. The default mapping file is defined
   * with the charset.file property. In addition, the service maintains
   * a set of most common mappings.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Id: DefaultMimeTypeService.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   *
   * @avalon.component name="mimetype" lifestyle="singleton"
   * @avalon.service type="org.apache.fulcrum.mimetype.MimeTypeService"
   */
  public class DefaultMimeTypeService
      extends AbstractLogEnabled
      implements MimeTypeService, Configurable, Initializable, Contextualizable
  {
      private String applicationRoot;
      /**
       * The MIME type file property.
       */
      public static final String MIME_TYPES = "mimetypes";
      /**
       * The charset file property.
       */
      public static final String CHARSETS = "charsets";
      // path to a mimetypes-file_extension mapping file
      private String mimetypePath;
      // path to a charset-language mapping file
      private String charsetPath;
      /**
       * The MIME type map used by the service.
       */
      private MimeTypeMap mimeTypeMap;
      /**
       * The charset map used by the service.
       */
      private CharSetMap charSetMap;
      /** The Avalon Context */
      private Context context = null;
      /**
       * Constructs a new service.
       */
      public DefaultMimeTypeService()
      {
      }
      /**
       * Sets a MIME content type mapping to extensions to the map.
       * The extension is specified by a MIME type name followed
       * by a list of file name extensions separated by a whitespace.
       *
       * @param spec a MIME type extension specification to add.
       */
      public void setContentType(String spec)
      {
          mimeTypeMap.setContentType(spec);
      }
      /**
       * Gets the MIME content type for a file as a string.
       *
       * @param file the file.
       * @return the MIME type string.
       */
      public String getContentType(File file)
      {
          return mimeTypeMap.getContentType(file);
      }
      /**
       * Gets the MIME content type for a named file as a string.
       *
       * @param name the name of the file.
       * @return the MIME type string.
       */
      public String getContentType(String name)
      {
          return mimeTypeMap.getContentType(name);
      }
      /**
       * Gets the MIME content type for a file name extension as a string.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type string.
       */
      public String getContentType(String ext, String def)
      {
          return mimeTypeMap.getContentType(ext, def);
      }
      /**
       * Gets the MIME content type for a file.
       *
       * @param file the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(File file)
      {
          return mimeTypeMap.getMimeContentType(file);
      }
      /**
       * Gets the MIME content type for a named file.
       *
       * @param name the name of the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String name)
      {
          return mimeTypeMap.getMimeContentType(name);
      }
      /**
       * Gets the MIME content type for a file name extension.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String ext, String def)
      {
          return mimeTypeMap.getMimeContentType(ext, def);
      }
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param mime the MIME type as a string.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(String type)
      {
          return mimeTypeMap.getDefaultExtension(type);
      }
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param mime the MIME type.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(MimeType mime)
      {
          return mimeTypeMap.getDefaultExtension(mime);
      }
      /**
       * Sets a locale-charset mapping.
       *
       * @param key the key for the charset.
       * @param charset the corresponding charset.
       */
      public void setCharSet(String key, String charset)
      {
          charSetMap.setCharSet(key, charset);
      }
      /**
       * Gets the charset for a locale. First a locale specific charset
       * is searched for, then a country specific one and lastly a language
       * specific one. If none is found, the default charset is returned.
       *
       * @param locale the locale.
       * @return the charset.
       */
      public String getCharSet(Locale locale)
      {
          return charSetMap.getCharSet(locale);
      }
      /**
       * Gets the charset for a locale with a variant. The search
       * is performed in the following order:
       * "lang"_"country"_"variant"="charset",
       * _"counry"_"variant"="charset",
       * "lang"__"variant"="charset",
       * __"variant"="charset",
       * "lang"_"country"="charset",
       * _"country"="charset",
       * "lang"="charset".
       * If nothing of the above is found, the default charset is returned.
       *
       * @param locale the locale.
       * @param variant a variant field.
       * @return the charset.
       */
      public String getCharSet(Locale locale, String variant)
      {
          return charSetMap.getCharSet(locale, variant);
      }
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @return the found charset or the default one.
       */
      public String getCharSet(String key)
      {
          return charSetMap.getCharSet(key);
      }
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @param def the default charset if none is found.
       * @return the found charset or the given default.
       */
      public String getCharSet(String key, String def)
      {
          return charSetMap.getCharSet(key, def);
      }
  
      private String getRealPath(String path)
      {
          String absolutePath = null;
          if (applicationRoot == null)
          {
              absolutePath = new File(path).getAbsolutePath();
          }
          else
          {
              absolutePath = new File(applicationRoot, path).getAbsolutePath();
          }
          return absolutePath;
      }
      // ---------------- Avalon Lifecycle Methods ---------------------
      /**
       * Avalon component lifecycle method
       */
      public void configure(Configuration conf) throws ConfigurationException
      {
          mimetypePath = conf.getAttribute(MIME_TYPES, null);
          charsetPath = conf.getAttribute(CHARSETS, null);
          if (mimetypePath != null)
          {
              mimetypePath = getRealPath(mimetypePath);
          }
          if (charsetPath != null)
          {
              charsetPath = getRealPath(charsetPath);
          }
      }
      /**
       * Avalon component lifecycle method
       */
      public void initialize() throws Exception
      {
          if (mimetypePath != null)
          {
              try
              {
                  mimeTypeMap = new MimeTypeMap(mimetypePath);
              }
              catch (IOException x)
              {
                  throw new Exception(mimetypePath, x);
              }
          }
          else
          {
              mimeTypeMap = new MimeTypeMap();
          }
          if (charsetPath != null)
          {
              try
              {
                  charSetMap = new CharSetMap(charsetPath);
              }
              catch (IOException x)
              {
                  throw new Exception(charsetPath, x);
              }
          }
          else
          {
              charSetMap = new CharSetMap();
          }
      }
      public void contextualize(Context context) throws ContextException
      {
          this.context = context;
          this.applicationRoot = context.get( "urn:avalon:home" ).toString();
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/api/src/java/org/apache/fulcrum/mimetype/MimeTypeService.java
  
  Index: MimeTypeService.java
  ===================================================================
  package org.apache.fulcrum.mimetype;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.File;
  import java.util.Locale;
  
  import org.apache.fulcrum.mimetype.util.MimeType;
  
  /**
   * The MimeType Service maintains mappings between MIME types and
   * the corresponding file name extensions, and between locales and
   * character encodings. The mappings are typically defined in
   * properties or files located in user's home directory, Java home
   * directory or the current class jar depending on the implementation.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Id: MimeTypeService.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public interface MimeTypeService 
  {
      /** Avalon role - used to id the component within the manager */
      String ROLE = MimeTypeService.class.getName();
  
      /**
       * Sets a MIME content type mapping to extensions to the map.
       * The extension is specified by a MIME type name followed
       * by a list of file name extensions separated by a whitespace.
       *
       * @param spec a MIME type extension specification to add.
       */
      public void setContentType(String spec);
  
      /**
       * Gets the MIME content type for a file as a string.
       *
       * @param file the file.
       * @return the MIME type string.
       */
      public String getContentType(File file);
  
      /**
       * Gets the MIME content type for a named file as a string.
       *
       * @param name the name of the file.
       * @return the MIME type string.
       */
      public String getContentType(String name);
  
      /**
       * Gets the MIME content type for a file name extension as a string.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type string.
       */
      public String getContentType(String ext,
                                   String def);
  
      /**
       * Gets the MIME content type for a file.
       *
       * @param file the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(File file);
  
      /**
       * Gets the MIME content type for a named file.
       *
       * @param name the name of the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String name);
  
      /**
       * Gets the MIME content type for a file name extension.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String ext,
                                         String def);
  
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param type the MIME type as a string.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(String type);
  
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param mime the MIME type.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(MimeType mime);
  
      /**
       * Sets a locale-charset mapping.
       *
       * @param key the key for the charset.
       * @param charset the corresponding charset.
       */
      public  void setCharSet(String key,
                              String charset);
  
      /**
       * Gets the charset for a locale. First a locale specific charset
       * is searched for, then a country specific one and lastly a language
       * specific one. If none is found, the default charset is returned.
       *
       * @param locale the locale.
       * @return the charset.
       */
      public String getCharSet(Locale locale);
  
      /**
       * Gets the charset for a locale with a variant. The search
       * is performed in the following order:
       * "lang"_"country"_"variant"="charset",
       * _"counry"_"variant"="charset",
       * "lang"__"variant"="charset",
       * __"variant"="charset",
       * "lang"_"country"="charset",
       * _"country"="charset",
       * "lang"="charset".
       * If nothing of the above is found, the default charset is returned.
       *
       * @param locale the locale.
       * @param variant a variant field.
       * @return the charset.
       */
      public String getCharSet(Locale locale,
                               String variant);
  
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @return the found charset or the default one.
       */
      public String getCharSet(String key);
  
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @param def the default charset if none is found.
       * @return the found charset or the given default.
       */
      public String getCharSet(String key,
                               String def);
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/api/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  target
  *.log
  .classpath
  .project
  jcoverage.ser
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/api/project.xml
  
  Index: project.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <project>
  
    <extend>${basedir}/../../project.xml</extend>
    <id>fulcrum-mimetype-api</id>
    <name>Fulcrum Mimetype API</name>
    <currentVersion>1.0-alpha-4</currentVersion>
    <package>org.apache.fulcrum.mimetype</package>
   
  </project>
  
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/java/org/apache/fulcrum/mimetype/util/MimeTypeMap.java
  
  Index: MimeTypeMap.java
  ===================================================================
  package org.apache.fulcrum.mimetype.util;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.File;
  import java.io.InputStream;
  import java.io.IOException;
  
  /**
   * This class maintains a set of mappers defining mappings
   * between MIME types and the corresponding file name extensions.
   * The mappings are defined as lines formed by a MIME type name
   * followed by a list of extensions separated by a whitespace.
   * The definitions can be listed in MIME type files located in user's
   * home directory, Java home directory or the current class jar.
   * In addition, this class maintains static default mappings
   * and constructors support application specific mappings.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @version $Id: MimeTypeMap.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public class MimeTypeMap
  {
      /**
       * The default MIME type when nothing else is applicable.
       */
      public static final MimeType DEFAULT_MIMETYPE =
          MimeType.APPLICATION_OCTET_STREAM;
  
      /**
       * The default MIME type as a string.
       */
      public static final String DEFAULT_TYPE = DEFAULT_MIMETYPE.toString();
  
      /**
       * The name for MIME type mapper resources.
       */
      public static final String MIMETYPE_RESOURCE = "mime.types";
  
      /**
       * Common MIME type extensions.
       */
      public static final String EXT_HTML = "html";
      public static final String EXT_HTM = "htm";
      public static final String EXT_WML = "wml";
      public static final String EXT_HDML = "hdml";
      public static final String EXT_HDM = "hdm";
      public static final String EXT_CHTML = "chtml";
      public static final String EXT_TEXT = "txt";
      public static final String EXT_GIF = "gif";
      public static final String EXT_JPEG = "jpeg";
      public static final String EXT_JPG = "jpg";
      public static final String EXT_WBMP = "wbmp";
  
      /**
       * Priorities of available mappers.
       */
      private static final int MAP_PROG = 0;
      private static final int MAP_HOME = 1;
      private static final int MAP_SYS = 2;
      private static final int MAP_JAR = 3;
      private static final int MAP_COM = 4;
  
      /**
       * A common MIME type mapper.
       */
      private static MimeTypeMapper commonMapper = new MimeTypeMapper();
      static
      {
          commonMapper.setContentType(
              MimeType.TEXT_HTML.toString() + " " + EXT_HTML + " " + EXT_HTM);
          commonMapper.setContentType(
              MimeType.TEXT_WML.toString() + " " + EXT_WML);
          commonMapper.setContentType(
              MimeType.TEXT_HDML.toString() + " " + EXT_HDML + " " + EXT_HDM);
          commonMapper.setContentType(
              MimeType.TEXT_CHTML.toString() + " " + EXT_CHTML);
          commonMapper.setContentType(
              MimeType.TEXT_PLAIN.toString() + " " + EXT_TEXT);
          commonMapper.setContentType(
              MimeType.IMAGE_GIF.toString() + " " + EXT_GIF);
          commonMapper.setContentType(
              MimeType.IMAGE_JPEG.toString() + " " + EXT_JPEG + " " + EXT_JPG);
          commonMapper.setContentType(
              MimeType.IMAGE_WBMP.toString() + " " + EXT_WBMP);
      }
  
      /**
       * An array of available MIME type mappers.
       */
      private MimeTypeMapper mappers[] = new MimeTypeMapper[5];
  
      /**
       * Loads mappings from a file path.
       *
       * @param path a file path.
       * @returns the mappings.
       * @throws IOException for an incorrect file.
       */
      protected static MimeTypeMapper loadPath(String path)
          throws IOException
      {
          return new MimeTypeMapper(path);
      }
  
      /**
       * Loads mappings from a resource.
       *
       * @param name a resource name.
       * @return the mappings.
       */
      protected static MimeTypeMapper loadResource(String name)
      {
          InputStream input = MimeTypeMap.class.getResourceAsStream(name);
          if (input != null)
          {
              try
              {
                  return new MimeTypeMapper(input);
              }
              catch (IOException x)
              {
                  return null;
              }
          }
          else
          {
              return null;
          }
      }
  
      /**
       * Constructs a new MIME type map with default mappers.
       */
      public MimeTypeMap()
      {
          String path;
          try
          {
              // Check whether the user directory contains mappings.
              path = System.getProperty("user.home");
              if (path != null)
              {
                  path = path + File.separator + MIMETYPE_RESOURCE;
                  mappers[MAP_HOME] = loadPath(path);
              }
          }
          catch (Exception x)
          {
          }
  
          try
          {
              // Check whether the system directory contains mappings.
              path = System.getProperty("java.home") +
                  File.separator + "lib" + File.separator + MIMETYPE_RESOURCE;
              mappers[MAP_SYS] = loadPath(path);
          }
          catch (Exception x)
          {
          }
  
          // Check whether the current class jar contains mappings.
          mappers[MAP_JAR] = loadResource("/META-INF/" + MIMETYPE_RESOURCE);
  
          // Set the common mapper to have the lowest priority.
          mappers[MAP_COM] = commonMapper;
      }
  
      /**
       * Contructs a MIME type map read from a stream.
       *
       * @param input an input stream.
       * @throws IOException for an incorrect stream.
       */
      public MimeTypeMap(InputStream input)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = new MimeTypeMapper(input);
      }
  
      /**
       * Contructs a MIME type map read from a file.
       *
       * @param path an input file.
       * @throws IOException for an incorrect input file.
       */
      public MimeTypeMap(File file)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = new MimeTypeMapper(file);
      }
  
      /**
       * Contructs a MIME type map read from a file path.
       *
       * @param path an input file path.
       * @throws IOException for an incorrect input file.
       */
      public MimeTypeMap(String path)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = new MimeTypeMapper(path);
      }
  
      /**
       * Sets a MIME content type mapping to extensions.
       *
       * @param spec a MIME type extension specification to set.
       */
      public synchronized void setContentType(String spec)
      {
          if (mappers[MAP_PROG] == null)
          {
              mappers[MAP_PROG] = new MimeTypeMapper();
          }
          mappers[MAP_PROG].setContentType(spec);
      }
  
      /**
       * Gets the MIME content type for a file as a string.
       *
       * @param file the file.
       * @return the MIME type string.
       */
      public String getContentType(File file)
      {
          return getContentType(file.getName());
      }
  
      /**
       * Gets the MIME content type for a named file as a string.
       *
       * @param name the name of the file.
       * @return the MIME type string.
       */
      public String getContentType(String name)
      {
          int i = name.lastIndexOf('.');
          if (i >= 0)
          {
              String ext = name.substring(i + 1);
              return ext.length() > 0 ?
                  getContentType(ext,DEFAULT_TYPE) : DEFAULT_TYPE;
          }
          else
          {
              return DEFAULT_TYPE;
          }
      }
  
      /**
       * Gets the MIME content type for a file name extension as a string.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type string.
       */
      public String getContentType(String ext,
                                   String def)
      {
          int i = ext.lastIndexOf('.');
          if (i >= 0)
          {
              ext = ext.substring(i + 1);
          }
  
          String mime;
          MimeTypeMapper mapper;
          for (i = 0; i < mappers.length; i++)
          {
              mapper = mappers[i];
              if (mapper != null)
              {
                  mime = mapper.getContentType(ext);
                  if (mime != null)
                  {
                      return mime;
                  }
              }
          }
          return def;
      }
  
      /**
       * Gets the MIME content type for a file.
       *
       * @param file the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(File file)
      {
          try
          {
              return new MimeType(getContentType(file));
          }
          catch (Exception x)
          {
              return DEFAULT_MIMETYPE;
          }
      }
  
      /**
       * Gets the MIME content type for a named file.
       *
       * @param name the name of the file.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String name)
      {
          try
          {
              return new MimeType(getContentType(name));
          }
          catch (Exception x)
          {
              return DEFAULT_MIMETYPE;
          }
      }
  
      /**
       * Gets the MIME content type for a file name extension.
       *
       * @param ext the file name extension.
       * @param def the default type if none is found.
       * @return the MIME type.
       */
      public MimeType getMimeContentType(String ext,
                                         String def)
      {
          try
          {
              return new MimeType(getContentType(ext,def));
          }
          catch (Exception x)
          {
              return DEFAULT_MIMETYPE;
          }
      }
  
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param type the MIME type as a string.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(String type)
      {
          String ext;
          MimeTypeMapper mapper;
          int i = type.indexOf(';');
          if (i >= 0)
          {
              type = type.substring(0,i);
          }
          type = type.trim();
          for (i = mappers.length - 1; i >= 0; i--)
          {
              mapper = mappers[i];
              if (mapper != null)
              {
                  ext = mapper.getExtension(type);
                  if (ext != null)
                  {
                      return ext;
                  }
              }
          }
          return null;
      }
  
      /**
       * Gets the default file name extension for a MIME type.
       * Note that the mappers are called in the reverse order.
       *
       * @param mime the MIME type.
       * @return the file name extension or null.
       */
      public String getDefaultExtension(MimeType mime)
      {
          return getDefaultExtension(mime.getTypes());
      }
  
      /**
       * Sets a common MIME content type mapping to extensions.
       *
       * @param spec a MIME type extension specification to set.
       */
      protected synchronized void setCommonContentType(String spec)
      {
          mappers[MAP_COM].setContentType(spec);
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/java/org/apache/fulcrum/mimetype/util/CharSetMap.java
  
  Index: CharSetMap.java
  ===================================================================
  package org.apache.fulcrum.mimetype.util;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.util.Locale;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.Hashtable;
  import java.util.Properties;
  import java.io.File;
  import java.io.InputStream;
  import java.io.FileInputStream;
  import java.io.IOException;
  
  /**
   * This class maintains a set of mappers defining mappings
   * between locales and the corresponding charsets. The mappings
   * are defined as properties between locale and charset names.
   * The definitions can be listed in property files located in user's
   * home directory, Java home directory or the current class jar.
   * In addition, this class maintains static default mappings
   * and constructors support application specific mappings.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @version $Id: CharSetMap.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public class CharSetMap
  {
      /**
       * The default charset when nothing else is applicable.
       */
      public static final String DEFAULT_CHARSET = "ISO-8859-1";
  
      /**
       * The name for charset mapper resources.
       */
      public static final String CHARSET_RESOURCE = "charset.properties";
  
      /**
       * Priorities of available mappers.
       */
      private static final int MAP_CACHE = 0;
      private static final int MAP_PROG = 1;
      private static final int MAP_HOME = 2;
      private static final int MAP_SYS = 3;
      private static final int MAP_JAR = 4;
      private static final int MAP_COM = 5;
  
      /**
       * A common charset mapper for languages.
       */
      private static HashMap commonMapper = new HashMap();
      static
      {
          commonMapper.put("ar","ISO-8859-6");
          commonMapper.put("be","ISO-8859-5");
          commonMapper.put("bg","ISO-8859-5");
          commonMapper.put("ca","ISO-8859-1");
          commonMapper.put("cs","ISO-8859-2");
          commonMapper.put("da","ISO-8859-1");
          commonMapper.put("de","ISO-8859-1");
          commonMapper.put("el","ISO-8859-7");
          commonMapper.put("en","ISO-8859-1");
          commonMapper.put("es","ISO-8859-1");
          commonMapper.put("et","ISO-8859-1");
          commonMapper.put("fi","ISO-8859-1");
          commonMapper.put("fr","ISO-8859-1");
          commonMapper.put("hr","ISO-8859-2");
          commonMapper.put("hu","ISO-8859-2");
          commonMapper.put("is","ISO-8859-1");
          commonMapper.put("it","ISO-8859-1");
          commonMapper.put("iw","ISO-8859-8");
          commonMapper.put("ja","Shift_JIS");
          commonMapper.put("ko","EUC-KR");
          commonMapper.put("lt","ISO-8859-2");
          commonMapper.put("lv","ISO-8859-2");
          commonMapper.put("mk","ISO-8859-5");
          commonMapper.put("nl","ISO-8859-1");
          commonMapper.put("no","ISO-8859-1");
          commonMapper.put("pl","ISO-8859-2");
          commonMapper.put("pt","ISO-8859-1");
          commonMapper.put("ro","ISO-8859-2");
          commonMapper.put("ru","ISO-8859-5");
          commonMapper.put("sh","ISO-8859-5");
          commonMapper.put("sk","ISO-8859-2");
          commonMapper.put("sl","ISO-8859-2");
          commonMapper.put("sq","ISO-8859-2");
          commonMapper.put("sr","ISO-8859-5");
          commonMapper.put("sv","ISO-8859-1");
          commonMapper.put("tr","ISO-8859-9");
          commonMapper.put("uk","ISO-8859-5");
          commonMapper.put("zh","GB2312");
          commonMapper.put("zh_TW","Big5");
      }
  
      /**
       * An array of available charset mappers.
       */
      private Map mappers[] = new Map[6];
  
      /**
       * Loads mappings from a stream.
       *
       * @param input an input stream.
       * @return the mappings.
       * @throws IOException for an incorrect stream.
       */
      protected static Map loadStream(InputStream input)
          throws IOException
      {
          Properties props = new Properties();
          props.load(input);
          return new HashMap(props);
      }
  
      /**
       * Loads mappings from a file.
       *
       * @param file a file.
       * @return the mappings.
       * @throws IOException for an incorrect file.
       */
      protected static Map loadFile(File file)
          throws IOException
      {
          return loadStream(new FileInputStream(file));
      }
  
      /**
       * Loads mappings from a file path.
       *
       * @param path a file path.
       * @return the mappings.
       * @throws IOException for an incorrect file.
       */
      protected static Map loadPath(String path)
          throws IOException
      {
          return loadFile(new File(path));
      }
  
      /**
       * Loads mappings from a resource.
       *
       * @param name a resource name.
       * @return the mappings.
       */
      protected static Map loadResource(String name)
      {
          InputStream input = CharSetMap.class.getResourceAsStream(name);
          if (input != null)
          {
              try
              {
                  return loadStream(input);
              }
              catch (IOException x)
              {
                  return null;
              }
          }
          else
          {
              return null;
          }
      }
  
      /**
       * Constructs a new charset map with default mappers.
       */
      public CharSetMap()
      {
          String path;
          try
          {
              // Check whether the user directory contains mappings.
              path = System.getProperty("user.home");
              if (path != null)
              {
                  path = path + File.separator + CHARSET_RESOURCE;
                  mappers[MAP_HOME] = loadPath(path);
              }
          }
          catch (Exception x)
          {
          }
  
          try
          {
              // Check whether the system directory contains mappings.
              path = System.getProperty("java.home") +
                  File.separator + "lib" + File.separator + CHARSET_RESOURCE;
              mappers[MAP_SYS] = loadPath(path);
          }
          catch (Exception x)
          {
          }
  
          // Check whether the current class jar contains mappings.
          mappers[MAP_JAR] = loadResource("/META-INF/" + CHARSET_RESOURCE);
  
          // Set the common mapper to have the lowest priority.
          mappers[MAP_COM] = commonMapper;
  
          // Set the cache mapper to have the highest priority.
          mappers[MAP_CACHE] = new Hashtable();
      }
  
      /**
       * Contructs a charset map from properties.
       *
       * @param props charset mapping propeties.
       */
      public CharSetMap(Properties props)
      {
          this();
          mappers[MAP_PROG] = new HashMap(props);
      }
  
      /**
       * Contructs a charset map read from a stream.
       *
       * @param input an input stream.
       * @throws IOException for an incorrect stream.
       */
      public CharSetMap(InputStream input)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = loadStream(input);
      }
  
      /**
       * Contructs a charset map read from a property file.
       *
       * @param file a property file.
       * @throws IOException for an incorrect property file.
       */
      public CharSetMap(File file)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = loadFile(file);
      }
  
      /**
       * Contructs a charset map read from a property file path.
       *
       * @param path a property file path.
       * @throws IOException for an incorrect property file.
       */
      public CharSetMap(String path)
          throws IOException
      {
          this();
          mappers[MAP_PROG] = loadPath(path);
      }
  
      /**
       * Sets a locale-charset mapping.
       *
       * @param key the key for the charset.
       * @param charset the corresponding charset.
       */
      public synchronized void setCharSet(String key,
                                          String charset)
      {
          HashMap mapper = (HashMap) mappers[MAP_PROG];
          mapper = mapper != null ?
              (HashMap) mapper.clone() : new HashMap();
          mapper.put(key,charset);
          mappers[MAP_PROG] = mapper;
          mappers[MAP_CACHE].clear();
      }
  
      /**
       * Gets the charset for a locale. First a locale specific charset
       * is searched for, then a country specific one and lastly a language
       * specific one. If none is found, the default charset is returned.
       *
       * @param locale the locale.
       * @return the charset.
       */
      public String getCharSet(Locale locale)
      {
          // Check the cache first.
          String key = locale.toString();
          if (key.length() == 0)
          {
              key = "__" + locale.getVariant();
              if (key.length() == 2)
              {
                  return DEFAULT_CHARSET;
              }
          }
          String charset = searchCharSet(key);
          if (charset.length() == 0)
          {
              // Not found, perform a full search and update the cache.
              String[] items = new String[3];
              items[2] = locale.getVariant();
              items[1] = locale.getCountry();
              items[0] = locale.getLanguage();
              charset = searchCharSet(items);
              if (charset.length() == 0)
              {
                  charset = DEFAULT_CHARSET;
              }
              mappers[MAP_CACHE].put(key,charset);
          }
          return charset;
      }
  
      /**
       * Gets the charset for a locale with a variant. The search
       * is performed in the following order:
       * "lang"_"country"_"variant"="charset",
       * _"counry"_"variant"="charset",
       * "lang"__"variant"="charset",
       * __"variant"="charset",
       * "lang"_"country"="charset",
       * _"country"="charset",
       * "lang"="charset".
       * If nothing of the above is found, the default charset is returned.
       *
       * @param locale the locale.
       * @param variant a variant field.
       * @return the charset.
       */
      public String getCharSet(Locale locale,
                               String variant)
      {
          // Check the cache first.
          if ((variant != null) &&
              (variant.length() > 0))
          {
              String key = locale.toString();
              if (key.length() == 0)
              {
                  key = "__" + locale.getVariant();
                  if (key.length() > 2)
                  {
                      key += '_' + variant;
                  }
                  else
                  {
                      key += variant;
                  }
              }
              else if (locale.getCountry().length() == 0)
              {
                  key += "__" + variant;
              }
              else
              {
                  key += '_' + variant;
              }
              String charset = searchCharSet(key);
              if (charset.length() == 0)
              {
                  // Not found, perform a full search and update the cache.
                  String[] items = new String[4];
                  items[3] = variant;
                  items[2] = locale.getVariant();
                  items[1] = locale.getCountry();
                  items[0] = locale.getLanguage();
                  charset = searchCharSet(items);
                  if (charset.length() == 0)
                  {
                      charset = DEFAULT_CHARSET;
                  }
                  mappers[MAP_CACHE].put(key,charset);
              }
              return charset;
          }
          else
          {
              return getCharSet(locale);
          }
      }
  
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @return the found charset or the default one.
       */
      public String getCharSet(String key)
      {
          String charset = searchCharSet(key);
          return charset.length() > 0 ? charset : DEFAULT_CHARSET;
      }
  
      /**
       * Gets the charset for a specified key.
       *
       * @param key the key for the charset.
       * @param def the default charset if none is found.
       * @return the found charset or the given default.
       */
      public String getCharSet(String key,
                               String def)
      {
          String charset = searchCharSet(key);
          return charset.length() > 0 ? charset : def;
      }
  
      /**
       * Searches for a charset for a specified locale.
       *
       * @param items an array of locale items.
       * @return the found charset or an empty string.
       */
      private String searchCharSet(String[] items)
      {
          String charset;
          StringBuffer sb = new StringBuffer();
          for (int i = items.length; i > 0; i--)
          {
              charset = searchCharSet(items,sb,i);
              if (charset.length() > 0)
              {
                  return charset;
              }
              sb.setLength(0);
          }
          return "";
      }
  
    /**
     * Searches recursively for a charset for a specified locale.
     *
     * @param items an array of locale items.
     * @param base a buffer of base items.
     * @param count the number of items to go through.
     * @return the found charset or an empty string.
     */
      private String searchCharSet(String[] items,
                                   StringBuffer base,
                                   int count)
      {
          if ((--count >= 0) &&
              (items[count] != null) &&
              (items[count].length() > 0))
          {
              String charset;
              base.insert(0,items[count]);
              int length = base.length();
              for (int i = count; i > 0; i--)
              {
                  if ((i == count) ||
                      (i <= 1))
                  {
                      base.insert(0,'_');
                      length++;
                  }
                  charset = searchCharSet(items,base,i);
                  if (charset.length() > 0)
                  {
                      return charset;
                  }
                  base.delete(0,base.length() - length);
              }
              return searchCharSet(base.toString());
          }
          else
          {
              return "";
          }
      }
  
      /**
       * Searches for a charset for a specified key.
       *
       * @param key the key for the charset.
       * @return the found charset or an empty string.
       */
      private String searchCharSet(String key)
      {
          if ((key != null) &&
              (key.length() > 0))
          {
              // Go through mappers.
              Map mapper;
              String charset;
              for (int i = 0; i < mappers.length; i++)
              {
                  mapper = mappers[i];
                  if (mapper != null)
                  {
                      charset = (String) mapper.get(key);
                      if (charset != null)
                      {
                          // Update the cache.
                          if (i > MAP_CACHE)
                          {
                              mappers[MAP_CACHE].put(key,charset);
                          }
                          return charset;
                      }
                  }
              }
  
              // Not found, add an empty string to the cache.
              mappers[MAP_CACHE].put(key,"");
          }
          return "";
      }
  
      /**
       * Sets a common locale-charset mapping.
       *
       * @param key the key for the charset.
       * @param charset the corresponding charset.
       */
      protected synchronized void setCommonCharSet(String key,
                                                   String charset)
      {
          HashMap mapper = (HashMap) ((HashMap) mappers[MAP_COM]).clone();
          mapper.put(key,charset);
          mappers[MAP_COM] = mapper;
          mappers[MAP_CACHE].clear();
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/java/org/apache/fulcrum/mimetype/util/MimeTypeMapper.java
  
  Index: MimeTypeMapper.java
  ===================================================================
  package org.apache.fulcrum.mimetype.util;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.File;
  import java.io.FileReader;
  import java.io.StringReader;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.util.Map;
  import java.util.HashMap;
  import java.util.StringTokenizer;
  
  /**
   * This class defines mappings between MIME types and the corresponding
   * file name extensions. The mappings are defined as lines formed
   * by a MIME type name followed by a list of extensions separated
   * by a whitespace.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @version $Id: MimeTypeMapper.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public class MimeTypeMapper
  {
      /**
       * Mappings between MIME types and file name extensions.
       */
      private HashMap mimeTypeExtensions = new HashMap();
      protected HashMap extensionMimeTypes = new HashMap();
  
      /**
       * Constructs an empty MIME type mapper.
       */
      public MimeTypeMapper()
      {
      }
  
      /**
       * Constructs a mapper reading from a stream.
       *
       * @param input an input stream.
       * @throws IOException for an incorrect stream.
       */
      public MimeTypeMapper(InputStream input)
          throws IOException
      {
          parse(new BufferedReader(
              new InputStreamReader(input,CharSetMap.DEFAULT_CHARSET)));
      }
  
      /**
       * Constructs a mapper reading from a file.
       *
       * @param file an input file.
       * @throws IOException for an incorrect file.
       */
      public MimeTypeMapper(File file)
          throws IOException
      {
          FileReader freader = new FileReader(file);
          try
          {
              parse(new BufferedReader(freader));
          }
          finally
          {
              try
              {
                  freader.close();
              }
              catch (IOException x)
              {
              }
          }
      }
  
      /**
       * Constructs a mapper reading from a file path.
       *
       * @param path an input file path.
       * @throws IOException for an incorrect file.
       */
      public MimeTypeMapper(String path)
          throws IOException
      {
        this(new File(path));
      }
  
      /**
       * Sets a MIME content type mapping to extensions.
       *
       * @param spec a MIME type extension specification to parse.
       */
      public void setContentType(String spec)
      {
        try
        {
            parse(new BufferedReader(new StringReader(spec)));
        }
        catch (IOException x)
        {
        }
      }
  
      /**
       * Gets a MIME content type corresponding to a specified file name extension.
       *
       * @param ext a file name extension.
       * @return the corresponding MIME type as a string or null.
       */
      public String getContentType(String ext)
      {
          return (String) mimeTypeExtensions.get(ext);
      }
  
      /**
       * Gets a file name extension corresponding to a specified MIME content type.
       *
       * @param mime a MIME type as a string.
       * @return the corresponding file name extension or null.
       */
      public String getExtension(String type)
      {
          return (String) extensionMimeTypes.get(type);
      }
  
      /**
       * Parses MIME type extensions.
       *
       * @param reader a reader to parse.
       * @throws IOException for an incorrect reader.
       */
      protected synchronized void parse(BufferedReader reader)
          throws IOException
      {
        int l,count = 0;
        String next;
        String str = null;
        HashMap mimeTypes = (HashMap) extensionMimeTypes.clone();
        HashMap extensions = (HashMap) mimeTypeExtensions.clone();
        while ((next = reader.readLine()) != null)
        {
            str = str == null ? next : str + next;
            if ((l = str.length()) == 0)
            {
                str = null;
                continue;
            }
            // Check for continuation line.
            if (str.charAt(l - 1) != '\\')
            {
                count += parseMimeTypeExtension(str,mimeTypes,extensions);
                str = null;
            }
            else
            {
                str = str.substring(0,l - 1);
            }
        }
        if (str != null)
        {
            count += parseMimeTypeExtension(str,mimeTypes,extensions);
        }
        if (count > 0)
        {
            extensionMimeTypes = mimeTypes;
            mimeTypeExtensions = extensions;
        }
      }
  
      /**
       * Parses a MIME type extension.
       *
       * @param spec an extension specification to parse.
       * @param mimeTypes a map of MIME types.
       * @param extensions a map of extensions.
       * @return the number of file name extensions parsed.
       */
      protected int parseMimeTypeExtension(String spec,
                                           Map mimeTypes,
                                           Map extensions)
      {
          int count = 0;
          spec = spec.trim();
          if ((spec.length() > 0) &&
              (spec.charAt(0) != '#'))
          {
              StringTokenizer tokens = new StringTokenizer(spec);
              String type = tokens.nextToken();
              String ext;
              while (tokens.hasMoreTokens())
              {
                  ext = tokens.nextToken();
                  if (ext.length() == 0)
                  {
                      continue;
                  }
                  extensions.put(ext,type);
                  if (count++ == 0)
                  {
                      mimeTypes.put(type,ext);
                  }
              }
          }
          return count;
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/test/org/apache/fulcrum/mimetype/util/MimeTypeMapperTest.java
  
  Index: MimeTypeMapperTest.java
  ===================================================================
  /*
   * Created on Aug 20, 2003
   *
   * To change the template for this generated file go to
   * Window>Preferences>Java>Code Generation>Code and Comments
   */
  package org.apache.fulcrum.mimetype.util;
  import junit.framework.TestCase;
  /**
   * @author Eric Pugh
   *
   * To change the template for this generated type comment go to
   * Window>Preferences>Java>Code Generation>Code and Comments
   */
  public class MimeTypeMapperTest extends TestCase
  {
      public static void main(String[] args)
      {
          junit.textui.TestRunner.run(MimeTypeMapperTest.class);
      }
      /**
       * Constructor for MimeTypeMapperTest.
       * @param arg0
       */
      public MimeTypeMapperTest(String arg0)
      {
          super(arg0);
      }
      public void testGetSetContentType()
      {
          String mimeType = "text/crazy";
          String fileExtensions = "crazy crzy czy";
          MimeTypeMapper mtm = new MimeTypeMapper();
          mtm.setContentType(mimeType + " " + fileExtensions);
          
  		assertEquals(mimeType,mtm.getContentType("crazy"));
  		assertEquals(mimeType,mtm.getContentType("crzy"));
  		assertEquals(mimeType,mtm.getContentType("czy"));
          
      }
      
  	public void testGetDefaultExtension() throws Exception
  {
  }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/impl/src/test/org/apache/fulcrum/mimetype/MimetypeTest.java
  
  Index: MimetypeTest.java
  ===================================================================
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000-2001 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *     "Apache Jetspeed" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache" or
   *    "Apache Jetspeed", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.fulcrum.mimetype;
  // Cactus and Junit imports
  import java.io.File;
  import java.util.Locale;
  import junit.awtui.TestRunner;
  import junit.framework.Test;
  import junit.framework.TestSuite;
  import org.apache.avalon.merlin.unit.AbstractMerlinTestCase;
  import org.apache.fulcrum.mimetype.util.MimeType;
  
  /**
   * CacheTest
   *
   * @author <a href="paulsp@apache.org">Paul Spencer</a>
   * @author <a href="epugh@upstate.com">Eric Pugh</a> 
   * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
   * @version $Id: MimetypeTest.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public class MimetypeTest extends AbstractMerlinTestCase
  {
      private MimeTypeService mimeTypeService = null;
      private static final String mimeType = "text/crazy";
      private static final String fileExtensions = "crazy crzy czy";
      /**
       * Defines the testcase name for JUnit.
       *
       * @param name the testcase's name.
       */
      public MimetypeTest(String name)
      {
          super(name);
      }
      /**
       * Start the tests.
       *
       * @param args the arguments. Not used
       */
      public static void main(String args[])
      {
          TestRunner.main(new String[] { MimetypeTest.class.getName()});
      }
      /**
       * Creates the test suite.
       *
       * @return a test suite (<code>TestSuite</code>) that includes all methods
       *         starting with "test"
       */
      public static Test suite()
      {
          // All methods starting with "test" will be executed in the test suite.
          return new TestSuite(MimetypeTest.class);
      }
      public  void setUp() throws Exception
      {
          super.setUp();
          try
          {
              mimeTypeService = (MimeTypeService) this.resolve( "mimetype" );
          }
          catch (Throwable e)
          {
              getLogger().error( "Setup failure.", e );
              fail(e.getMessage());
          }
      }
      public void testGetCharSet() throws Exception
      {
          Locale locale = new Locale("en", "US");
          String s = mimeTypeService.getCharSet(locale);
          assertEquals("ISO-8859-1", s);
          getLogger().info( "OK" );
      }
      public void testSetGetContentType() throws Exception
      {
          mimeTypeService.setContentType(mimeType + " " + fileExtensions);
          File files[] = new File[3];
          files[0] = new File("test.crazy");
          files[1] = new File("test.crzy");
          files[2] = new File("test.czy");
          assertEquals(mimeType, mimeTypeService.getContentType(files[0]));
          assertEquals(mimeType, mimeTypeService.getContentType(files[1]));
          assertEquals(mimeType, mimeTypeService.getContentType(files[2]));
          getLogger().info( "OK" );
      }
      public void testGetDefaultExtension() throws Exception
      {
          mimeTypeService.setContentType(mimeType + " " + fileExtensions);
          String result = mimeTypeService.getDefaultExtension(mimeType);
          assertEquals("crazy", result);
          MimeType mt = new MimeType(mimeType);
          result = mimeTypeService.getDefaultExtension(mt);
          assertEquals("crazy", result);
          getLogger().info( "OK" );
      }
  }
  
  
  
  1.1                  jakarta-turbine-fulcrum/mimetype/api/src/java/org/apache/fulcrum/mimetype/util/MimeType.java
  
  Index: MimeType.java
  ===================================================================
  package org.apache.fulcrum.mimetype.util;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.util.ArrayList;
  
  /**
   * This class is used to represent parsed MIME types.
   * The representation is parsed from a string based
   * representation of the MIME type, as defined in the RFC1345.
   *
   * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
   * @version $Id: MimeType.java,v 1.1 2003/11/13 20:28:29 epugh Exp $
   */
  public class MimeType
      implements Cloneable
  {
      /**
       * A list of well known MIME types.
       */
      public static MimeType TEXT_HTML;
      public static MimeType TEXT_WML;
      public static MimeType TEXT_HDML;
      public static MimeType TEXT_CHTML;
      public static MimeType TEXT_PLAIN;
      public static MimeType MULTIPART;
      public static MimeType MULTIPART_FORM_DATA;
      public static MimeType APPLICATION_POSTSCRIPT;
      public static MimeType APPLICATION_OCTET_STREAM;
      public static MimeType APPLICATION_X_JAVA_AGENT;
      public static MimeType APPLICATION_X_WWW_FORM_URLENCODED;
      public static MimeType MESSAGE_HTTP;
      public static MimeType TEXT_CSS;
      public static MimeType TEXT;
      public static MimeType IMAGE_GIF;
      public static MimeType IMAGE_JPEG;
      public static MimeType IMAGE_WBMP;
      static
      {
          TEXT_HTML =
              new MimeType("text/html");
          TEXT_WML =
              new MimeType("text/vnd.wap.wml");
          TEXT_HDML =
              new MimeType("text/x-hdml");
          TEXT_CHTML =
              new MimeType("text/x-chtml");
          TEXT_PLAIN =
              new MimeType("text/plain");
          MULTIPART	=
              new MimeType("multipart/*");
          MULTIPART_FORM_DATA	=
              new MimeType("multipart/form-data");
          APPLICATION_POSTSCRIPT =
              new MimeType("application/postscript");
          APPLICATION_OCTET_STREAM =
              new MimeType("application/octet-stream");
          APPLICATION_X_JAVA_AGENT =
              new MimeType("application/x-java-agent");
          APPLICATION_X_WWW_FORM_URLENCODED =
              new MimeType("application/x-www-form-urlencoded");
          MESSAGE_HTTP =
              new MimeType("message/http");
          TEXT_CSS =
              new MimeType("text/css");
          TEXT =
              new MimeType("text/*");
          IMAGE_GIF =
              new MimeType("image/gif");
          IMAGE_JPEG =
              new MimeType("image/jpeg");
          IMAGE_WBMP =
              new MimeType("image/vnd.wap.wbmp");
      }
  
      /**
       * MIME type matching constants.
       */
      public static final int NO_MATCH = 0;
      public static final int MATCH_TYPE = 1;
      public static final int MATCH_SUBTYPE = 2;
      public static final int MATCH_SPECIFIC_SUBTYPE = 3;
  
      /**
       * A string representation of the main type.
       */
      private String mimeType;
  
      /**
       * A string representation of the subtype.
       */
      private String mimeSubtype;
  
      /**
       * Parameter names.
       */
      private String parameterNames[];
  
      /**
       * Parameter values.
       */
      private String parameterValues[];
  
      /**
       * A string representation of the MIME type.
       */
      private String mimeTypeString;
  
      /**
       * Constructs a new MIME type by parsing a specification string.
       *
       * @parameter spec a string representing a MIME type.
       * @throws IllegalArgument for parsing errors.
       */
      public MimeType(String spec)
      {
          this(spec,true);
      }
  
      /**
       * Constructs a new MIME type by parsing a specification string.
       *
       * @param spec a string representing a MIME type.
       * @param parsep a flag for parsing parameters also.
       * @throws IllegalArgumentException for parsing errors.
       */
      public MimeType(String spec,
                      boolean parsep)
      {
          int start = 0;
          char look = '\0';
          int length = spec.length();
  
          // Skip leading/trailing blanks.
          while ((start < length) &&
                 Character.isWhitespace(spec.charAt(start)))
          {
              start++;
          }
          while ((length > start) &&
                 Character.isWhitespace(spec.charAt(length - 1)))
          {
              length--;
          }
  
          // Get the type.
          StringBuffer sb = new StringBuffer();
          while ((start < length) &&
                 ((look = spec.charAt(start)) != '/'))
          {
              sb.append((char) look);
              start++;
          }
          if (look != '/')
          {
              throw new IllegalArgumentException(
                  "Syntax error in MIME type " + spec);
          }
          mimeType = sb.toString();
  
          // Get the subtype.
          start++;
          sb.setLength(0);
          while ((start < length) &&
                 ((look = spec.charAt(start)) != ';') &&
                 !Character.isWhitespace(look))
          {
              sb.append((char) look);
              start++;
          }
          mimeSubtype = sb.toString();
  
          if (parsep)
          {
              // Get parameters, if any.
              while ((start < length) &&
                     Character.isWhitespace(spec.charAt(start)))
              {
                  start++;
              }
              if (start < length)
              {
                  if (spec.charAt(start) != ';')
                  {
                      throw new IllegalArgumentException(
                          "Syntax error in MIME type parameters " + spec);
                  }
                  start++;
                  ArrayList na = new ArrayList(4);
                  ArrayList va = new ArrayList(4);
                  while (start < length)
                  {
                      // Get the name.
                      while ((start < length) &&
                             Character.isWhitespace(spec.charAt(start)))
                      {
                          start++;
                      }
                      sb.setLength(0);
                      while ((start < length) &&
                             ((look=spec.charAt(start)) != '=') &&
                             !Character.isWhitespace(look))
                      {
                          sb.append(Character.toLowerCase((char) look));
                          start++ ;
                      }
                      String name = sb.toString();
  
                      // Get the value.
                      while ((start < length) &&
                             Character.isWhitespace(spec.charAt(start)))
                      {
                          start++;
                      }
                      if (spec.charAt(start) != '=')
                      {
                          throw new IllegalArgumentException(
                              "Syntax error in MIME type parameters " + spec);
                      }
                      start++ ;
                      while ((start < length) &&
                             Character.isWhitespace(spec.charAt(start)))
                      {
                          start++;
                      }
                      sb.setLength(0);
                      char delim = ';';
                      if (spec.charAt(start) == '"')
                      {
                          start++;
                          delim = '"';
                      }
                      while ((start < length) &&
                             ((look = spec.charAt(start)) != delim) &&
                             ((delim == '"') ||
                              !Character.isWhitespace(look)))
                      {
                          sb.append((char) look);
                          start++;
                      }
                      while ((start < length) &&
                             (spec.charAt(start) != ';'))
                      {
                          start++;
                      }
                      start++;
                      String value = sb.toString();
  
                      na.add(name);
                      va.add(value);
                  }
                  parameterNames = (String[]) na.toArray(new String[na.size()]);
                  parameterValues = (String[]) va.toArray(new String[va.size()]);
              }
          }
      }
  
      /**
       * Contructs a new MIME type from specified types.
       *
       * @param type a type.
       * @param subtype a subtype.
       * @throws NullPointerException if type or subtype are nulls.
       */
      public MimeType(String type,
                      String subtype)
      {
          this(type,subtype,null,null);
      }
  
      /**
       * Contructs a new MIME type from specified parameters.
       *
       * @param type a type.
       * @param subtype a subtype.
       * @param names parameters names.
       * @param values parameter values.
       * @throws NullPointerException if type or subtype are nulls.
       */
      public MimeType(String type,
                      String subtype,
                      String names[],
                      String values[])
      {
          if ((type == null) ||
              (subtype == null))
          {
              throw new NullPointerException("MIME type or subtype missing");
          }
          mimeType = type.trim();
          mimeSubtype = subtype.trim();
          parameterNames  = names;
          parameterValues = values;
      }
  
      /**
       * Compares the specified MIME type to this one
       * and returns a matching level:
       * NO_MATCH=types do not match,
       * MATCH_TYPE=types match,
       * MATCH_SPECIFIC_TYPE=types match exactly,
       * MATCH_SUBTYPE=types match, subtypes match too,
       * MATCH_SPECIFIC_SUBTYPE=types match, subtypes match exactly.
       *
       * @param other the MimeType to compare.
       * @return the matching level.
       */
      public int match(MimeType other)
      {
          if (mimeType.equals("*") ||
              other.mimeType.equals("*"))
          {
              return MATCH_TYPE;
          }
          else if (!mimeType.equalsIgnoreCase(other.mimeType))
          {
              return NO_MATCH;
          }
          else if (mimeSubtype.equals("*") ||
                   other.mimeSubtype.equals("*"))
          {
              return MATCH_SUBTYPE;
          }
          else if (!mimeSubtype.equalsIgnoreCase(other.mimeSubtype))
          {
              return NO_MATCH;
          }
          else
          {
              return MATCH_SPECIFIC_SUBTYPE;
          }
      }
  
      /**
       * Gets the main type of the MIME type.
       *
       * @return the main type as a string.
       */
      public String getType()
      {
          return mimeType;
      }
  
      /**
       * Gets the subtype of the MIME type.
       *
       * @return the subtype as a string.
       */
      public String getSubtype()
      {
          return mimeSubtype;
      }
  
      /**
       * Gets the type and the subtype of the MIME type.
       *
       * @return the types as a string.
       */
      public String getTypes()
      {
          return mimeType + '/' + mimeSubtype;
      }
  
      /**
       * Checks whether the MIME type contains the specified parameter.
       *
       * @param param the name opf the parameter.
       * @return true if the parameter found, otherwise false.
       */
      public boolean hasParameter(String param)
      {
          String[] na = parameterNames;
          if (na != null)
          {
              for (int i = 0; i < na.length; i++)
              {
                  if (na[i].equalsIgnoreCase(param))
                  {
                      return true;
                  }
              }
          }
          return false;
      }
  
      /**
       * Gets the value of a MIME type parameter.
       * The first parameter with the specifed name will be returned.
       *
       * @param param the name of the parameter.
       * @return the value of the parameter, or null.
       */
      public String getParameter(String param)
      {
          String[] na = parameterNames;
          if (na != null)
          {
              String[] va = parameterValues;
              for (int i = 0; i < na.length; i++)
              {
                  if (na[i].equalsIgnoreCase(param))
                  {
                      return va[i];
                  }
              }
          }
          return null ;
      }
  
      /**
       * Sets the value of a MIME type parameter replacing the old one.
       *
       * @param param the name of the parameter.
       * @param value the value of the parameter.
       */
      public synchronized void setParameter(String param,
                                            String value)
      {
        if (parameterNames != null)
        {
            for (int i = 0; i < parameterNames.length; i++)
            {
                if (parameterNames[i].equalsIgnoreCase(param))
                {
                    parameterValues[i] = value;
                    mimeTypeString = null;
                    return;
                }
            }
        }
        addParameter(param,value);
      }
  
      /**
       * Adds a parameter to the MIME type.
       *
       * @param param the name of the parameter.
       * @param value the value of the parameter.
       */
      public void addParameter(String param,
                               String value)
      {
          addParameters(new String[]{ param },new String[]{ value });
      }
  
      /**
       * Adds parameters to the MIME type.
       *
       * @param params an array of parameter names.
       * @param values an array of parameter values.
       * @throw IllegalArgumentException for incorrect parameters.
       */
      public synchronized void addParameters(String[] params,
                                             String[] values)
      {
          if ((params == null) ||
              (values == null) ||
              (params.length != values.length))
              throw new IllegalArgumentException("Incorrect MIME type parameters");
  
          if (parameterNames != null)
          {
              String[] na = new String[parameterNames.length + params.length];
              String[] va = new String[parameterValues.length + values.length];
              System.arraycopy(parameterNames,0,na,0,parameterNames.length);
              System.arraycopy(params,0,na,parameterNames.length,params.length);
              System.arraycopy(parameterValues,0,va,0,parameterValues.length);
              System.arraycopy(values,0,va,parameterValues.length,values.length);
              parameterNames = na;
              parameterValues = va;
          }
          else
          {
              parameterNames = params;
              parameterValues = values;
          }
          mimeTypeString = null;
      }
  
      /**
       * Converts the MIME type into a string.
       *
       * @return the string representation of the MIME type.
       */
      public String toString()
      {
          if (mimeTypeString == null)
          {
              StringBuffer sb = new StringBuffer(mimeType);
              sb.append('/');
              sb.append(mimeSubtype);
              String[] na = parameterNames;
              if (na != null)
              {
                  String[] va = parameterValues;
                  for (int i = 0; i < va.length; i++)
                  {
                      sb.append(';');
                      sb.append(na[i]);
                      if (va[i] != null)
                      {
                          sb.append('=');
                          sb.append(va[i]);
                      }
                  }
              }
              mimeTypeString = sb.toString();
          }
          return mimeTypeString;
      }
  }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: turbine-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: turbine-dev-help@jakarta.apache.org