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