OSDN Git Service

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