feisty meow concerns codebase 2.140
ListTransferable.java
Go to the documentation of this file.
1package org.feistymeow.dragdrop;
2
3import java.awt.datatransfer.DataFlavor;
4import java.awt.datatransfer.Transferable;
5import java.awt.datatransfer.UnsupportedFlavorException;
6import java.io.BufferedReader;
7import java.io.File;
8import java.io.IOException;
9import java.io.Reader;
10import java.util.ArrayList;
11import java.util.Arrays;
12import java.util.Iterator;
13import java.util.List;
14import java.util.Vector;
15import java.util.StringTokenizer;
16import org.apache.commons.logging.Log;
17import org.apache.commons.logging.LogFactory;
18
29@SuppressWarnings("serial")
30public class ListTransferable extends Vector<Object> implements Transferable
31{
32 static private Log logger = LogFactory.getLog(ListTransferable.class);
33
35 {
36 }
37
38 public ListTransferable(Object initial)
39 {
40 if (initial != null) add(initial);
41 }
42
43 public ListTransferable(List<Object> initial)
44 {
45 if (initial != null) addAll(initial);
46 }
47
52 private static DataFlavor URIListFlavor;
53 static {
54 try {
55 URIListFlavor = new DataFlavor("text/uri-list;class=java.lang.String");
56 } catch (ClassNotFoundException e) {
57 logger.error("should never happen", e);
58 }
59 }
60 private static DataFlavor AltURIListFlavor;
61 static {
62 try {
63 AltURIListFlavor = new DataFlavor("text/uri-list;representationclass=java.lang.String");
64 } catch (ClassNotFoundException e) {
65 logger.error("should never happen", e);
66 }
67 }
68
72 public static DataFlavor getURIListFlavor1()
73 {
74 return URIListFlavor;
75 }
76
77 public static DataFlavor getURIListFlavor2()
78 {
79 return AltURIListFlavor;
80 }
81
86 protected ArrayList<DataFlavor> FLAVORS = new ArrayList<DataFlavor>(Arrays.asList(
87 DataFlavor.javaFileListFlavor, URIListFlavor, AltURIListFlavor));
88
94 public boolean loadDataJustInTime(DataFlavor flavor)
95 {
96 logger.warn("base loadDataJustInTime. derived class should have implemented this.");
97 return false;
98 }
99
104 public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException,
105 java.io.IOException
106 {
107 if (flavor == null) return null;
108 if (size() == 0) {
109 logger.debug("size was zero, so loading data just in time");
110 boolean worked = loadDataJustInTime(flavor);
111 if (!worked || (size() == 0)) {
112 logger.warn("failed to retrieve data just in time for getTransferData.");
113 return null;
114 }
115 }
116 // help from workaround at http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4899516
117 logger.debug("responding to flavor: " + flavor.toString());
118 if (flavor.equals(DataFlavor.javaFileListFlavor)) {
119 logger.debug("java file list flavor...");
120 List<Object> data = new java.util.ArrayList<Object>();
121 data.addAll(this);
122 return data;
123 } else if (flavor.equals(URIListFlavor) || flavor.equals(AltURIListFlavor)) {
124 logger.debug("uri list flavor...");
125 StringBuilder data = new StringBuilder();
126 Iterator<Object> iter = iterator();
127 while (iter.hasNext()) {
128 Object x = iter.next();
129 if (x instanceof File) {
130 File elem = (File) x;
131 data.append(elem.toURI() + "\r\n");
132 } else if (x instanceof String) {
133 data.append((String) x + "\r\n");
134 } else {
135 logger.debug("did not know how to handle type in transfer: " + x.toString());
136 }
137 }
138 logger.debug("returning URI string: " + data.toString());
139 return data.toString();
140 } else {
141 logger.debug("getTransferData: didn't know how to handle the requested flavor.");
142 throw new UnsupportedFlavorException(flavor);
143 }
144 }
145
149 public DataFlavor[] getTransferDataFlavors()
150 {
151 return (DataFlavor[]) FLAVORS.toArray(new DataFlavor[FLAVORS.size()]);
152 }
153
157 public boolean isDataFlavorSupported(DataFlavor flavor)
158 {
159 if (flavor == null) return false;
160 for (int i = 0; i < FLAVORS.size(); i++) {
161 if (flavor.equals((DataFlavor) FLAVORS.get(i))) {
162 return true;
163 }
164 }
165 logger.debug("failed to find flavor: " + flavor.toString());
166 return false;
167 }
168
172 @SuppressWarnings("unchecked")
173 static public List<Object> extractData(Transferable tran) {
174 if (tran == null) return null;
175 if (tran.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
176 logger.debug("extractData seeing java files flavor.");
177 try {
178 return (List<Object>) tran.getTransferData(DataFlavor.javaFileListFlavor);
179 } catch (Throwable cause) {
180 logger.error("extractData caught exception for java file list.", cause);
181 return null;
182 }
183 } else if (tran.isDataFlavorSupported(ListTransferable.getURIListFlavor1())
184 || tran.isDataFlavorSupported(ListTransferable.getURIListFlavor2())) {
185 logger.debug("extractData seeing uri list flavor.");
186 try {
187 return textURIListToFileList((String) tran.getTransferData(getURIListFlavor1()));
188 } catch (Throwable cause) {
189 logger.error("extractData caught exception for URI list.", cause);
190 return null;
191 }
192 }
193 logger.error("extractData: Transferable did not support known data flavor.");
194 return null;
195 }
196
205 public static List<Object> textURIListToFileList(String data)
206 {
207 if (data == null) return null;
208 List<Object> list = new ArrayList<Object>(0);
209 for (StringTokenizer st = new StringTokenizer(data, "\r\n"); st.hasMoreTokens();) {
210 String s = st.nextToken();
211 if (s.startsWith("#")) {
212 // the line is a comment (as per the RFC 2483)
213 continue;
214 }
215 try {
216 java.net.URI uri = new java.net.URI(s);
217 java.io.File file = new java.io.File(uri);
218 list.add(file);
219 } catch (java.net.URISyntaxException e) {
220 // this is a malformed URI.
221 logger.error("Found a malformed URI of: " + data);
222 } catch (IllegalArgumentException e) {
223 // the URI is not a valid 'file:' URI
224 logger.error("Found invalid 'file:' URI of: " + data);
225 }
226 }
227 return list;
228 }
229
233 @SuppressWarnings("unchecked")
234 public static List<Object> processStandardFileList(Transferable tran)
235 {
236 if (tran == null) return null;
237 logger.debug("trying java file list flavor.");
238 try {
239 return (List<Object>) tran.getTransferData(DataFlavor.javaFileListFlavor);
240 } catch (Throwable cause) {
241 logger.debug("failed to retrieve transfer data for standard java file list flavor.",
242 cause);
243 }
244 return new ArrayList<Object>();
245 }
246
250 public static boolean checkReaderFlavor(Transferable tran)
251 {
252 if (tran == null) return false;
253 DataFlavor[] flavors = tran.getTransferDataFlavors();
254 for (int i = 0; i < flavors.length; i++) {
255 if (flavors[i].isRepresentationClassReader())
256 return true;
257 }
258 return false;
259 }
260
264 public static List<Object> processReaderFlavor(Transferable tran)
265 {
266 if (tran == null) return null;
267 logger.debug("trying URI list flavor.");
268 DataFlavor[] flavors = tran.getTransferDataFlavors();
269 for (int i = 0; i < flavors.length; i++) {
270 if (flavors[i].isRepresentationClassReader()) {
271 // it looks like we can work with this flavor just fine.
272 logger.debug("found a reader flavor.");
273 try {
274 Reader reader = flavors[i].getReaderForText(tran);
275 BufferedReader br = new BufferedReader(reader);
276 return createFileArray(br);
277 } catch (Throwable cause) {
278 logger.debug("failed to scan reader for file list.");
279 }
280 }
281 }
282 return new ArrayList<Object>();
283 }
284
285 private static String ZERO_CHAR_STRING = "" + (char) 0;
286
287 public static List<Object> createFileArray(BufferedReader bReader) {
288 if (bReader == null) return null;
289 try {
290 List<Object> list = new ArrayList<Object>();
291 String line = null;
292 while ((line = bReader.readLine()) != null) {
293 try {
294 // kde seems to append a 0 char to the end of the reader
295 if (ZERO_CHAR_STRING.equals(line))
296 continue;
297 File file = new java.io.File(new java.net.URI(line));
298 list.add(file);
299 } catch (Exception ex) {
300 logger.error("Error with " + line + ": " + ex.getMessage());
301 }
302 }
303
304 return list;
305 } catch (IOException ex) {
306 logger.error("IOException while working on file list");
307 }
308 return new ArrayList<Object>();
309 }
310
311}
static List< Object > processReaderFlavor(Transferable tran)
boolean isDataFlavorSupported(DataFlavor flavor)
static boolean checkReaderFlavor(Transferable tran)
static List< Object > textURIListToFileList(String data)
static List< Object > createFileArray(BufferedReader bReader)
boolean loadDataJustInTime(DataFlavor flavor)