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