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