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