Source for java.awt.datatransfer.DataFlavor

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