History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/awt/datatransfer (36 of 18352 files). Show all

Unified · Split

36 files
  1. java/pkg/java/awt/datatransfer/Clipboard$1.class +0 −0
  2. java/pkg/java/awt/datatransfer/Clipboard$2.class +0 −0
  3. java/pkg/java/awt/datatransfer/Clipboard.class +0 −0
  4. java/pkg/java/awt/datatransfer/Clipboard.java +354 −0
  5. java/pkg/java/awt/datatransfer/ClipboardOwner.class +0 −0
  6. java/pkg/java/awt/datatransfer/ClipboardOwner.java +56 −0
  7. java/pkg/java/awt/datatransfer/DataFlavor$1.class +0 −0
  8. java/pkg/java/awt/datatransfer/DataFlavor$TextFlavorComparator.class +0 −0
  9. java/pkg/java/awt/datatransfer/DataFlavor.class +0 −0
  10. java/pkg/java/awt/datatransfer/DataFlavor.java +1381 −0
  11. java/pkg/java/awt/datatransfer/FlavorEvent.class +0 −0
  12. java/pkg/java/awt/datatransfer/FlavorEvent.java +51 −0
  13. java/pkg/java/awt/datatransfer/FlavorListener.class +0 −0
  14. java/pkg/java/awt/datatransfer/FlavorListener.java +55 −0
  15. java/pkg/java/awt/datatransfer/FlavorMap.class +0 −0
  16. java/pkg/java/awt/datatransfer/FlavorMap.java +75 −0
  17. java/pkg/java/awt/datatransfer/FlavorTable.class +0 −0
  18. java/pkg/java/awt/datatransfer/FlavorTable.java +82 −0
  19. java/pkg/java/awt/datatransfer/MimeType.class +0 −0
  20. java/pkg/java/awt/datatransfer/MimeType.java +393 −0
  21. java/pkg/java/awt/datatransfer/MimeTypeParameterList.class +0 −0
  22. java/pkg/java/awt/datatransfer/MimeTypeParameterList.java +404 −0
  23. java/pkg/java/awt/datatransfer/MimeTypeParseException.class +0 −0
  24. java/pkg/java/awt/datatransfer/MimeTypeParseException.java +55 −0
  25. java/pkg/java/awt/datatransfer/StringSelection.class +0 −0
  26. java/pkg/java/awt/datatransfer/StringSelection.java +140 −0
  27. java/pkg/java/awt/datatransfer/SystemFlavorMap$1.class +0 −0
  28. java/pkg/java/awt/datatransfer/SystemFlavorMap$2.class +0 −0
  29. java/pkg/java/awt/datatransfer/SystemFlavorMap.class +0 −0
  30. java/pkg/java/awt/datatransfer/SystemFlavorMap.java +1299 −0
  31. java/pkg/java/awt/datatransfer/Transferable.class +0 −0
  32. java/pkg/java/awt/datatransfer/Transferable.java +73 −0
  33. java/pkg/java/awt/datatransfer/UnsupportedFlavorException.class +0 −0
  34. java/pkg/java/awt/datatransfer/UnsupportedFlavorException.java +50 −0
  35. java/pkg/java/awt/datatransfer/mkfile +21 −0
  36. java/pkg/java/awt/datatransfer/package.html +63 −0
java/pkg/java/awt/datatransfer/Clipboard$1.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/Clipboard$2.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/Clipboard.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/Clipboard.java+354−0
@@ -0,0 +1,354 @@
1/*
2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.awt.EventQueue;
29
30import java.util.Set;
31import java.util.HashSet;
32import java.util.Arrays;
33
34import java.io.IOException;
35
36import sun.awt.EventListenerAggregate;
37
38
39/**
40 * A class that implements a mechanism to transfer data using
41 * cut/copy/paste operations.
42 * <p>
43 * {@link FlavorListener}s may be registered on an instance of the
44 * Clipboard class to be notified about changes to the set of
45 * {@link DataFlavor}s available on this clipboard (see
46 * {@link #addFlavorListener}).
47 *
48 * @see java.awt.Toolkit#getSystemClipboard
49 * @see java.awt.Toolkit#getSystemSelection
50 *
51 * @author Amy Fowler
52 * @author Alexander Gerasimov
53 */
54public class Clipboard {
55
56 String name;
57
58 protected ClipboardOwner owner;
59 protected Transferable contents;
60
61 /**
62 * An aggregate of flavor listeners registered on this local clipboard.
63 *
64 * @since 1.5
65 */
66 private EventListenerAggregate flavorListeners;
67
68 /**
69 * A set of <code>DataFlavor</code>s that is available on
70 * this local clipboard. It is used for tracking changes
71 * of <code>DataFlavor</code>s available on this clipboard.
72 *
73 * @since 1.5
74 */
75 private Set currentDataFlavors;
76
77 /**
78 * Creates a clipboard object.
79 *
80 * @see java.awt.Toolkit#getSystemClipboard
81 */
82 public Clipboard(String name) {
83 this.name = name;
84 }
85
86 /**
87 * Returns the name of this clipboard object.
88 *
89 * @see java.awt.Toolkit#getSystemClipboard
90 */
91 public String getName() {
92 return name;
93 }
94
95 /**
96 * Sets the current contents of the clipboard to the specified
97 * transferable object and registers the specified clipboard owner
98 * as the owner of the new contents.
99 * <p>
100 * If there is an existing owner different from the argument
101 * <code>owner</code>, that owner is notified that it no longer
102 * holds ownership of the clipboard contents via an invocation
103 * of <code>ClipboardOwner.lostOwnership()</code> on that owner.
104 * An implementation of <code>setContents()</code> is free not
105 * to invoke <code>lostOwnership()</code> directly from this method.
106 * For example, <code>lostOwnership()</code> may be invoked later on
107 * a different thread. The same applies to <code>FlavorListener</code>s
108 * registered on this clipboard.
109 * <p>
110 * The method throws <code>IllegalStateException</code> if the clipboard
111 * is currently unavailable. For example, on some platforms, the system
112 * clipboard is unavailable while it is accessed by another application.
113 *
114 * @param contents the transferable object representing the
115 * clipboard content
116 * @param owner the object which owns the clipboard content
117 * @throws IllegalStateException if the clipboard is currently unavailable
118 * @see java.awt.Toolkit#getSystemClipboard
119 */
120 public synchronized void setContents(Transferable contents, ClipboardOwner owner) {
121 final ClipboardOwner oldOwner = this.owner;
122 final Transferable oldContents = this.contents;
123
124 this.owner = owner;
125 this.contents = contents;
126
127 if (oldOwner != null && oldOwner != owner) {
128 EventQueue.invokeLater(new Runnable() {
129 public void run() {
130 oldOwner.lostOwnership(Clipboard.this, oldContents);
131 }
132 });
133 }
134 fireFlavorsChanged();
135 }
136
137 /**
138 * Returns a transferable object representing the current contents
139 * of the clipboard. If the clipboard currently has no contents,
140 * it returns <code>null</code>. The parameter Object requestor is
141 * not currently used. The method throws
142 * <code>IllegalStateException</code> if the clipboard is currently
143 * unavailable. For example, on some platforms, the system clipboard is
144 * unavailable while it is accessed by another application.
145 *
146 * @param requestor the object requesting the clip data (not used)
147 * @return the current transferable object on the clipboard
148 * @throws IllegalStateException if the clipboard is currently unavailable
149 * @see java.awt.Toolkit#getSystemClipboard
150 */
151 public synchronized Transferable getContents(Object requestor) {
152 return contents;
153 }
154
155
156 /**
157 * Returns an array of <code>DataFlavor</code>s in which the current
158 * contents of this clipboard can be provided. If there are no
159 * <code>DataFlavor</code>s available, this method returns a zero-length
160 * array.
161 *
162 * @return an array of <code>DataFlavor</code>s in which the current
163 * contents of this clipboard can be provided
164 *
165 * @throws IllegalStateException if this clipboard is currently unavailable
166 *
167 * @since 1.5
168 */
169 public DataFlavor[] getAvailableDataFlavors() {
170 Transferable cntnts = getContents(null);
171 if (cntnts == null) {
172 return new DataFlavor[0];
173 }
174 return cntnts.getTransferDataFlavors();
175 }
176
177 /**
178 * Returns whether or not the current contents of this clipboard can be
179 * provided in the specified <code>DataFlavor</code>.
180 *
181 * @param flavor the requested <code>DataFlavor</code> for the contents
182 *
183 * @return <code>true</code> if the current contents of this clipboard
184 * can be provided in the specified <code>DataFlavor</code>;
185 * <code>false</code> otherwise
186 *
187 * @throws NullPointerException if <code>flavor</code> is <code>null</code>
188 * @throws IllegalStateException if this clipboard is currently unavailable
189 *
190 * @since 1.5
191 */
192 public boolean isDataFlavorAvailable(DataFlavor flavor) {
193 if (flavor == null) {
194 throw new NullPointerException("flavor");
195 }
196
197 Transferable cntnts = getContents(null);
198 if (cntnts == null) {
199 return false;
200 }
201 return cntnts.isDataFlavorSupported(flavor);
202 }
203
204 /**
205 * Returns an object representing the current contents of this clipboard
206 * in the specified <code>DataFlavor</code>.
207 * The class of the object returned is defined by the representation
208 * class of <code>flavor</code>.
209 *
210 * @param flavor the requested <code>DataFlavor</code> for the contents
211 *
212 * @return an object representing the current contents of this clipboard
213 * in the specified <code>DataFlavor</code>
214 *
215 * @throws NullPointerException if <code>flavor</code> is <code>null</code>
216 * @throws IllegalStateException if this clipboard is currently unavailable
217 * @throws UnsupportedFlavorException if the requested <code>DataFlavor</code>
218 * is not available
219 * @throws IOException if the data in the requested <code>DataFlavor</code>
220 * can not be retrieved
221 *
222 * @see DataFlavor#getRepresentationClass
223 *
224 * @since 1.5
225 */
226 public Object getData(DataFlavor flavor)
227 throws UnsupportedFlavorException, IOException {
228 if (flavor == null) {
229 throw new NullPointerException("flavor");
230 }
231
232 Transferable cntnts = getContents(null);
233 if (cntnts == null) {
234 throw new UnsupportedFlavorException(flavor);
235 }
236 return cntnts.getTransferData(flavor);
237 }
238
239
240 /**
241 * Registers the specified <code>FlavorListener</code> to receive
242 * <code>FlavorEvent</code>s from this clipboard.
243 * If <code>listener</code> is <code>null</code>, no exception
244 * is thrown and no action is performed.
245 *
246 * @param listener the listener to be added
247 *
248 * @see #removeFlavorListener
249 * @see #getFlavorListeners
250 * @see FlavorListener
251 * @see FlavorEvent
252 * @since 1.5
253 */
254 public synchronized void addFlavorListener(FlavorListener listener) {
255 if (listener == null) {
256 return;
257 }
258 if (flavorListeners == null) {
259 currentDataFlavors = getAvailableDataFlavorSet();
260 flavorListeners = new EventListenerAggregate(FlavorListener.class);
261 }
262 flavorListeners.add(listener);
263 }
264
265 /**
266 * Removes the specified <code>FlavorListener</code> so that it no longer
267 * receives <code>FlavorEvent</code>s from this <code>Clipboard</code>.
268 * This method performs no function, nor does it throw an exception, if
269 * the listener specified by the argument was not previously added to this
270 * <code>Clipboard</code>.
271 * If <code>listener</code> is <code>null</code>, no exception
272 * is thrown and no action is performed.
273 *
274 * @param listener the listener to be removed
275 *
276 * @see #addFlavorListener
277 * @see #getFlavorListeners
278 * @see FlavorListener
279 * @see FlavorEvent
280 * @since 1.5
281 */
282 public synchronized void removeFlavorListener(FlavorListener listener) {
283 if (listener == null || flavorListeners == null) {
284 return;
285 }
286 flavorListeners.remove(listener);
287 }
288
289 /**
290 * Returns an array of all the <code>FlavorListener</code>s currently
291 * registered on this <code>Clipboard</code>.
292 *
293 * @return all of this clipboard's <code>FlavorListener</code>s or an empty
294 * array if no listeners are currently registered
295 * @see #addFlavorListener
296 * @see #removeFlavorListener
297 * @see FlavorListener
298 * @see FlavorEvent
299 * @since 1.5
300 */
301 public synchronized FlavorListener[] getFlavorListeners() {
302 return flavorListeners == null ? new FlavorListener[0] :
303 (FlavorListener[])flavorListeners.getListenersCopy();
304 }
305
306 /**
307 * Checks change of the <code>DataFlavor</code>s and, if necessary,
308 * notifies all listeners that have registered interest for notification
309 * on <code>FlavorEvent</code>s.
310 *
311 * @since 1.5
312 */
313 private void fireFlavorsChanged() {
314 if (flavorListeners == null) {
315 return;
316 }
317 Set prevDataFlavors = currentDataFlavors;
318 currentDataFlavors = getAvailableDataFlavorSet();
319 if (prevDataFlavors.equals(currentDataFlavors)) {
320 return;
321 }
322 FlavorListener[] flavorListenerArray =
323 (FlavorListener[])flavorListeners.getListenersInternal();
324 for (int i = 0; i < flavorListenerArray.length; i++) {
325 final FlavorListener listener = flavorListenerArray[i];
326 EventQueue.invokeLater(new Runnable() {
327 public void run() {
328 listener.flavorsChanged(new FlavorEvent(Clipboard.this));
329 }
330 });
331 }
332 }
333
334 /**
335 * Returns a set of <code>DataFlavor</code>s currently available
336 * on this clipboard.
337 *
338 * @return a set of <code>DataFlavor</code>s currently available
339 * on this clipboard
340 *
341 * @since 1.5
342 */
343 private Set getAvailableDataFlavorSet() {
344 Set set = new HashSet();
345 Transferable contents = getContents(null);
346 if (contents != null) {
347 DataFlavor[] flavors = contents.getTransferDataFlavors();
348 if (flavors != null) {
349 set.addAll(Arrays.asList(flavors));
350 }
351 }
352 return set;
353 }
354}
java/pkg/java/awt/datatransfer/ClipboardOwner.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/ClipboardOwner.java+56−0
@@ -0,0 +1,56 @@
1/*
2 * Copyright (c) 1996, 2002, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28/**
29 * Defines the interface for classes that will provide data to
30 * a clipboard. An instance of this interface becomes the owner
31 * of the contents of a clipboard (clipboard owner) if it is
32 * passed as an argument to
33 * {@link java.awt.datatransfer.Clipboard#setContents} method of
34 * the clipboard and this method returns successfully.
35 * The instance remains the clipboard owner until another application
36 * or another object within this application asserts ownership
37 * of this clipboard.
38 *
39 * @see java.awt.datatransfer.Clipboard
40 *
41 * @author Amy Fowler
42 */
43
44public interface ClipboardOwner {
45
46 /**
47 * Notifies this object that it is no longer the clipboard owner.
48 * This method will be called when another application or another
49 * object within this application asserts ownership of the clipboard.
50 *
51 * @param clipboard the clipboard that is no longer owned
52 * @param contents the contents which this owner had placed on the clipboard
53 */
54 public void lostOwnership(Clipboard clipboard, Transferable contents);
55
56}
java/pkg/java/awt/datatransfer/DataFlavor$1.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/DataFlavor$TextFlavorComparator.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/DataFlavor.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/DataFlavor.java+1381−0
@@ -0,0 +1,1381 @@
1/*
2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.awt.Toolkit;
29import java.io.*;
30import java.nio.*;
31import java.util.*;
32
33import sun.awt.datatransfer.DataTransferer;
34
35/**
36 * A {@code DataFlavor} provides meta information about data. {@code DataFlavor}
37 * is typically used to access data on the clipboard, or during
38 * a drag and drop operation.
39 * <p>
40 * An instance of {@code DataFlavor} encapsulates a content type as
41 * defined in <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
42 * and <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a>.
43 * A content type is typically referred to as a MIME type.
44 * <p>
45 * A content type consists of a media type (referred
46 * to as the primary type), a subtype, and optional parameters. See
47 * <a href="http://www.ietf.org/rfc/rfc2045.txt">RFC 2045</a>
48 * for details on the syntax of a MIME type.
49 * <p>
50 * The JRE data transfer implementation interprets the parameter &quot;class&quot;
51 * of a MIME type as <B>a representation class</b>.
52 * The representation class reflects the class of the object being
53 * transferred. In other words, the representation class is the type of
54 * object returned by {@link Transferable#getTransferData}.
55 * For example, the MIME type of {@link #imageFlavor} is
56 * {@code "image/x-java-image;class=java.awt.Image"},
57 * the primary type is {@code image}, the subtype is
58 * {@code x-java-image}, and the representation class is
59 * {@code java.awt.Image}. When {@code getTransferData} is invoked
60 * with a {@code DataFlavor} of {@code imageFlavor}, an instance of
61 * {@code java.awt.Image} is returned.
62 * It's important to note that {@code DataFlavor} does no error checking
63 * against the representation class. It is up to consumers of
64 * {@code DataFlavor}, such as {@code Transferable}, to honor the representation
65 * class.
66 * <br>
67 * Note, if you do not specify a representation class when
68 * creating a {@code DataFlavor}, the default
69 * representation class is used. See appropriate documentation for
70 * {@code DataFlavor}'s constructors.
71 * <p>
72 * Also, {@code DataFlavor} instances with the &quot;text&quot; primary
73 * MIME type may have a &quot;charset&quot; parameter. Refer to
74 * <a href="http://www.ietf.org/rfc/rfc2046.txt">RFC 2046</a> and
75 * {@link #selectBestTextFlavor} for details on &quot;text&quot; MIME types
76 * and the &quot;charset&quot; parameter.
77 * <p>
78 * Equality of {@code DataFlavors} is determined by the primary type,
79 * subtype, and representation class. Refer to {@link #equals(DataFlavor)} for
80 * details. When determining equality, any optional parameters are ignored.
81 * For example, the following produces two {@code DataFlavors} that
82 * are considered identical:
83 * <pre>
84 * DataFlavor flavor1 = new DataFlavor(Object.class, &quot;X-test/test; class=&lt;java.lang.Object&gt;; foo=bar&quot;);
85 * DataFlavor flavor2 = new DataFlavor(Object.class, &quot;X-test/test; class=&lt;java.lang.Object&gt;; x=y&quot;);
86 * // The following returns true.
87 * flavor1.equals(flavor2);
88 * </pre>
89 * As mentioned, {@code flavor1} and {@code flavor2} are considered identical.
90 * As such, asking a {@code Transferable} for either {@code DataFlavor} returns
91 * the same results.
92 * <p>
93 * For more information on the using data transfer with Swing see
94 * the <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html">
95 * How to Use Drag and Drop and Data Transfer</a>,
96 * section in <em>Java Tutorial</em>.
97 *
98 * @author Blake Sullivan
99 * @author Laurence P. G. Cable
100 * @author Jeff Dunn
101 */
102public class DataFlavor implements Externalizable, Cloneable {
103
104 private static final long serialVersionUID = 8367026044764648243L;
105 private static final Class ioInputStreamClass = java.io.InputStream.class;
106
107 /**
108 * Tries to load a class from: the bootstrap loader, the system loader,
109 * the context loader (if one is present) and finally the loader specified.
110 *
111 * @param className the name of the class to be loaded
112 * @param fallback the fallback loader
113 * @return the class loaded
114 * @exception ClassNotFoundException if class is not found
115 */
116 protected final static Class<?> tryToLoadClass(String className,
117 ClassLoader fallback)
118 throws ClassNotFoundException
119 {
120 ClassLoader systemClassLoader = (ClassLoader)
121 java.security.AccessController.doPrivileged(
122 new java.security.PrivilegedAction() {
123 public Object run() {
124 ClassLoader cl = Thread.currentThread().
125 getContextClassLoader();
126 return (cl != null)
127 ? cl
128 : ClassLoader.getSystemClassLoader();
129 }
130 });
131
132 try {
133 return Class.forName(className, true, systemClassLoader);
134 } catch (ClassNotFoundException e2) {
135 if (fallback != null) {
136 return Class.forName(className, true, fallback);
137 } else {
138 throw new ClassNotFoundException(className);
139 }
140 }
141 }
142
143 /*
144 * private initializer
145 */
146 static private DataFlavor createConstant(Class rc, String prn) {
147 try {
148 return new DataFlavor(rc, prn);
149 } catch (Exception e) {
150 return null;
151 }
152 }
153
154 /*
155 * private initializer
156 */
157 static private DataFlavor createConstant(String mt, String prn) {
158 try {
159 return new DataFlavor(mt, prn);
160 } catch (Exception e) {
161 return null;
162 }
163 }
164
165 /**
166 * The <code>DataFlavor</code> representing a Java Unicode String class,
167 * where:
168 * <pre>
169 * representationClass = java.lang.String
170 * mimeType = "application/x-java-serialized-object"
171 * </pre>
172 */
173 public static final DataFlavor stringFlavor = createConstant(java.lang.String.class, "Unicode String");
174
175 /**
176 * The <code>DataFlavor</code> representing a Java Image class,
177 * where:
178 * <pre>
179 * representationClass = java.awt.Image
180 * mimeType = "image/x-java-image"
181 * </pre>
182 */
183 public static final DataFlavor imageFlavor = createConstant("image/x-java-image; class=java.awt.Image", "Image");
184
185 /**
186 * The <code>DataFlavor</code> representing plain text with Unicode
187 * encoding, where:
188 * <pre>
189 * representationClass = InputStream
190 * mimeType = "text/plain; charset=unicode"
191 * </pre>
192 * This <code>DataFlavor</code> has been <b>deprecated</b> because
193 * (1) Its representation is an InputStream, an 8-bit based representation,
194 * while Unicode is a 16-bit character set; and (2) The charset "unicode"
195 * is not well-defined. "unicode" implies a particular platform's
196 * implementation of Unicode, not a cross-platform implementation.
197 *
198 * @deprecated as of 1.3. Use <code>DataFlavor.getReaderForText(Transferable)</code>
199 * instead of <code>Transferable.getTransferData(DataFlavor.plainTextFlavor)</code>.
200 */
201 @Deprecated
202 public static final DataFlavor plainTextFlavor = createConstant("text/plain; charset=unicode; class=java.io.InputStream", "Plain Text");
203
204 /**
205 * A MIME Content-Type of application/x-java-serialized-object represents
206 * a graph of Java object(s) that have been made persistent.
207 *
208 * The representation class associated with this <code>DataFlavor</code>
209 * identifies the Java type of an object returned as a reference
210 * from an invocation <code>java.awt.datatransfer.getTransferData</code>.
211 */
212 public static final String javaSerializedObjectMimeType = "application/x-java-serialized-object";
213
214 /**
215 * To transfer a list of files to/from Java (and the underlying
216 * platform) a <code>DataFlavor</code> of this type/subtype and
217 * representation class of <code>java.util.List</code> is used.
218 * Each element of the list is required/guaranteed to be of type
219 * <code>java.io.File</code>.
220 */
221 public static final DataFlavor javaFileListFlavor = createConstant("application/x-java-file-list;class=java.util.List", null);
222
223 /**
224 * To transfer a reference to an arbitrary Java object reference that
225 * has no associated MIME Content-type, across a <code>Transferable</code>
226 * interface WITHIN THE SAME JVM, a <code>DataFlavor</code>
227 * with this type/subtype is used, with a <code>representationClass</code>
228 * equal to the type of the class/interface being passed across the
229 * <code>Transferable</code>.
230 * <p>
231 * The object reference returned from
232 * <code>Transferable.getTransferData</code> for a <code>DataFlavor</code>
233 * with this MIME Content-Type is required to be
234 * an instance of the representation Class of the <code>DataFlavor</code>.
235 */
236 public static final String javaJVMLocalObjectMimeType = "application/x-java-jvm-local-objectref";
237
238 /**
239 * In order to pass a live link to a Remote object via a Drag and Drop
240 * <code>ACTION_LINK</code> operation a Mime Content Type of
241 * application/x-java-remote-object should be used,
242 * where the representation class of the <code>DataFlavor</code>
243 * represents the type of the <code>Remote</code> interface to be
244 * transferred.
245 */
246 public static final String javaRemoteObjectMimeType = "application/x-java-remote-object";
247
248 /**
249 * Constructs a new <code>DataFlavor</code>. This constructor is
250 * provided only for the purpose of supporting the
251 * <code>Externalizable</code> interface. It is not
252 * intended for public (client) use.
253 *
254 * @since 1.2
255 */
256 public DataFlavor() {
257 super();
258 }
259
260 /**
261 * Constructs a fully specified <code>DataFlavor</code>.
262 *
263 * @exception NullPointerException if either <code>primaryType</code>,
264 * <code>subType</code> or <code>representationClass</code> is null
265 */
266 private DataFlavor(String primaryType, String subType, MimeTypeParameterList params, Class representationClass, String humanPresentableName) {
267 super();
268 if (primaryType == null) {
269 throw new NullPointerException("primaryType");
270 }
271 if (subType == null) {
272 throw new NullPointerException("subType");
273 }
274 if (representationClass == null) {
275 throw new NullPointerException("representationClass");
276 }
277
278 if (params == null) params = new MimeTypeParameterList();
279
280 params.set("class", representationClass.getName());
281
282 if (humanPresentableName == null) {
283 humanPresentableName = (String)params.get("humanPresentableName");
284
285 if (humanPresentableName == null)
286 humanPresentableName = primaryType + "/" + subType;
287 }
288
289 try {
290 mimeType = new MimeType(primaryType, subType, params);
291 } catch (MimeTypeParseException mtpe) {
292 throw new IllegalArgumentException("MimeType Parse Exception: " + mtpe.getMessage());
293 }
294
295 this.representationClass = representationClass;
296 this.humanPresentableName = humanPresentableName;
297
298 mimeType.removeParameter("humanPresentableName");
299 }
300
301 /**
302 * Constructs a <code>DataFlavor</code> that represents a Java class.
303 * <p>
304 * The returned <code>DataFlavor</code> will have the following
305 * characteristics:
306 * <pre>
307 * representationClass = representationClass
308 * mimeType = application/x-java-serialized-object
309 * </pre>
310 * @param representationClass the class used to transfer data in this flavor
311 * @param humanPresentableName the human-readable string used to identify
312 * this flavor; if this parameter is <code>null</code>
313 * then the value of the the MIME Content Type is used
314 * @exception NullPointerException if <code>representationClass</code> is null
315 */
316 public DataFlavor(Class<?> representationClass, String humanPresentableName) {
317 this("application", "x-java-serialized-object", null, representationClass, humanPresentableName);
318 if (representationClass == null) {
319 throw new NullPointerException("representationClass");
320 }
321 }
322
323 /**
324 * Constructs a <code>DataFlavor</code> that represents a
325 * <code>MimeType</code>.
326 * <p>
327 * The returned <code>DataFlavor</code> will have the following
328 * characteristics:
329 * <p>
330 * If the <code>mimeType</code> is
331 * "application/x-java-serialized-object; class=&lt;representation class&gt;",
332 * the result is the same as calling
333 * <code>new DataFlavor(Class:forName(&lt;representation class&gt;)</code>.
334 * <p>
335 * Otherwise:
336 * <pre>
337 * representationClass = InputStream
338 * mimeType = mimeType
339 * </pre>
340 * @param mimeType the string used to identify the MIME type for this flavor;
341 * if the the <code>mimeType</code> does not specify a
342 * "class=" parameter, or if the class is not successfully
343 * loaded, then an <code>IllegalArgumentException</code>
344 * is thrown
345 * @param humanPresentableName the human-readable string used to identify
346 * this flavor; if this parameter is <code>null</code>
347 * then the value of the the MIME Content Type is used
348 * @exception IllegalArgumentException if <code>mimeType</code> is
349 * invalid or if the class is not successfully loaded
350 * @exception NullPointerException if <code>mimeType</code> is null
351 */
352 public DataFlavor(String mimeType, String humanPresentableName) {
353 super();
354 if (mimeType == null) {
355 throw new NullPointerException("mimeType");
356 }
357 try {
358 initialize(mimeType, humanPresentableName, this.getClass().getClassLoader());
359 } catch (MimeTypeParseException mtpe) {
360 throw new IllegalArgumentException("failed to parse:" + mimeType);
361 } catch (ClassNotFoundException cnfe) {
362 throw new IllegalArgumentException("can't find specified class: " + cnfe.getMessage());
363 }
364 }
365
366 /**
367 * Constructs a <code>DataFlavor</code> that represents a
368 * <code>MimeType</code>.
369 * <p>
370 * The returned <code>DataFlavor</code> will have the following
371 * characteristics:
372 * <p>
373 * If the mimeType is
374 * "application/x-java-serialized-object; class=&lt;representation class&gt;",
375 * the result is the same as calling
376 * <code>new DataFlavor(Class:forName(&lt;representation class&gt;)</code>.
377 * <p>
378 * Otherwise:
379 * <pre>
380 * representationClass = InputStream
381 * mimeType = mimeType
382 * </pre>
383 * @param mimeType the string used to identify the MIME type for this flavor
384 * @param humanPresentableName the human-readable string used to
385 * identify this flavor
386 * @param classLoader the class loader to use
387 * @exception ClassNotFoundException if the class is not loaded
388 * @exception IllegalArgumentException if <code>mimeType</code> is
389 * invalid
390 * @exception NullPointerException if <code>mimeType</code> is null
391 */
392 public DataFlavor(String mimeType, String humanPresentableName, ClassLoader classLoader) throws ClassNotFoundException {
393 super();
394 if (mimeType == null) {
395 throw new NullPointerException("mimeType");
396 }
397 try {
398 initialize(mimeType, humanPresentableName, classLoader);
399 } catch (MimeTypeParseException mtpe) {
400 throw new IllegalArgumentException("failed to parse:" + mimeType);
401 }
402 }
403
404 /**
405 * Constructs a <code>DataFlavor</code> from a <code>mimeType</code> string.
406 * The string can specify a "class=<fully specified Java class name>"
407 * parameter to create a <code>DataFlavor</code> with the desired
408 * representation class. If the string does not contain "class=" parameter,
409 * <code>java.io.InputStream</code> is used as default.
410 *
411 * @param mimeType the string used to identify the MIME type for this flavor;
412 * if the class specified by "class=" parameter is not
413 * successfully loaded, then an
414 * <code>ClassNotFoundException</code> is thrown
415 * @exception ClassNotFoundException if the class is not loaded
416 * @exception IllegalArgumentException if <code>mimeType</code> is
417 * invalid
418 * @exception NullPointerException if <code>mimeType</code> is null
419 */
420 public DataFlavor(String mimeType) throws ClassNotFoundException {
421 super();
422 if (mimeType == null) {
423 throw new NullPointerException("mimeType");
424 }
425 try {
426 initialize(mimeType, null, this.getClass().getClassLoader());
427 } catch (MimeTypeParseException mtpe) {
428 throw new IllegalArgumentException("failed to parse:" + mimeType);
429 }
430 }
431
432 /**
433 * Common initialization code called from various constructors.
434 *
435 * @param mimeType the MIME Content Type (must have a class= param)
436 * @param humanPresentableName the human Presentable Name or
437 * <code>null</code>
438 * @param classLoader the fallback class loader to resolve against
439 *
440 * @throws MimeTypeParseException
441 * @throws ClassNotFoundException
442 * @throws NullPointerException if <code>mimeType</code> is null
443 *
444 * @see tryToLoadClass
445 */
446 private void initialize(String mimeType, String humanPresentableName, ClassLoader classLoader) throws MimeTypeParseException, ClassNotFoundException {
447 if (mimeType == null) {
448 throw new NullPointerException("mimeType");
449 }
450
451 this.mimeType = new MimeType(mimeType); // throws
452
453 String rcn = getParameter("class");
454
455 if (rcn == null) {
456 if ("application/x-java-serialized-object".equals(this.mimeType.getBaseType()))
457
458 throw new IllegalArgumentException("no representation class specified for:" + mimeType);
459 else
460 representationClass = java.io.InputStream.class; // default
461 } else { // got a class name
462 representationClass = DataFlavor.tryToLoadClass(rcn, classLoader);
463 }
464
465 this.mimeType.setParameter("class", representationClass.getName());
466
467 if (humanPresentableName == null) {
468 humanPresentableName = this.mimeType.getParameter("humanPresentableName");
469 if (humanPresentableName == null)
470 humanPresentableName = this.mimeType.getPrimaryType() + "/" + this.mimeType.getSubType();
471 }
472
473 this.humanPresentableName = humanPresentableName; // set it.
474
475 this.mimeType.removeParameter("humanPresentableName"); // just in case
476 }
477
478 /**
479 * String representation of this <code>DataFlavor</code> and its
480 * parameters. The resulting <code>String</code> contains the name of
481 * the <code>DataFlavor</code> class, this flavor's MIME type, and its
482 * representation class. If this flavor has a primary MIME type of "text",
483 * supports the charset parameter, and has an encoded representation, the
484 * flavor's charset is also included. See <code>selectBestTextFlavor</code>
485 * for a list of text flavors which support the charset parameter.
486 *
487 * @return string representation of this <code>DataFlavor</code>
488 * @see #selectBestTextFlavor
489 */
490 public String toString() {
491 String string = getClass().getName();
492 string += "["+paramString()+"]";
493 return string;
494 }
495
496 private String paramString() {
497 String params = "";
498 params += "mimetype=";
499 if (mimeType == null) {
500 params += "null";
501 } else {
502 params += mimeType.getBaseType();
503 }
504 params += ";representationclass=";
505 if (representationClass == null) {
506 params += "null";
507 } else {
508 params += representationClass.getName();
509 }
510 if (DataTransferer.isFlavorCharsetTextType(this) &&
511 (isRepresentationClassInputStream() ||
512 isRepresentationClassByteBuffer() ||
513 DataTransferer.byteArrayClass.equals(representationClass)))
514 {
515 params += ";charset=" + DataTransferer.getTextCharset(this);
516 }
517 return params;
518 }
519
520 /**
521 * Returns a <code>DataFlavor</code> representing plain text with Unicode
522 * encoding, where:
523 * <pre>
524 * representationClass = java.io.InputStream
525 * mimeType = "text/plain;
526 * charset=&lt;platform default Unicode encoding&gt;"
527 * </pre>
528 * Sun's implementation for Microsoft Windows uses the encoding <code>utf-16le</code>.
529 * Sun's implementation for Solaris and Linux uses the encoding
530 * <code>iso-10646-ucs-2</code>.
531 *
532 * @return a <code>DataFlavor</code> representing plain text
533 * with Unicode encoding
534 * @since 1.3
535 */
536 public static final DataFlavor getTextPlainUnicodeFlavor() {
537 String encoding = null;
538 DataTransferer transferer = DataTransferer.getInstance();
539 if (transferer != null) {
540 encoding = transferer.getDefaultUnicodeEncoding();
541 }
542 return new DataFlavor(
543 "text/plain;charset="+encoding
544 +";class=java.io.InputStream", "Plain Text");
545 }
546
547 /**
548 * Selects the best text <code>DataFlavor</code> from an array of <code>
549 * DataFlavor</code>s. Only <code>DataFlavor.stringFlavor</code>, and
550 * equivalent flavors, and flavors that have a primary MIME type of "text",
551 * are considered for selection.
552 * <p>
553 * Flavors are first sorted by their MIME types in the following order:
554 * <ul>
555 * <li>"text/sgml"
556 * <li>"text/xml"
557 * <li>"text/html"
558 * <li>"text/rtf"
559 * <li>"text/enriched"
560 * <li>"text/richtext"
561 * <li>"text/uri-list"
562 * <li>"text/tab-separated-values"
563 * <li>"text/t140"
564 * <li>"text/rfc822-headers"
565 * <li>"text/parityfec"
566 * <li>"text/directory"
567 * <li>"text/css"
568 * <li>"text/calendar"
569 * <li>"application/x-java-serialized-object"
570 * <li>"text/plain"
571 * <li>"text/&lt;other&gt;"
572 * </ul>
573 * <p>For example, "text/sgml" will be selected over
574 * "text/html", and <code>DataFlavor.stringFlavor</code> will be chosen
575 * over <code>DataFlavor.plainTextFlavor</code>.
576 * <p>
577 * If two or more flavors share the best MIME type in the array, then that
578 * MIME type will be checked to see if it supports the charset parameter.
579 * <p>
580 * The following MIME types support, or are treated as though they support,
581 * the charset parameter:
582 * <ul>
583 * <li>"text/sgml"
584 * <li>"text/xml"
585 * <li>"text/html"
586 * <li>"text/enriched"
587 * <li>"text/richtext"
588 * <li>"text/uri-list"
589 * <li>"text/directory"
590 * <li>"text/css"
591 * <li>"text/calendar"
592 * <li>"application/x-java-serialized-object"
593 * <li>"text/plain"
594 * </ul>
595 * The following MIME types do not support, or are treated as though they
596 * do not support, the charset parameter:
597 * <ul>
598 * <li>"text/rtf"
599 * <li>"text/tab-separated-values"
600 * <li>"text/t140"
601 * <li>"text/rfc822-headers"
602 * <li>"text/parityfec"
603 * </ul>
604 * For "text/&lt;other&gt;" MIME types, the first time the JRE needs to
605 * determine whether the MIME type supports the charset parameter, it will
606 * check whether the parameter is explicitly listed in an arbitrarily
607 * chosen <code>DataFlavor</code> which uses that MIME type. If so, the JRE
608 * will assume from that point on that the MIME type supports the charset
609 * parameter and will not check again. If the parameter is not explicitly
610 * listed, the JRE will assume from that point on that the MIME type does
611 * not support the charset parameter and will not check again. Because
612 * this check is performed on an arbitrarily chosen
613 * <code>DataFlavor</code>, developers must ensure that all
614 * <code>DataFlavor</code>s with a "text/&lt;other&gt;" MIME type specify
615 * the charset parameter if it is supported by that MIME type. Developers
616 * should never rely on the JRE to substitute the platform's default
617 * charset for a "text/&lt;other&gt;" DataFlavor. Failure to adhere to this
618 * restriction will lead to undefined behavior.
619 * <p>
620 * If the best MIME type in the array does not support the charset
621 * parameter, the flavors which share that MIME type will then be sorted by
622 * their representation classes in the following order:
623 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
624 * <code>[B</code>, &lt;all others&gt;.
625 * <p>
626 * If two or more flavors share the best representation class, or if no
627 * flavor has one of the three specified representations, then one of those
628 * flavors will be chosen non-deterministically.
629 * <p>
630 * If the best MIME type in the array does support the charset parameter,
631 * the flavors which share that MIME type will then be sorted by their
632 * representation classes in the following order:
633 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
634 * <code>java.nio.CharBuffer</code>, <code>[C</code>, &lt;all others&gt;.
635 * <p>
636 * If two or more flavors share the best representation class, and that
637 * representation is one of the four explicitly listed, then one of those
638 * flavors will be chosen non-deterministically. If, however, no flavor has
639 * one of the four specified representations, the flavors will then be
640 * sorted by their charsets. Unicode charsets, such as "UTF-16", "UTF-8",
641 * "UTF-16BE", "UTF-16LE", and their aliases, are considered best. After
642 * them, the platform default charset and its aliases are selected.
643 * "US-ASCII" and its aliases are worst. All other charsets are chosen in
644 * alphabetical order, but only charsets supported by this implementation
645 * of the Java platform will be considered.
646 * <p>
647 * If two or more flavors share the best charset, the flavors will then
648 * again be sorted by their representation classes in the following order:
649 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
650 * <code>[B</code>, &lt;all others&gt;.
651 * <p>
652 * If two or more flavors share the best representation class, or if no
653 * flavor has one of the three specified representations, then one of those
654 * flavors will be chosen non-deterministically.
655 *
656 * @param availableFlavors an array of available <code>DataFlavor</code>s
657 * @return the best (highest fidelity) flavor according to the rules
658 * specified above, or <code>null</code>,
659 * if <code>availableFlavors</code> is <code>null</code>,
660 * has zero length, or contains no text flavors
661 * @since 1.3
662 */
663 public static final DataFlavor selectBestTextFlavor(
664 DataFlavor[] availableFlavors) {
665 if (availableFlavors == null || availableFlavors.length == 0) {
666 return null;
667 }
668
669 if (textFlavorComparator == null) {
670 textFlavorComparator = new TextFlavorComparator();
671 }
672
673 DataFlavor bestFlavor =
674 (DataFlavor)Collections.max(Arrays.asList(availableFlavors),
675 textFlavorComparator);
676
677 if (!bestFlavor.isFlavorTextType()) {
678 return null;
679 }
680
681 return bestFlavor;
682 }
683
684 private static Comparator textFlavorComparator;
685
686 static class TextFlavorComparator
687 extends DataTransferer.DataFlavorComparator {
688
689 /**
690 * Compares two <code>DataFlavor</code> objects. Returns a negative
691 * integer, zero, or a positive integer as the first
692 * <code>DataFlavor</code> is worse than, equal to, or better than the
693 * second.
694 * <p>
695 * <code>DataFlavor</code>s are ordered according to the rules outlined
696 * for <code>selectBestTextFlavor</code>.
697 *
698 * @param obj1 the first <code>DataFlavor</code> to be compared
699 * @param obj2 the second <code>DataFlavor</code> to be compared
700 * @return a negative integer, zero, or a positive integer as the first
701 * argument is worse, equal to, or better than the second
702 * @throws ClassCastException if either of the arguments is not an
703 * instance of <code>DataFlavor</code>
704 * @throws NullPointerException if either of the arguments is
705 * <code>null</code>
706 *
707 * @see #selectBestTextFlavor
708 */
709 public int compare(Object obj1, Object obj2) {
710 DataFlavor flavor1 = (DataFlavor)obj1;
711 DataFlavor flavor2 = (DataFlavor)obj2;
712
713 if (flavor1.isFlavorTextType()) {
714 if (flavor2.isFlavorTextType()) {
715 return super.compare(obj1, obj2);
716 } else {
717 return 1;
718 }
719 } else if (flavor2.isFlavorTextType()) {
720 return -1;
721 } else {
722 return 0;
723 }
724 }
725 }
726
727 /**
728 * Gets a Reader for a text flavor, decoded, if necessary, for the expected
729 * charset (encoding). The supported representation classes are
730 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
731 * <code>java.nio.CharBuffer</code>, <code>[C</code>,
732 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>,
733 * and <code>[B</code>.
734 * <p>
735 * Because text flavors which do not support the charset parameter are
736 * encoded in a non-standard format, this method should not be called for
737 * such flavors. However, in order to maintain backward-compatibility,
738 * if this method is called for such a flavor, this method will treat the
739 * flavor as though it supports the charset parameter and attempt to
740 * decode it accordingly. See <code>selectBestTextFlavor</code> for a list
741 * of text flavors which do not support the charset parameter.
742 *
743 * @param transferable the <code>Transferable</code> whose data will be
744 * requested in this flavor
745 *
746 * @return a <code>Reader</code> to read the <code>Transferable</code>'s
747 * data
748 *
749 * @exception IllegalArgumentException if the representation class
750 * is not one of the seven listed above
751 * @exception IllegalArgumentException if the <code>Transferable</code>
752 * has <code>null</code> data
753 * @exception NullPointerException if the <code>Transferable</code> is
754 * <code>null</code>
755 * @exception UnsupportedEncodingException if this flavor's representation
756 * is <code>java.io.InputStream</code>,
757 * <code>java.nio.ByteBuffer</code>, or <code>[B</code> and
758 * this flavor's encoding is not supported by this
759 * implementation of the Java platform
760 * @exception UnsupportedFlavorException if the <code>Transferable</code>
761 * does not support this flavor
762 * @exception IOException if the data cannot be read because of an
763 * I/O error
764 * @see #selectBestTextFlavor
765 * @since 1.3
766 */
767 public Reader getReaderForText(Transferable transferable)
768 throws UnsupportedFlavorException, IOException
769 {
770 Object transferObject = transferable.getTransferData(this);
771 if (transferObject == null) {
772 throw new IllegalArgumentException
773 ("getTransferData() returned null");
774 }
775
776 if (transferObject instanceof Reader) {
777 return (Reader)transferObject;
778 } else if (transferObject instanceof String) {
779 return new StringReader((String)transferObject);
780 } else if (transferObject instanceof CharBuffer) {
781 CharBuffer buffer = (CharBuffer)transferObject;
782 int size = buffer.remaining();
783 char[] chars = new char[size];
784 buffer.get(chars, 0, size);
785 return new CharArrayReader(chars);
786 } else if (transferObject instanceof char[]) {
787 return new CharArrayReader((char[])transferObject);
788 }
789
790 InputStream stream = null;
791
792 if (transferObject instanceof InputStream) {
793 stream = (InputStream)transferObject;
794 } else if (transferObject instanceof ByteBuffer) {
795 ByteBuffer buffer = (ByteBuffer)transferObject;
796 int size = buffer.remaining();
797 byte[] bytes = new byte[size];
798 buffer.get(bytes, 0, size);
799 stream = new ByteArrayInputStream(bytes);
800 } else if (transferObject instanceof byte[]) {
801 stream = new ByteArrayInputStream((byte[])transferObject);
802 }
803
804 if (stream == null) {
805 throw new IllegalArgumentException("transfer data is not Reader, String, CharBuffer, char array, InputStream, ByteBuffer, or byte array");
806 }
807
808 String encoding = getParameter("charset");
809 return (encoding == null)
810 ? new InputStreamReader(stream)
811 : new InputStreamReader(stream, encoding);
812 }
813
814 /**
815 * Returns the MIME type string for this <code>DataFlavor</code>.
816 * @return the MIME type string for this flavor
817 */
818 public String getMimeType() {
819 return (mimeType != null) ? mimeType.toString() : null;
820 }
821
822 /**
823 * Returns the <code>Class</code> which objects supporting this
824 * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
825 * is requested.
826 * @return the <code>Class</code> which objects supporting this
827 * <code>DataFlavor</code> will return when this <code>DataFlavor</code>
828 * is requested
829 */
830 public Class<?> getRepresentationClass() {
831 return representationClass;
832 }
833
834 /**
835 * Returns the human presentable name for the data format that this
836 * <code>DataFlavor</code> represents. This name would be localized
837 * for different countries.
838 * @return the human presentable name for the data format that this
839 * <code>DataFlavor</code> represents
840 */
841 public String getHumanPresentableName() {
842 return humanPresentableName;
843 }
844
845 /**
846 * Returns the primary MIME type for this <code>DataFlavor</code>.
847 * @return the primary MIME type of this <code>DataFlavor</code>
848 */
849 public String getPrimaryType() {
850 return (mimeType != null) ? mimeType.getPrimaryType() : null;
851 }
852
853 /**
854 * Returns the sub MIME type of this <code>DataFlavor</code>.
855 * @return the Sub MIME type of this <code>DataFlavor</code>
856 */
857 public String getSubType() {
858 return (mimeType != null) ? mimeType.getSubType() : null;
859 }
860
861 /**
862 * Returns the human presentable name for this <code>DataFlavor</code>
863 * if <code>paramName</code> equals "humanPresentableName". Otherwise
864 * returns the MIME type value associated with <code>paramName</code>.
865 *
866 * @param paramName the parameter name requested
867 * @return the value of the name parameter, or <code>null</code>
868 * if there is no associated value
869 */
870 public String getParameter(String paramName) {
871 if (paramName.equals("humanPresentableName")) {
872 return humanPresentableName;
873 } else {
874 return (mimeType != null)
875 ? mimeType.getParameter(paramName) : null;
876 }
877 }
878
879 /**
880 * Sets the human presentable name for the data format that this
881 * <code>DataFlavor</code> represents. This name would be localized
882 * for different countries.
883 * @param humanPresentableName the new human presentable name
884 */
885 public void setHumanPresentableName(String humanPresentableName) {
886 this.humanPresentableName = humanPresentableName;
887 }
888
889 /**
890 * {@inheritDoc}
891 * <p>
892 * The equals comparison for the {@code DataFlavor} class is implemented
893 * as follows: Two <code>DataFlavor</code>s are considered equal if and
894 * only if their MIME primary type and subtype and representation class are
895 * equal. Additionally, if the primary type is "text", the subtype denotes
896 * a text flavor which supports the charset parameter, and the
897 * representation class is not <code>java.io.Reader</code>,
898 * <code>java.lang.String</code>, <code>java.nio.CharBuffer</code>, or
899 * <code>[C</code>, the <code>charset</code> parameter must also be equal.
900 * If a charset is not explicitly specified for one or both
901 * <code>DataFlavor</code>s, the platform default encoding is assumed. See
902 * <code>selectBestTextFlavor</code> for a list of text flavors which
903 * support the charset parameter.
904 *
905 * @param o the <code>Object</code> to compare with <code>this</code>
906 * @return <code>true</code> if <code>that</code> is equivalent to this
907 * <code>DataFlavor</code>; <code>false</code> otherwise
908 * @see #selectBestTextFlavor
909 */
910 public boolean equals(Object o) {
911 return ((o instanceof DataFlavor) && equals((DataFlavor)o));
912 }
913
914 /**
915 * This method has the same behavior as {@link #equals(Object)}.
916 * The only difference being that it takes a {@code DataFlavor} instance
917 * as a parameter.
918 *
919 * @param that the <code>DataFlavor</code> to compare with
920 * <code>this</code>
921 * @return <code>true</code> if <code>that</code> is equivalent to this
922 * <code>DataFlavor</code>; <code>false</code> otherwise
923 * @see #selectBestTextFlavor
924 */
925 public boolean equals(DataFlavor that) {
926 if (that == null) {
927 return false;
928 }
929 if (this == that) {
930 return true;
931 }
932
933 if (representationClass == null) {
934 if (that.getRepresentationClass() != null) {
935 return false;
936 }
937 } else {
938 if (!representationClass.equals(that.getRepresentationClass())) {
939 return false;
940 }
941 }
942
943 if (mimeType == null) {
944 if (that.mimeType != null) {
945 return false;
946 }
947 } else {
948 if (!mimeType.match(that.mimeType)) {
949 return false;
950 }
951
952 if ("text".equals(getPrimaryType()) &&
953 DataTransferer.doesSubtypeSupportCharset(this) &&
954 representationClass != null &&
955 !(isRepresentationClassReader() ||
956 String.class.equals(representationClass) ||
957 isRepresentationClassCharBuffer() ||
958 DataTransferer.charArrayClass.equals(representationClass)))
959 {
960 String thisCharset =
961 DataTransferer.canonicalName(getParameter("charset"));
962 String thatCharset =
963 DataTransferer.canonicalName(that.getParameter("charset"));
964 if (thisCharset == null) {
965 if (thatCharset != null) {
966 return false;
967 }
968 } else {
969 if (!thisCharset.equals(thatCharset)) {
970 return false;
971 }
972 }
973 }
974 }
975
976 return true;
977 }
978
979 /**
980 * Compares only the <code>mimeType</code> against the passed in
981 * <code>String</code> and <code>representationClass</code> is
982 * not considered in the comparison.
983 *
984 * If <code>representationClass</code> needs to be compared, then
985 * <code>equals(new DataFlavor(s))</code> may be used.
986 * @deprecated As inconsistent with <code>hashCode()</code> contract,
987 * use <code>isMimeTypeEqual(String)</code> instead.
988 * @param s the {@code mimeType} to compare.
989 * @return true if the String (MimeType) is equal; false otherwise or if
990 * {@code s} is {@code null}
991 */
992 @Deprecated
993 public boolean equals(String s) {
994 if (s == null || mimeType == null)
995 return false;
996 return isMimeTypeEqual(s);
997 }
998
999 /**
1000 * Returns hash code for this <code>DataFlavor</code>.
1001 * For two equal <code>DataFlavor</code>s, hash codes are equal.
1002 * For the <code>String</code>
1003 * that matches <code>DataFlavor.equals(String)</code>, it is not
1004 * guaranteed that <code>DataFlavor</code>'s hash code is equal
1005 * to the hash code of the <code>String</code>.
1006 *
1007 * @return a hash code for this <code>DataFlavor</code>
1008 */
1009 public int hashCode() {
1010 int total = 0;
1011
1012 if (representationClass != null) {
1013 total += representationClass.hashCode();
1014 }
1015
1016 if (mimeType != null) {
1017 String primaryType = mimeType.getPrimaryType();
1018 if (primaryType != null) {
1019 total += primaryType.hashCode();
1020 }
1021
1022 // Do not add subType.hashCode() to the total. equals uses
1023 // MimeType.match which reports a match if one or both of the
1024 // subTypes is '*', regardless of the other subType.
1025
1026 if ("text".equals(primaryType) &&
1027 DataTransferer.doesSubtypeSupportCharset(this) &&
1028 representationClass != null &&
1029 !(isRepresentationClassReader() ||
1030 String.class.equals(representationClass) ||
1031 isRepresentationClassCharBuffer() ||
1032 DataTransferer.charArrayClass.equals
1033 (representationClass)))
1034 {
1035 String charset =
1036 DataTransferer.canonicalName(getParameter("charset"));
1037 if (charset != null) {
1038 total += charset.hashCode();
1039 }
1040 }
1041 }
1042
1043 return total;
1044 }
1045
1046 /**
1047 * Identical to {@link #equals(DataFlavor)}.
1048 *
1049 * @param that the <code>DataFlavor</code> to compare with
1050 * <code>this</code>
1051 * @return <code>true</code> if <code>that</code> is equivalent to this
1052 * <code>DataFlavor</code>; <code>false</code> otherwise
1053 * @see #selectBestTextFlavor
1054 * @since 1.3
1055 */
1056 public boolean match(DataFlavor that) {
1057 return equals(that);
1058 }
1059
1060 /**
1061 * Returns whether the string representation of the MIME type passed in
1062 * is equivalent to the MIME type of this <code>DataFlavor</code>.
1063 * Parameters are not included in the comparison.
1064 *
1065 * @param mimeType the string representation of the MIME type
1066 * @return true if the string representation of the MIME type passed in is
1067 * equivalent to the MIME type of this <code>DataFlavor</code>;
1068 * false otherwise
1069 * @throws NullPointerException if mimeType is <code>null</code>
1070 */
1071 public boolean isMimeTypeEqual(String mimeType) {
1072 // JCK Test DataFlavor0117: if 'mimeType' is null, throw NPE
1073 if (mimeType == null) {
1074 throw new NullPointerException("mimeType");
1075 }
1076 if (this.mimeType == null) {
1077 return false;
1078 }
1079 try {
1080 return this.mimeType.match(new MimeType(mimeType));
1081 } catch (MimeTypeParseException mtpe) {
1082 return false;
1083 }
1084 }
1085
1086 /**
1087 * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
1088 * objects. No parameters are considered.
1089 *
1090 * @param dataFlavor the <code>DataFlavor</code> to be compared
1091 * @return true if the <code>MimeType</code>s are equal,
1092 * otherwise false
1093 */
1094
1095 public final boolean isMimeTypeEqual(DataFlavor dataFlavor) {
1096 return isMimeTypeEqual(dataFlavor.mimeType);
1097 }
1098
1099 /**
1100 * Compares the <code>mimeType</code> of two <code>DataFlavor</code>
1101 * objects. No parameters are considered.
1102 *
1103 * @return true if the <code>MimeType</code>s are equal,
1104 * otherwise false
1105 */
1106
1107 private boolean isMimeTypeEqual(MimeType mtype) {
1108 if (this.mimeType == null) {
1109 return (mtype == null);
1110 }
1111 return mimeType.match(mtype);
1112 }
1113
1114 /**
1115 * Does the <code>DataFlavor</code> represent a serialized object?
1116 */
1117
1118 public boolean isMimeTypeSerializedObject() {
1119 return isMimeTypeEqual(javaSerializedObjectMimeType);
1120 }
1121
1122 public final Class<?> getDefaultRepresentationClass() {
1123 return ioInputStreamClass;
1124 }
1125
1126 public final String getDefaultRepresentationClassAsString() {
1127 return getDefaultRepresentationClass().getName();
1128 }
1129
1130 /**
1131 * Does the <code>DataFlavor</code> represent a
1132 * <code>java.io.InputStream</code>?
1133 */
1134
1135 public boolean isRepresentationClassInputStream() {
1136 return ioInputStreamClass.isAssignableFrom(representationClass);
1137 }
1138
1139 /**
1140 * Returns whether the representation class for this
1141 * <code>DataFlavor</code> is <code>java.io.Reader</code> or a subclass
1142 * thereof.
1143 *
1144 * @since 1.4
1145 */
1146 public boolean isRepresentationClassReader() {
1147 return java.io.Reader.class.isAssignableFrom(representationClass);
1148 }
1149
1150 /**
1151 * Returns whether the representation class for this
1152 * <code>DataFlavor</code> is <code>java.nio.CharBuffer</code> or a
1153 * subclass thereof.
1154 *
1155 * @since 1.4
1156 */
1157 public boolean isRepresentationClassCharBuffer() {
1158 return java.nio.CharBuffer.class.isAssignableFrom(representationClass);
1159 }
1160
1161 /**
1162 * Returns whether the representation class for this
1163 * <code>DataFlavor</code> is <code>java.nio.ByteBuffer</code> or a
1164 * subclass thereof.
1165 *
1166 * @since 1.4
1167 */
1168 public boolean isRepresentationClassByteBuffer() {
1169 return java.nio.ByteBuffer.class.isAssignableFrom(representationClass);
1170 }
1171
1172 /**
1173 * Returns true if the representation class can be serialized.
1174 * @return true if the representation class can be serialized
1175 */
1176
1177 public boolean isRepresentationClassSerializable() {
1178 return java.io.Serializable.class.isAssignableFrom(representationClass);
1179 }
1180
1181 /**
1182 * Returns true if the representation class is <code>Remote</code>.
1183 * @return true if the representation class is <code>Remote</code>
1184 */
1185
1186 public boolean isRepresentationClassRemote() {
1187 return DataTransferer.isRemote(representationClass);
1188 }
1189
1190 /**
1191 * Returns true if the <code>DataFlavor</code> specified represents
1192 * a serialized object.
1193 * @return true if the <code>DataFlavor</code> specified represents
1194 * a Serialized Object
1195 */
1196
1197 public boolean isFlavorSerializedObjectType() {
1198 return isRepresentationClassSerializable() && isMimeTypeEqual(javaSerializedObjectMimeType);
1199 }
1200
1201 /**
1202 * Returns true if the <code>DataFlavor</code> specified represents
1203 * a remote object.
1204 * @return true if the <code>DataFlavor</code> specified represents
1205 * a Remote Object
1206 */
1207
1208 public boolean isFlavorRemoteObjectType() {
1209 return isRepresentationClassRemote()
1210 && isRepresentationClassSerializable()
1211 && isMimeTypeEqual(javaRemoteObjectMimeType);
1212 }
1213
1214
1215 /**
1216 * Returns true if the <code>DataFlavor</code> specified represents
1217 * a list of file objects.
1218 * @return true if the <code>DataFlavor</code> specified represents
1219 * a List of File objects
1220 */
1221
1222 public boolean isFlavorJavaFileListType() {
1223 if (mimeType == null || representationClass == null)
1224 return false;
1225 return java.util.List.class.isAssignableFrom(representationClass) &&
1226 mimeType.match(javaFileListFlavor.mimeType);
1227
1228 }
1229
1230 /**
1231 * Returns whether this <code>DataFlavor</code> is a valid text flavor for
1232 * this implementation of the Java platform. Only flavors equivalent to
1233 * <code>DataFlavor.stringFlavor</code> and <code>DataFlavor</code>s with
1234 * a primary MIME type of "text" can be valid text flavors.
1235 * <p>
1236 * If this flavor supports the charset parameter, it must be equivalent to
1237 * <code>DataFlavor.stringFlavor</code>, or its representation must be
1238 * <code>java.io.Reader</code>, <code>java.lang.String</code>,
1239 * <code>java.nio.CharBuffer</code>, <code>[C</code>,
1240 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
1241 * <code>[B</code>. If the representation is
1242 * <code>java.io.InputStream</code>, <code>java.nio.ByteBuffer</code>, or
1243 * <code>[B</code>, then this flavor's <code>charset</code> parameter must
1244 * be supported by this implementation of the Java platform. If a charset
1245 * is not specified, then the platform default charset, which is always
1246 * supported, is assumed.
1247 * <p>
1248 * If this flavor does not support the charset parameter, its
1249 * representation must be <code>java.io.InputStream</code>,
1250 * <code>java.nio.ByteBuffer</code>, or <code>[B</code>.
1251 * <p>
1252 * See <code>selectBestTextFlavor</code> for a list of text flavors which
1253 * support the charset parameter.
1254 *
1255 * @return <code>true</code> if this <code>DataFlavor</code> is a valid
1256 * text flavor as described above; <code>false</code> otherwise
1257 * @see #selectBestTextFlavor
1258 * @since 1.4
1259 */
1260 public boolean isFlavorTextType() {
1261 return (DataTransferer.isFlavorCharsetTextType(this) ||
1262 DataTransferer.isFlavorNoncharsetTextType(this));
1263 }
1264
1265 /**
1266 * Serializes this <code>DataFlavor</code>.
1267 */
1268
1269 public synchronized void writeExternal(ObjectOutput os) throws IOException {
1270 if (mimeType != null) {
1271 mimeType.setParameter("humanPresentableName", humanPresentableName);
1272 os.writeObject(mimeType);
1273 mimeType.removeParameter("humanPresentableName");
1274 } else {
1275 os.writeObject(null);
1276 }
1277
1278 os.writeObject(representationClass);
1279 }
1280
1281 /**
1282 * Restores this <code>DataFlavor</code> from a Serialized state.
1283 */
1284
1285 public synchronized void readExternal(ObjectInput is) throws IOException , ClassNotFoundException {
1286 String rcn = null;
1287 mimeType = (MimeType)is.readObject();
1288
1289 if (mimeType != null) {
1290 humanPresentableName =
1291 mimeType.getParameter("humanPresentableName");
1292 mimeType.removeParameter("humanPresentableName");
1293 rcn = mimeType.getParameter("class");
1294 if (rcn == null) {
1295 throw new IOException("no class parameter specified in: " +
1296 mimeType);
1297 }
1298 }
1299
1300 try {
1301 representationClass = (Class)is.readObject();
1302 } catch (OptionalDataException ode) {
1303 if (!ode.eof || ode.length != 0) {
1304 throw ode;
1305 }
1306 // Ensure backward compatibility.
1307 // Old versions didn't write the representation class to the stream.
1308 if (rcn != null) {
1309 representationClass =
1310 DataFlavor.tryToLoadClass(rcn, getClass().getClassLoader());
1311 }
1312 }
1313 }
1314
1315 /**
1316 * Returns a clone of this <code>DataFlavor</code>.
1317 * @return a clone of this <code>DataFlavor</code>
1318 */
1319
1320 public Object clone() throws CloneNotSupportedException {
1321 Object newObj = super.clone();
1322 if (mimeType != null) {
1323 ((DataFlavor)newObj).mimeType = (MimeType)mimeType.clone();
1324 }
1325 return newObj;
1326 } // clone()
1327
1328 /**
1329 * Called on <code>DataFlavor</code> for every MIME Type parameter
1330 * to allow <code>DataFlavor</code> subclasses to handle special
1331 * parameters like the text/plain <code>charset</code>
1332 * parameters, whose values are case insensitive. (MIME type parameter
1333 * values are supposed to be case sensitive.
1334 * <p>
1335 * This method is called for each parameter name/value pair and should
1336 * return the normalized representation of the <code>parameterValue</code>.
1337 *
1338 * This method is never invoked by this implementation from 1.1 onwards.
1339 *
1340 * @deprecated
1341 */
1342 @Deprecated
1343 protected String normalizeMimeTypeParameter(String parameterName, String parameterValue) {
1344 return parameterValue;
1345 }
1346
1347 /**
1348 * Called for each MIME type string to give <code>DataFlavor</code> subtypes
1349 * the opportunity to change how the normalization of MIME types is
1350 * accomplished. One possible use would be to add default
1351 * parameter/value pairs in cases where none are present in the MIME
1352 * type string passed in.
1353 *
1354 * This method is never invoked by this implementation from 1.1 onwards.
1355 *
1356 * @deprecated
1357 */
1358 @Deprecated
1359 protected String normalizeMimeType(String mimeType) {
1360 return mimeType;
1361 }
1362
1363 /*
1364 * fields
1365 */
1366
1367 /* placeholder for caching any platform-specific data for flavor */
1368
1369 transient int atom;
1370
1371 /* Mime Type of DataFlavor */
1372
1373 MimeType mimeType;
1374
1375 private String humanPresentableName;
1376
1377 /** Java class of objects this DataFlavor represents **/
1378
1379 private Class representationClass;
1380
1381} // class DataFlavor
java/pkg/java/awt/datatransfer/FlavorEvent.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/FlavorEvent.java+51−0
@@ -0,0 +1,51 @@
1/*
2 * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package java.awt.datatransfer;
26
27import java.util.EventObject;
28
29
30/**
31 * <code>FlavorEvent</code> is used to notify interested parties
32 * that available {@link DataFlavor}s have changed in the
33 * {@link Clipboard} (the event source).
34 *
35 * @see FlavorListener
36 *
37 * @author Alexander Gerasimov
38 * @since 1.5
39 */
40public class FlavorEvent extends EventObject {
41 /**
42 * Constructs a <code>FlavorEvent</code> object.
43 *
44 * @param source the <code>Clipboard</code> that is the source of the event
45 *
46 * @throws IllegalArgumentException if the {@code source} is {@code null}
47 */
48 public FlavorEvent(Clipboard source) {
49 super(source);
50 }
51}
java/pkg/java/awt/datatransfer/FlavorListener.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/FlavorListener.java+55−0
@@ -0,0 +1,55 @@
1/*
2 * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package java.awt.datatransfer;
26
27import java.util.EventListener;
28
29
30/**
31 * Defines an object which listens for {@link FlavorEvent}s.
32 *
33 * @author Alexander Gerasimov
34 * @since 1.5
35 */
36public interface FlavorListener extends EventListener {
37 /**
38 * Invoked when the target {@link Clipboard} of the listener
39 * has changed its available {@link DataFlavor}s.
40 * <p>
41 * Some notifications may be redundant &#151; they are not
42 * caused by a change of the set of DataFlavors available
43 * on the clipboard.
44 * For example, if the clipboard subsystem supposes that
45 * the system clipboard's contents has been changed but it
46 * can't ascertain whether its DataFlavors have been changed
47 * because of some exceptional condition when accessing the
48 * clipboard, the notification is sent to ensure from omitting
49 * a significant notification. Ordinarily, those redundant
50 * notifications should be occasional.
51 *
52 * @param e a <code>FlavorEvent</code> object
53 */
54 void flavorsChanged(FlavorEvent e);
55}
java/pkg/java/awt/datatransfer/FlavorMap.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/FlavorMap.java+75−0
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) 1997, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.util.Map;
29
30
31/**
32 * A two-way Map between "natives" (Strings), which correspond to platform-
33 * specfic data formats, and "flavors" (DataFlavors), which corerspond to
34 * platform-independent MIME types. FlavorMaps need not be symmetric, but
35 * typically are.
36 *
37 *
38 * @since 1.2
39 */
40public interface FlavorMap {
41
42 /**
43 * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
44 * their corresponding <code>String</code> native. The returned
45 * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
46 * internal data. Client code is free to modify the <code>Map</code>
47 * without affecting this object.
48 *
49 * @param flavors an array of <code>DataFlavor</code>s which will be the
50 * key set of the returned <code>Map</code>. If <code>null</code> is
51 * specified, a mapping of all <code>DataFlavor</code>s currently
52 * known to this <code>FlavorMap</code> to their corresponding
53 * <code>String</code> natives will be returned.
54 * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
55 * <code>String</code> natives
56 */
57 Map<DataFlavor,String> getNativesForFlavors(DataFlavor[] flavors);
58
59 /**
60 * Returns a <code>Map</code> of the specified <code>String</code> natives
61 * to their corresponding <code>DataFlavor</code>. The returned
62 * <code>Map</code> is a modifiable copy of this <code>FlavorMap</code>'s
63 * internal data. Client code is free to modify the <code>Map</code>
64 * without affecting this object.
65 *
66 * @param natives an array of <code>String</code>s which will be the
67 * key set of the returned <code>Map</code>. If <code>null</code> is
68 * specified, a mapping of all <code>String</code> natives currently
69 * known to this <code>FlavorMap</code> to their corresponding
70 * <code>DataFlavor</code>s will be returned.
71 * @return a <code>java.util.Map</code> of <code>String</code> natives to
72 * <code>DataFlavor</code>s
73 */
74 Map<String,DataFlavor> getFlavorsForNatives(String[] natives);
75}
java/pkg/java/awt/datatransfer/FlavorTable.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/FlavorTable.java+82−0
@@ -0,0 +1,82 @@
1/*
2 * Copyright (c) 2000, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.util.List;
29
30
31/**
32 * A FlavorMap which relaxes the traditional 1-to-1 restriction of a Map. A
33 * flavor is permitted to map to any number of natives, and likewise a native
34 * is permitted to map to any number of flavors. FlavorTables need not be
35 * symmetric, but typically are.
36 *
37 * @author David Mendenhall
38 *
39 * @since 1.4
40 */
41public interface FlavorTable extends FlavorMap {
42
43 /**
44 * Returns a <code>List</code> of <code>String</code> natives to which the
45 * specified <code>DataFlavor</code> corresponds. The <code>List</code>
46 * will be sorted from best native to worst. That is, the first native will
47 * best reflect data in the specified flavor to the underlying native
48 * platform. The returned <code>List</code> is a modifiable copy of this
49 * <code>FlavorTable</code>'s internal data. Client code is free to modify
50 * the <code>List</code> without affecting this object.
51 *
52 * @param flav the <code>DataFlavor</code> whose corresponding natives
53 * should be returned. If <code>null</code> is specified, all
54 * natives currently known to this <code>FlavorTable</code> are
55 * returned in a non-deterministic order.
56 * @return a <code>java.util.List</code> of <code>java.lang.String</code>
57 * objects which are platform-specific representations of platform-
58 * specific data formats
59 */
60 List<String> getNativesForFlavor(DataFlavor flav);
61
62 /**
63 * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
64 * specified <code>String</code> corresponds. The <code>List</code> will be
65 * sorted from best <code>DataFlavor</code> to worst. That is, the first
66 * <code>DataFlavor</code> will best reflect data in the specified
67 * native to a Java application. The returned <code>List</code> is a
68 * modifiable copy of this <code>FlavorTable</code>'s internal data.
69 * Client code is free to modify the <code>List</code> without affecting
70 * this object.
71 *
72 * @param nat the native whose corresponding <code>DataFlavor</code>s
73 * should be returned. If <code>null</code> is specified, all
74 * <code>DataFlavor</code>s currently known to this
75 * <code>FlavorTable</code> are returned in a non-deterministic
76 * order.
77 * @return a <code>java.util.List</code> of <code>DataFlavor</code>
78 * objects into which platform-specific data in the specified,
79 * platform-specific native can be translated
80 */
81 List<DataFlavor> getFlavorsForNative(String nat);
82}
java/pkg/java/awt/datatransfer/MimeType.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/MimeType.java+393−0
@@ -0,0 +1,393 @@
1/*
2 * Copyright (c) 1997, 2002, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.io.Externalizable;
29import java.io.ObjectOutput;
30import java.io.ObjectInput;
31import java.io.IOException;
32import java.util.Enumeration;
33
34
35/**
36 * A Multipurpose Internet Mail Extension (MIME) type, as defined
37 * in RFC 2045 and 2046.
38 *
39 * THIS IS *NOT* - REPEAT *NOT* - A PUBLIC CLASS! DataFlavor IS
40 * THE PUBLIC INTERFACE, AND THIS IS PROVIDED AS A ***PRIVATE***
41 * (THAT IS AS IN *NOT* PUBLIC) HELPER CLASS!
42 */
43class MimeType implements Externalizable, Cloneable {
44
45 /*
46 * serialization support
47 */
48
49 static final long serialVersionUID = -6568722458793895906L;
50
51 /**
52 * Constructor for externalization; this constructor should not be
53 * called directly by an application, since the result will be an
54 * uninitialized, immutable <code>MimeType</code> object.
55 */
56 public MimeType() {
57 }
58
59 /**
60 * Builds a <code>MimeType</code> from a <code>String</code>.
61 *
62 * @param rawdata text used to initialize the <code>MimeType</code>
63 * @throws NullPointerException if <code>rawdata</code> is null
64 */
65 public MimeType(String rawdata) throws MimeTypeParseException {
66 parse(rawdata);
67 }
68
69 /**
70 * Builds a <code>MimeType</code> with the given primary and sub
71 * type but has an empty parameter list.
72 *
73 * @param primary the primary type of this <code>MimeType</code>
74 * @param sub the subtype of this <code>MimeType</code>
75 * @throws NullPointerException if either <code>primary</code> or
76 * <code>sub</code> is null
77 */
78 public MimeType(String primary, String sub) throws MimeTypeParseException {
79 this(primary, sub, new MimeTypeParameterList());
80 }
81
82 /**
83 * Builds a <code>MimeType</code> with a pre-defined
84 * and valid (or empty) parameter list.
85 *
86 * @param primary the primary type of this <code>MimeType</code>
87 * @param sub the subtype of this <code>MimeType</code>
88 * @param mtpl the requested parameter list
89 * @throws NullPointerException if either <code>primary</code>,
90 * <code>sub</code> or <code>mtpl</code> is null
91 */
92 public MimeType(String primary, String sub, MimeTypeParameterList mtpl) throws
93MimeTypeParseException {
94 // check to see if primary is valid
95 if(isValidToken(primary)) {
96 primaryType = primary.toLowerCase();
97 } else {
98 throw new MimeTypeParseException("Primary type is invalid.");
99 }
100
101 // check to see if sub is valid
102 if(isValidToken(sub)) {
103 subType = sub.toLowerCase();
104 } else {
105 throw new MimeTypeParseException("Sub type is invalid.");
106 }
107
108 parameters = (MimeTypeParameterList)mtpl.clone();
109 }
110
111 public int hashCode() {
112
113 // We sum up the hash codes for all of the strings. This
114 // way, the order of the strings is irrelevant
115 int code = 0;
116 code += primaryType.hashCode();
117 code += subType.hashCode();
118 code += parameters.hashCode();
119 return code;
120 } // hashCode()
121
122 /**
123 * <code>MimeType</code>s are equal if their primary types,
124 * subtypes, and parameters are all equal. No default values
125 * are taken into account.
126 * @param thatObject the object to be evaluated as a
127 * <code>MimeType</code>
128 * @return <code>true</code> if <code>thatObject</code> is
129 * a <code>MimeType</code>; otherwise returns <code>false</code>
130 */
131 public boolean equals(Object thatObject) {
132 if (!(thatObject instanceof MimeType)) {
133 return false;
134 }
135 MimeType that = (MimeType)thatObject;
136 boolean isIt =
137 ((this.primaryType.equals(that.primaryType)) &&
138 (this.subType.equals(that.subType)) &&
139 (this.parameters.equals(that.parameters)));
140 return isIt;
141 } // equals()
142
143 /**
144 * A routine for parsing the MIME type out of a String.
145 *
146 * @throws NullPointerException if <code>rawdata</code> is null
147 */
148 private void parse(String rawdata) throws MimeTypeParseException {
149 int slashIndex = rawdata.indexOf('/');
150 int semIndex = rawdata.indexOf(';');
151 if((slashIndex < 0) && (semIndex < 0)) {
152 // neither character is present, so treat it
153 // as an error
154 throw new MimeTypeParseException("Unable to find a sub type.");
155 } else if((slashIndex < 0) && (semIndex >= 0)) {
156 // we have a ';' (and therefore a parameter list),
157 // but no '/' indicating a sub type is present
158 throw new MimeTypeParseException("Unable to find a sub type.");
159 } else if((slashIndex >= 0) && (semIndex < 0)) {
160 // we have a primary and sub type but no parameter list
161 primaryType = rawdata.substring(0,
162slashIndex).trim().toLowerCase();
163 subType = rawdata.substring(slashIndex +
1641).trim().toLowerCase();
165 parameters = new MimeTypeParameterList();
166 } else if (slashIndex < semIndex) {
167 // we have all three items in the proper sequence
168 primaryType = rawdata.substring(0,
169slashIndex).trim().toLowerCase();
170 subType = rawdata.substring(slashIndex + 1,
171semIndex).trim().toLowerCase();
172 parameters = new
173MimeTypeParameterList(rawdata.substring(semIndex));
174 } else {
175 // we have a ';' lexically before a '/' which means we have a primary type
176 // & a parameter list but no sub type
177 throw new MimeTypeParseException("Unable to find a sub type.");
178 }
179
180 // now validate the primary and sub types
181
182 // check to see if primary is valid
183 if(!isValidToken(primaryType)) {
184 throw new MimeTypeParseException("Primary type is invalid.");
185 }
186
187 // check to see if sub is valid
188 if(!isValidToken(subType)) {
189 throw new MimeTypeParseException("Sub type is invalid.");
190 }
191 }
192
193 /**
194 * Retrieve the primary type of this object.
195 */
196 public String getPrimaryType() {
197 return primaryType;
198 }
199
200 /**
201 * Retrieve the sub type of this object.
202 */
203 public String getSubType() {
204 return subType;
205 }
206
207 /**
208 * Retrieve a copy of this object's parameter list.
209 */
210 public MimeTypeParameterList getParameters() {
211 return (MimeTypeParameterList)parameters.clone();
212 }
213
214 /**
215 * Retrieve the value associated with the given name, or null if there
216 * is no current association.
217 */
218 public String getParameter(String name) {
219 return parameters.get(name);
220 }
221
222 /**
223 * Set the value to be associated with the given name, replacing
224 * any previous association.
225 *
226 * @throw IllegalArgumentException if parameter or value is illegal
227 */
228 public void setParameter(String name, String value) {
229 parameters.set(name, value);
230 }
231
232 /**
233 * Remove any value associated with the given name.
234 *
235 * @throw IllegalArgumentExcpetion if parameter may not be deleted
236 */
237 public void removeParameter(String name) {
238 parameters.remove(name);
239 }
240
241 /**
242 * Return the String representation of this object.
243 */
244 public String toString() {
245 return getBaseType() + parameters.toString();
246 }
247
248 /**
249 * Return a String representation of this object
250 * without the parameter list.
251 */
252 public String getBaseType() {
253 return primaryType + "/" + subType;
254 }
255
256 /**
257 * Returns <code>true</code> if the primary type and the
258 * subtype of this object are the same as the specified
259 * <code>type</code>; otherwise returns <code>false</code>.
260 *
261 * @param type the type to compare to <code>this</code>'s type
262 * @return <code>true</code> if the primary type and the
263 * subtype of this object are the same as the
264 * specified <code>type</code>; otherwise returns
265 * <code>false</code>
266 */
267 public boolean match(MimeType type) {
268 if (type == null)
269 return false;
270 return primaryType.equals(type.getPrimaryType())
271 && (subType.equals("*")
272 || type.getSubType().equals("*")
273 || (subType.equals(type.getSubType())));
274 }
275
276 /**
277 * Returns <code>true</code> if the primary type and the
278 * subtype of this object are the same as the content type
279 * described in <code>rawdata</code>; otherwise returns
280 * <code>false</code>.
281 *
282 * @param rawdata the raw data to be examined
283 * @return <code>true</code> if the primary type and the
284 * subtype of this object are the same as the content type
285 * described in <code>rawdata</code>; otherwise returns
286 * <code>false</code>; if <code>rawdata</code> is
287 * <code>null</code>, returns <code>false</code>
288 */
289 public boolean match(String rawdata) throws MimeTypeParseException {
290 if (rawdata == null)
291 return false;
292 return match(new MimeType(rawdata));
293 }
294
295 /**
296 * The object implements the writeExternal method to save its contents
297 * by calling the methods of DataOutput for its primitive values or
298 * calling the writeObject method of ObjectOutput for objects, strings
299 * and arrays.
300 * @exception IOException Includes any I/O exceptions that may occur
301 */
302 public void writeExternal(ObjectOutput out) throws IOException {
303 String s = toString(); // contains ASCII chars only
304 // one-to-one correspondence between ASCII char and byte in UTF string
305 if (s.length() <= 65535) { // 65535 is max length of UTF string
306 out.writeUTF(s);
307 } else {
308 out.writeByte(0);
309 out.writeByte(0);
310 out.writeInt(s.length());
311 out.write(s.getBytes());
312 }
313 }
314
315 /**
316 * The object implements the readExternal method to restore its
317 * contents by calling the methods of DataInput for primitive
318 * types and readObject for objects, strings and arrays. The
319 * readExternal method must read the values in the same sequence
320 * and with the same types as were written by writeExternal.
321 * @exception ClassNotFoundException If the class for an object being
322 * restored cannot be found.
323 */
324 public void readExternal(ObjectInput in) throws IOException,
325ClassNotFoundException {
326 String s = in.readUTF();
327 if (s == null || s.length() == 0) { // long mime type
328 byte[] ba = new byte[in.readInt()];
329 in.readFully(ba);
330 s = new String(ba);
331 }
332 try {
333 parse(s);
334 } catch(MimeTypeParseException e) {
335 throw new IOException(e.toString());
336 }
337 }
338
339 /**
340 * Returns a clone of this object.
341 * @return a clone of this object
342 */
343
344 public Object clone() {
345 MimeType newObj = null;
346 try {
347 newObj = (MimeType)super.clone();
348 } catch (CloneNotSupportedException cannotHappen) {
349 }
350 newObj.parameters = (MimeTypeParameterList)parameters.clone();
351 return newObj;
352 }
353
354 private String primaryType;
355 private String subType;
356 private MimeTypeParameterList parameters;
357
358 // below here be scary parsing related things
359
360 /**
361 * Determines whether or not a given character belongs to a legal token.
362 */
363 private static boolean isTokenChar(char c) {
364 return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
365 }
366
367 /**
368 * Determines whether or not a given string is a legal token.
369 *
370 * @throws NullPointerException if <code>s</code> is null
371 */
372 private boolean isValidToken(String s) {
373 int len = s.length();
374 if(len > 0) {
375 for (int i = 0; i < len; ++i) {
376 char c = s.charAt(i);
377 if (!isTokenChar(c)) {
378 return false;
379 }
380 }
381 return true;
382 } else {
383 return false;
384 }
385 }
386
387 /**
388 * A string that holds all the special chars.
389 */
390
391 private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
392
393} // class MimeType
java/pkg/java/awt/datatransfer/MimeTypeParameterList.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/MimeTypeParameterList.java+404−0
@@ -0,0 +1,404 @@
1/*
2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.util.Enumeration;
29import java.util.Hashtable;
30import java.util.Iterator;
31import java.util.Map;
32import java.util.Set;
33
34
35/**
36 * An object that encapsualtes the parameter list of a MimeType
37 * as defined in RFC 2045 and 2046.
38 *
39 * @author jeff.dunn@eng.sun.com
40 */
41class MimeTypeParameterList implements Cloneable {
42
43 /**
44 * Default constructor.
45 */
46 public MimeTypeParameterList() {
47 parameters = new Hashtable();
48 }
49
50 public MimeTypeParameterList(String rawdata)
51 throws MimeTypeParseException
52 {
53 parameters = new Hashtable();
54
55 // now parse rawdata
56 parse(rawdata);
57 }
58
59 public int hashCode() {
60 int code = Integer.MAX_VALUE/45; // "random" value for empty lists
61 String paramName = null;
62 Enumeration enum_ = this.getNames();
63
64 while (enum_.hasMoreElements()) {
65 paramName = (String)enum_.nextElement();
66 code += paramName.hashCode();
67 code += this.get(paramName).hashCode();
68 }
69
70 return code;
71 } // hashCode()
72
73 /**
74 * Two parameter lists are considered equal if they have exactly
75 * the same set of parameter names and associated values. The
76 * order of the parameters is not considered.
77 */
78 public boolean equals(Object thatObject) {
79 //System.out.println("MimeTypeParameterList.equals("+this+","+thatObject+")");
80 if (!(thatObject instanceof MimeTypeParameterList)) {
81 return false;
82 }
83 MimeTypeParameterList that = (MimeTypeParameterList)thatObject;
84 if (this.size() != that.size()) {
85 return false;
86 }
87 String name = null;
88 String thisValue = null;
89 String thatValue = null;
90 Set entries = parameters.entrySet();
91 Iterator iterator = entries.iterator();
92 Map.Entry entry = null;
93 while (iterator.hasNext()) {
94 entry = (Map.Entry)iterator.next();
95 name = (String)entry.getKey();
96 thisValue = (String)entry.getValue();
97 thatValue = (String)that.parameters.get(name);
98 if ((thisValue == null) || (thatValue == null)) {
99 // both null -> equal, only one null -> not equal
100 if (thisValue != thatValue) {
101 return false;
102 }
103 } else if (!thisValue.equals(thatValue)) {
104 return false;
105 }
106 } // while iterator
107
108 return true;
109 } // equals()
110
111 /**
112 * A routine for parsing the parameter list out of a String.
113 */
114 protected void parse(String rawdata) throws MimeTypeParseException {
115 int length = rawdata.length();
116 if(length > 0) {
117 int currentIndex = skipWhiteSpace(rawdata, 0);
118 int lastIndex = 0;
119
120 if(currentIndex < length) {
121 char currentChar = rawdata.charAt(currentIndex);
122 while ((currentIndex < length) && (currentChar == ';')) {
123 String name;
124 String value;
125 boolean foundit;
126
127 // eat the ';'
128 ++currentIndex;
129
130 // now parse the parameter name
131
132 // skip whitespace
133 currentIndex = skipWhiteSpace(rawdata, currentIndex);
134
135 if(currentIndex < length) {
136 // find the end of the token char run
137 lastIndex = currentIndex;
138 currentChar = rawdata.charAt(currentIndex);
139 while((currentIndex < length) && isTokenChar(currentChar)) {
140 ++currentIndex;
141 currentChar = rawdata.charAt(currentIndex);
142 }
143 name = rawdata.substring(lastIndex, currentIndex).toLowerCase();
144
145 // now parse the '=' that separates the name from the value
146
147 // skip whitespace
148 currentIndex = skipWhiteSpace(rawdata, currentIndex);
149
150 if((currentIndex < length) && (rawdata.charAt(currentIndex) == '=')) {
151 // eat it and parse the parameter value
152 ++currentIndex;
153
154 // skip whitespace
155 currentIndex = skipWhiteSpace(rawdata, currentIndex);
156
157 if(currentIndex < length) {
158 // now find out whether or not we have a quoted value
159 currentChar = rawdata.charAt(currentIndex);
160 if(currentChar == '"') {
161 // yup it's quoted so eat it and capture the quoted string
162 ++currentIndex;
163 lastIndex = currentIndex;
164
165 if(currentIndex < length) {
166 // find the next unescqped quote
167 foundit = false;
168 while((currentIndex < length) && !foundit) {
169 currentChar = rawdata.charAt(currentIndex);
170 if(currentChar == '\\') {
171 // found an escape sequence so pass this and the next character
172 currentIndex += 2;
173 } else if(currentChar == '"') {
174 // foundit!
175 foundit = true;
176 } else {
177 ++currentIndex;
178 }
179 }
180 if(currentChar == '"') {
181 value = unquote(rawdata.substring(lastIndex, currentIndex));
182 // eat the quote
183 ++currentIndex;
184 } else {
185 throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
186 }
187 } else {
188 throw new MimeTypeParseException("Encountered unterminated quoted parameter value.");
189 }
190 } else if(isTokenChar(currentChar)) {
191 // nope it's an ordinary token so it ends with a non-token char
192 lastIndex = currentIndex;
193 foundit = false;
194 while((currentIndex < length) && !foundit) {
195 currentChar = rawdata.charAt(currentIndex);
196
197 if(isTokenChar(currentChar)) {
198 ++currentIndex;
199 } else {
200 foundit = true;
201 }
202 }
203 value = rawdata.substring(lastIndex, currentIndex);
204 } else {
205 // it ain't a value
206 throw new MimeTypeParseException("Unexpected character encountered at index " + currentIndex);
207 }
208
209 // now put the data into the hashtable
210 parameters.put(name, value);
211 } else {
212 throw new MimeTypeParseException("Couldn't find a value for parameter named " + name);
213 }
214 } else {
215 throw new MimeTypeParseException("Couldn't find the '=' that separates a parameter name from its value.");
216 }
217 } else {
218 throw new MimeTypeParseException("Couldn't find parameter name");
219 }
220
221 // setup the next iteration
222 currentIndex = skipWhiteSpace(rawdata, currentIndex);
223 if(currentIndex < length) {
224 currentChar = rawdata.charAt(currentIndex);
225 }
226 }
227 if(currentIndex < length) {
228 throw new MimeTypeParseException("More characters encountered in input than expected.");
229 }
230 }
231 }
232 }
233
234 /**
235 * return the number of name-value pairs in this list.
236 */
237 public int size() {
238 return parameters.size();
239 }
240
241 /**
242 * Determine whether or not this list is empty.
243 */
244 public boolean isEmpty() {
245 return parameters.isEmpty();
246 }
247
248 /**
249 * Retrieve the value associated with the given name, or null if there
250 * is no current association.
251 */
252 public String get(String name) {
253 return (String)parameters.get(name.trim().toLowerCase());
254 }
255
256 /**
257 * Set the value to be associated with the given name, replacing
258 * any previous association.
259 */
260 public void set(String name, String value) {
261 parameters.put(name.trim().toLowerCase(), value);
262 }
263
264 /**
265 * Remove any value associated with the given name.
266 */
267 public void remove(String name) {
268 parameters.remove(name.trim().toLowerCase());
269 }
270
271 /**
272 * Retrieve an enumeration of all the names in this list.
273 */
274 public Enumeration getNames() {
275 return parameters.keys();
276 }
277
278 public String toString() {
279 // Heuristic: 8 characters per field
280 StringBuilder buffer = new StringBuilder(parameters.size() * 16);
281
282 Enumeration keys = parameters.keys();
283 while(keys.hasMoreElements())
284 {
285 buffer.append("; ");
286
287 String key = (String)keys.nextElement();
288 buffer.append(key);
289 buffer.append('=');
290 buffer.append(quote((String)parameters.get(key)));
291 }
292
293 return buffer.toString();
294 }
295
296 /**
297 * @return a clone of this object
298 */
299
300 public Object clone() {
301 MimeTypeParameterList newObj = null;
302 try {
303 newObj = (MimeTypeParameterList)super.clone();
304 } catch (CloneNotSupportedException cannotHappen) {
305 }
306 newObj.parameters = (Hashtable)parameters.clone();
307 return newObj;
308 }
309
310 private Hashtable parameters;
311
312 // below here be scary parsing related things
313
314 /**
315 * Determine whether or not a given character belongs to a legal token.
316 */
317 private static boolean isTokenChar(char c) {
318 return ((c > 040) && (c < 0177)) && (TSPECIALS.indexOf(c) < 0);
319 }
320
321 /**
322 * return the index of the first non white space character in
323 * rawdata at or after index i.
324 */
325 private static int skipWhiteSpace(String rawdata, int i) {
326 int length = rawdata.length();
327 if (i < length) {
328 char c = rawdata.charAt(i);
329 while ((i < length) && Character.isWhitespace(c)) {
330 ++i;
331 c = rawdata.charAt(i);
332 }
333 }
334
335 return i;
336 }
337
338 /**
339 * A routine that knows how and when to quote and escape the given value.
340 */
341 private static String quote(String value) {
342 boolean needsQuotes = false;
343
344 // check to see if we actually have to quote this thing
345 int length = value.length();
346 for(int i = 0; (i < length) && !needsQuotes; ++i) {
347 needsQuotes = !isTokenChar(value.charAt(i));
348 }
349
350 if(needsQuotes) {
351 StringBuilder buffer = new StringBuilder((int)(length * 1.5));
352
353 // add the initial quote
354 buffer.append('"');
355
356 // add the properly escaped text
357 for(int i = 0; i < length; ++i) {
358 char c = value.charAt(i);
359 if((c == '\\') || (c == '"')) {
360 buffer.append('\\');
361 }
362 buffer.append(c);
363 }
364
365 // add the closing quote
366 buffer.append('"');
367
368 return buffer.toString();
369 }
370 else
371 {
372 return value;
373 }
374 }
375
376 /**
377 * A routine that knows how to strip the quotes and escape sequences from the given value.
378 */
379 private static String unquote(String value) {
380 int valueLength = value.length();
381 StringBuilder buffer = new StringBuilder(valueLength);
382
383 boolean escaped = false;
384 for(int i = 0; i < valueLength; ++i) {
385 char currentChar = value.charAt(i);
386 if(!escaped && (currentChar != '\\')) {
387 buffer.append(currentChar);
388 } else if(escaped) {
389 buffer.append(currentChar);
390 escaped = false;
391 } else {
392 escaped = true;
393 }
394 }
395
396 return buffer.toString();
397 }
398
399 /**
400 * A string that holds all the special chars.
401 */
402 private static final String TSPECIALS = "()<>@,;:\\\"/[]?=";
403
404}
java/pkg/java/awt/datatransfer/MimeTypeParseException.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/MimeTypeParseException.java+55−0
@@ -0,0 +1,55 @@
1/*
2 * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28
29/**
30 * A class to encapsulate MimeType parsing related exceptions
31 *
32 * @serial exclude
33 * @since 1.3
34 */
35public class MimeTypeParseException extends Exception {
36
37 // use serialVersionUID from JDK 1.2.2 for interoperability
38 private static final long serialVersionUID = -5604407764691570741L;
39
40 /**
41 * Constructs a MimeTypeParseException with no specified detail message.
42 */
43 public MimeTypeParseException() {
44 super();
45 }
46
47 /**
48 * Constructs a MimeTypeParseException with the specified detail message.
49 *
50 * @param s the detail message.
51 */
52 public MimeTypeParseException(String s) {
53 super(s);
54 }
55} // class MimeTypeParseException
java/pkg/java/awt/datatransfer/StringSelection.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/StringSelection.java+140−0
@@ -0,0 +1,140 @@
1/*
2 * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.io.*;
29
30/**
31 * A <code>Transferable</code> which implements the capability required
32 * to transfer a <code>String</code>.
33 *
34 * This <code>Transferable</code> properly supports
35 * <code>DataFlavor.stringFlavor</code>
36 * and all equivalent flavors. Support for
37 * <code>DataFlavor.plainTextFlavor</code>
38 * and all equivalent flavors is <b>deprecated</b>. No other
39 * <code>DataFlavor</code>s are supported.
40 *
41 * @see java.awt.datatransfer.DataFlavor#stringFlavor
42 * @see java.awt.datatransfer.DataFlavor#plainTextFlavor
43 */
44public class StringSelection implements Transferable, ClipboardOwner {
45
46 private static final int STRING = 0;
47 private static final int PLAIN_TEXT = 1;
48
49 private static final DataFlavor[] flavors = {
50 DataFlavor.stringFlavor,
51 DataFlavor.plainTextFlavor // deprecated
52 };
53
54 private String data;
55
56 /**
57 * Creates a <code>Transferable</code> capable of transferring
58 * the specified <code>String</code>.
59 */
60 public StringSelection(String data) {
61 this.data = data;
62 }
63
64 /**
65 * Returns an array of flavors in which this <code>Transferable</code>
66 * can provide the data. <code>DataFlavor.stringFlavor</code>
67 * is properly supported.
68 * Support for <code>DataFlavor.plainTextFlavor</code> is
69 * <b>deprecated</b>.
70 *
71 * @return an array of length two, whose elements are <code>DataFlavor.
72 * stringFlavor</code> and <code>DataFlavor.plainTextFlavor</code>
73 */
74 public DataFlavor[] getTransferDataFlavors() {
75 // returning flavors itself would allow client code to modify
76 // our internal behavior
77 return (DataFlavor[])flavors.clone();
78 }
79
80 /**
81 * Returns whether the requested flavor is supported by this
82 * <code>Transferable</code>.
83 *
84 * @param flavor the requested flavor for the data
85 * @return true if <code>flavor</code> is equal to
86 * <code>DataFlavor.stringFlavor</code> or
87 * <code>DataFlavor.plainTextFlavor</code>; false if <code>flavor</code>
88 * is not one of the above flavors
89 * @throws NullPointerException if flavor is <code>null</code>
90 */
91 public boolean isDataFlavorSupported(DataFlavor flavor) {
92 // JCK Test StringSelection0003: if 'flavor' is null, throw NPE
93 for (int i = 0; i < flavors.length; i++) {
94 if (flavor.equals(flavors[i])) {
95 return true;
96 }
97 }
98 return false;
99 }
100
101 /**
102 * Returns the <code>Transferable</code>'s data in the requested
103 * <code>DataFlavor</code> if possible. If the desired flavor is
104 * <code>DataFlavor.stringFlavor</code>, or an equivalent flavor,
105 * the <code>String</code> representing the selection is
106 * returned. If the desired flavor is
107 * <code>DataFlavor.plainTextFlavor</code>,
108 * or an equivalent flavor, a <code>Reader</code> is returned.
109 * <b>Note:</b> The behavior of this method for
110 * <code>DataFlavor.plainTextFlavor</code>
111 * and equivalent <code>DataFlavor</code>s is inconsistent with the
112 * definition of <code>DataFlavor.plainTextFlavor</code>.
113 *
114 * @param flavor the requested flavor for the data
115 * @return the data in the requested flavor, as outlined above
116 * @throws UnsupportedFlavorException if the requested data flavor is
117 * not equivalent to either <code>DataFlavor.stringFlavor</code>
118 * or <code>DataFlavor.plainTextFlavor</code>
119 * @throws IOException if an IOException occurs while retrieving the data.
120 * By default, StringSelection never throws this exception, but a
121 * subclass may.
122 * @throws NullPointerException if flavor is <code>null</code>
123 * @see java.io.Reader
124 */
125 public Object getTransferData(DataFlavor flavor)
126 throws UnsupportedFlavorException, IOException
127 {
128 // JCK Test StringSelection0007: if 'flavor' is null, throw NPE
129 if (flavor.equals(flavors[STRING])) {
130 return (Object)data;
131 } else if (flavor.equals(flavors[PLAIN_TEXT])) {
132 return new StringReader(data == null ? "" : data);
133 } else {
134 throw new UnsupportedFlavorException(flavor);
135 }
136 }
137
138 public void lostOwnership(Clipboard clipboard, Transferable contents) {
139 }
140}
java/pkg/java/awt/datatransfer/SystemFlavorMap$1.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/SystemFlavorMap$2.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/SystemFlavorMap.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/SystemFlavorMap.java+1299−0
@@ -0,0 +1,1299 @@
1/*
2 * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.awt.Toolkit;
29
30import java.lang.ref.SoftReference;
31
32import java.io.BufferedReader;
33import java.io.File;
34import java.io.InputStreamReader;
35import java.io.IOException;
36
37import java.net.URL;
38import java.net.MalformedURLException;
39
40import java.util.ArrayList;
41import java.util.HashMap;
42import java.util.HashSet;
43import java.util.Iterator;
44import java.util.LinkedList;
45import java.util.List;
46import java.util.Map;
47import java.util.Set;
48import java.util.WeakHashMap;
49
50import sun.awt.datatransfer.DataTransferer;
51
52/**
53 * The SystemFlavorMap is a configurable map between "natives" (Strings), which
54 * correspond to platform-specific data formats, and "flavors" (DataFlavors),
55 * which correspond to platform-independent MIME types. This mapping is used
56 * by the data transfer subsystem to transfer data between Java and native
57 * applications, and between Java applications in separate VMs.
58 * <p>
59 * In the Sun reference implementation, the default SystemFlavorMap is
60 * initialized by the file <code>jre/lib/flavormap.properties</code> and the
61 * contents of the URL referenced by the AWT property
62 * <code>AWT.DnD.flavorMapFileURL</code>. See <code>flavormap.properties</code>
63 * for details.
64 *
65 * @since 1.2
66 */
67public final class SystemFlavorMap implements FlavorMap, FlavorTable {
68
69 /**
70 * Constant prefix used to tag Java types converted to native platform
71 * type.
72 */
73 private static String JavaMIME = "JAVA_DATAFLAVOR:";
74
75 /**
76 * System singleton which maps a thread's ClassLoader to a SystemFlavorMap.
77 */
78 private static final WeakHashMap flavorMaps = new WeakHashMap();
79
80 /**
81 * Copied from java.util.Properties.
82 */
83 private static final String keyValueSeparators = "=: \t\r\n\f";
84 private static final String strictKeyValueSeparators = "=:";
85 private static final String whiteSpaceChars = " \t\r\n\f";
86
87 /**
88 * The list of valid, decoded text flavor representation classes, in order
89 * from best to worst.
90 */
91 private static final String[] UNICODE_TEXT_CLASSES = {
92 "java.io.Reader", "java.lang.String", "java.nio.CharBuffer", "\"[C\""
93 };
94
95 /**
96 * The list of valid, encoded text flavor representation classes, in order
97 * from best to worst.
98 */
99 private static final String[] ENCODED_TEXT_CLASSES = {
100 "java.io.InputStream", "java.nio.ByteBuffer", "\"[B\""
101 };
102
103 /**
104 * A String representing text/plain MIME type.
105 */
106 private static final String TEXT_PLAIN_BASE_TYPE = "text/plain";
107
108 /**
109 * This constant is passed to flavorToNativeLookup() to indicate that a
110 * a native should be synthesized, stored, and returned by encoding the
111 * DataFlavor's MIME type in case if the DataFlavor is not found in
112 * 'flavorToNative' map.
113 */
114 private static final boolean SYNTHESIZE_IF_NOT_FOUND = true;
115
116 /**
117 * Maps native Strings to Lists of DataFlavors (or base type Strings for
118 * text DataFlavors).
119 * Do not use the field directly, use getNativeToFlavor() instead.
120 */
121 private Map nativeToFlavor = new HashMap();
122
123 /**
124 * Accessor to nativeToFlavor map. Since we use lazy initialization we must
125 * use this accessor instead of direct access to the field which may not be
126 * initialized yet. This method will initialize the field if needed.
127 *
128 * @return nativeToFlavor
129 */
130 private Map getNativeToFlavor() {
131 if (!isMapInitialized) {
132 initSystemFlavorMap();
133 }
134 return nativeToFlavor;
135 }
136
137 /**
138 * Maps DataFlavors (or base type Strings for text DataFlavors) to Lists of
139 * native Strings.
140 * Do not use the field directly, use getFlavorToNative() instead.
141 */
142 private Map flavorToNative = new HashMap();
143
144 /**
145 * Accessor to flavorToNative map. Since we use lazy initialization we must
146 * use this accessor instead of direct access to the field which may not be
147 * initialized yet. This method will initialize the field if needed.
148 *
149 * @return flavorToNative
150 */
151 private synchronized Map getFlavorToNative() {
152 if (!isMapInitialized) {
153 initSystemFlavorMap();
154 }
155 return flavorToNative;
156 }
157
158 /**
159 * Shows if the object has been initialized.
160 */
161 private boolean isMapInitialized = false;
162
163 /**
164 * Caches the result of getNativesForFlavor(). Maps DataFlavors to
165 * SoftReferences which reference Lists of String natives.
166 */
167 private Map getNativesForFlavorCache = new HashMap();
168
169 /**
170 * Caches the result getFlavorsForNative(). Maps String natives to
171 * SoftReferences which reference Lists of DataFlavors.
172 */
173 private Map getFlavorsForNativeCache = new HashMap();
174
175 /**
176 * Dynamic mapping generation used for text mappings should not be applied
177 * to the DataFlavors and String natives for which the mappings have been
178 * explicitly specified with setFlavorsForNative() or
179 * setNativesForFlavor(). This keeps all such keys.
180 */
181 private Set disabledMappingGenerationKeys = new HashSet();
182
183 /**
184 * Returns the default FlavorMap for this thread's ClassLoader.
185 */
186 public static FlavorMap getDefaultFlavorMap() {
187 ClassLoader contextClassLoader =
188 Thread.currentThread().getContextClassLoader();
189 if (contextClassLoader == null) {
190 contextClassLoader = ClassLoader.getSystemClassLoader();
191 }
192
193 FlavorMap fm;
194
195 synchronized(flavorMaps) {
196 fm = (FlavorMap)flavorMaps.get(contextClassLoader);
197 if (fm == null) {
198 fm = new SystemFlavorMap();
199 flavorMaps.put(contextClassLoader, fm);
200 }
201 }
202
203 return fm;
204 }
205
206 private SystemFlavorMap() {
207 }
208
209 /**
210 * Initializes a SystemFlavorMap by reading flavormap.properties and
211 * AWT.DnD.flavorMapFileURL.
212 * For thread-safety must be called under lock on this.
213 */
214 private void initSystemFlavorMap() {
215 if (isMapInitialized) {
216 return;
217 }
218
219 isMapInitialized = true;
220 BufferedReader flavormapDotProperties =
221 java.security.AccessController.doPrivileged(
222 new java.security.PrivilegedAction<BufferedReader>() {
223 public BufferedReader run() {
224 String fileName =
225 System.getProperty("java.home") +
226 File.separator +
227 "lib" +
228 File.separator +
229 "flavormap.properties";
230 try {
231 return new BufferedReader
232 (new InputStreamReader
233 (new File(fileName).toURI().toURL().openStream(), "ISO-8859-1"));
234 } catch (MalformedURLException e) {
235 System.err.println("MalformedURLException:" + e + " while loading default flavormap.properties file:" + fileName);
236 } catch (IOException e) {
237 System.err.println("IOException:" + e + " while loading default flavormap.properties file:" + fileName);
238 }
239 return null;
240 }
241 });
242
243 BufferedReader flavormapURL =
244 java.security.AccessController.doPrivileged(
245 new java.security.PrivilegedAction<BufferedReader>() {
246 public BufferedReader run() {
247 String url = Toolkit.getProperty("AWT.DnD.flavorMapFileURL", null);
248
249 if (url == null) {
250 return null;
251 }
252
253 try {
254 return new BufferedReader
255 (new InputStreamReader
256 (new URL(url).openStream(), "ISO-8859-1"));
257 } catch (MalformedURLException e) {
258 System.err.println("MalformedURLException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
259 } catch (IOException e) {
260 System.err.println("IOException:" + e + " while reading AWT.DnD.flavorMapFileURL:" + url);
261 }
262 return null;
263 }
264 });
265
266 if (flavormapDotProperties != null) {
267 try {
268 parseAndStoreReader(flavormapDotProperties);
269 } catch (IOException e) {
270 System.err.println("IOException:" + e + " while parsing default flavormap.properties file");
271 }
272 }
273
274 if (flavormapURL != null) {
275 try {
276 parseAndStoreReader(flavormapURL);
277 } catch (IOException e) {
278 System.err.println("IOException:" + e + " while parsing AWT.DnD.flavorMapFileURL");
279 }
280 }
281 }
282 /**
283 * Copied code from java.util.Properties. Parsing the data ourselves is the
284 * only way to handle duplicate keys and values.
285 */
286 private void parseAndStoreReader(BufferedReader in) throws IOException {
287 while (true) {
288 // Get next line
289 String line = in.readLine();
290 if (line == null) {
291 return;
292 }
293
294 if (line.length() > 0) {
295 // Continue lines that end in slashes if they are not comments
296 char firstChar = line.charAt(0);
297 if (firstChar != '#' && firstChar != '!') {
298 while (continueLine(line)) {
299 String nextLine = in.readLine();
300 if (nextLine == null) {
301 nextLine = "";
302 }
303 String loppedLine =
304 line.substring(0, line.length() - 1);
305 // Advance beyond whitespace on new line
306 int startIndex = 0;
307 for(; startIndex < nextLine.length(); startIndex++) {
308 if (whiteSpaceChars.
309 indexOf(nextLine.charAt(startIndex)) == -1)
310 {
311 break;
312 }
313 }
314 nextLine = nextLine.substring(startIndex,
315 nextLine.length());
316 line = loppedLine+nextLine;
317 }
318
319 // Find start of key
320 int len = line.length();
321 int keyStart = 0;
322 for(; keyStart < len; keyStart++) {
323 if(whiteSpaceChars.
324 indexOf(line.charAt(keyStart)) == -1) {
325 break;
326 }
327 }
328
329 // Blank lines are ignored
330 if (keyStart == len) {
331 continue;
332 }
333
334 // Find separation between key and value
335 int separatorIndex = keyStart;
336 for(; separatorIndex < len; separatorIndex++) {
337 char currentChar = line.charAt(separatorIndex);
338 if (currentChar == '\\') {
339 separatorIndex++;
340 } else if (keyValueSeparators.
341 indexOf(currentChar) != -1) {
342 break;
343 }
344 }
345
346 // Skip over whitespace after key if any
347 int valueIndex = separatorIndex;
348 for (; valueIndex < len; valueIndex++) {
349 if (whiteSpaceChars.
350 indexOf(line.charAt(valueIndex)) == -1) {
351 break;
352 }
353 }
354
355 // Skip over one non whitespace key value separators if any
356 if (valueIndex < len) {
357 if (strictKeyValueSeparators.
358 indexOf(line.charAt(valueIndex)) != -1) {
359 valueIndex++;
360 }
361 }
362
363 // Skip over white space after other separators if any
364 while (valueIndex < len) {
365 if (whiteSpaceChars.
366 indexOf(line.charAt(valueIndex)) == -1) {
367 break;
368 }
369 valueIndex++;
370 }
371
372 String key = line.substring(keyStart, separatorIndex);
373 String value = (separatorIndex < len)
374 ? line.substring(valueIndex, len)
375 : "";
376
377 // Convert then store key and value
378 key = loadConvert(key);
379 value = loadConvert(value);
380
381 try {
382 MimeType mime = new MimeType(value);
383 if ("text".equals(mime.getPrimaryType())) {
384 String charset = mime.getParameter("charset");
385 if (DataTransferer.doesSubtypeSupportCharset
386 (mime.getSubType(), charset))
387 {
388 // We need to store the charset and eoln
389 // parameters, if any, so that the
390 // DataTransferer will have this information
391 // for conversion into the native format.
392 DataTransferer transferer =
393 DataTransferer.getInstance();
394 if (transferer != null) {
395 transferer.registerTextFlavorProperties
396 (key, charset,
397 mime.getParameter("eoln"),
398 mime.getParameter("terminators"));
399 }
400 }
401
402 // But don't store any of these parameters in the
403 // DataFlavor itself for any text natives (even
404 // non-charset ones). The SystemFlavorMap will
405 // synthesize the appropriate mappings later.
406 mime.removeParameter("charset");
407 mime.removeParameter("class");
408 mime.removeParameter("eoln");
409 mime.removeParameter("terminators");
410 value = mime.toString();
411 }
412 } catch (MimeTypeParseException e) {
413 e.printStackTrace();
414 continue;
415 }
416
417 DataFlavor flavor;
418 try {
419 flavor = new DataFlavor(value);
420 } catch (Exception e) {
421 try {
422 flavor = new DataFlavor(value, (String)null);
423 } catch (Exception ee) {
424 ee.printStackTrace();
425 continue;
426 }
427 }
428
429 // For text/* flavors, store mappings in separate maps to
430 // enable dynamic mapping generation at a run-time.
431 if ("text".equals(flavor.getPrimaryType())) {
432 store(value, key, getFlavorToNative());
433 store(key, value, getNativeToFlavor());
434 } else {
435 store(flavor, key, getFlavorToNative());
436 store(key, flavor, getNativeToFlavor());
437 }
438 }
439 }
440 }
441 }
442
443 /**
444 * Copied from java.util.Properties.
445 */
446 private boolean continueLine (String line) {
447 int slashCount = 0;
448 int index = line.length() - 1;
449 while((index >= 0) && (line.charAt(index--) == '\\')) {
450 slashCount++;
451 }
452 return (slashCount % 2 == 1);
453 }
454
455 /**
456 * Copied from java.util.Properties.
457 */
458 private String loadConvert(String theString) {
459 char aChar;
460 int len = theString.length();
461 StringBuilder outBuffer = new StringBuilder(len);
462
463 for (int x = 0; x < len; ) {
464 aChar = theString.charAt(x++);
465 if (aChar == '\\') {
466 aChar = theString.charAt(x++);
467 if (aChar == 'u') {
468 // Read the xxxx
469 int value = 0;
470 for (int i = 0; i < 4; i++) {
471 aChar = theString.charAt(x++);
472 switch (aChar) {
473 case '0': case '1': case '2': case '3': case '4':
474 case '5': case '6': case '7': case '8': case '9': {
475 value = (value << 4) + aChar - '0';
476 break;
477 }
478 case 'a': case 'b': case 'c':
479 case 'd': case 'e': case 'f': {
480 value = (value << 4) + 10 + aChar - 'a';
481 break;
482 }
483 case 'A': case 'B': case 'C':
484 case 'D': case 'E': case 'F': {
485 value = (value << 4) + 10 + aChar - 'A';
486 break;
487 }
488 default: {
489 throw new IllegalArgumentException(
490 "Malformed \\uxxxx encoding.");
491 }
492 }
493 }
494 outBuffer.append((char)value);
495 } else {
496 if (aChar == 't') {
497 aChar = '\t';
498 } else if (aChar == 'r') {
499 aChar = '\r';
500 } else if (aChar == 'n') {
501 aChar = '\n';
502 } else if (aChar == 'f') {
503 aChar = '\f';
504 }
505 outBuffer.append(aChar);
506 }
507 } else {
508 outBuffer.append(aChar);
509 }
510 }
511 return outBuffer.toString();
512 }
513
514 /**
515 * Stores the listed object under the specified hash key in map. Unlike a
516 * standard map, the listed object will not replace any object already at
517 * the appropriate Map location, but rather will be appended to a List
518 * stored in that location.
519 */
520 private void store(Object hashed, Object listed, Map map) {
521 List list = (List)map.get(hashed);
522 if (list == null) {
523 list = new ArrayList(1);
524 map.put(hashed, list);
525 }
526 if (!list.contains(listed)) {
527 list.add(listed);
528 }
529 }
530
531 /**
532 * Semantically equivalent to 'nativeToFlavor.get(nat)'. This method
533 * handles the case where 'nat' is not found in 'nativeToFlavor'. In that
534 * case, a new DataFlavor is synthesized, stored, and returned, if and
535 * only if the specified native is encoded as a Java MIME type.
536 */
537 private List nativeToFlavorLookup(String nat) {
538 List flavors = (List)getNativeToFlavor().get(nat);
539
540 if (nat != null && !disabledMappingGenerationKeys.contains(nat)) {
541 DataTransferer transferer = DataTransferer.getInstance();
542 if (transferer != null) {
543 List platformFlavors =
544 transferer.getPlatformMappingsForNative(nat);
545 if (!platformFlavors.isEmpty()) {
546 if (flavors != null) {
547 platformFlavors.removeAll(new HashSet(flavors));
548 // Prepending the platform-specific mappings ensures
549 // that the flavors added with
550 // addFlavorForUnencodedNative() are at the end of
551 // list.
552 platformFlavors.addAll(flavors);
553 }
554 flavors = platformFlavors;
555 }
556 }
557 }
558
559 if (flavors == null && isJavaMIMEType(nat)) {
560 String decoded = decodeJavaMIMEType(nat);
561 DataFlavor flavor = null;
562
563 try {
564 flavor = new DataFlavor(decoded);
565 } catch (Exception e) {
566 System.err.println("Exception \"" + e.getClass().getName() +
567 ": " + e.getMessage() +
568 "\"while constructing DataFlavor for: " +
569 decoded);
570 }
571
572 if (flavor != null) {
573 flavors = new ArrayList(1);
574 getNativeToFlavor().put(nat, flavors);
575 flavors.add(flavor);
576 getFlavorsForNativeCache.remove(nat);
577 getFlavorsForNativeCache.remove(null);
578
579 List natives = (List)getFlavorToNative().get(flavor);
580 if (natives == null) {
581 natives = new ArrayList(1);
582 getFlavorToNative().put(flavor, natives);
583 }
584 natives.add(nat);
585 getNativesForFlavorCache.remove(flavor);
586 getNativesForFlavorCache.remove(null);
587 }
588 }
589
590 return (flavors != null) ? flavors : new ArrayList(0);
591 }
592
593 /**
594 * Semantically equivalent to 'flavorToNative.get(flav)'. This method
595 * handles the case where 'flav' is not found in 'flavorToNative' depending
596 * on the value of passes 'synthesize' parameter. If 'synthesize' is
597 * SYNTHESIZE_IF_NOT_FOUND a native is synthesized, stored, and returned by
598 * encoding the DataFlavor's MIME type. Otherwise an empty List is returned
599 * and 'flavorToNative' remains unaffected.
600 */
601 private List flavorToNativeLookup(final DataFlavor flav,
602 final boolean synthesize) {
603 List natives = (List)getFlavorToNative().get(flav);
604
605 if (flav != null && !disabledMappingGenerationKeys.contains(flav)) {
606 DataTransferer transferer = DataTransferer.getInstance();
607 if (transferer != null) {
608 List platformNatives =
609 transferer.getPlatformMappingsForFlavor(flav);
610 if (!platformNatives.isEmpty()) {
611 if (natives != null) {
612 platformNatives.removeAll(new HashSet(natives));
613 // Prepend the platform-specific mappings to ensure
614 // that the natives added with
615 // addUnencodedNativeForFlavor() are at the end of
616 // list.
617 platformNatives.addAll(natives);
618 }
619 natives = platformNatives;
620 }
621 }
622 }
623
624 if (natives == null) {
625 if (synthesize) {
626 String encoded = encodeDataFlavor(flav);
627 natives = new ArrayList(1);
628 getFlavorToNative().put(flav, natives);
629 natives.add(encoded);
630 getNativesForFlavorCache.remove(flav);
631 getNativesForFlavorCache.remove(null);
632
633 List flavors = (List)getNativeToFlavor().get(encoded);
634 if (flavors == null) {
635 flavors = new ArrayList(1);
636 getNativeToFlavor().put(encoded, flavors);
637 }
638 flavors.add(flav);
639 getFlavorsForNativeCache.remove(encoded);
640 getFlavorsForNativeCache.remove(null);
641 } else {
642 natives = new ArrayList(0);
643 }
644 }
645
646 return natives;
647 }
648
649 /**
650 * Returns a <code>List</code> of <code>String</code> natives to which the
651 * specified <code>DataFlavor</code> can be translated by the data transfer
652 * subsystem. The <code>List</code> will be sorted from best native to
653 * worst. That is, the first native will best reflect data in the specified
654 * flavor to the underlying native platform.
655 * <p>
656 * If the specified <code>DataFlavor</code> is previously unknown to the
657 * data transfer subsystem and the data transfer subsystem is unable to
658 * translate this <code>DataFlavor</code> to any existing native, then
659 * invoking this method will establish a
660 * mapping in both directions between the specified <code>DataFlavor</code>
661 * and an encoded version of its MIME type as its native.
662 *
663 * @param flav the <code>DataFlavor</code> whose corresponding natives
664 * should be returned. If <code>null</code> is specified, all
665 * natives currently known to the data transfer subsystem are
666 * returned in a non-deterministic order.
667 * @return a <code>java.util.List</code> of <code>java.lang.String</code>
668 * objects which are platform-specific representations of platform-
669 * specific data formats
670 *
671 * @see #encodeDataFlavor
672 * @since 1.4
673 */
674 public synchronized List<String> getNativesForFlavor(DataFlavor flav) {
675 List retval = null;
676
677 // Check cache, even for null flav
678 SoftReference ref = (SoftReference)getNativesForFlavorCache.get(flav);
679 if (ref != null) {
680 retval = (List)ref.get();
681 if (retval != null) {
682 // Create a copy, because client code can modify the returned
683 // list.
684 return new ArrayList(retval);
685 }
686 }
687
688 if (flav == null) {
689 retval = new ArrayList(getNativeToFlavor().keySet());
690 } else if (disabledMappingGenerationKeys.contains(flav)) {
691 // In this case we shouldn't synthesize a native for this flavor,
692 // since its mappings were explicitly specified.
693 retval = flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND);
694 } else if (DataTransferer.isFlavorCharsetTextType(flav)) {
695
696 // For text/* flavors, flavor-to-native mappings specified in
697 // flavormap.properties are stored per flavor's base type.
698 if ("text".equals(flav.getPrimaryType())) {
699 retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
700 if (retval != null) {
701 // To prevent the List stored in the map from modification.
702 retval = new ArrayList(retval);
703 }
704 }
705
706 // Also include text/plain natives, but don't duplicate Strings
707 List textPlainList = (List)getFlavorToNative().get(TEXT_PLAIN_BASE_TYPE);
708
709 if (textPlainList != null && !textPlainList.isEmpty()) {
710 // To prevent the List stored in the map from modification.
711 // This also guarantees that removeAll() is supported.
712 textPlainList = new ArrayList(textPlainList);
713 if (retval != null && !retval.isEmpty()) {
714 // Use HashSet to get constant-time performance for search.
715 textPlainList.removeAll(new HashSet(retval));
716 retval.addAll(textPlainList);
717 } else {
718 retval = textPlainList;
719 }
720 }
721
722 if (retval == null || retval.isEmpty()) {
723 retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND);
724 } else {
725 // In this branch it is guaranteed that natives explicitly
726 // listed for flav's MIME type were added with
727 // addUnencodedNativeForFlavor(), so they have lower priority.
728 List explicitList =
729 flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND);
730
731 // flavorToNativeLookup() never returns null.
732 // It can return an empty List, however.
733 if (!explicitList.isEmpty()) {
734 // To prevent the List stored in the map from modification.
735 // This also guarantees that removeAll() is supported.
736 explicitList = new ArrayList(explicitList);
737 // Use HashSet to get constant-time performance for search.
738 explicitList.removeAll(new HashSet(retval));
739 retval.addAll(explicitList);
740 }
741 }
742 } else if (DataTransferer.isFlavorNoncharsetTextType(flav)) {
743 retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType());
744
745 if (retval == null || retval.isEmpty()) {
746 retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND);
747 } else {
748 // In this branch it is guaranteed that natives explicitly
749 // listed for flav's MIME type were added with
750 // addUnencodedNativeForFlavor(), so they have lower priority.
751 List explicitList =
752 flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND);
753
754 // flavorToNativeLookup() never returns null.
755 // It can return an empty List, however.
756 if (!explicitList.isEmpty()) {
757 // To prevent the List stored in the map from modification.
758 // This also guarantees that add/removeAll() are supported.
759 retval = new ArrayList(retval);
760 explicitList = new ArrayList(explicitList);
761 // Use HashSet to get constant-time performance for search.
762 explicitList.removeAll(new HashSet(retval));
763 retval.addAll(explicitList);
764 }
765 }
766 } else {
767 retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND);
768 }
769
770 getNativesForFlavorCache.put(flav, new SoftReference(retval));
771 // Create a copy, because client code can modify the returned list.
772 return new ArrayList(retval);
773 }
774
775 /**
776 * Returns a <code>List</code> of <code>DataFlavor</code>s to which the
777 * specified <code>String</code> native can be translated by the data
778 * transfer subsystem. The <code>List</code> will be sorted from best
779 * <code>DataFlavor</code> to worst. That is, the first
780 * <code>DataFlavor</code> will best reflect data in the specified
781 * native to a Java application.
782 * <p>
783 * If the specified native is previously unknown to the data transfer
784 * subsystem, and that native has been properly encoded, then invoking this
785 * method will establish a mapping in both directions between the specified
786 * native and a <code>DataFlavor</code> whose MIME type is a decoded
787 * version of the native.
788 * <p>
789 * If the specified native is not a properly encoded native and the
790 * mappings for this native have not been altered with
791 * <code>setFlavorsForNative</code>, then the contents of the
792 * <code>List</code> is platform dependent, but <code>null</code>
793 * cannot be returned.
794 *
795 * @param nat the native whose corresponding <code>DataFlavor</code>s
796 * should be returned. If <code>null</code> is specified, all
797 * <code>DataFlavor</code>s currently known to the data transfer
798 * subsystem are returned in a non-deterministic order.
799 * @return a <code>java.util.List</code> of <code>DataFlavor</code>
800 * objects into which platform-specific data in the specified,
801 * platform-specific native can be translated
802 *
803 * @see #encodeJavaMIMEType
804 * @since 1.4
805 */
806 public synchronized List<DataFlavor> getFlavorsForNative(String nat) {
807
808 // Check cache, even for null nat
809 SoftReference ref = (SoftReference)getFlavorsForNativeCache.get(nat);
810 if (ref != null) {
811 ArrayList retval = (ArrayList)ref.get();
812 if (retval != null) {
813 return (List)retval.clone();
814 }
815 }
816
817 LinkedList retval = new LinkedList();
818
819 if (nat == null) {
820 List natives = getNativesForFlavor(null);
821 HashSet dups = new HashSet(natives.size());
822
823 for (Iterator natives_iter = natives.iterator();
824 natives_iter.hasNext(); )
825 {
826 List flavors =
827 getFlavorsForNative((String)natives_iter.next());
828 for (Iterator flavors_iter = flavors.iterator();
829 flavors_iter.hasNext(); )
830 {
831 Object flavor = flavors_iter.next();
832 if (dups.add(flavor)) {
833 retval.add(flavor);
834 }
835 }
836 }
837 } else {
838 List flavors = nativeToFlavorLookup(nat);
839
840 if (disabledMappingGenerationKeys.contains(nat)) {
841 return flavors;
842 }
843
844 HashSet dups = new HashSet(flavors.size());
845
846 List flavorsAndbaseTypes = nativeToFlavorLookup(nat);
847
848 for (Iterator flavorsAndbaseTypes_iter =
849 flavorsAndbaseTypes.iterator();
850 flavorsAndbaseTypes_iter.hasNext(); )
851 {
852 Object value = flavorsAndbaseTypes_iter.next();
853 if (value instanceof String) {
854 String baseType = (String)value;
855 String subType = null;
856 try {
857 MimeType mimeType = new MimeType(baseType);
858 subType = mimeType.getSubType();
859 } catch (MimeTypeParseException mtpe) {
860 // Cannot happen, since we checked all mappings
861 // on load from flavormap.properties.
862 assert(false);
863 }
864 if (DataTransferer.doesSubtypeSupportCharset(subType,
865 null)) {
866 if (TEXT_PLAIN_BASE_TYPE.equals(baseType) &&
867 dups.add(DataFlavor.stringFlavor))
868 {
869 retval.add(DataFlavor.stringFlavor);
870 }
871
872 for (int i = 0; i < UNICODE_TEXT_CLASSES.length; i++) {
873 DataFlavor toAdd = null;
874 try {
875 toAdd = new DataFlavor
876 (baseType + ";charset=Unicode;class=" +
877 UNICODE_TEXT_CLASSES[i]);
878 } catch (ClassNotFoundException cannotHappen) {
879 }
880 if (dups.add(toAdd)) {
881 retval.add(toAdd);
882 }
883 }
884
885 for (Iterator charset_iter =
886 DataTransferer.standardEncodings();
887 charset_iter.hasNext(); )
888 {
889 String charset = (String)charset_iter.next();
890
891 for (int i = 0; i < ENCODED_TEXT_CLASSES.length;
892 i++)
893 {
894 DataFlavor toAdd = null;
895 try {
896 toAdd = new DataFlavor
897 (baseType + ";charset=" + charset +
898 ";class=" + ENCODED_TEXT_CLASSES[i]);
899 } catch (ClassNotFoundException cannotHappen) {
900 }
901
902 // Check for equality to plainTextFlavor so
903 // that we can ensure that the exact charset of
904 // plainTextFlavor, not the canonical charset
905 // or another equivalent charset with a
906 // different name, is used.
907 if (toAdd.equals(DataFlavor.plainTextFlavor)) {
908 toAdd = DataFlavor.plainTextFlavor;
909 }
910
911 if (dups.add(toAdd)) {
912 retval.add(toAdd);
913 }
914 }
915 }
916
917 if (TEXT_PLAIN_BASE_TYPE.equals(baseType) &&
918 dups.add(DataFlavor.plainTextFlavor))
919 {
920 retval.add(DataFlavor.plainTextFlavor);
921 }
922 } else {
923 // Non-charset text natives should be treated as
924 // opaque, 8-bit data in any of its various
925 // representations.
926 for (int i = 0; i < ENCODED_TEXT_CLASSES.length; i++) {
927 DataFlavor toAdd = null;
928 try {
929 toAdd = new DataFlavor(baseType +
930 ";class=" + ENCODED_TEXT_CLASSES[i]);
931 } catch (ClassNotFoundException cannotHappen) {
932 }
933
934 if (dups.add(toAdd)) {
935 retval.add(toAdd);
936 }
937 }
938 }
939 } else {
940 DataFlavor flavor = (DataFlavor)value;
941 if (dups.add(flavor)) {
942 retval.add(flavor);
943 }
944 }
945 }
946 }
947
948 ArrayList arrayList = new ArrayList(retval);
949 getFlavorsForNativeCache.put(nat, new SoftReference(arrayList));
950 return (List)arrayList.clone();
951 }
952
953 /**
954 * Returns a <code>Map</code> of the specified <code>DataFlavor</code>s to
955 * their most preferred <code>String</code> native. Each native value will
956 * be the same as the first native in the List returned by
957 * <code>getNativesForFlavor</code> for the specified flavor.
958 * <p>
959 * If a specified <code>DataFlavor</code> is previously unknown to the
960 * data transfer subsystem, then invoking this method will establish a
961 * mapping in both directions between the specified <code>DataFlavor</code>
962 * and an encoded version of its MIME type as its native.
963 *
964 * @param flavors an array of <code>DataFlavor</code>s which will be the
965 * key set of the returned <code>Map</code>. If <code>null</code> is
966 * specified, a mapping of all <code>DataFlavor</code>s known to the
967 * data transfer subsystem to their most preferred
968 * <code>String</code> natives will be returned.
969 * @return a <code>java.util.Map</code> of <code>DataFlavor</code>s to
970 * <code>String</code> natives
971 *
972 * @see #getNativesForFlavor
973 * @see #encodeDataFlavor
974 */
975 public synchronized Map<DataFlavor,String>
976 getNativesForFlavors(DataFlavor[] flavors)
977 {
978 // Use getNativesForFlavor to generate extra natives for text flavors
979 // and stringFlavor
980
981 if (flavors == null) {
982 List flavor_list = getFlavorsForNative(null);
983 flavors = new DataFlavor[flavor_list.size()];
984 flavor_list.toArray(flavors);
985 }
986
987 HashMap retval = new HashMap(flavors.length, 1.0f);
988 for (int i = 0; i < flavors.length; i++) {
989 List natives = getNativesForFlavor(flavors[i]);
990 String nat = (natives.isEmpty()) ? null : (String)natives.get(0);
991 retval.put(flavors[i], nat);
992 }
993
994 return retval;
995 }
996
997 /**
998 * Returns a <code>Map</code> of the specified <code>String</code> natives
999 * to their most preferred <code>DataFlavor</code>. Each
1000 * <code>DataFlavor</code> value will be the same as the first
1001 * <code>DataFlavor</code> in the List returned by
1002 * <code>getFlavorsForNative</code> for the specified native.
1003 * <p>
1004 * If a specified native is previously unknown to the data transfer
1005 * subsystem, and that native has been properly encoded, then invoking this
1006 * method will establish a mapping in both directions between the specified
1007 * native and a <code>DataFlavor</code> whose MIME type is a decoded
1008 * version of the native.
1009 *
1010 * @param natives an array of <code>String</code>s which will be the
1011 * key set of the returned <code>Map</code>. If <code>null</code> is
1012 * specified, a mapping of all supported <code>String</code> natives
1013 * to their most preferred <code>DataFlavor</code>s will be
1014 * returned.
1015 * @return a <code>java.util.Map</code> of <code>String</code> natives to
1016 * <code>DataFlavor</code>s
1017 *
1018 * @see #getFlavorsForNative
1019 * @see #encodeJavaMIMEType
1020 */
1021 public synchronized Map<String,DataFlavor>
1022 getFlavorsForNatives(String[] natives)
1023 {
1024 // Use getFlavorsForNative to generate extra flavors for text natives
1025
1026 if (natives == null) {
1027 List native_list = getNativesForFlavor(null);
1028 natives = new String[native_list.size()];
1029 native_list.toArray(natives);
1030 }
1031
1032 HashMap retval = new HashMap(natives.length, 1.0f);
1033 for (int i = 0; i < natives.length; i++) {
1034 List flavors = getFlavorsForNative(natives[i]);
1035 DataFlavor flav = (flavors.isEmpty())
1036 ? null : (DataFlavor)flavors.get(0);
1037 retval.put(natives[i], flav);
1038 }
1039
1040 return retval;
1041 }
1042
1043 /**
1044 * Adds a mapping from the specified <code>DataFlavor</code> (and all
1045 * <code>DataFlavor</code>s equal to the specified <code>DataFlavor</code>)
1046 * to the specified <code>String</code> native.
1047 * Unlike <code>getNativesForFlavor</code>, the mapping will only be
1048 * established in one direction, and the native will not be encoded. To
1049 * establish a two-way mapping, call
1050 * <code>addFlavorForUnencodedNative</code> as well. The new mapping will
1051 * be of lower priority than any existing mapping.
1052 * This method has no effect if a mapping from the specified or equal
1053 * <code>DataFlavor</code> to the specified <code>String</code> native
1054 * already exists.
1055 *
1056 * @param flav the <code>DataFlavor</code> key for the mapping
1057 * @param nat the <code>String</code> native value for the mapping
1058 * @throws NullPointerException if flav or nat is <code>null</code>
1059 *
1060 * @see #addFlavorForUnencodedNative
1061 * @since 1.4
1062 */
1063 public synchronized void addUnencodedNativeForFlavor(DataFlavor flav,
1064 String nat) {
1065 if (flav == null || nat == null) {
1066 throw new NullPointerException("null arguments not permitted");
1067 }
1068
1069 List natives = (List)getFlavorToNative().get(flav);
1070 if (natives == null) {
1071 natives = new ArrayList(1);
1072 getFlavorToNative().put(flav, natives);
1073 } else if (natives.contains(nat)) {
1074 return;
1075 }
1076 natives.add(nat);
1077 getNativesForFlavorCache.remove(flav);
1078 getNativesForFlavorCache.remove(null);
1079 }
1080
1081 /**
1082 * Discards the current mappings for the specified <code>DataFlavor</code>
1083 * and all <code>DataFlavor</code>s equal to the specified
1084 * <code>DataFlavor</code>, and creates new mappings to the
1085 * specified <code>String</code> natives.
1086 * Unlike <code>getNativesForFlavor</code>, the mappings will only be
1087 * established in one direction, and the natives will not be encoded. To
1088 * establish two-way mappings, call <code>setFlavorsForNative</code>
1089 * as well. The first native in the array will represent the highest
1090 * priority mapping. Subsequent natives will represent mappings of
1091 * decreasing priority.
1092 * <p>
1093 * If the array contains several elements that reference equal
1094 * <code>String</code> natives, this method will establish new mappings
1095 * for the first of those elements and ignore the rest of them.
1096 * <p>
1097 * It is recommended that client code not reset mappings established by the
1098 * data transfer subsystem. This method should only be used for
1099 * application-level mappings.
1100 *
1101 * @param flav the <code>DataFlavor</code> key for the mappings
1102 * @param natives the <code>String</code> native values for the mappings
1103 * @throws NullPointerException if flav or natives is <code>null</code>
1104 * or if natives contains <code>null</code> elements
1105 *
1106 * @see #setFlavorsForNative
1107 * @since 1.4
1108 */
1109 public synchronized void setNativesForFlavor(DataFlavor flav,
1110 String[] natives) {
1111 if (flav == null || natives == null) {
1112 throw new NullPointerException("null arguments not permitted");
1113 }
1114
1115 getFlavorToNative().remove(flav);
1116 for (int i = 0; i < natives.length; i++) {
1117 addUnencodedNativeForFlavor(flav, natives[i]);
1118 }
1119 disabledMappingGenerationKeys.add(flav);
1120 // Clear the cache to handle the case of empty natives.
1121 getNativesForFlavorCache.remove(flav);
1122 getNativesForFlavorCache.remove(null);
1123 }
1124
1125 /**
1126 * Adds a mapping from a single <code>String</code> native to a single
1127 * <code>DataFlavor</code>. Unlike <code>getFlavorsForNative</code>, the
1128 * mapping will only be established in one direction, and the native will
1129 * not be encoded. To establish a two-way mapping, call
1130 * <code>addUnencodedNativeForFlavor</code> as well. The new mapping will
1131 * be of lower priority than any existing mapping.
1132 * This method has no effect if a mapping from the specified
1133 * <code>String</code> native to the specified or equal
1134 * <code>DataFlavor</code> already exists.
1135 *
1136 * @param nat the <code>String</code> native key for the mapping
1137 * @param flav the <code>DataFlavor</code> value for the mapping
1138 * @throws NullPointerException if nat or flav is <code>null</code>
1139 *
1140 * @see #addUnencodedNativeForFlavor
1141 * @since 1.4
1142 */
1143 public synchronized void addFlavorForUnencodedNative(String nat,
1144 DataFlavor flav) {
1145 if (nat == null || flav == null) {
1146 throw new NullPointerException("null arguments not permitted");
1147 }
1148
1149 List flavors = (List)getNativeToFlavor().get(nat);
1150 if (flavors == null) {
1151 flavors = new ArrayList(1);
1152 getNativeToFlavor().put(nat, flavors);
1153 } else if (flavors.contains(flav)) {
1154 return;
1155 }
1156 flavors.add(flav);
1157 getFlavorsForNativeCache.remove(nat);
1158 getFlavorsForNativeCache.remove(null);
1159 }
1160
1161 /**
1162 * Discards the current mappings for the specified <code>String</code>
1163 * native, and creates new mappings to the specified
1164 * <code>DataFlavor</code>s. Unlike <code>getFlavorsForNative</code>, the
1165 * mappings will only be established in one direction, and the natives need
1166 * not be encoded. To establish two-way mappings, call
1167 * <code>setNativesForFlavor</code> as well. The first
1168 * <code>DataFlavor</code> in the array will represent the highest priority
1169 * mapping. Subsequent <code>DataFlavor</code>s will represent mappings of
1170 * decreasing priority.
1171 * <p>
1172 * If the array contains several elements that reference equal
1173 * <code>DataFlavor</code>s, this method will establish new mappings
1174 * for the first of those elements and ignore the rest of them.
1175 * <p>
1176 * It is recommended that client code not reset mappings established by the
1177 * data transfer subsystem. This method should only be used for
1178 * application-level mappings.
1179 *
1180 * @param nat the <code>String</code> native key for the mappings
1181 * @param flavors the <code>DataFlavor</code> values for the mappings
1182 * @throws NullPointerException if nat or flavors is <code>null</code>
1183 * or if flavors contains <code>null</code> elements
1184 *
1185 * @see #setNativesForFlavor
1186 * @since 1.4
1187 */
1188 public synchronized void setFlavorsForNative(String nat,
1189 DataFlavor[] flavors) {
1190 if (nat == null || flavors == null) {
1191 throw new NullPointerException("null arguments not permitted");
1192 }
1193
1194 getNativeToFlavor().remove(nat);
1195 for (int i = 0; i < flavors.length; i++) {
1196 addFlavorForUnencodedNative(nat, flavors[i]);
1197 }
1198 disabledMappingGenerationKeys.add(nat);
1199 // Clear the cache to handle the case of empty flavors.
1200 getFlavorsForNativeCache.remove(nat);
1201 getFlavorsForNativeCache.remove(null);
1202 }
1203
1204 /**
1205 * Encodes a MIME type for use as a <code>String</code> native. The format
1206 * of an encoded representation of a MIME type is implementation-dependent.
1207 * The only restrictions are:
1208 * <ul>
1209 * <li>The encoded representation is <code>null</code> if and only if the
1210 * MIME type <code>String</code> is <code>null</code>.</li>
1211 * <li>The encoded representations for two non-<code>null</code> MIME type
1212 * <code>String</code>s are equal if and only if these <code>String</code>s
1213 * are equal according to <code>String.equals(Object)</code>.</li>
1214 * </ul>
1215 * <p>
1216 * Sun's reference implementation of this method returns the specified MIME
1217 * type <code>String</code> prefixed with <code>JAVA_DATAFLAVOR:</code>.
1218 *
1219 * @param mimeType the MIME type to encode
1220 * @return the encoded <code>String</code>, or <code>null</code> if
1221 * mimeType is <code>null</code>
1222 */
1223 public static String encodeJavaMIMEType(String mimeType) {
1224 return (mimeType != null)
1225 ? JavaMIME + mimeType
1226 : null;
1227 }
1228
1229 /**
1230 * Encodes a <code>DataFlavor</code> for use as a <code>String</code>
1231 * native. The format of an encoded <code>DataFlavor</code> is
1232 * implementation-dependent. The only restrictions are:
1233 * <ul>
1234 * <li>The encoded representation is <code>null</code> if and only if the
1235 * specified <code>DataFlavor</code> is <code>null</code> or its MIME type
1236 * <code>String</code> is <code>null</code>.</li>
1237 * <li>The encoded representations for two non-<code>null</code>
1238 * <code>DataFlavor</code>s with non-<code>null</code> MIME type
1239 * <code>String</code>s are equal if and only if the MIME type
1240 * <code>String</code>s of these <code>DataFlavor</code>s are equal
1241 * according to <code>String.equals(Object)</code>.</li>
1242 * </ul>
1243 * <p>
1244 * Sun's reference implementation of this method returns the MIME type
1245 * <code>String</code> of the specified <code>DataFlavor</code> prefixed
1246 * with <code>JAVA_DATAFLAVOR:</code>.
1247 *
1248 * @param flav the <code>DataFlavor</code> to encode
1249 * @return the encoded <code>String</code>, or <code>null</code> if
1250 * flav is <code>null</code> or has a <code>null</code> MIME type
1251 */
1252 public static String encodeDataFlavor(DataFlavor flav) {
1253 return (flav != null)
1254 ? SystemFlavorMap.encodeJavaMIMEType(flav.getMimeType())
1255 : null;
1256 }
1257
1258 /**
1259 * Returns whether the specified <code>String</code> is an encoded Java
1260 * MIME type.
1261 *
1262 * @param str the <code>String</code> to test
1263 * @return <code>true</code> if the <code>String</code> is encoded;
1264 * <code>false</code> otherwise
1265 */
1266 public static boolean isJavaMIMEType(String str) {
1267 return (str != null && str.startsWith(JavaMIME, 0));
1268 }
1269
1270 /**
1271 * Decodes a <code>String</code> native for use as a Java MIME type.
1272 *
1273 * @param nat the <code>String</code> to decode
1274 * @return the decoded Java MIME type, or <code>null</code> if nat is not
1275 * an encoded <code>String</code> native
1276 */
1277 public static String decodeJavaMIMEType(String nat) {
1278 return (isJavaMIMEType(nat))
1279 ? nat.substring(JavaMIME.length(), nat.length()).trim()
1280 : null;
1281 }
1282
1283 /**
1284 * Decodes a <code>String</code> native for use as a
1285 * <code>DataFlavor</code>.
1286 *
1287 * @param nat the <code>String</code> to decode
1288 * @return the decoded <code>DataFlavor</code>, or <code>null</code> if
1289 * nat is not an encoded <code>String</code> native
1290 */
1291 public static DataFlavor decodeDataFlavor(String nat)
1292 throws ClassNotFoundException
1293 {
1294 String retval_str = SystemFlavorMap.decodeJavaMIMEType(nat);
1295 return (retval_str != null)
1296 ? new DataFlavor(retval_str)
1297 : null;
1298 }
1299}
java/pkg/java/awt/datatransfer/Transferable.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/Transferable.java+73−0
@@ -0,0 +1,73 @@
1/*
2 * Copyright (c) 1996, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28import java.io.IOException;
29
30/**
31 * Defines the interface for classes that can be used to provide data
32 * for a transfer operation.
33 * <p>
34 * For information on using data transfer with Swing, see
35 * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/dnd.html">
36 * How to Use Drag and Drop and Data Transfer</a>,
37 * a section in <em>The Java Tutorial</em>, for more information.
38 *
39 * @author Amy Fowler
40 */
41
42public interface Transferable {
43
44 /**
45 * Returns an array of DataFlavor objects indicating the flavors the data
46 * can be provided in. The array should be ordered according to preference
47 * for providing the data (from most richly descriptive to least descriptive).
48 * @return an array of data flavors in which this data can be transferred
49 */
50 public DataFlavor[] getTransferDataFlavors();
51
52 /**
53 * Returns whether or not the specified data flavor is supported for
54 * this object.
55 * @param flavor the requested flavor for the data
56 * @return boolean indicating whether or not the data flavor is supported
57 */
58 public boolean isDataFlavorSupported(DataFlavor flavor);
59
60 /**
61 * Returns an object which represents the data to be transferred. The class
62 * of the object returned is defined by the representation class of the flavor.
63 *
64 * @param flavor the requested flavor for the data
65 * @see DataFlavor#getRepresentationClass
66 * @exception IOException if the data is no longer available
67 * in the requested flavor.
68 * @exception UnsupportedFlavorException if the requested data flavor is
69 * not supported.
70 */
71 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException;
72
73}
java/pkg/java/awt/datatransfer/UnsupportedFlavorException.class+0−0

Binary file not shown.

java/pkg/java/awt/datatransfer/UnsupportedFlavorException.java+50−0
@@ -0,0 +1,50 @@
1/*
2 * Copyright (c) 1996, 2000, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package java.awt.datatransfer;
27
28/**
29 * Signals that the requested data is not supported in this flavor.
30 * @see Transferable#getTransferData
31 *
32 * @author Amy Fowler
33 */
34public class UnsupportedFlavorException extends Exception {
35
36 /*
37 * JDK 1.1 serialVersionUID
38 */
39 private static final long serialVersionUID = 5383814944251665601L;
40
41 /**
42 * Constructs an UnsupportedFlavorException.
43 *
44 * @param flavor the flavor object which caused the exception. May
45 * be <code>null</code>.
46 */
47 public UnsupportedFlavorException(DataFlavor flavor) {
48 super((flavor != null) ? flavor.getHumanPresentableName() : null);
49 }
50}
java/pkg/java/awt/datatransfer/mkfile+21−0
@@ -0,0 +1,21 @@
1<../../../../../mkconfig
2
3TARG=\
4 Clipboard.dis\
5 ClipboardOwner.dis\
6 DataFlavor.dis\
7 FlavorEvent.dis\
8 FlavorListener.dis\
9 FlavorMap.dis\
10 FlavorTable.dis\
11 MimeType.dis\
12 MimeTypeParameterList.dis\
13 MimeTypeParseException.dis\
14 StringSelection.dis\
15 SystemFlavorMap.dis\
16 Transferable.dis\
17 UnsupportedFlavorException.dis\
18
19DISBIN=$ROOT/java/dis/java/java/java/awt/datatransfer
20
21<$ROOT/mkfiles/mkjava
java/pkg/java/awt/datatransfer/package.html+63−0
@@ -0,0 +1,63 @@
1<!--
2 Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
3 DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
5 This code is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License version 2 only, as
7 published by the Free Software Foundation. Oracle designates this
8 particular file as subject to the "Classpath" exception as provided
9 by Oracle in the LICENSE file that accompanied this code.
10
11 This code is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 version 2 for more details (a copy is included in the LICENSE file that
15 accompanied this code).
16
17 You should have received a copy of the GNU General Public License version
18 2 along with this work; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
21 Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 or visit www.oracle.com if you need additional information or have any
23 questions.
24-->
25
26<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
27<html>
28<body bgcolor="white">
29
30Provides interfaces and classes for transferring data
31between and within applications. It defines the notion of a
32"transferable" object, which is an object capable of being
33transferred between or within applications. An object identifies
34itself as being transferable by implementing the Transferable
35interface.
36<p>
37It also provides a clipboard mechanism, which is an object that
38temporarily holds a transferable object that can be transferred
39between or within an application. The clipboard is typically used
40for copy and paste operations. Although it is possible to create
41a clipboard to use within an application, most applications will
42use the system clipboard to ensure the data can be transferred
43across applications running on the platform.
44
45<!--
46<h2>Package Specification</h2>
47
48##### FILL IN ANY SPECS NEEDED BY JAVA COMPATIBILITY KIT #####
49<ul>
50 <li><a href="">##### REFER TO ANY FRAMEMAKER SPECIFICATION HERE #####</a>
51</ul>
52
53<h2>Related Documentation</h2>
54
55For overviews, tutorials, examples, guides, and tool documentation, please see:
56<ul>
57 <li><a href="">##### REFER TO NON-SPEC DOCUMENTATION HERE #####</a>
58</ul>
59-->
60
61@since JDK1.1
62</body>
63</html>