Source for java.awt.datatransfer.DataFlavor

   1: /* DataFlavor.java -- A type of data to transfer via the clipboard.
   2:    Copyright (C) 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.awt.datatransfer;
  40: 
  41: import java.io.ByteArrayInputStream;
  42: import java.io.IOException;
  43: import java.io.InputStream;
  44: import java.io.InputStreamReader;
  45: import java.io.ObjectInput;
  46: import java.io.ObjectOutput;
  47: import java.io.Reader;
  48: import java.io.StringReader;
  49: import java.io.UnsupportedEncodingException;
  50: import java.nio.ByteBuffer;
  51: import java.nio.CharBuffer;
  52: import java.nio.charset.Charset;
  53: import java.rmi.Remote;
  54: 
  55: /**
  56:  * This class represents a particular data format used for transferring
  57:  * data via the clipboard.
  58:  *
  59:  * @author Aaron M. Renn (arenn@urbanophile.com)
  60:  */
  61: public class DataFlavor implements java.io.Externalizable, Cloneable
  62: {
  63:   static final long serialVersionUID = 8367026044764648243L;
  64: 
  65:   // FIXME: Serialization: Need to write methods for.
  66: 
  67:   /**
  68:    * This is the data flavor used for tranferring plain text.  The MIME
  69:    * type is "text/plain; charset=unicode".  The representation class
  70:    * is <code>java.io.InputStream</code>.
  71:    *
  72:    * @deprecated The charset unicode is platform specific and InputStream
  73:    * deals with bytes not chars. Use <code>getRederForText()</code>.
  74:    */
  75:   public static final DataFlavor plainTextFlavor = 
  76:     new DataFlavor(java.io.InputStream.class,
  77:                    "text/plain; charset=unicode",
  78:                    "plain unicode text");
  79: 
  80:   /**
  81:    * This is the data flavor used for transferring Java strings.  The
  82:    * MIME type is "application/x-java-serialized-object" and the 
  83:    * representation class is <code>java.lang.String</code>.
  84:    */
  85:   public static final DataFlavor stringFlavor = 
  86:     new DataFlavor(java.lang.String.class, "Java Unicode String");
  87: 
  88:   /**
  89:    * This is a data flavor used for transferring lists of files.  The
  90:    * representation type is a <code>java.util.List</code>, with each 
  91:    * element of the list being a <code>java.io.File</code>.
  92:    */
  93:   public static final DataFlavor javaFileListFlavor = 
  94:     new DataFlavor(java.util.List.class,
  95:                    "application/x-java-file-list; class=java.util.List",
  96:                    "Java File List");
  97: 
  98:   /**
  99:    * This is an image flavor used for transferring images.  The
 100:    * representation type is a <code>java.awt.Image</code>.
 101:    */
 102:   public static final DataFlavor imageFlavor = 
 103:     new DataFlavor(java.awt.Image.class, "Java Image");
 104: 
 105:   /**
 106:    * This is the MIME type used for transferring a serialized object.
 107:    * The representation class is the type of object be deserialized.
 108:    */
 109:   public static final String javaSerializedObjectMimeType =
 110:     "application/x-java-serialized-object";
 111: 
 112:   /**
 113:    * This is the MIME type used to transfer a Java object reference within
 114:    * the same JVM.  The representation class is the class of the object
 115:    * being transferred.
 116:    */
 117:   public static final String javaJVMLocalObjectMimeType =
 118:     "application/x-java-jvm-local-objectref";
 119: 
 120:   /**
 121:    * This is the MIME type used to transfer a link to a remote object.
 122:    * The representation class is the type of object being linked to.
 123:    */
 124:   public static final String javaRemoteObjectMimeType =
 125:     "application/x-java-remote-object";
 126: 
 127:   /*
 128:    * Instance Variables
 129:    */
 130:   
 131:   // The MIME type for this flavor
 132:   private final String mimeType;
 133:   
 134:   // The representation class for this flavor
 135:   private final Class representationClass;
 136:   
 137:   // The human readable name of this flavor
 138:   private String humanPresentableName;
 139: 
 140:   /*
 141:    * Static Methods
 142:    */
 143:   
 144:   /**
 145:    * This method attempts to load the named class.  The following class
 146:    * loaders are searched in order: the bootstrap class loader, the
 147:    * system class loader, the context class loader (if it exists), and
 148:    * the specified fallback class loader.
 149:    *
 150:    * @param className The name of the class to load.
 151:    * @param classLoader The class loader to use if all others fail, which
 152:    * may be <code>null</code>.
 153:    *
 154:    * @exception ClassNotFoundException If the class cannot be loaded.
 155:    */
 156:   protected static final Class tryToLoadClass(String className,
 157:                                              ClassLoader classLoader)
 158:     throws ClassNotFoundException
 159:   {
 160:     try
 161:       {
 162:         return(Class.forName(className));
 163:       }
 164:     catch(Exception e) { ; }
 165:     // Commented out for Java 1.1
 166:     /*
 167:     try
 168:       {
 169:         return(className.getClass().getClassLoader().findClass(className));
 170:       }
 171:     catch(Exception e) { ; }
 172:   
 173:     try
 174:       {
 175:         return(ClassLoader.getSystemClassLoader().findClass(className));
 176:       }
 177:     catch(Exception e) { ; }
 178:     */
 179:   
 180:     // FIXME: What is the context class loader?
 181:     /*
 182:     try
 183:       {
 184:       }
 185:     catch(Exception e) { ; }
 186:     */
 187:   
 188:     if (classLoader != null)
 189:       return(classLoader.loadClass(className));
 190:     else
 191:       throw new ClassNotFoundException(className);
 192:   }
 193:   
 194:   private static Class getRepresentationClassFromMime(String mimeString,
 195:                                                       ClassLoader classLoader)
 196:     {
 197:       String classname = getParameter("class", mimeString);
 198:       if (classname != null)
 199:         {
 200:           try
 201:             {
 202:               return tryToLoadClass(classname, classLoader);
 203:             }
 204:           catch(Exception e)
 205:             {
 206:               throw new IllegalArgumentException("classname: " + e.getMessage());
 207:             }
 208:         }
 209:       else
 210:         return java.io.InputStream.class;
 211:     }
 212:   
 213:   /**
 214:    * Returns the value of the named MIME type parameter, or <code>null</code>
 215:    * if the parameter does not exist. Given the parameter name and the mime
 216:    * string.
 217:    *
 218:    * @param paramName The name of the parameter.
 219:    * @param mimeString The mime string from where the name should be found.
 220:    *
 221:    * @return The value of the parameter or null.
 222:    */
 223:   private static String getParameter(String paramName, String mimeString)
 224:   {
 225:     int idx = mimeString.indexOf(paramName + "=");
 226:     if (idx == -1)
 227:       return(null);
 228:   
 229:     String value = mimeString.substring(idx + paramName.length() + 1);
 230:   
 231:     idx = value.indexOf(" ");
 232:     if (idx == -1)
 233:       return(value);
 234:     else
 235:       return(value.substring(0, idx));
 236:   }
 237:   
 238:   /**
 239:    * XXX - Currently returns <code>plainTextFlavor</code>.
 240:    */
 241:   public static final DataFlavor getTextPlainUnicodeFlavor()
 242:   {
 243:     return plainTextFlavor;
 244:   }
 245:   
 246:   /**
 247:    * Selects the best supported text flavor on this implementation.
 248:    * Returns <code>null</code> when none of the given flavors is liked.
 249:    *
 250:    * The <code>DataFlavor</code> returned the first data flavor in the
 251:    * array that has either a representation class which is (a subclass of)
 252:    * <code>Reader</code> or <code>String</code>, or has a representation
 253:    * class which is (a subclass of) <code>InputStream</code> and has a
 254:    * primary MIME type of "text" and has an supported encoding.
 255:    */
 256:   public static final DataFlavor 
 257:     selectBestTextFlavor(DataFlavor[] availableFlavors)
 258:   {
 259:     for(int i = 0; i < availableFlavors.length; i++)
 260:       {
 261:         DataFlavor df = availableFlavors[i];
 262:         Class c = df.representationClass;
 263:   
 264:         // A Reader or String is good.
 265:         if ((Reader.class.isAssignableFrom(c))
 266:            || (String.class.isAssignableFrom(c)))
 267:       return df;
 268:   
 269:         // A InputStream is good if the mime primary type is "text"
 270:         if ((InputStream.class.isAssignableFrom(c))
 271:            && ("text".equals(df.getPrimaryType())))
 272:           {
 273:             String encoding = availableFlavors[i].getParameter("charset");
 274:             if (encoding == null)
 275:               encoding = "us-ascii";
 276:             Reader r = null;
 277:             try
 278:               {
 279:                 // Try to construct a dummy reader with the found encoding
 280:                 r = new InputStreamReader
 281:                       (new ByteArrayInputStream(new byte[0]), encoding);
 282:               }
 283:             catch(UnsupportedEncodingException uee) { /* ignore */ }
 284: 
 285:             if (r != null)
 286:               return df;
 287:           }
 288:       }
 289:   
 290:     // Nothing found
 291:     return null;
 292:   }
 293: 
 294: 
 295:   /*
 296:    * Constructors
 297:    */
 298:   
 299:   /**
 300:    * Empty public constructor needed for externalization.
 301:    * Should not be used for normal instantiation.
 302:    */
 303:   public DataFlavor()
 304:   {
 305:     mimeType = null;
 306:     representationClass = null;
 307:     humanPresentableName = null;
 308:   }
 309: 
 310:   /**
 311:    * Private constructor.
 312:    */
 313:   private DataFlavor(Class representationClass,
 314:                     String mimeType,
 315:                     String humanPresentableName)
 316:   {
 317:     this.representationClass = representationClass;
 318:     this.mimeType = mimeType;
 319:     if (humanPresentableName != null)
 320:       this.humanPresentableName = humanPresentableName;
 321:     else
 322:       this.humanPresentableName = mimeType;
 323:   }
 324: 
 325:   /**
 326:    * Initializes a new instance of <code>DataFlavor</code>.  The class
 327:    * and human readable name are specified, the MIME type will be
 328:    * "application/x-java-serialized-object". If the human readable name
 329:    * is not specified (<code>null</code>) then the human readable name
 330:    * will be the same as the MIME type.
 331:    *
 332:    * @param representationClass The representation class for this object.
 333:    * @param humanPresentableName The display name of the object.
 334:    */
 335:   public DataFlavor(Class representationClass, String humanPresentableName)
 336:   {
 337:     this(representationClass,
 338:          "application/x-java-serialized-object"
 339:          + "; class="
 340:          + representationClass.getName(),
 341:          humanPresentableName);
 342:   }
 343: 
 344:   /**
 345:    * Initializes a new instance of <code>DataFlavor</code> with the
 346:    * specified MIME type and description.  If the MIME type has a
 347:    * "class=&lt;rep class&gt;" parameter then the representation class will
 348:    * be the class name specified. Otherwise the class defaults to
 349:    * <code>java.io.InputStream</code>. If the human readable name
 350:    * is not specified (<code>null</code>) then the human readable name
 351:    * will be the same as the MIME type.
 352:    *
 353:    * @param mimeType The MIME type for this flavor.
 354:    * @param humanPresentableName The display name of this flavor.
 355:    * @param classLoader The class loader for finding classes if the default
 356:    * class loaders do not work.
 357:    *
 358:    * @exception IllegalArgumentException If the representation class
 359:    * specified cannot be loaded.
 360:    * @exception ClassNotFoundException If the class is not loaded.
 361:    */
 362:   public DataFlavor(String mimeType, String humanPresentableName, 
 363:                    ClassLoader classLoader)
 364:     throws ClassNotFoundException
 365:   {
 366:     this(getRepresentationClassFromMime(mimeType, classLoader),
 367:          mimeType, humanPresentableName);
 368:   }
 369: 
 370:   /**
 371:    * Initializes a new instance of <code>DataFlavor</code> with the
 372:    * specified MIME type and description.  If the MIME type has a
 373:    * "class=&lt;rep class&gt;" parameter then the representation class will
 374:    * be the class name specified. Otherwise the class defaults to
 375:    * <code>java.io.InputStream</code>. If the human readable name
 376:    * is not specified (<code>null</code>) then the human readable name
 377:    * will be the same as the MIME type. This is the same as calling
 378:    * <code>new DataFlavor(mimeType, humanPresentableName, null)</code>.
 379:    *
 380:    * @param mimeType The MIME type for this flavor.
 381:    * @param humanPresentableName The display name of this flavor.
 382:    *
 383:    * @exception IllegalArgumentException If the representation class
 384:    * specified cannot be loaded.
 385:    */
 386:   public DataFlavor(String mimeType, String humanPresentableName)
 387:   {
 388:     this(getRepresentationClassFromMime (mimeType, null),
 389:         mimeType, humanPresentableName);
 390:   }
 391: 
 392:   /**
 393:    * Initializes a new instance of <code>DataFlavor</code> with the specified
 394:    * MIME type.  This type can have a "class=" parameter to specify the
 395:    * representation class, and then the class must exist or an exception will
 396:    * be thrown. If there is no "class=" parameter then the representation class
 397:    * will be <code>java.io.InputStream</code>. This is the same as calling
 398:    * <code>new DataFlavor(mimeType, null)</code>.
 399:    *
 400:    * @param mimeType The MIME type for this flavor.
 401:    *
 402:    * @exception IllegalArgumentException If a class is not specified in
 403:    * the MIME type.
 404:    * @exception ClassNotFoundException If the class cannot be loaded.
 405:    */
 406:   public DataFlavor(String mimeType) throws ClassNotFoundException
 407:   {
 408:     this(mimeType, null);
 409:   }
 410: 
 411:   /**
 412:    * Returns the MIME type of this flavor.
 413:    *
 414:    * @return The MIME type for this flavor.
 415:    */
 416:   public String getMimeType()
 417:   {
 418:     return(mimeType);
 419:   }
 420: 
 421:   /**
 422:    * Returns the representation class for this flavor.
 423:    *
 424:    * @return The representation class for this flavor.
 425:    */
 426:   public Class getRepresentationClass()
 427:   {
 428:     return(representationClass);
 429:   }
 430: 
 431:   /**
 432:    * Returns the human presentable name for this flavor.
 433:    *
 434:    * @return The human presentable name for this flavor.
 435:    */
 436:   public String getHumanPresentableName()
 437:   {
 438:     return(humanPresentableName);
 439:   } 
 440: 
 441:   /**
 442:    * Returns the primary MIME type for this flavor.
 443:    *
 444:    * @return The primary MIME type for this flavor.
 445:    */
 446:   public String getPrimaryType()
 447:   {
 448:     int idx = mimeType.indexOf("/");
 449:     if (idx == -1)
 450:       return(mimeType);
 451:   
 452:     return(mimeType.substring(0, idx));
 453:   }
 454: 
 455:   /**
 456:    * Returns the MIME subtype for this flavor.
 457:    *
 458:    * @return The MIME subtype for this flavor.
 459:    */
 460:   public String getSubType()
 461:   {
 462:     int start = mimeType.indexOf("/");
 463:     if (start == -1)
 464:       return "";
 465:   
 466:     int end = mimeType.indexOf(";", start + 1);
 467:     if (end == -1)
 468:       return mimeType.substring(start + 1);
 469:     else
 470:       return mimeType.substring(start + 1, end);
 471:   }
 472: 
 473:   /**
 474:    * Returns the value of the named MIME type parameter, or <code>null</code>
 475:    * if the parameter does not exist.
 476:    *
 477:    * @param paramName The name of the paramter.
 478:    *
 479:    * @return The value of the parameter.
 480:    */
 481:   public String getParameter(String paramName)
 482:   {
 483:     if ("humanPresentableName".equals(paramName))
 484:       return getHumanPresentableName();
 485:   
 486:     return getParameter(paramName, mimeType);
 487:   }
 488: 
 489:   /**
 490:    * Sets the human presentable name to the specified value.
 491:    *
 492:    * @param humanPresentableName The new display name.
 493:    */
 494:   public void setHumanPresentableName(String humanPresentableName)
 495:   {
 496:     this.humanPresentableName = humanPresentableName;
 497:   }
 498: 
 499:   /**
 500:    * Tests the MIME type of this object for equality against the specified
 501:    * MIME type. Ignores parameters.
 502:    *
 503:    * @param mimeType The MIME type to test against.
 504:    *
 505:    * @return <code>true</code> if the MIME type is equal to this object's
 506:    * MIME type (ignoring parameters), <code>false</code> otherwise.
 507:    *
 508:    * @exception NullPointerException If mimeType is null.
 509:    */
 510:   public boolean isMimeTypeEqual(String mimeType)
 511:   {
 512:     String mime = getMimeType();
 513:     int i = mime.indexOf(";");
 514:     if (i != -1)
 515:       mime = mime.substring(0, i);
 516:   
 517:     i = mimeType.indexOf(";");
 518:     if (i != -1)
 519:       mimeType = mimeType.substring(0, i);
 520:   
 521:     return mime.equals(mimeType);
 522:   }
 523: 
 524:   /**
 525:    * Tests the MIME type of this object for equality against the specified
 526:    * data flavor's MIME type
 527:    *
 528:    * @param flavor The flavor to test against.
 529:    *
 530:    * @return <code>true</code> if the flavor's MIME type is equal to this 
 531:    * object's MIME type, <code>false</code> otherwise.
 532:    */
 533:   public final boolean isMimeTypeEqual(DataFlavor flavor)
 534:   {
 535:     return isMimeTypeEqual(flavor.getMimeType());
 536:   }
 537: 
 538:   /**
 539:    * Tests whether or not this flavor represents a serialized object.
 540:    *
 541:    * @return <code>true</code> if this flavor represents a serialized
 542:    * object, <code>false</code> otherwise.
 543:    */
 544:   public boolean isMimeTypeSerializedObject()
 545:   {
 546:     return mimeType.startsWith(javaSerializedObjectMimeType);
 547:   }
 548: 
 549:   /**
 550:    * Tests whether or not this flavor has a representation class of
 551:    * <code>java.io.InputStream</code>.
 552:    *
 553:    * @return <code>true</code> if the representation class of this flavor
 554:    * is <code>java.io.InputStream</code>, <code>false</code> otherwise.
 555:    */
 556:   public boolean isRepresentationClassInputStream()
 557:   {
 558:     return representationClass.getName().equals("java.io.InputStream");
 559:   }
 560: 
 561:   /**
 562:    * Tests whether the representation class for this flavor is
 563:    * serializable.
 564:    *
 565:    * @return <code>true</code> if the representation class is serializable,
 566:    * <code>false</code> otherwise.
 567:    */
 568:   public boolean isRepresentationClassSerializable()
 569:   {
 570:     Class[] interfaces = representationClass.getInterfaces();
 571:   
 572:     int i = 0;
 573:     while (i < interfaces.length)
 574:       {
 575:         if (interfaces[i].getName().equals("java.io.Serializable"))
 576:           return true;
 577:         ++i;
 578:       }
 579:   
 580:     return false;
 581:   }
 582: 
 583:   /**
 584:    * Tests whether the representation class for his flavor is remote.
 585:    *
 586:    * @return <code>true</code> if the representation class is remote,
 587:    * <code>false</code> otherwise.
 588:    */
 589:   public boolean isRepresentationClassRemote()
 590:   {
 591:     return Remote.class.isAssignableFrom (representationClass);
 592:   }
 593: 
 594:   /**
 595:    * Tests whether or not this flavor represents a serialized object.
 596:    *
 597:    * @return <code>true</code> if this flavor represents a serialized
 598:    * object, <code>false</code> otherwise.
 599:    */
 600:   public boolean isFlavorSerializedObjectType()
 601:   {
 602:     // FIXME: What is the diff between this and isMimeTypeSerializedObject?
 603:     return(mimeType.startsWith(javaSerializedObjectMimeType));
 604:   }
 605: 
 606:   /**
 607:    * Tests whether or not this flavor represents a remote object.
 608:    *
 609:    * @return <code>true</code> if this flavor represents a remote object,
 610:    * <code>false</code> otherwise.
 611:    */
 612:   public boolean isFlavorRemoteObjectType()
 613:   {
 614:     return(mimeType.startsWith(javaRemoteObjectMimeType));
 615:   }
 616: 
 617:   /**
 618:    * Tests whether or not this flavor represents a list of files.
 619:    *
 620:    * @return <code>true</code> if this flavor represents a list of files,
 621:    * <code>false</code> otherwise.
 622:    */
 623:   public boolean isFlavorJavaFileListType()
 624:   {
 625:     if (mimeType.equals(javaFileListFlavor.mimeType)
 626:         && representationClass.equals(javaFileListFlavor.representationClass))
 627:       return true;
 628:   
 629:     return false ;
 630:   }
 631: 
 632:   /**
 633:    * Returns a copy of this object.
 634:    *
 635:    * @return A copy of this object.
 636:    *
 637:    * @exception CloneNotSupportedException If the object's class does not support
 638:    * the Cloneable interface. Subclasses that override the clone method can also
 639:    * throw this exception to indicate that an instance cannot be cloned.
 640:    */
 641:   public Object clone () throws CloneNotSupportedException
 642:   {
 643:     // FIXME - This cannot be right.
 644:     try
 645:       {
 646:         return super.clone();
 647:       }
 648:     catch(Exception e)
 649:       {
 650:         return null;
 651:       }
 652:   }
 653: 
 654:   /**
 655:    * This method test the specified <code>DataFlavor</code> for equality
 656:    * against this object.  This will be true if the MIME type and
 657:    * representation type are the equal.
 658:    *
 659:    * @param flavor The <code>DataFlavor</code> to test against.
 660:    *
 661:    * @return <code>true</code> if the flavor is equal to this object,
 662:    * <code>false</code> otherwise.
 663:    */
 664:   public boolean equals(DataFlavor flavor)
 665:   {
 666:     if (flavor == null)
 667:       return false;
 668:   
 669:     if (! this.mimeType.toLowerCase().equals(flavor.mimeType.toLowerCase()))
 670:       return false;
 671:   
 672:     if (! this.representationClass.equals(flavor.representationClass))
 673:       return false;
 674:   
 675:     return true;
 676:   }
 677: 
 678:   /**
 679:    * This method test the specified <code>Object</code> for equality
 680:    * against this object.  This will be true if the following conditions
 681:    * are met:
 682:    * <p>
 683:    * <ul>
 684:    * <li>The object is not <code>null</code>.</li>
 685:    * <li>The object is an instance of <code>DataFlavor</code>.</li>
 686:    * <li>The object's MIME type and representation class are equal to
 687:    * this object's.</li>
 688:    * </ul>
 689:    *
 690:    * @param obj The <code>Object</code> to test against.
 691:    *
 692:    * @return <code>true</code> if the flavor is equal to this object,
 693:    * <code>false</code> otherwise.
 694:    */
 695:   public boolean equals(Object obj)
 696:   {
 697:     if (! (obj instanceof DataFlavor))
 698:       return false;
 699:   
 700:     return equals((DataFlavor) obj);
 701:   }
 702: 
 703:   /**
 704:    * Tests whether or not the specified string is equal to the MIME type
 705:    * of this object.
 706:    *
 707:    * @param str The string to test against.
 708:    *
 709:    * @return <code>true</code> if the string is equal to this object's MIME
 710:    * type, <code>false</code> otherwise.
 711:    *
 712:    * @deprecated Not compatible with <code>hashCode()</code>.
 713:    *             Use <code>isMimeTypeEqual()</code>
 714:    */
 715:   public boolean equals(String str)
 716:   {
 717:     return isMimeTypeEqual(str);
 718:   }
 719: 
 720:   /**
 721:    * Returns the hash code for this data flavor.
 722:    * The hash code is based on the (lower case) mime type and the
 723:    * representation class.
 724:    */
 725:   public int hashCode()
 726:   {
 727:     return mimeType.toLowerCase().hashCode() ^ representationClass.hashCode();
 728:   }
 729: 
 730:   /**
 731:    * Returns <code>true</code> when the given <code>DataFlavor</code>
 732:    * matches this one.
 733:    */
 734:   public boolean match(DataFlavor dataFlavor)
 735:   {
 736:     // XXX - How is this different from equals?
 737:     return equals(dataFlavor);
 738:   }
 739: 
 740:   /**
 741:    * This method exists for backward compatibility.  It simply returns
 742:    * the same name/value pair passed in.
 743:    *
 744:    * @param name The parameter name.
 745:    * @param value The parameter value.
 746:    *
 747:    * @return The name/value pair.
 748:    *
 749:    * @deprecated
 750:    */
 751:   protected String normalizeMimeTypeParameter(String name, String value)
 752:   {
 753:     return name + "=" + value;
 754:   }
 755: 
 756:   /**
 757:    * This method exists for backward compatibility.  It simply returns
 758:    * the MIME type string unchanged.
 759:    *
 760:    * @param type The MIME type.
 761:    * 
 762:    * @return The MIME type.
 763:    *
 764:    * @deprecated
 765:    */
 766:   protected String normalizeMimeType(String type)
 767:   {
 768:     return type;
 769:   }
 770: 
 771:   /**
 772:    * Serialize this class.
 773:    *
 774:    * @param stream The <code>ObjectOutput</code> stream to serialize to.
 775:    *
 776:    * @exception IOException If an error occurs.
 777:    */
 778:   public void writeExternal(ObjectOutput stream) throws IOException
 779:   {
 780:     // FIXME: Implement me
 781:   }
 782: 
 783: 
 784:   /**
 785:    * De-serialize this class.
 786:    *
 787:    * @param stream The <code>ObjectInput</code> stream to deserialize from.
 788:    *
 789:    * @exception IOException If an error ocurs.
 790:    * @exception ClassNotFoundException If the class for an object being restored
 791:    * cannot be found.
 792:    */
 793:   public void readExternal(ObjectInput stream) 
 794:     throws IOException, ClassNotFoundException
 795:   {
 796:     // FIXME: Implement me
 797:   }
 798: 
 799:   /**
 800:    * Returns a string representation of this DataFlavor. Including the
 801:    * representation class name, MIME type and human presentable name.
 802:    */
 803:   public String toString()
 804:   {
 805:     return (getClass().getName()
 806:            + "[representationClass=" + getRepresentationClass().getName()
 807:            + ",mimeType=" + getMimeType()
 808:            + ",humanPresentableName=" + getHumanPresentableName()
 809:            + "]");
 810:   }
 811: 
 812:   /**
 813:    * XXX - Currently returns <code>java.io.InputStream</code>.
 814:    *
 815:    * @since 1.3
 816:    */
 817:   public final Class getDefaultRepresentationClass()
 818:   {
 819:     return java.io.InputStream.class;
 820:   }
 821: 
 822:   /**
 823:    * XXX - Currently returns <code>java.io.InputStream</code>.
 824:    */
 825:   public final String getDefaultRepresentationClassAsString()
 826:   {
 827:     return getDefaultRepresentationClass().getName();
 828:   }
 829: 
 830:   /**
 831:    * Creates a <code>Reader</code> for a given <code>Transferable</code>.
 832:    *
 833:    * If the representation class is a (subclass of) <code>Reader</code>
 834:    * then an instance of the representation class is returned. If the
 835:    * representatation class is a <code>String</code> then a
 836:    * <code>StringReader</code> is returned. And if the representation class
 837:    * is a (subclass of) <code>InputStream</code> and the primary MIME type
 838:    * is "text" then a <code>InputStreamReader</code> for the correct charset
 839:    * encoding is returned.
 840:    *
 841:    * @param transferable The <code>Transferable</code> for which a text
 842:    *                     <code>Reader</code> is requested.
 843:    *
 844:    * @exception IllegalArgumentException If the representation class is not one
 845:    * of the seven listed above or the Transferable has null data.
 846:    * @exception NullPointerException If the Transferable is null.
 847:    * @exception UnsupportedFlavorException when the transferable doesn't
 848:    * support this <code>DataFlavor</code>. Or if the representable class
 849:    * isn't a (subclass of) <code>Reader</code>, <code>String</code>,
 850:    * <code>InputStream</code> and/or the primary MIME type isn't "text".
 851:    * @exception IOException when any IOException occurs.
 852:    * @exception UnsupportedEncodingException if the "charset" isn't supported
 853:    * on this platform.
 854:    */
 855:   public Reader getReaderForText(Transferable transferable)
 856:     throws UnsupportedFlavorException, IOException
 857:   {
 858:       if (!transferable.isDataFlavorSupported(this))
 859:           throw new UnsupportedFlavorException(this);
 860:   
 861:       if (Reader.class.isAssignableFrom(representationClass))
 862:           return (Reader)transferable.getTransferData(this);
 863:   
 864:       if (String.class.isAssignableFrom(representationClass))
 865:           return new StringReader((String)transferable.getTransferData(this));
 866:   
 867:       if (InputStream.class.isAssignableFrom(representationClass)
 868:           && "text".equals(getPrimaryType()))
 869:         {
 870:           InputStream in = (InputStream)transferable.getTransferData(this);
 871:           String encoding = getParameter("charset");
 872:           if (encoding == null)
 873:               encoding = "us-ascii";
 874:           return new InputStreamReader(in, encoding);
 875:         }
 876:   
 877:       throw new UnsupportedFlavorException(this);
 878:   }
 879: 
 880:   /**
 881:    * Returns whether the representation class for this DataFlavor is
 882:    * @see java.nio.ByteBuffer or a subclass thereof.
 883:    *
 884:    * @since 1.4
 885:    */
 886:   public boolean isRepresentationClassByteBuffer()
 887:   {
 888:     return ByteBuffer.class.isAssignableFrom(representationClass);
 889:   }
 890: 
 891:   /**
 892:    * Returns whether the representation class for this DataFlavor is
 893:    * @see java.nio.CharBuffer or a subclass thereof.
 894:    *
 895:    * @since 1.4
 896:    */
 897:   public boolean isRepresentationClassCharBuffer()
 898:   {
 899:     return CharBuffer.class.isAssignableFrom(representationClass);
 900:   }
 901: 
 902:   /**
 903:    * Returns whether the representation class for this DataFlavor is
 904:    * @see java.io.Reader or a subclass thereof.
 905:    *
 906:    * @since 1.4
 907:    */
 908:   public boolean isRepresentationClassReader()
 909:   {
 910:     return Reader.class.isAssignableFrom(representationClass);
 911:   }
 912:   
 913:   /**
 914:    * Returns whether this <code>DataFlavor</code> is a valid text flavor for
 915:    * this implementation of the Java platform. Only flavors equivalent to
 916:    * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
 917:    * a primary MIME type of "text" can be valid text flavors.
 918:    * <p>
 919:    * If this flavor supports the charset parameter, it must be equivalent to
 920:    * <code>DataFlavor.stringFlavor</code>, or its representation must be
 921:    * <code>java.io.Reader</code>, <code>java.lang.String</code>,
 922:    * <code>java.nio.CharBuffer</code>, <code>java.io.InputStream</code> or 
 923:    * <code>java.nio.ByteBuffer</code>,
 924:    * If the representation is <code>java.io.InputStream</code> or 
 925:    * <code>java.nio.ByteBuffer</code>, then this flavor's <code>charset</code> 
 926:    * parameter must be supported by this implementation of the Java platform. 
 927:    * If a charset is not specified, then the platform default charset, which 
 928:    * is always supported, is assumed.
 929:    * <p>
 930:    * If this flavor does not support the charset parameter, its
 931:    * representation must be <code>java.io.InputStream</code>,
 932:    * <code>java.nio.ByteBuffer</code>.
 933:    * <p>
 934:    * See <code>selectBestTextFlavor</code> for a list of text flavors which
 935:    * support the charset parameter.
 936:    *
 937:    * @return <code>true</code> if this <code>DataFlavor</code> is a valid
 938:    *         text flavor as described above; <code>false</code> otherwise
 939:    * @see #selectBestTextFlavor
 940:    * @since 1.4
 941:    */
 942:   public boolean isFlavorTextType() {
 943:     // FIXME: I'm not 100% sure if this implementation does the same like sun's does    
 944:     if(equals(DataFlavor.stringFlavor) || getPrimaryType().equals("text"))
 945:       {
 946:         String charset = getParameter("charset");
 947:         Class c = getRepresentationClass();
 948:         if(charset != null) 
 949:           {            
 950:             if(Reader.class.isAssignableFrom(c) 
 951:                 || CharBuffer.class.isAssignableFrom(c) 
 952:                 || String.class.isAssignableFrom(c)) 
 953:               {
 954:                 return true;
 955:               }
 956:             else if(InputStream.class.isAssignableFrom(c)
 957:                     || ByteBuffer.class.isAssignableFrom(c))
 958:               {
 959:                 return Charset.isSupported(charset);
 960:               }
 961:           }
 962:         else if(InputStream.class.isAssignableFrom(c)
 963:             || ByteBuffer.class.isAssignableFrom(c))
 964:           {
 965:             return true;
 966:           }
 967:       }
 968:     return false;
 969:   }
 970: } // class DataFlavor