OSDN Git Service

libjava/ChangeLog:
[pf3gnuchains/gcc-fork.git] / libjava / classpath / javax / activation / DataHandler.java
1 /* DataHandler.java -- Handler for data available in multiple formats.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GNU Classpath.
5
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37
38 package javax.activation;
39
40 import java.awt.datatransfer.DataFlavor;
41 import java.awt.datatransfer.Transferable;
42 import java.awt.datatransfer.UnsupportedFlavorException;
43 import java.io.InputStream;
44 import java.io.IOException;
45 import java.io.OutputStream;
46 import java.io.PipedInputStream;
47 import java.io.PipedOutputStream;
48 import java.net.URL;
49
50 /**
51  * Handler for data available in multiple sources and formats.
52  *
53  * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
54  * @version 1.1
55  */
56 public class DataHandler
57   implements Transferable
58 {
59
60   private static final DataFlavor[] NO_FLAVORS = new DataFlavor[0];
61   private static DataContentHandlerFactory factory = null;
62   
63   private final DataSource dataSource;
64   private DataSource objDataSource;
65   private Object object;
66   private String objectMimeType;
67   private CommandMap currentCommandMap;
68   private DataFlavor[] transferFlavors = NO_FLAVORS;
69   private DataContentHandler dataContentHandler;
70   private DataContentHandler factoryDCH;
71   private DataContentHandlerFactory oldFactory;
72   private String shortType;
73   
74   /**
75    * Constructor in which the data is read from a data source.
76    * @param ds the data source
77    */
78   public DataHandler(DataSource ds)
79   {
80     dataSource = ds;
81     oldFactory = factory;
82   }
83   
84   /**
85    * Constructor using a reified object representation.
86    * @param obj the object representation of the data
87    * @param mimeType the MIME type of the object
88    */
89   public DataHandler(Object obj, String mimeType)
90   {
91     dataSource = null;
92     object = obj;
93     objectMimeType = mimeType;
94     oldFactory = factory;
95   }
96   
97   /**
98    * Constructor in which the data is read from a URL.
99    * @param url the URL
100    */
101   public DataHandler(URL url)
102   {
103     dataSource = new URLDataSource(url);
104     oldFactory = factory;
105   }
106   
107   /**
108    * Returns the data source from which data is read.
109    */
110   public DataSource getDataSource()
111   {
112     if (dataSource != null)
113       {
114         return dataSource;
115       }
116     if (objDataSource == null)
117       {
118         objDataSource = new DataHandlerDataSource(this);
119       }
120     return objDataSource;
121   }
122   
123   /**
124    * Returns the name of the data object if created with a DataSource.
125    */
126   public String getName()
127   {
128     if (dataSource != null)
129       {
130         return dataSource.getName();
131       }
132     return null;
133   }
134   
135   /**
136    * Returns the MIME type of the data (with parameters).
137    */
138   public String getContentType()
139   {
140     if (dataSource != null)
141       {
142         return dataSource.getContentType();
143       }
144     return objectMimeType;
145   }
146   
147   /**
148    * Returns an input stream from which the data can be read.
149    */
150   public InputStream getInputStream()
151     throws IOException
152   {
153     if (dataSource != null)
154       {
155         return dataSource.getInputStream();
156       }
157     DataContentHandler dch = getDataContentHandler();
158     if (dch == null)
159       {
160         throw new UnsupportedDataTypeException("no DCH for MIME type " +
161                                                getShortType());
162       }
163     if ((dch instanceof ObjectDataContentHandler) &&
164         ((ObjectDataContentHandler)dch).getDCH() == null)
165       {
166         throw new UnsupportedDataTypeException("no object DCH " +
167                                                "for MIME type " +
168                                                getShortType());
169       }
170     PipedOutputStream pos = new PipedOutputStream();
171     DataContentHandlerWriter dchw =
172       new DataContentHandlerWriter(dch, object, objectMimeType, pos);
173     Thread thread = new Thread(dchw, "DataHandler.getInputStream");
174     thread.start();
175     return new PipedInputStream(pos);
176   }
177   
178   static class DataContentHandlerWriter
179     implements Runnable
180   {
181     
182     DataContentHandler dch;
183     Object object;
184     String mimeType;
185     OutputStream out;
186     
187     DataContentHandlerWriter(DataContentHandler dch, Object object,
188                              String mimeType, OutputStream out)
189     {
190       this.dch = dch;
191       this.object = object;
192       this.mimeType = mimeType;
193       this.out = out;
194     }
195     
196     public void run()
197     {
198       try
199         {
200           dch.writeTo(object, mimeType, out);
201         }
202       catch(IOException e)
203         {
204         }
205       finally
206         {
207           try
208             {
209               out.close();
210             }
211           catch(IOException e)
212             {
213             }
214         }
215     }
216   }
217   
218   /**
219    * Writes the data as a byte stream.
220    * @param os the stream to write to
221    */
222   public void writeTo(OutputStream os)
223     throws IOException
224   {
225     if (dataSource != null)
226       {
227         InputStream in = dataSource.getInputStream();
228         byte[] buf = new byte[8192];
229         for (int len = in.read(buf); len != -1; len = in.read(buf))
230           {
231             os.write(buf, 0, len);
232           }
233         in.close();
234       }
235     else
236       {
237         DataContentHandler dch = getDataContentHandler();
238         dch.writeTo(object, objectMimeType, os);
239       }
240   }
241   
242   /**
243    * Returns an output stream that can be used to overwrite the underlying
244    * data, if the DataSource constructor was used.
245    */
246   public OutputStream getOutputStream()
247     throws IOException
248   {
249     if (dataSource != null)
250       {
251         return dataSource.getOutputStream();
252       }
253     return null;
254   }
255   
256   /**
257    * Returns the data flavors in which this data is available.
258    */
259   public synchronized DataFlavor[] getTransferDataFlavors()
260   {
261     if (factory != oldFactory || transferFlavors == NO_FLAVORS)
262       {
263         DataContentHandler dch = getDataContentHandler();
264         transferFlavors = dch.getTransferDataFlavors();
265       }
266     return transferFlavors;
267   }
268   
269   /**
270    * Indicates whether the specified data flavor is supported for this
271    * data.
272    */
273   public boolean isDataFlavorSupported(DataFlavor flavor)
274   {
275     DataFlavor[] flavors = getTransferDataFlavors();
276     for (int i = 0; i < flavors.length; i++)
277       {
278         if (flavors[i].equals(flavor))
279           {
280             return true;
281           }
282       }
283     return false;
284   }
285   
286   /**
287    * Returns an object representing the data to be transferred.
288    * @param flavor the requested data flavor
289    */
290   public Object getTransferData(DataFlavor flavor)
291     throws UnsupportedFlavorException, IOException
292   {
293     DataContentHandler dch = getDataContentHandler();
294     return dch.getTransferData(flavor, dataSource);
295   }
296   
297   /**
298    * Sets the command map to be used by this data handler.
299    * Setting to null uses the default command map.
300    * @param commandMap the command map to use
301    */
302   public synchronized void setCommandMap(CommandMap commandMap)
303   {
304     if (commandMap != currentCommandMap || commandMap == null)
305       {
306         transferFlavors = NO_FLAVORS;
307         dataContentHandler = null;
308         currentCommandMap = commandMap;
309       }
310   }
311   
312   /**
313    * Returns the preferred commands for this type of data.
314    */
315   public CommandInfo[] getPreferredCommands()
316   {
317     CommandMap commandMap = getCommandMap();
318     return commandMap.getPreferredCommands(getShortType());
319   }
320
321   /**
322    * Returns the complete list of commands for this type of data.
323    */
324   public CommandInfo[] getAllCommands()
325   {
326     CommandMap commandMap = getCommandMap();
327     return commandMap.getAllCommands(getShortType());
328   }
329
330   /**
331    * Returns the specified command.
332    * @param cmdName the command name
333    */
334   public CommandInfo getCommand(String cmdName)
335   {
336     CommandMap commandMap = getCommandMap();
337     return commandMap.getCommand(getShortType(), cmdName);
338   }
339   
340   /**
341    * Returns the data as a reified object.
342    */
343   public Object getContent()
344     throws IOException
345   {
346     DataContentHandler dch = getDataContentHandler();
347     return dch.getContent(getDataSource());
348   }
349   
350   /**
351    * Returns the instantiated bean using the specified command.
352    * @param cmdInfo the command to instantiate the bean with
353    */
354   public Object getBean(CommandInfo cmdInfo)
355   {
356     try
357       {
358         return cmdInfo.getCommandObject(this, getClass().getClassLoader());
359       }
360     catch (IOException e)
361       {
362         e.printStackTrace(System.err);
363         return null;
364       }
365     catch (ClassNotFoundException e)
366       {
367         e.printStackTrace(System.err);
368         return null;
369       }
370   }
371
372   /**
373    * Sets the data content handler factory.
374    * If the factory has already been set, throws an Error.
375    * @param newFactory the factory to set
376    */
377   public static synchronized void
378     setDataContentHandlerFactory(DataContentHandlerFactory newFactory)
379   {
380     if (factory != null)
381       {
382         throw new Error("DataContentHandlerFactory already defined");
383       }
384     SecurityManager security = System.getSecurityManager();
385     if (security != null)
386       {
387         try
388           {
389             security.checkSetFactory();
390           }
391         catch (SecurityException e)
392           {
393             if (newFactory != null && DataHandler.class.getClassLoader()
394                 != newFactory.getClass().getClassLoader())
395               {
396                 throw e;
397               }
398           }
399       }
400     factory = newFactory;
401   }
402   
403   /*
404    * Returns just the base part of the data's content-type, with no
405    * parameters.
406    */
407   private synchronized String getShortType()
408   {
409     if (shortType == null)
410       {
411         String contentType = getContentType();
412         try
413           {
414             MimeType mimeType = new MimeType(contentType);
415             shortType = mimeType.getBaseType();
416           }
417         catch (MimeTypeParseException e)
418           {
419             shortType = contentType;
420           }
421       }
422     return shortType;
423   }
424   
425   /*
426    * Returns the command map for this handler.
427    */
428   private synchronized CommandMap getCommandMap()
429   {
430     if (currentCommandMap != null)
431       {
432         return currentCommandMap;
433       }
434     return CommandMap.getDefaultCommandMap();
435   }
436   
437   /*
438    * Returns the DCH for this handler.
439    */
440   private synchronized DataContentHandler getDataContentHandler()
441   {
442     if (factory != oldFactory)
443       {
444         oldFactory = factory;
445         factoryDCH = null;
446         dataContentHandler = null;
447         transferFlavors = NO_FLAVORS;
448       }
449     if (dataContentHandler != null)
450       {
451         return dataContentHandler;
452       }
453     String mimeType = getShortType();
454     if (factoryDCH == null && factory != null)
455       {
456         factoryDCH = factory.createDataContentHandler(mimeType);
457       }
458     if (factoryDCH != null)
459       {
460         dataContentHandler = factoryDCH;
461       }
462     if (dataContentHandler == null)
463       {
464         CommandMap commandMap = getCommandMap();
465         dataContentHandler = commandMap.createDataContentHandler(mimeType);
466       }
467     if (dataSource != null)
468       {
469         dataContentHandler =
470           new DataSourceDataContentHandler(dataContentHandler, dataSource);
471       }
472     else
473       {
474         dataContentHandler =
475           new ObjectDataContentHandler(dataContentHandler, object,
476                                        objectMimeType);
477       }
478     return dataContentHandler;
479   }
480   
481 }
482