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