org.w3c.www.mime.MimeType V1.17...

Hi !

----

Sorry, again, I couldn't get my claws from the code...

Here comes a slighly modified MimeType class:

New since V1.16:
 - added static object for text/xml
 - added static object for text/xsl
 - added static object for application/octet-stream
 - some javadoc fixes
 - added javadoc for MATCH_* entries
 - main() got javadoc, returns now usable exit-codes (for automated
tests etc.)
 - added new private method parse() to implement the constructor
MimeType( MimeType x )
 - added new constructor MimeType( MimeType x )
 - interface Cloneable implemented
   (question: is it a good idea that this method is public ? What about
a "final class" MimeType ?

Source is included as an attachment.

ToDo:
 - quoted-text is currently not being accepted
 - what to do with the current clone() implementation: leave "public",
make it "proteced" ?
    If "public", make whole class MimeType "final" ?

----

Bye,
Roland

--
  __ .  . __
 (o.\ \/ /.o)  Roland Mainz                               C programmer
  \__\/\/__/   Roland.Mainz@informatik.med.uni-giessen.de MPEG specialist
  /O /==\ O\   gisburn@w-specht.rhein-ruhr.de             Sun&&Amiga programmer
 (;O/ \/ \O;)  TEL +49 (0) 2426901568  FAX +49 (0) 2426901569
// MimeType.java
// $Id: MimeType.java,v 1.17 1999/04/23 09:48:12 gisburn Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

// new for V1.17 (gisburn):
// - added static object for text/xml
// - added static object for text/xsl
// - added static object for application/octet-stream
// - some javadoc fixes 
// - added javadoc for MATCH_* entries
// - main() got javadoc, returns now usable exit-codes (for automated tests etc.)
// - added new private method parse() to implement the constructor MimeType( MimeType x )
// - interface Cloneable implemented 
//   (question: is it a good idea that this method is public ? What about a "final class" MimeType ?

package org.w3c.www.mime;

import java.util.*;
import java.io.*;

/**
 * This class is used to represent parsed MIME types. 
 * It creates this representation from a string based representation of
 * the MIME type, as defined in the RFC 1345.
 */
public class MimeType implements Serializable, Cloneable {
    // List of well known MIME types:
    public static MimeType TEXT_PLAIN                        = null;
    public static MimeType TEXT_HTML                         = null;
    public static MimeType TEXT_XML                          = null;
    public static MimeType TEXT_CSS                          = null;
    public static MimeType TEXT_XSL                          = null;
    public static MimeType APPLICATION_OCTET_STREAM          = null;
    public static MimeType APPLICATION_POSTSCRIPT            = null;
    public static MimeType APPLICATION_X_WWW_FORM_URLENCODED = null;
    public static MimeType APPLICATION_X_JAVA_AGENT          = null;
    public static MimeType MULTIPART_FORM_DATA               = null;
    public static MimeType MESSAGE_HTTP                      = null;

    static {
	try {
	    TEXT_PLAIN             		= new MimeType("text/plain") ;
	    TEXT_HTML 		                = new MimeType("text/html");
	    TEXT_XML                            = new MimeType("text/xml");
	    TEXT_CSS		                = new MimeType("text/css");
	    TEXT_XSL                            = new MimeType("text/xsl");
	    APPLICATION_OCTET_STREAM            = new MimeType("application/octet-stream");
	    APPLICATION_POSTSCRIPT 		= new MimeType("application/postscript") ;
	    APPLICATION_X_WWW_FORM_URLENCODED	= new MimeType("application/x-www-form-urlencoded") ;
	    APPLICATION_X_JAVA_AGENT		= new MimeType("application/x-java-agent") ;
	    MULTIPART_FORM_DATA		        = new MimeType("multipart/form-data") ;
	    MESSAGE_HTTP		        = new MimeType("message/http");
	} catch (MimeTypeFormatException e) {
	    System.out.println ("org.w3c.www.mime.MimeType: invalid static init.") ;
	    System.exit(1) ;
	}
    }

    /**
     * Matches any type.
     * The following is everytimes true: MATCH_TYPE < MATCH_SPECIFIC_TYPE.
     */
    public final static int MATCH_TYPE             = 1;
    /**
     * Matches a specific base type.
     * The following is everytimes true: MATCH_SPECIFIC_TYPE < MATCH_SUBTYPE.
     */
    public final static int MATCH_SPECIFIC_TYPE    = 2;
    /**
     * Matches any subtype.
     * The following is everytimes true: MATCH_SPECIFIC_TYPE < MATCH_SUBTYPE.
     */
    public final static int MATCH_SUBTYPE          = 3;
    /**
     * Matches a specific subtype.
     * The following is everytimes true: MATCH_SUBTYPE < MATCH_SPECIFIC_SUBTYPE.
     */
    public final static int MATCH_SPECIFIC_SUBTYPE = 4;

    /**
     * String representation of type
     *
     * @serial
     */
    protected String type      = null ;
    /**
     * String representation of subtype
     *
     * @serial
     */
    protected String subtype   = null ;
    /**
     * parameter names
     *
     * @serial
     */
    protected String pnames[]  = null;
    /**
     * parameter values
     *
     * @serial
     */
    protected String pvalues[] = null;
    /**
     * external form of this mime type
     *
     * @serial
     */
    protected String external  = null ;

    /**
     * How good the given MimeType matches the receiver of the method ?
     *  This method returns a matching level among:
     * <dl>
     * <dt>MATCH_TYPE<dd>Types match,</dd>
     * <dt>MATCH_SPECIFIC_TYPE<dd>Types match exactly,</dd>
     * <dt>MATCH_SUBTYPE<dd>Types match, subtypes matches too</dd>
     * <dt>MATCH_SPECIFIC_SUBTYPE<dd>Types match, subtypes matches exactly</dd>
     * </dl>
     * @param other The other MimeType to match against ourself.
     */

    public int match (MimeType other) {
	int match = -1;
	// match types:
	if ( type.equals("*") || other.type.equals("*") ) {
	    match = MATCH_TYPE;
	} else if ( ! type.equals (other.type) ) {
	    return -1 ;
	} else {
	    match = MATCH_SPECIFIC_TYPE;
	}
	// match subtypes:
	if ( subtype.equals("*") || other.subtype.equals("*") ) {
	    match = MATCH_SUBTYPE ;
	} else if ( ! subtype.equals (other.subtype) ) {
	    return -1;
	} else {
	    match = MATCH_SPECIFIC_SUBTYPE;
	}
	return match;
    }

    /**
     * A printable representation of this MimeType. 
     * The printed representation is guaranteed to be parseable by the
     * String constructor.
     */

    public String toString () {
	if ( external == null ) {
	    StringBuffer sb = new StringBuffer (type) ;
	    sb.append((char) '/') ;
	    sb.append (subtype) ;
	    if ( pnames != null ) {
		for (int i = 0 ; i < pnames.length; i++) {
		    sb.append(';');
		    sb.append(pnames[i]);
		    if ( pvalues[i] != null ) {
			sb.append('=');
			sb.append(pvalues[i]);
		    }
		}
	    }
	    external = sb.toString() ;
	}
	return external ;
    }


    /**
     * Does this MIME type has some value for the given parameter ?
     * @param name The parameter to check.
     * @return <strong>True</strong> if this parameter has a value, false
     *    otherwise.
     */

    public boolean hasParameter (String name) {
	if ( pnames != null ) {
	    for (int i = 0 ; i < pnames.length ; i++) {
		if ( pnames[i].equals(name) ) 
		    return true ;
	    }
	}
	return false ;
    }

    /**
     * Get the major type of this mime type.
     * @return The major type, encoded as a String.
     */

    public String getType() {
	return type;
    }

    /**
     * Get the minor type (subtype) of this mime type.
     * @return The minor or subtype encoded as a String.
     */

    public String getSubtype() {
	return subtype;
    }


    /**
     * Get a mime type parameter value.
     * @param name The parameter whose value is to be returned.
     * @return The parameter value, or <b>null</b> if not found.
     */
    
    public String getParameterValue (String name) {
	if ( pnames != null ) {
	    for (int i = 0 ; i < pnames.length ; i++) {
		if ( pnames[i].equals(name) ) 
		    return pvalues[i];
	    }
	}
	return null ;
    }


    /**
     * Construct  MimeType object for the given string.
     * The string should be the representation of the type. This methods
     * tries to be compliant with HTTP1.1, p 15, although it is not
     * (because of quoted-text not being accepted).
     * FIXME
     * @parameter spec A string representing a MimeType
     * @return A MimeType object
     * @exception MimeTypeFormatException if the string couldn't be parsed.
     */
    public MimeType (String spec)
	throws MimeTypeFormatException
    {
        parse( spec );
    }
    
    
    /**
     * Parse the given string and store the results in the object.
     * The string should be the representation of the type. This methods
     * tries to be compliant with HTTP1.1, p 15, although it is not
     * (because of quoted-text not being accepted).
     * FIXME
     * @parameter spec A string representing a MimeType
     * @exception MimeTypeFormatException if the string couldn't be parsed.  
     */  
    private void parse (String spec)
	throws MimeTypeFormatException
    {    
	int strl  = spec.length() ;
	int start = 0, look = -1 ;
	
	// skip leading/trailing blanks:
	while ((start < strl) && (spec.charAt (start)) <= ' ')
	    start++ ;
	while ((strl > start) && (spec.charAt (strl-1) <= ' '))
	    strl-- ;
	    
	// get the type:
	StringBuffer sb = new StringBuffer () ;
	while ((start < strl) && ((look = spec.charAt(start)) != '/')) {
	    sb.append ((char) look) ;
	    start++ ;
	}
	if ( look != '/' ) 
	    throw new MimeTypeFormatException (spec) ;
	this.type = sb.toString() ;
	// get the subtype:
	start++ ;
	sb.setLength(0) ;
	while ((start < strl) 
	       && ((look = spec.charAt(start)) > ' ') && (look != ';')) {
	    sb.append ((char) look) ;
	    start++ ;
	}
	this.subtype = sb.toString() ;
	
	// get parameters, if any:
	while ((start < strl) && ((look = spec.charAt(start)) <= ' '))
	    start++ ;
	if ( start < strl ) {
	    if (spec.charAt(start) != ';') 
		throw new MimeTypeFormatException (spec) ;
	    start++ ;
	    Vector vp = new Vector(4) ;
	    Vector vv = new Vector(4) ;
	    while ( start < strl ) {
		while ((start < strl) && (spec.charAt(start) <= ' ')) start++ ;
		// get parameter name:
		sb.setLength (0) ;
		while ((start < strl) 
		       && ((look=spec.charAt(start)) > ' ') && (look != '=')) {
		    sb.append (Character.toLowerCase((char) look)) ;
		    start++ ;
		}
		String name = sb.toString() ;
		// get the value:
		while ((start < strl) && (spec.charAt(start) <= ' ')) start++ ;
		if (spec.charAt(start) != '=') 
		    throw new MimeTypeFormatException (spec) ;
		start++ ;
		while ((start < strl) && 
		       ((spec.charAt(start) == '"') ||
			(spec.charAt(start) <= ' '))) start++ ;
		sb.setLength(0) ;
		while ((start < strl) 
		       && ((look=spec.charAt(start)) > ' ') 
		       && (look != ';')
		       && (look != '"')) {
		    sb.append ((char) look) ;
		    start++ ;
		}
		while ((start < strl) && (spec.charAt(start) != ';')) start++ ;
		start++ ; 
		String value = sb.toString() ;
		vp.addElement(name);
		vv.addElement(value);
	    }
	    this.pnames = new String[vp.size()];
	    vp.copyInto(pnames);
	    this.pvalues = new String[vv.size()];
	    vv.copyInto(pvalues);
	}
    }
    
    
    public MimeType (String type, String subtype, String pnames[], String pvalues[]) {
	this.type    = type ;
	this.subtype = subtype ;
	this.pnames  = pnames;
	this.pvalues = pvalues;
    }


    public MimeType (String type, String subtype) {
	this.type    = type;
	this.subtype = subtype;
    }


    public MimeType( MimeType mt ) 
    {
        try
        {          
          parse( mt.toString() );
        } 
        catch( MimeTypeFormatException exc )
        {
          // should never ever happen (if parse() and toString() are working correct... works !!
          exc.printStackTrace();
        }
    }
    
    
    // implements interface Cloneable
    public Object clone()
    {
        return( new MimeType( this ) );
    }
    
    
    /**
     * Test a given mimetype.
     * Usage: java org.w3c.www.mime.MimeType <type-to-parse>
     */
    public static void main (String args[]) 
    {
	if( args.length == 1 ) 
	{
	  MimeType type = null ;
	  try 
	  {
	    type = new MimeType (args[0]) ;
	  } 
	  catch (MimeTypeFormatException e) 
	  {
	    // ignored.
	  }
	  
	  if ( type != null )
	  {
	    // success !
	    System.out.println (type) ;
	    System.exit(0);
          }		
	  else
	  {
	    System.err.println ("Invalid mime type specification.") ;
	  }  
	} 
	else 
	{
	    System.err.println ("Usage: java org.w3c.www.mime.MimeType <type-to-parse>") ;
	}
	
	// failure !
	System.exit(1);
    }
}

Received on Thursday, 22 April 1999 19:17:00 UTC