OSDN Git Service

Imported GNU Classpath 0.20
[pf3gnuchains/gcc-fork.git] / libjava / classpath / java / awt / datatransfer / DataFlavor.java
index 38f415b..32bf4d6 100644 (file)
@@ -1,5 +1,5 @@
 /* DataFlavor.java -- A type of data to transfer via the clipboard.
-   Copyright (C) 1999, 2001, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
 
 This file is part of GNU Classpath.
 
@@ -49,6 +49,7 @@ import java.io.StringReader;
 import java.io.UnsupportedEncodingException;
 import java.nio.ByteBuffer;
 import java.nio.CharBuffer;
+import java.nio.charset.Charset;
 import java.rmi.Remote;
 
 /**
@@ -63,946 +64,818 @@ public class DataFlavor implements java.io.Externalizable, Cloneable
 
   // FIXME: Serialization: Need to write methods for.
 
-/**
- * This is the data flavor used for tranferring plain text.  The MIME
- * type is "text/plain; charset=unicode".  The representation class
- * is <code>java.io.InputStream</code>.
- *
- * @deprecated The charset unicode is platform specific and InputStream
- * deals with bytes not chars. Use <code>getRederForText()</code>.
- */
-public static final DataFlavor plainTextFlavor;
-
-/**
- * This is the data flavor used for transferring Java strings.  The
- * MIME type is "application/x-java-serialized-object" and the 
- * representation class is <code>java.lang.String</code>.
- */
-public static final DataFlavor stringFlavor;
-
-/**
- * This is a data flavor used for transferring lists of files.  The
- * representation type is a <code>java.util.List</code>, with each element of 
- * the list being a <code>java.io.File</code>.
- */
-public static final DataFlavor javaFileListFlavor;
-
-/**
- * This is an image flavor used for transferring images.  The
- * representation type is a <code>java.awt.Image</code>.
- */
-public static final DataFlavor imageFlavor;
-
-/**
- * This is the MIME type used for transferring a serialized object.
- * The representation class is the type of object be deserialized.
- */
-public static final String javaSerializedObjectMimeType =
-  "application/x-java-serialized-object";
-
-/**
- * This is the MIME type used to transfer a Java object reference within
- * the same JVM.  The representation class is the class of the object
- * being transferred.
- */
-public static final String javaJVMLocalObjectMimeType =
-  "application/x-java-jvm-local-objectref";
-
-/**
- * This is the MIME type used to transfer a link to a remote object.
- * The representation class is the type of object being linked to.
- */
-public static final String javaRemoteObjectMimeType =
-  "application/x-java-remote-object";
-
-static
-{
-  plainTextFlavor
-      = new DataFlavor(java.io.InputStream.class,
-                      "text/plain; charset=unicode",
-                      "plain unicode text");
-
-  stringFlavor
-      = new DataFlavor(java.lang.String.class,
-                      "Java Unicode String");
-
-  javaFileListFlavor
-      = new DataFlavor(java.util.List.class,
-                      "application/x-java-file-list; class=java.util.List",
-                      "Java File List");
-
-  imageFlavor
-      = new DataFlavor(java.awt.Image.class,
-                       "Java Image");
-}
-
-/*************************************************************************/
+  /**
+   * This is the data flavor used for tranferring plain text.  The MIME
+   * type is "text/plain; charset=unicode".  The representation class
+   * is <code>java.io.InputStream</code>.
+   *
+   * @deprecated The charset unicode is platform specific and InputStream
+   * deals with bytes not chars. Use <code>getRederForText()</code>.
+   */
+  public static final DataFlavor plainTextFlavor = 
+    new DataFlavor(java.io.InputStream.class,
+                   "text/plain; charset=unicode",
+                   "plain unicode text");
 
-/*
- * Instance Variables
- */
+  /**
+   * This is the data flavor used for transferring Java strings.  The
+   * MIME type is "application/x-java-serialized-object" and the 
+   * representation class is <code>java.lang.String</code>.
+   */
+  public static final DataFlavor stringFlavor = 
+    new DataFlavor(java.lang.String.class, "Java Unicode String");
 
-// The MIME type for this flavor
-private final String mimeType;
+  /**
+   * This is a data flavor used for transferring lists of files.  The
+   * representation type is a <code>java.util.List</code>, with each 
+   * element of the list being a <code>java.io.File</code>.
+   */
+  public static final DataFlavor javaFileListFlavor = 
+    new DataFlavor(java.util.List.class,
+                   "application/x-java-file-list; class=java.util.List",
+                   "Java File List");
 
-// The representation class for this flavor
-private final Class representationClass;
+  /**
+   * This is an image flavor used for transferring images.  The
+   * representation type is a <code>java.awt.Image</code>.
+   */
+  public static final DataFlavor imageFlavor = 
+    new DataFlavor(java.awt.Image.class, "Java Image");
 
-// The human readable name of this flavor
-private String humanPresentableName;
+  /**
+   * This is the MIME type used for transferring a serialized object.
+   * The representation class is the type of object be deserialized.
+   */
+  public static final String javaSerializedObjectMimeType =
+    "application/x-java-serialized-object";
 
-/*************************************************************************/
+  /**
+   * This is the MIME type used to transfer a Java object reference within
+   * the same JVM.  The representation class is the class of the object
+   * being transferred.
+   */
+  public static final String javaJVMLocalObjectMimeType =
+    "application/x-java-jvm-local-objectref";
 
-/*
- * Static Methods
- */
+  /**
+   * This is the MIME type used to transfer a link to a remote object.
+   * The representation class is the type of object being linked to.
+   */
+  public static final String javaRemoteObjectMimeType =
+    "application/x-java-remote-object";
 
-/**
- * This method attempts to load the named class.  The following class
- * loaders are searched in order: the bootstrap class loader, the
- * system class loader, the context class loader (if it exists), and
- * the specified fallback class loader.
- *
- * @param className The name of the class to load.
- * @param classLoader The class loader to use if all others fail, which
- * may be <code>null</code>.
- *
- * @exception ClassNotFoundException If the class cannot be loaded.
- */
-protected static final Class
-tryToLoadClass(String className, ClassLoader classLoader)
-               throws ClassNotFoundException
-{
-  try
-    {
-      return(Class.forName(className));
-    }
-  catch(Exception e) { ; }
-  // Commented out for Java 1.1
   /*
-  try
-    {
-      return(className.getClass().getClassLoader().findClass(className));
-    }
-  catch(Exception e) { ; }
-
-  try
-    {
-      return(ClassLoader.getSystemClassLoader().findClass(className));
-    }
-  catch(Exception e) { ; }
-  */
+   * Instance Variables
+   */
+  
+  // The MIME type for this flavor
+  private final String mimeType;
+  
+  // The representation class for this flavor
+  private final Class representationClass;
+  
+  // The human readable name of this flavor
+  private String humanPresentableName;
 
-  // FIXME: What is the context class loader?
   /*
-  try
+   * Static Methods
+   */
+  
+  /**
+   * This method attempts to load the named class.  The following class
+   * loaders are searched in order: the bootstrap class loader, the
+   * system class loader, the context class loader (if it exists), and
+   * the specified fallback class loader.
+   *
+   * @param className The name of the class to load.
+   * @param classLoader The class loader to use if all others fail, which
+   * may be <code>null</code>.
+   *
+   * @exception ClassNotFoundException If the class cannot be loaded.
+   */
+  protected static final Class tryToLoadClass(String className,
+                                             ClassLoader classLoader)
+    throws ClassNotFoundException
+  {
+    try
+      {
+        return(Class.forName(className));
+      }
+    catch(Exception e) { ; }
+    // Commented out for Java 1.1
+    /*
+    try
+      {
+        return(className.getClass().getClassLoader().findClass(className));
+      }
+    catch(Exception e) { ; }
+  
+    try
+      {
+        return(ClassLoader.getSystemClassLoader().findClass(className));
+      }
+    catch(Exception e) { ; }
+    */
+  
+    // FIXME: What is the context class loader?
+    /*
+    try
+      {
+      }
+    catch(Exception e) { ; }
+    */
+  
+    if (classLoader != null)
+      return(classLoader.loadClass(className));
+    else
+      throw new ClassNotFoundException(className);
+  }
+  
+  private static Class getRepresentationClassFromMime(String mimeString,
+                                                      ClassLoader classLoader)
     {
+      String classname = getParameter("class", mimeString);
+      if (classname != null)
+        {
+          try
+            {
+              return tryToLoadClass(classname, classLoader);
+            }
+          catch(Exception e)
+            {
+              throw new IllegalArgumentException("classname: " + e.getMessage());
+            }
+        }
+      else
+        return java.io.InputStream.class;
     }
-  catch(Exception e) { ; }
-  */
-
-  if (classLoader != null)
-    return(classLoader.loadClass(className));
-  else
-    throw new ClassNotFoundException(className);
-}
-
-/*************************************************************************/
+  
+  /**
+   * Returns the value of the named MIME type parameter, or <code>null</code>
+   * if the parameter does not exist. Given the parameter name and the mime
+   * string.
+   *
+   * @param paramName The name of the parameter.
+   * @param mimeString The mime string from where the name should be found.
+   *
+   * @return The value of the parameter or null.
+   */
+  private static String getParameter(String paramName, String mimeString)
+  {
+    int idx = mimeString.indexOf(paramName + "=");
+    if (idx == -1)
+      return(null);
+  
+    String value = mimeString.substring(idx + paramName.length() + 1);
+  
+    idx = value.indexOf(" ");
+    if (idx == -1)
+      return(value);
+    else
+      return(value.substring(0, idx));
+  }
+  
+  /**
+   * XXX - Currently returns <code>plainTextFlavor</code>.
+   */
+  public static final DataFlavor getTextPlainUnicodeFlavor()
+  {
+    return plainTextFlavor;
+  }
+  
+  /**
+   * Selects the best supported text flavor on this implementation.
+   * Returns <code>null</code> when none of the given flavors is liked.
+   *
+   * The <code>DataFlavor</code> returned the first data flavor in the
+   * array that has either a representation class which is (a subclass of)
+   * <code>Reader</code> or <code>String</code>, or has a representation
+   * class which is (a subclass of) <code>InputStream</code> and has a
+   * primary MIME type of "text" and has an supported encoding.
+   */
+  public static final DataFlavor 
+    selectBestTextFlavor(DataFlavor[] availableFlavors)
+  {
+    for(int i = 0; i < availableFlavors.length; i++)
+      {
+        DataFlavor df = availableFlavors[i];
+        Class c = df.representationClass;
+  
+        // A Reader or String is good.
+        if ((Reader.class.isAssignableFrom(c))
+           || (String.class.isAssignableFrom(c)))
+      return df;
+  
+        // A InputStream is good if the mime primary type is "text"
+        if ((InputStream.class.isAssignableFrom(c))
+           && ("text".equals(df.getPrimaryType())))
+          {
+            String encoding = availableFlavors[i].getParameter("charset");
+            if (encoding == null)
+              encoding = "us-ascii";
+            Reader r = null;
+            try
+              {
+                // Try to construct a dummy reader with the found encoding
+                r = new InputStreamReader
+                      (new ByteArrayInputStream(new byte[0]), encoding);
+              }
+            catch(UnsupportedEncodingException uee) { /* ignore */ }
+
+            if (r != null)
+              return df;
+          }
+      }
+  
+    // Nothing found
+    return null;
+  }
 
-/*
- * Constructors
- */
 
-/**
- * Empty public constructor needed for externalization.
- * Should not be used for normal instantiation.
- */
-public
-DataFlavor()
-{
+  /*
+   * Constructors
+   */
+  
+  /**
+   * Empty public constructor needed for externalization.
+   * Should not be used for normal instantiation.
+   */
+  public DataFlavor()
+  {
     mimeType = null;
     representationClass = null;
     humanPresentableName = null;
-}
-
-/*************************************************************************/
+  }
 
-/**
- * Private constructor.
- */
-private
-DataFlavor(Class representationClass,
-          String mimeType,
-          String humanPresentableName)
-{
+  /**
+   * Private constructor.
+   */
+  private DataFlavor(Class representationClass,
+                    String mimeType,
+                    String humanPresentableName)
+  {
     this.representationClass = representationClass;
     this.mimeType = mimeType;
     if (humanPresentableName != null)
-       this.humanPresentableName = humanPresentableName;
+      this.humanPresentableName = humanPresentableName;
     else
-       this.humanPresentableName = mimeType;
-}
-
-/*************************************************************************/
+      this.humanPresentableName = mimeType;
+  }
 
-/**
- * Initializes a new instance of <code>DataFlavor</code>.  The class
- * and human readable name are specified, the MIME type will be
- * "application/x-java-serialized-object". If the human readable name
- * is not specified (<code>null</code>) then the human readable name
- * will be the same as the MIME type.
- *
- * @param representationClass The representation class for this object.
- * @param humanPresentableName The display name of the object.
- */
-public
-DataFlavor(Class representationClass, String humanPresentableName)
-{
+  /**
+   * Initializes a new instance of <code>DataFlavor</code>.  The class
+   * and human readable name are specified, the MIME type will be
+   * "application/x-java-serialized-object". If the human readable name
+   * is not specified (<code>null</code>) then the human readable name
+   * will be the same as the MIME type.
+   *
+   * @param representationClass The representation class for this object.
+   * @param humanPresentableName The display name of the object.
+   */
+  public DataFlavor(Class representationClass, String humanPresentableName)
+  {
     this(representationClass,
-       "application/x-java-serialized-object"
-       + "; class="
-       + representationClass.getName(),
-       humanPresentableName);
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of <code>DataFlavor</code> with the
- * specified MIME type and description.  If the MIME type has a
- * "class=&lt;rep class&gt;" parameter then the representation class will
- * be the class name specified. Otherwise the class defaults to
- * <code>java.io.InputStream</code>. If the human readable name
- * is not specified (<code>null</code>) then the human readable name
- * will be the same as the MIME type.
- *
- * @param mimeType The MIME type for this flavor.
- * @param humanPresentableName The display name of this flavor.
- * @param classLoader The class loader for finding classes if the default
- * class loaders do not work.
- *
- * @exception IllegalArgumentException If the representation class
- * specified cannot be loaded.
- * @exception ClassNotFoundException If the class is not loaded.
- */
-public
-DataFlavor(String mimeType, String humanPresentableName, 
-           ClassLoader classLoader) throws ClassNotFoundException
-{
-  this(getRepresentationClassFromMime(mimeType, classLoader),
-       mimeType, humanPresentableName);
-}
-
-private static Class
-getRepresentationClassFromMime(String mimeString, ClassLoader classLoader)
-{
-  String classname = getParameter("class", mimeString);
-  if (classname != null)
-    {
-      try
-        {
-          return tryToLoadClass(classname, classLoader);
-        }
-      catch(Exception e)
-        {
-          throw new IllegalArgumentException("classname: " + e.getMessage());
-        }
-    }
-  else
-    {
-      return java.io.InputStream.class;
-    }
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of <code>DataFlavor</code> with the
- * specified MIME type and description.  If the MIME type has a
- * "class=&lt;rep class&gt;" parameter then the representation class will
- * be the class name specified. Otherwise the class defaults to
- * <code>java.io.InputStream</code>. If the human readable name
- * is not specified (<code>null</code>) then the human readable name
- * will be the same as the MIME type. This is the same as calling
- * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>.
- *
- * @param mimeType The MIME type for this flavor.
- * @param humanPresentableName The display name of this flavor.
- *
- * @exception IllegalArgumentException If the representation class
- * specified cannot be loaded.
- */
-public
-DataFlavor(String mimeType, String humanPresentableName)
-{
-  this (getRepresentationClassFromMime (mimeType, null),
-       mimeType, humanPresentableName);
-}
-
-/*************************************************************************/
-
-/**
- * Initializes a new instance of <code>DataFlavor</code> with the specified
- * MIME type.  This type can have a "class=" parameter to specify the
- * representation class, and then the class must exist or an exception will
- * be thrown. If there is no "class=" parameter then the representation class
- * will be <code>java.io.InputStream</code>. This is the same as calling
- * <code>new DataFlavor(mimeType, null)</code>.
- *
- * @param mimeType The MIME type for this flavor.
- *
- * @exception IllegalArgumentException If a class is not specified in
- * the MIME type.
- * @exception ClassNotFoundException If the class cannot be loaded.
- */
-public
-DataFlavor(String mimeType) throws ClassNotFoundException
-{
-  this(mimeType, null);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the MIME type of this flavor.
- *
- * @return The MIME type for this flavor.
- */
-public String
-getMimeType()
-{
-  return(mimeType);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the representation class for this flavor.
- *
- * @return The representation class for this flavor.
- */
-public Class
-getRepresentationClass()
-{
-  return(representationClass);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the human presentable name for this flavor.
- *
- * @return The human presentable name for this flavor.
- */
-public String
-getHumanPresentableName()
-{
-  return(humanPresentableName);
-} 
-
-/*************************************************************************/
-
-/**
- * Returns the primary MIME type for this flavor.
- *
- * @return The primary MIME type for this flavor.
- */
-public String
-getPrimaryType()
-{
-  int idx = mimeType.indexOf("/");
-  if (idx == -1)
-    return(mimeType);
-
-  return(mimeType.substring(0, idx));
-}
-
-/*************************************************************************/
-
-/**
- * Returns the MIME subtype for this flavor.
- *
- * @return The MIME subtype for this flavor.
- */
-public String
-getSubType()
-{
-  int start = mimeType.indexOf("/");
-  if (start == -1)
-    return "";
-
-  int end = mimeType.indexOf(";", start + 1);
-  if (end == -1)
-    return mimeType.substring(start + 1);
-  else
-    return mimeType.substring(start + 1, end);
-}
-
-/*************************************************************************/
-
-/**
- * Returns the value of the named MIME type parameter, or <code>null</code>
- * if the parameter does not exist. Given the parameter name and the mime
- * string.
- *
- * @param paramName The name of the parameter.
- * @param mimeString The mime string from where the name should be found.
- *
- * @return The value of the parameter or null.
- */
-private static String
-getParameter(String paramName, String mimeString)
-{
-  int idx = mimeString.indexOf(paramName + "=");
-  if (idx == -1)
-    return(null);
-
-  String value = mimeString.substring(idx + paramName.length() + 1);
-
-  idx = value.indexOf(" ");
-  if (idx == -1)
-    return(value);
-  else
-    return(value.substring(0, idx));
-}
-
-/*************************************************************************/
-
-/**
- * Returns the value of the named MIME type parameter, or <code>null</code>
- * if the parameter does not exist.
- *
- * @param paramName The name of the paramter.
- *
- * @return The value of the parameter.
- */
-public String
-getParameter(String paramName)
-{
-  if ("humanPresentableName".equals(paramName))
-    return getHumanPresentableName();
-
-  return getParameter(paramName, mimeType);
-}
-
-/*************************************************************************/
-
-/**
- * Sets the human presentable name to the specified value.
- *
- * @param humanPresentableName The new display name.
- */
-public void
-setHumanPresentableName(String humanPresentableName)
-{
-  this.humanPresentableName = humanPresentableName;
-}
-
-/*************************************************************************/
-
-/**
- * Tests the MIME type of this object for equality against the specified
- * MIME type. Ignores parameters.
- *
- * @param mimeType The MIME type to test against.
- *
- * @return <code>true</code> if the MIME type is equal to this object's
- * MIME type (ignoring parameters), <code>false</code> otherwise.
- *
- * @exception NullPointerException If mimeType is null.
- */
-public boolean
-isMimeTypeEqual(String mimeType)
-{
-  String mime = getMimeType();
-  int i = mime.indexOf(";");
-  if (i != -1)
-    mime = mime.substring(0, i);
-
-  i = mimeType.indexOf(";");
-  if (i != -1)
-    mimeType = mimeType.substring(0, i);
-
-  return mime.equals(mimeType);
-}
-
-/*************************************************************************/
-
-/**
- * Tests the MIME type of this object for equality against the specified
- * data flavor's MIME type
- *
- * @param flavor The flavor to test against.
- *
- * @return <code>true</code> if the flavor's MIME type is equal to this 
- * object's MIME type, <code>false</code> otherwise.
- */
-public final boolean
-isMimeTypeEqual(DataFlavor flavor)
-{
-  return(isMimeTypeEqual(flavor.getMimeType()));
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not this flavor represents a serialized object.
- *
- * @return <code>true</code> if this flavor represents a serialized
- * object, <code>false</code> otherwise.
- */
-public boolean
-isMimeTypeSerializedObject()
-{
-  return(mimeType.startsWith(javaSerializedObjectMimeType));
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not this flavor has a representation class of
- * <code>java.io.InputStream</code>.
- *
- * @return <code>true</code> if the representation class of this flavor
- * is <code>java.io.InputStream</code>, <code>false</code> otherwise.
- */
-public boolean
-isRepresentationClassInputStream()
-{
-  return(representationClass.getName().equals("java.io.InputStream"));
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether the representation class for this flavor is
- * serializable.
- *
- * @return <code>true</code> if the representation class is serializable,
- * <code>false</code> otherwise.
- */
-public boolean
-isRepresentationClassSerializable()
-{
-  Class[] interfaces = representationClass.getInterfaces();
-
-  int i = 0;
-  while (i < interfaces.length)
-    {
-      if (interfaces[i].getName().equals("java.io.Serializable"))
-        return(true);
-      ++i;
-    }
-
-  return(false);
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether the representation class for his flavor is remote.
- *
- * @return <code>true</code> if the representation class is remote,
- * <code>false</code> otherwise.
- */
-public boolean
-isRepresentationClassRemote()
-{
-  return Remote.class.isAssignableFrom (representationClass);
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not this flavor represents a serialized object.
- *
- * @return <code>true</code> if this flavor represents a serialized
- * object, <code>false</code> otherwise.
- */
-public boolean
-isFlavorSerializedObjectType()
-{
-  // FIXME: What is the diff between this and isMimeTypeSerializedObject?
-  return(mimeType.startsWith(javaSerializedObjectMimeType));
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not this flavor represents a remote object.
- *
- * @return <code>true</code> if this flavor represents a remote object,
- * <code>false</code> otherwise.
- */
-public boolean
-isFlavorRemoteObjectType()
-{
-  return(mimeType.startsWith(javaRemoteObjectMimeType));
-}
-
-/*************************************************************************/
-
-/**
- * Tests whether or not this flavor represents a list of files.
- *
- * @return <code>true</code> if this flavor represents a list of files,
- * <code>false</code> otherwise.
- */
-public boolean
-isFlavorJavaFileListType()
-{
-  if (this.mimeType.equals(javaFileListFlavor.mimeType) &&
-      this.representationClass.equals(javaFileListFlavor.representationClass))
-    return(true);
-
-  return(false);
-}
-
-/*************************************************************************/
+         "application/x-java-serialized-object"
+         + "; class="
+         + representationClass.getName(),
+         humanPresentableName);
+  }
 
-/**
- * Returns a copy of this object.
- *
- * @return A copy of this object.
- *
- * @exception CloneNotSupportedException If the object's class does not support
- * the Cloneable interface. Subclasses that override the clone method can also
- * throw this exception to indicate that an instance cannot be cloned.
- */
-public Object clone () throws CloneNotSupportedException
-{
-  try
-    {
-      return(super.clone());
-    }
-  catch(Exception e)
-    {
-      return(null);
-    }
-}
+  /**
+   * Initializes a new instance of <code>DataFlavor</code> with the
+   * specified MIME type and description.  If the MIME type has a
+   * "class=&lt;rep class&gt;" parameter then the representation class will
+   * be the class name specified. Otherwise the class defaults to
+   * <code>java.io.InputStream</code>. If the human readable name
+   * is not specified (<code>null</code>) then the human readable name
+   * will be the same as the MIME type.
+   *
+   * @param mimeType The MIME type for this flavor.
+   * @param humanPresentableName The display name of this flavor.
+   * @param classLoader The class loader for finding classes if the default
+   * class loaders do not work.
+   *
+   * @exception IllegalArgumentException If the representation class
+   * specified cannot be loaded.
+   * @exception ClassNotFoundException If the class is not loaded.
+   */
+  public DataFlavor(String mimeType, String humanPresentableName, 
+                   ClassLoader classLoader)
+    throws ClassNotFoundException
+  {
+    this(getRepresentationClassFromMime(mimeType, classLoader),
+         mimeType, humanPresentableName);
+  }
 
-/*************************************************************************/
+  /**
+   * Initializes a new instance of <code>DataFlavor</code> with the
+   * specified MIME type and description.  If the MIME type has a
+   * "class=&lt;rep class&gt;" parameter then the representation class will
+   * be the class name specified. Otherwise the class defaults to
+   * <code>java.io.InputStream</code>. If the human readable name
+   * is not specified (<code>null</code>) then the human readable name
+   * will be the same as the MIME type. This is the same as calling
+   * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>.
+   *
+   * @param mimeType The MIME type for this flavor.
+   * @param humanPresentableName The display name of this flavor.
+   *
+   * @exception IllegalArgumentException If the representation class
+   * specified cannot be loaded.
+   */
+  public DataFlavor(String mimeType, String humanPresentableName)
+  {
+    this(getRepresentationClassFromMime (mimeType, null),
+        mimeType, humanPresentableName);
+  }
 
-/**
- * This method test the specified <code>DataFlavor</code> for equality
- * against this object.  This will be true if the MIME type and
- * representation type are the equal.
- *
- * @param flavor The <code>DataFlavor</code> to test against.
- *
- * @return <code>true</code> if the flavor is equal to this object,
- * <code>false</code> otherwise.
- */
-public boolean
-equals(DataFlavor flavor)
-{
-  if (flavor == null)
-    return(false);
+  /**
+   * Initializes a new instance of <code>DataFlavor</code> with the specified
+   * MIME type.  This type can have a "class=" parameter to specify the
+   * representation class, and then the class must exist or an exception will
+   * be thrown. If there is no "class=" parameter then the representation class
+   * will be <code>java.io.InputStream</code>. This is the same as calling
+   * <code>new DataFlavor(mimeType, null)</code>.
+   *
+   * @param mimeType The MIME type for this flavor.
+   *
+   * @exception IllegalArgumentException If a class is not specified in
+   * the MIME type.
+   * @exception ClassNotFoundException If the class cannot be loaded.
+   */
+  public DataFlavor(String mimeType) throws ClassNotFoundException
+  {
+    this(mimeType, null);
+  }
 
-  if (!this.mimeType.toLowerCase().equals(flavor.mimeType.toLowerCase()))
-    return(false);
+  /**
+   * Returns the MIME type of this flavor.
+   *
+   * @return The MIME type for this flavor.
+   */
+  public String getMimeType()
+  {
+    return(mimeType);
+  }
 
-  if (!this.representationClass.equals(flavor.representationClass))
-    return(false);
+  /**
+   * Returns the representation class for this flavor.
+   *
+   * @return The representation class for this flavor.
+   */
+  public Class getRepresentationClass()
+  {
+    return(representationClass);
+  }
 
-  return(true);
-}
+  /**
+   * Returns the human presentable name for this flavor.
+   *
+   * @return The human presentable name for this flavor.
+   */
+  public String getHumanPresentableName()
+  {
+    return(humanPresentableName);
+  } 
 
-/*************************************************************************/
+  /**
+   * Returns the primary MIME type for this flavor.
+   *
+   * @return The primary MIME type for this flavor.
+   */
+  public String getPrimaryType()
+  {
+    int idx = mimeType.indexOf("/");
+    if (idx == -1)
+      return(mimeType);
+  
+    return(mimeType.substring(0, idx));
+  }
 
-/**
- * This method test the specified <code>Object</code> for equality
- * against this object.  This will be true if the following conditions
- * are met:
- * <p>
- * <ul>
- * <li>The object is not <code>null</code>.</li>
- * <li>The object is an instance of <code>DataFlavor</code>.</li>
- * <li>The object's MIME type and representation class are equal to
- * this object's.</li>
- * </ul>
- *
- * @param obj The <code>Object</code> to test against.
- *
- * @return <code>true</code> if the flavor is equal to this object,
- * <code>false</code> otherwise.
- */
-public boolean
-equals(Object obj)
-{
-  if (!(obj instanceof DataFlavor))
-    return(false);
+  /**
+   * Returns the MIME subtype for this flavor.
+   *
+   * @return The MIME subtype for this flavor.
+   */
+  public String getSubType()
+  {
+    int start = mimeType.indexOf("/");
+    if (start == -1)
+      return "";
+  
+    int end = mimeType.indexOf(";", start + 1);
+    if (end == -1)
+      return mimeType.substring(start + 1);
+    else
+      return mimeType.substring(start + 1, end);
+  }
 
-  return(equals((DataFlavor)obj));
-}
+  /**
+   * Returns the value of the named MIME type parameter, or <code>null</code>
+   * if the parameter does not exist.
+   *
+   * @param paramName The name of the paramter.
+   *
+   * @return The value of the parameter.
+   */
+  public String getParameter(String paramName)
+  {
+    if ("humanPresentableName".equals(paramName))
+      return getHumanPresentableName();
+  
+    return getParameter(paramName, mimeType);
+  }
 
-/*************************************************************************/
+  /**
+   * Sets the human presentable name to the specified value.
+   *
+   * @param humanPresentableName The new display name.
+   */
+  public void setHumanPresentableName(String humanPresentableName)
+  {
+    this.humanPresentableName = humanPresentableName;
+  }
 
-/**
- * Tests whether or not the specified string is equal to the MIME type
- * of this object.
- *
- * @param str The string to test against.
- *
- * @return <code>true</code> if the string is equal to this object's MIME
- * type, <code>false</code> otherwise.
- *
- * @deprecated Not compatible with <code>hashCode()</code>.
- *             Use <code>isMimeTypeEqual()</code>
- */
-public boolean
-equals(String str)
-{
-  return(isMimeTypeEqual(str));
-}
+  /**
+   * Tests the MIME type of this object for equality against the specified
+   * MIME type. Ignores parameters.
+   *
+   * @param mimeType The MIME type to test against.
+   *
+   * @return <code>true</code> if the MIME type is equal to this object's
+   * MIME type (ignoring parameters), <code>false</code> otherwise.
+   *
+   * @exception NullPointerException If mimeType is null.
+   */
+  public boolean isMimeTypeEqual(String mimeType)
+  {
+    String mime = getMimeType();
+    int i = mime.indexOf(";");
+    if (i != -1)
+      mime = mime.substring(0, i);
+  
+    i = mimeType.indexOf(";");
+    if (i != -1)
+      mimeType = mimeType.substring(0, i);
+  
+    return mime.equals(mimeType);
+  }
 
-/*************************************************************************/
+  /**
+   * Tests the MIME type of this object for equality against the specified
+   * data flavor's MIME type
+   *
+   * @param flavor The flavor to test against.
+   *
+   * @return <code>true</code> if the flavor's MIME type is equal to this 
+   * object's MIME type, <code>false</code> otherwise.
+   */
+  public final boolean isMimeTypeEqual(DataFlavor flavor)
+  {
+    return isMimeTypeEqual(flavor.getMimeType());
+  }
 
-/**
* Returns the hash code for this data flavor.
- * The hash code is based on the (lower case) mime type and the
- * representation class.
- */
-public int
-hashCode()
-{
-  return(mimeType.toLowerCase().hashCode()^representationClass.hashCode());
-}
+  /**
  * Tests whether or not this flavor represents a serialized object.
+   *
+   * @return <code>true</code> if this flavor represents a serialized
+   * object, <code>false</code> otherwise.
+   */
+  public boolean isMimeTypeSerializedObject()
+  {
+    return mimeType.startsWith(javaSerializedObjectMimeType);
+  }
 
-/*************************************************************************/
+  /**
+   * Tests whether or not this flavor has a representation class of
+   * <code>java.io.InputStream</code>.
+   *
+   * @return <code>true</code> if the representation class of this flavor
+   * is <code>java.io.InputStream</code>, <code>false</code> otherwise.
+   */
+  public boolean isRepresentationClassInputStream()
+  {
+    return representationClass.getName().equals("java.io.InputStream");
+  }
 
-/**
- * Returns <code>true</code> when the given <code>DataFlavor</code>
- * matches this one.
- */
-public boolean
-match(DataFlavor dataFlavor)
-{
-  // XXX - How is this different from equals?
-  return(equals(dataFlavor));
-}
+  /**
+   * Tests whether the representation class for this flavor is
+   * serializable.
+   *
+   * @return <code>true</code> if the representation class is serializable,
+   * <code>false</code> otherwise.
+   */
+  public boolean isRepresentationClassSerializable()
+  {
+    Class[] interfaces = representationClass.getInterfaces();
+  
+    int i = 0;
+    while (i < interfaces.length)
+      {
+        if (interfaces[i].getName().equals("java.io.Serializable"))
+          return true;
+        ++i;
+      }
+  
+    return false;
+  }
 
-/*************************************************************************/
+  /**
+   * Tests whether the representation class for his flavor is remote.
+   *
+   * @return <code>true</code> if the representation class is remote,
+   * <code>false</code> otherwise.
+   */
+  public boolean isRepresentationClassRemote()
+  {
+    return Remote.class.isAssignableFrom (representationClass);
+  }
 
-/**
- * This method exists for backward compatibility.  It simply returns
- * the same name/value pair passed in.
- *
- * @param name The parameter name.
- * @param value The parameter value.
- *
- * @return The name/value pair.
- *
- * @deprecated
- */
-protected String
-normalizeMimeTypeParameter(String name, String value)
-{
-  return(name + "=" + value);
-}
+  /**
+   * Tests whether or not this flavor represents a serialized object.
+   *
+   * @return <code>true</code> if this flavor represents a serialized
+   * object, <code>false</code> otherwise.
+   */
+  public boolean isFlavorSerializedObjectType()
+  {
+    // FIXME: What is the diff between this and isMimeTypeSerializedObject?
+    return(mimeType.startsWith(javaSerializedObjectMimeType));
+  }
 
-/*************************************************************************/
+  /**
+   * Tests whether or not this flavor represents a remote object.
+   *
+   * @return <code>true</code> if this flavor represents a remote object,
+   * <code>false</code> otherwise.
+   */
+  public boolean isFlavorRemoteObjectType()
+  {
+    return(mimeType.startsWith(javaRemoteObjectMimeType));
+  }
 
-/**
- * This method exists for backward compatibility.  It simply returns
- * the MIME type string unchanged.
- *
- * @param type The MIME type.
- * 
- * @return The MIME type.
- *
- * @deprecated
- */
-protected String
-normalizeMimeType(String type)
-{
-  return(type);
-}
+  /**
+   * Tests whether or not this flavor represents a list of files.
+   *
+   * @return <code>true</code> if this flavor represents a list of files,
+   * <code>false</code> otherwise.
+   */
+  public boolean isFlavorJavaFileListType()
+  {
+    if (mimeType.equals(javaFileListFlavor.mimeType)
+        && representationClass.equals(javaFileListFlavor.representationClass))
+      return true;
+  
+    return false ;
+  }
 
-/*************************************************************************/
+  /**
+   * Returns a copy of this object.
+   *
+   * @return A copy of this object.
+   *
+   * @exception CloneNotSupportedException If the object's class does not support
+   * the Cloneable interface. Subclasses that override the clone method can also
+   * throw this exception to indicate that an instance cannot be cloned.
+   */
+  public Object clone () throws CloneNotSupportedException
+  {
+    // FIXME - This cannot be right.
+    try
+      {
+        return super.clone();
+      }
+    catch(Exception e)
+      {
+        return null;
+      }
+  }
 
-/**
- * Serialize this class.
- *
- * @param stream The <code>ObjectOutput</code> stream to serialize to.
- *
- * @exception IOException If an error occurs.
- */
-public void
-writeExternal(ObjectOutput stream) throws IOException
-{
-  // FIXME: Implement me
-}
+  /**
+   * This method test the specified <code>DataFlavor</code> for equality
+   * against this object.  This will be true if the MIME type and
+   * representation type are the equal.
+   *
+   * @param flavor The <code>DataFlavor</code> to test against.
+   *
+   * @return <code>true</code> if the flavor is equal to this object,
+   * <code>false</code> otherwise.
+   */
+  public boolean equals(DataFlavor flavor)
+  {
+    if (flavor == null)
+      return false;
+  
+    if (! this.mimeType.toLowerCase().equals(flavor.mimeType.toLowerCase()))
+      return false;
+  
+    if (! this.representationClass.equals(flavor.representationClass))
+      return false;
+  
+    return true;
+  }
 
-/*************************************************************************/
+  /**
+   * This method test the specified <code>Object</code> for equality
+   * against this object.  This will be true if the following conditions
+   * are met:
+   * <p>
+   * <ul>
+   * <li>The object is not <code>null</code>.</li>
+   * <li>The object is an instance of <code>DataFlavor</code>.</li>
+   * <li>The object's MIME type and representation class are equal to
+   * this object's.</li>
+   * </ul>
+   *
+   * @param obj The <code>Object</code> to test against.
+   *
+   * @return <code>true</code> if the flavor is equal to this object,
+   * <code>false</code> otherwise.
+   */
+  public boolean equals(Object obj)
+  {
+    if (! (obj instanceof DataFlavor))
+      return false;
+  
+    return equals((DataFlavor) obj);
+  }
 
-/**
- * De-serialize this class.
- *
- * @param stream The <code>ObjectInput</code> stream to deserialize from.
- *
- * @exception IOException If an error ocurs.
- * @exception ClassNotFoundException If the class for an object being restored
- * cannot be found.
- */
-public void
-readExternal(ObjectInput stream) throws IOException, ClassNotFoundException
-{
-  // FIXME: Implement me
-}
+  /**
+   * Tests whether or not the specified string is equal to the MIME type
+   * of this object.
+   *
+   * @param str The string to test against.
+   *
+   * @return <code>true</code> if the string is equal to this object's MIME
+   * type, <code>false</code> otherwise.
+   *
+   * @deprecated Not compatible with <code>hashCode()</code>.
+   *             Use <code>isMimeTypeEqual()</code>
+   */
+  public boolean equals(String str)
+  {
+    return isMimeTypeEqual(str);
+  }
 
-/*************************************************************************/
+  /**
+   * Returns the hash code for this data flavor.
+   * The hash code is based on the (lower case) mime type and the
+   * representation class.
+   */
+  public int hashCode()
+  {
+    return mimeType.toLowerCase().hashCode() ^ representationClass.hashCode();
+  }
 
-/**
- * Returns a string representation of this DataFlavor. Including the
- * representation class name, MIME type and human presentable name.
- */
-public String
-toString()
-{
-  return(getClass().getName()
-        + "[representationClass=" + getRepresentationClass().getName()
-         + ",mimeType=" + getMimeType()
-         + ",humanPresentableName=" + getHumanPresentableName()
-        + "]");
-}
+  /**
+   * Returns <code>true</code> when the given <code>DataFlavor</code>
+   * matches this one.
+   */
+  public boolean match(DataFlavor dataFlavor)
+  {
+    // XXX - How is this different from equals?
+    return equals(dataFlavor);
+  }
 
-/*************************************************************************/
+  /**
+   * This method exists for backward compatibility.  It simply returns
+   * the same name/value pair passed in.
+   *
+   * @param name The parameter name.
+   * @param value The parameter value.
+   *
+   * @return The name/value pair.
+   *
+   * @deprecated
+   */
+  protected String normalizeMimeTypeParameter(String name, String value)
+  {
+    return name + "=" + value;
+  }
 
-/**
- * XXX - Currently returns <code>plainTextFlavor</code>.
- */
-public static final DataFlavor
-getTextPlainUnicodeFlavor()
-{
-  return(plainTextFlavor);
-}
+  /**
+   * This method exists for backward compatibility.  It simply returns
+   * the MIME type string unchanged.
+   *
+   * @param type The MIME type.
+   * 
+   * @return The MIME type.
+   *
+   * @deprecated
+   */
+  protected String normalizeMimeType(String type)
+  {
+    return type;
+  }
 
-/*************************************************************************/
+  /**
+   * Serialize this class.
+   *
+   * @param stream The <code>ObjectOutput</code> stream to serialize to.
+   *
+   * @exception IOException If an error occurs.
+   */
+  public void writeExternal(ObjectOutput stream) throws IOException
+  {
+    // FIXME: Implement me
+  }
 
-/**
- * XXX - Currently returns <code>java.io.InputStream</code>.
- *
- * @since 1.3
- */
-public final Class
-getDefaultRepresentationClass()
-{
-  return(java.io.InputStream.class);
-}
-/*************************************************************************/
 
-/**
- * XXX - Currently returns <code>java.io.InputStream</code>.
- */
-public final String
-getDefaultRepresentationClassAsString()
-{
-  return(getDefaultRepresentationClass().getName());
-}
+  /**
+   * De-serialize this class.
+   *
+   * @param stream The <code>ObjectInput</code> stream to deserialize from.
+   *
+   * @exception IOException If an error ocurs.
+   * @exception ClassNotFoundException If the class for an object being restored
+   * cannot be found.
+   */
+  public void readExternal(ObjectInput stream) 
+    throws IOException, ClassNotFoundException
+  {
+    // FIXME: Implement me
+  }
 
-/*************************************************************************/
+  /**
+   * Returns a string representation of this DataFlavor. Including the
+   * representation class name, MIME type and human presentable name.
+   */
+  public String toString()
+  {
+    return (getClass().getName()
+           + "[representationClass=" + getRepresentationClass().getName()
+           + ",mimeType=" + getMimeType()
+           + ",humanPresentableName=" + getHumanPresentableName()
+           + "]");
+  }
 
-/**
- * Selects the best supported text flavor on this implementation.
- * Returns <code>null</code> when none of the given flavors is liked.
- *
- * The <code>DataFlavor</code> returned the first data flavor in the
- * array that has either a representation class which is (a subclass of)
- * <code>Reader</code> or <code>String</code>, or has a representation
- * class which is (a subclass of) <code>InputStream</code> and has a
- * primary MIME type of "text" and has an supported encoding.
- */
-public static final DataFlavor
-selectBestTextFlavor(DataFlavor[] availableFlavors)
-{
-  for(int i=0; i<availableFlavors.length; i++)
-    {
-      DataFlavor df = availableFlavors[i];
-      Class c = df.representationClass;
+  /**
+   * XXX - Currently returns <code>java.io.InputStream</code>.
+   *
+   * @since 1.3
+   */
+  public final Class getDefaultRepresentationClass()
+  {
+    return java.io.InputStream.class;
+  }
 
-      // A Reader or String is good.
-      if ((Reader.class.isAssignableFrom(c))
-         || (String.class.isAssignableFrom(c)))
-       {
-         return df;
-       }
+  /**
+   * XXX - Currently returns <code>java.io.InputStream</code>.
+   */
+  public final String getDefaultRepresentationClassAsString()
+  {
+    return getDefaultRepresentationClass().getName();
+  }
 
-      // A InputStream is good if the mime primary type is "text"
-      if ((InputStream.class.isAssignableFrom(c))
-         && ("text".equals(df.getPrimaryType())))
+  /**
+   * Creates a <code>Reader</code> for a given <code>Transferable</code>.
+   *
+   * If the representation class is a (subclass of) <code>Reader</code>
+   * then an instance of the representation class is returned. If the
+   * representatation class is a <code>String</code> then a
+   * <code>StringReader</code> is returned. And if the representation class
+   * is a (subclass of) <code>InputStream</code> and the primary MIME type
+   * is "text" then a <code>InputStreamReader</code> for the correct charset
+   * encoding is returned.
+   *
+   * @param transferable The <code>Transferable</code> for which a text
+   *                     <code>Reader</code> is requested.
+   *
+   * @exception IllegalArgumentException If the representation class is not one
+   * of the seven listed above or the Transferable has null data.
+   * @exception NullPointerException If the Transferable is null.
+   * @exception UnsupportedFlavorException when the transferable doesn't
+   * support this <code>DataFlavor</code>. Or if the representable class
+   * isn't a (subclass of) <code>Reader</code>, <code>String</code>,
+   * <code>InputStream</code> and/or the primary MIME type isn't "text".
+   * @exception IOException when any IOException occurs.
+   * @exception UnsupportedEncodingException if the "charset" isn't supported
+   * on this platform.
+   */
+  public Reader getReaderForText(Transferable transferable)
+    throws UnsupportedFlavorException, IOException
+  {
+      if (!transferable.isDataFlavorSupported(this))
+          throw new UnsupportedFlavorException(this);
+  
+      if (Reader.class.isAssignableFrom(representationClass))
+          return (Reader)transferable.getTransferData(this);
+  
+      if (String.class.isAssignableFrom(representationClass))
+          return new StringReader((String)transferable.getTransferData(this));
+  
+      if (InputStream.class.isAssignableFrom(representationClass)
+          && "text".equals(getPrimaryType()))
         {
-          String encoding = availableFlavors[i].getParameter("charset");
+          InputStream in = (InputStream)transferable.getTransferData(this);
+          String encoding = getParameter("charset");
           if (encoding == null)
-            encoding = "us-ascii";
-          Reader r = null;
-          try
-            {
-              // Try to construct a dummy reader with the found encoding
-              r = new InputStreamReader
-                    (new ByteArrayInputStream(new byte[0]), encoding);
-            }
-          catch(UnsupportedEncodingException uee) { /* ignore */ }
-          if (r != null)
-            return df;
+              encoding = "us-ascii";
+          return new InputStreamReader(in, encoding);
         }
-    }
-
-  // Nothing found
-  return(null);
-}
-
-/*************************************************************************/
-
-/**
- * Creates a <code>Reader</code> for a given <code>Transferable</code>.
- *
- * If the representation class is a (subclass of) <code>Reader</code>
- * then an instance of the representation class is returned. If the
- * representatation class is a <code>String</code> then a
- * <code>StringReader</code> is returned. And if the representation class
- * is a (subclass of) <code>InputStream</code> and the primary MIME type
- * is "text" then a <code>InputStreamReader</code> for the correct charset
- * encoding is returned.
- *
- * @param transferable The <code>Transferable</code> for which a text
- *                     <code>Reader</code> is requested.
- *
- * @exception IllegalArgumentException If the representation class is not one
- * of the seven listed above or the Transferable has null data.
- * @exception NullPointerException If the Transferable is null.
- * @exception UnsupportedFlavorException when the transferable doesn't
- * support this <code>DataFlavor</code>. Or if the representable class
- * isn't a (subclass of) <code>Reader</code>, <code>String</code>,
- * <code>InputStream</code> and/or the primary MIME type isn't "text".
- * @exception IOException when any IOException occurs.
- * @exception UnsupportedEncodingException if the "charset" isn't supported
- * on this platform.
- */
-public Reader getReaderForText(Transferable transferable)
-  throws UnsupportedFlavorException, IOException
-{
-    if (!transferable.isDataFlavorSupported(this))
-        throw new UnsupportedFlavorException(this);
-
-    if (Reader.class.isAssignableFrom(representationClass))
-        return((Reader)transferable.getTransferData(this));
-
-    if (String.class.isAssignableFrom(representationClass))
-        return(new StringReader((String)transferable.getTransferData(this)));
-
-    if (InputStream.class.isAssignableFrom(representationClass)
-        && "text".equals(getPrimaryType()))
-      {
-        InputStream in = (InputStream)transferable.getTransferData(this);
-        String encoding = getParameter("charset");
-        if (encoding == null)
-            encoding = "us-ascii";
-        return(new InputStreamReader(in, encoding));
-      }
-
-    throw new UnsupportedFlavorException(this);
-}
+  
+      throw new UnsupportedFlavorException(this);
+  }
 
   /**
    * Returns whether the representation class for this DataFlavor is
@@ -1010,9 +883,9 @@ public Reader getReaderForText(Transferable transferable)
    *
    * @since 1.4
    */
-  public boolean isRepresentationClassByteBuffer ()
+  public boolean isRepresentationClassByteBuffer()
   {
-    return ByteBuffer.class.isAssignableFrom (representationClass);
+    return ByteBuffer.class.isAssignableFrom(representationClass);
   }
 
   /**
@@ -1021,9 +894,9 @@ public Reader getReaderForText(Transferable transferable)
    *
    * @since 1.4
    */
-  public boolean isRepresentationClassCharBuffer ()
+  public boolean isRepresentationClassCharBuffer()
   {
-    return CharBuffer.class.isAssignableFrom (representationClass);
+    return CharBuffer.class.isAssignableFrom(representationClass);
   }
 
   /**
@@ -1032,10 +905,67 @@ public Reader getReaderForText(Transferable transferable)
    *
    * @since 1.4
    */
-  public boolean isRepresentationClassReader ()
+  public boolean isRepresentationClassReader()
   {
-    return Reader.class.isAssignableFrom (representationClass);
+    return Reader.class.isAssignableFrom(representationClass);
+  }
+  
+  /**
+   * Returns whether this <code>DataFlavor</code> is a valid text flavor for
+   * this implementation of the Java platform. Only flavors equivalent to
+   * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
+   * a primary MIME type of "text" can be valid text flavors.
+   * <p>
+   * If this flavor supports the charset parameter, it must be equivalent to
+   * <code>DataFlavor.stringFlavor</code>, or its representation must be
+   * <code>java.io.Reader</code>, <code>java.lang.String</code>,
+   * <code>java.nio.CharBuffer</code>, <code>java.io.InputStream</code> or 
+   * <code>java.nio.ByteBuffer</code>,
+   * If the representation is <code>java.io.InputStream</code> or 
+   * <code>java.nio.ByteBuffer</code>, then this flavor's <code>charset</code> 
+   * parameter must be supported by this implementation of the Java platform. 
+   * If a charset is not specified, then the platform default charset, which 
+   * is always supported, is assumed.
+   * <p>
+   * If this flavor does not support the charset parameter, its
+   * representation must be <code>java.io.InputStream</code>,
+   * <code>java.nio.ByteBuffer</code>.
+   * <p>
+   * See <code>selectBestTextFlavor</code> for a list of text flavors which
+   * support the charset parameter.
+   *
+   * @return <code>true</code> if this <code>DataFlavor</code> is a valid
+   *         text flavor as described above; <code>false</code> otherwise
+   * @see #selectBestTextFlavor
+   * @since 1.4
+   */
+  public boolean isFlavorTextType() {
+    // FIXME: I'm not 100% sure if this implementation does the same like sun's does    
+    if(equals(DataFlavor.stringFlavor) || getPrimaryType().equals("text"))
+      {
+        String charset = getParameter("charset");
+        Class c = getRepresentationClass();
+        if(charset != null) 
+          {            
+            if(Reader.class.isAssignableFrom(c) 
+                || CharBuffer.class.isAssignableFrom(c) 
+                || String.class.isAssignableFrom(c)) 
+              {
+                return true;
+              }
+            else if(InputStream.class.isAssignableFrom(c)
+                    || ByteBuffer.class.isAssignableFrom(c))
+              {
+                return Charset.isSupported(charset);
+              }
+          }
+        else if(InputStream.class.isAssignableFrom(c)
+            || ByteBuffer.class.isAssignableFrom(c))
+          {
+            return true;
+          }
+      }
+    return false;
   }
-
 } // class DataFlavor