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