feisty meow concerns codebase  2.140
ListTransferable.java
Go to the documentation of this file.
1 package org.feistymeow.dragdrop;
2 
3 import java.awt.datatransfer.DataFlavor;
4 import java.awt.datatransfer.Transferable;
5 import java.awt.datatransfer.UnsupportedFlavorException;
6 import java.io.BufferedReader;
7 import java.io.File;
8 import java.io.IOException;
9 import java.io.Reader;
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Vector;
15 import java.util.StringTokenizer;
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 
29 @SuppressWarnings("serial")
30 public 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 }
boolean isDataFlavorSupported(DataFlavor flavor)
static List< Object > textURIListToFileList(String data)
static boolean checkReaderFlavor(Transferable tran)
boolean loadDataJustInTime(DataFlavor flavor)
static List< Object > processReaderFlavor(Transferable tran)
static List< Object > createFileArray(BufferedReader bReader)