Home » openjdk-7 » java » awt » datatransfer » [javadoc | source]

    1   /*
    2    * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.awt.datatransfer;
   27   
   28   import java.io.Externalizable;
   29   import java.io.ObjectOutput;
   30   import java.io.ObjectInput;
   31   import java.io.IOException;
   32   import java.util.Enumeration;
   33   
   34   
   35   /**
   36    * A Multipurpose Internet Mail Extension (MIME) type, as defined
   37    * in RFC 2045 and 2046.
   38    *
   39    * THIS IS *NOT* - REPEAT *NOT* - A PUBLIC CLASS! DataFlavor IS
   40    * THE PUBLIC INTERFACE, AND THIS IS PROVIDED AS A ***PRIVATE***
   41    * (THAT IS AS IN *NOT* PUBLIC) HELPER CLASS!
   42    */
   43   class MimeType implements Externalizable, Cloneable {
   44   
   45       /*
   46        * serialization support
   47        */
   48   
   49       static final long serialVersionUID = -6568722458793895906L;
   50   
   51       /**
   52        * Constructor for externalization; this constructor should not be
   53        * called directly by an application, since the result will be an
   54        * uninitialized, immutable <code>MimeType</code> object.
   55        */
   56       public MimeType() {
   57       }
   58   
   59       /**
   60        * Builds a <code>MimeType</code> from a <code>String</code>.
   61        *
   62        * @param rawdata text used to initialize the <code>MimeType</code>
   63        * @throws NullPointerException if <code>rawdata</code> is null
   64        */
   65       public MimeType(String rawdata) throws MimeTypeParseException {
   66           parse(rawdata);
   67       }
   68   
   69       /**
   70        * Builds a <code>MimeType</code> with the given primary and sub
   71        * type but has an empty parameter list.
   72        *
   73        * @param primary the primary type of this <code>MimeType</code>
   74        * @param sub the subtype of this <code>MimeType</code>
   75        * @throws NullPointerException if either <code>primary</code> or
   76        *         <code>sub</code> is null
   77        */
   78       public MimeType(String primary, String sub) throws MimeTypeParseException {
   79           this(primary, sub, new MimeTypeParameterList());
   80       }
   81   
   82       /**
   83        * Builds a <code>MimeType</code> with a pre-defined
   84        * and valid (or empty) parameter list.
   85        *
   86        * @param primary the primary type of this <code>MimeType</code>
   87        * @param sub the subtype of this <code>MimeType</code>
   88        * @param mtpl the requested parameter list
   89        * @throws NullPointerException if either <code>primary</code>,
   90        *         <code>sub</code> or <code>mtpl</code> is null
   91        */
   92       public MimeType(String primary, String sub, MimeTypeParameterList mtpl) throws
   93   MimeTypeParseException {
   94           //    check to see if primary is valid
   95           if(isValidToken(primary)) {
   96               primaryType = primary.toLowerCase();
   97           } else {
   98               throw new MimeTypeParseException("Primary type is invalid.");
   99           }
  100   
  101           //    check to see if sub is valid
  102           if(isValidToken(sub)) {
  103               subType = sub.toLowerCase();
  104           } else {
  105               throw new MimeTypeParseException("Sub type is invalid.");
  106           }
  107   
  108           parameters = (MimeTypeParameterList)mtpl.clone();
  109       }
  110   
  111       public int hashCode() {
  112   
  113           // We sum up the hash codes for all of the strings. This
  114           // way, the order of the strings is irrelevant
  115           int code = 0;
  116           code += primaryType.hashCode();
  117           code += subType.hashCode();
  118           code += parameters.hashCode();
  119           return code;
  120       } // hashCode()
  121   
  122       /**
  123        * <code>MimeType</code>s are equal if their primary types,
  124        * subtypes, and  parameters are all equal. No default values
  125        * are taken into account.
  126        * @param thatObject the object to be evaluated as a
  127        *    <code>MimeType</code>
  128        * @return <code>true</code> if <code>thatObject</code> is
  129        *    a <code>MimeType</code>; otherwise returns <code>false</code>
  130        */
  131       public boolean equals(Object thatObject) {
  132           if (!(thatObject instanceof MimeType)) {
  133               return false;
  134           }
  135           MimeType that = (MimeType)thatObject;
  136           boolean isIt =
  137               ((this.primaryType.equals(that.primaryType)) &&
  138                (this.subType.equals(that.subType)) &&
  139                (this.parameters.equals(that.parameters)));
  140           return isIt;
  141       } // equals()
  142   
  143       /**
  144        * A routine for parsing the MIME type out of a String.
  145        *
  146        * @throws NullPointerException if <code>rawdata</code> is null
  147        */
  148       private void parse(String rawdata) throws MimeTypeParseException {
  149           int slashIndex = rawdata.indexOf('/');
  150           int semIndex = rawdata.indexOf(';');
  151           if((slashIndex < 0) && (semIndex < 0)) {
  152               //    neither character is present, so treat it
  153               //    as an error
  154               throw new MimeTypeParseException("Unable to find a sub type.");
  155           } else if((slashIndex < 0) && (semIndex >= 0)) {
  156               //    we have a ';' (and therefore a parameter list),
  157               //    but no '/' indicating a sub type is present
  158               throw new MimeTypeParseException("Unable to find a sub type.");
  159           } else if((slashIndex >= 0) && (semIndex < 0)) {
  160               //    we have a primary and sub type but no parameter list
  161               primaryType = rawdata.substring(0,
  162   slashIndex).trim().toLowerCase();
  163               subType = rawdata.substring(slashIndex +
  164   1).trim().toLowerCase();
  165               parameters = new MimeTypeParameterList();
  166           } else if (slashIndex < semIndex) {
  167               //    we have all three items in the proper sequence
  168               primaryType = rawdata.substring(0,
  169   slashIndex).trim().toLowerCase();
  170               subType = rawdata.substring(slashIndex + 1,
  171   semIndex).trim().toLowerCase();
  172               parameters = new
  173   MimeTypeParameterList(rawdata.substring(semIndex));
  174           } else {
  175               //    we have a ';' lexically before a '/' which means we have a primary type
  176               //    & a parameter list but no sub type
  177               throw new MimeTypeParseException("Unable to find a sub type.");
  178           }
  179   
  180           //    now validate the primary and sub types
  181   
  182           //    check to see if primary is valid
  183           if(!isValidToken(primaryType)) {
  184               throw new MimeTypeParseException("Primary type is invalid.");
  185           }
  186   
  187           //    check to see if sub is valid
  188           if(!isValidToken(subType)) {
  189               throw new MimeTypeParseException("Sub type is invalid.");
  190           }
  191       }
  192   
  193       /**
  194        * Retrieve the primary type of this object.
  195        */
  196       public String getPrimaryType() {
  197           return primaryType;
  198       }
  199   
  200       /**
  201        * Retrieve the sub type of this object.
  202        */
  203       public String getSubType() {
  204           return subType;
  205       }
  206   
  207       /**
  208        * Retrieve a copy of this object's parameter list.
  209        */
  210       public MimeTypeParameterList getParameters() {
  211           return (MimeTypeParameterList)parameters.clone();
  212       }
  213   
  214       /**
  215        * Retrieve the value associated with the given name, or null if there
  216        * is no current association.
  217        */
  218       public String getParameter(String name) {
  219           return parameters.get(name);
  220       }
  221   
  222       /**
  223        * Set the value to be associated with the given name, replacing
  224        * any previous association.
  225        *
  226        * @throw IllegalArgumentException if parameter or value is illegal
  227        */
  228       public void setParameter(String name, String value) {
  229           parameters.set(name, value);
  230       }
  231   
  232       /**
  233        * Remove any value associated with the given name.
  234        *
  235        * @throw IllegalArgumentExcpetion if parameter may not be deleted
  236        */
  237       public void removeParameter(String name) {
  238           parameters.remove(name);
  239       }
  240   
  241       /**
  242        * Return the String representation of this object.
  243        */
  244       public String toString() {
  245           return getBaseType() + parameters.toString();
  246       }
  247   
  248       /**
  249        * Return a String representation of this object
  250        * without the parameter list.
  251        */
  252       public String getBaseType() {
  253           return primaryType + "/" + subType;
  254       }
  255   
  256       /**
  257        * Returns <code>true</code> if the primary type and the
  258        * subtype of this object are the same as the specified
  259        * <code>type</code>; otherwise returns <code>false</code>.
  260        *
  261        * @param type the type to compare to <code>this</code>'s type
  262        * @return <code>true</code> if the primary type and the
  263        *    subtype of this object are the same as the
  264        *    specified <code>type</code>; otherwise returns
  265        *    <code>false</code>
  266        */
  267       public boolean match(MimeType type) {
  268           if (type == null)
  269               return false;
  270           return primaryType.equals(type.getPrimaryType())
  271                       && (subType.equals("*")
  272                               || type.getSubType().equals("*")
  273                               || (subType.equals(type.getSubType())));
  274       }
  275   
  276       /**
  277        * Returns <code>true</code> if the primary type and the
  278        * subtype of this object are the same as the content type
  279        * described in <code>rawdata</code>; otherwise returns
  280        * <code>false</code>.
  281        *
  282        * @param rawdata the raw data to be examined
  283        * @return <code>true</code> if the primary type and the
  284        *    subtype of this object are the same as the content type
  285        *    described in <code>rawdata</code>; otherwise returns
  286        *    <code>false</code>; if <code>rawdata</code> is
  287        *    <code>null</code>, returns <code>false</code>
  288        */
  289       public boolean match(String rawdata) throws MimeTypeParseException {
  290           if (rawdata == null)
  291               return false;
  292           return match(new MimeType(rawdata));
  293       }
  294   
  295       /**
  296        * The object implements the writeExternal method to save its contents
  297        * by calling the methods of DataOutput for its primitive values or
  298        * calling the writeObject method of ObjectOutput for objects, strings
  299        * and arrays.
  300        * @exception IOException Includes any I/O exceptions that may occur
  301        */
  302       public void writeExternal(ObjectOutput out) throws IOException {
  303           String s = toString(); // contains ASCII chars only
  304           // one-to-one correspondence between ASCII char and byte in UTF string
  305           if (s.length() <= 65535) { // 65535 is max length of UTF string
  306               out.writeUTF(s);
  307           } else {
  308               out.writeByte(0);
  309               out.writeByte(0);
  310               out.writeInt(s.length());
  311               out.write(s.getBytes());
  312           }
  313       }
  314   
  315       /**
  316        * The object implements the readExternal method to restore its
  317        * contents by calling the methods of DataInput for primitive
  318        * types and readObject for objects, strings and arrays.  The
  319        * readExternal method must read the values in the same sequence
  320        * and with the same types as were written by writeExternal.
  321        * @exception ClassNotFoundException If the class for an object being
  322        *              restored cannot be found.
  323        */
  324       public void readExternal(ObjectInput in) throws IOException,
  325   ClassNotFoundException {
  326           String s = in.readUTF();
  327           if (s == null || s.length() == 0) { // long mime type
  328               byte[] ba = new byte[in.readInt()];
  329               in.readFully(ba);
  330               s = new String(ba);
  331           }
  332           try {
  333               parse(s);
  334           } catch(MimeTypeParseException e) {
  335               throw new IOException(e.toString());
  336           }
  337       }
  338   
  339       /**
  340        * Returns a clone of this object.
  341        * @return a clone of this object
  342        */
  343   
  344       public Object clone() {
  345           MimeType newObj = null;
  346           try {
  347               newObj = (MimeType)super.clone();
  348           } catch (CloneNotSupportedException cannotHappen) {
  349           }
  350           newObj.parameters = (MimeTypeParameterList)parameters.clone();
  351           return newObj;
  352       }
  353   
  354       private String    primaryType;
  355       private String    subType;
  356       private MimeTypeParameterList parameters;
  357   
  358       //    below here be scary parsing related things
  359   
  360       /**
  361        * Determines whether or not a given character belongs to a legal token.
  362        */
  363       private static boolean isTokenChar(char c) {
  364           return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
  365       }
  366   
  367       /**
  368        * Determines whether or not a given string is a legal token.
  369        *
  370        * @throws NullPointerException if <code>s</code> is null
  371        */
  372       private boolean isValidToken(String s) {
  373           int len = s.length();
  374           if(len > 0) {
  375               for (int i = 0; i < len; ++i) {
  376                   char c = s.charAt(i);
  377                   if (!isTokenChar(c)) {
  378                       return false;
  379                   }
  380               }
  381               return true;
  382           } else {
  383               return false;
  384           }
  385       }
  386   
  387       /**
  388        * A string that holds all the special chars.
  389        */
  390   
  391       private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
  392   
  393   } // class MimeType

Home » openjdk-7 » java » awt » datatransfer » [javadoc | source]