Save This Page
Home » Open-JDK-6.b17-src » javax » activation » [javadoc | source]
    1   /*
    2    * Copyright 1997-2006 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.activation;
   27   
   28   import java.io.InputStream;
   29   import java.io.IOException;
   30   import java.io.OutputStream;
   31   import java.io.PipedInputStream;
   32   import java.io.PipedOutputStream;
   33   import java.io.OutputStreamWriter;
   34   import java.net.URL;
   35   import java.awt.datatransfer.Transferable;
   36   import java.awt.datatransfer.DataFlavor;
   37   import java.awt.datatransfer.UnsupportedFlavorException;
   38   
   39   /**
   40    * The DataHandler class provides a consistent interface to data
   41    * available in many different sources and formats.
   42    * It manages simple stream to string conversions and related operations
   43    * using DataContentHandlers.
   44    * It provides access to commands that can operate on the data.
   45    * The commands are found using a CommandMap. <p>
   46    *
   47    * <b>DataHandler and the Transferable Interface</b><p>
   48    * DataHandler implements the Transferable interface so that data can
   49    * be used in AWT data transfer operations, such as cut and paste and
   50    * drag and drop. The implementation of the Transferable interface
   51    * relies on the availability of an installed DataContentHandler
   52    * object corresponding to the MIME type of the data represented in
   53    * the specific instance of the DataHandler.<p>
   54    *
   55    * <b>DataHandler and CommandMaps</b><p>
   56    * The DataHandler keeps track of the current CommandMap that it uses to
   57    * service requests for commands (<code>getCommand</code>,
   58    * <code>getAllCommands</code>, <code>getPreferredCommands</code>).
   59    * Each instance of a DataHandler may have a CommandMap associated with
   60    * it using the <code>setCommandMap</code> method.  If a CommandMap was
   61    * not set, DataHandler calls the <code>getDefaultCommandMap</code>
   62    * method in CommandMap and uses the value it returns. See
   63    * <i>CommandMap</i> for more information. <p>
   64    *
   65    * <b>DataHandler and URLs</b><p>
   66    * The current DataHandler implementation creates a private
   67    * instance of URLDataSource when it is constructed with a URL.
   68    *
   69    * @see javax.activation.CommandMap
   70    * @see javax.activation.DataContentHandler
   71    * @see javax.activation.DataSource
   72    * @see javax.activation.URLDataSource
   73    *
   74    * @since 1.6
   75    */
   76   
   77   public class DataHandler implements Transferable {
   78   
   79       // Use the datasource to indicate whether we were started via the
   80       // DataSource constructor or the object constructor.
   81       private DataSource dataSource = null;
   82       private DataSource objDataSource = null;
   83   
   84       // The Object and mimetype from the constructor (if passed in).
   85       // object remains null if it was instantiated with a
   86       // DataSource.
   87       private Object object = null;
   88       private String objectMimeType = null;
   89   
   90       // Keep track of the CommandMap
   91       private CommandMap currentCommandMap = null;
   92   
   93       // our transfer flavors
   94       private static final DataFlavor emptyFlavors[] = new DataFlavor[0];
   95       private DataFlavor transferFlavors[] = emptyFlavors;
   96   
   97       // our DataContentHandler
   98       private DataContentHandler dataContentHandler = null;
   99       private DataContentHandler factoryDCH = null;
  100   
  101       // our DataContentHandlerFactory
  102       private static DataContentHandlerFactory factory = null;
  103       private DataContentHandlerFactory oldFactory = null;
  104       // the short representation of the ContentType (sans params)
  105       private String shortType = null;
  106   
  107       /**
  108        * Create a <code>DataHandler</code> instance referencing the
  109        * specified DataSource.  The data exists in a byte stream form.
  110        * The DataSource will provide an InputStream to access the data.
  111        *
  112        * @param ds        the DataSource
  113        */
  114       public DataHandler(DataSource ds) {
  115           // save a reference to the incoming DS
  116           dataSource = ds;
  117           oldFactory = factory; // keep track of the factory
  118       }
  119   
  120       /**
  121        * Create a <code>DataHandler</code> instance representing an object
  122        * of this MIME type.  This constructor is
  123        * used when the application already has an in-memory representation
  124        * of the data in the form of a Java Object.
  125        *
  126        * @param obj       the Java Object
  127        * @param mimeType  the MIME type of the object
  128        */
  129       public DataHandler(Object obj, String mimeType) {
  130           object = obj;
  131           objectMimeType = mimeType;
  132           oldFactory = factory; // keep track of the factory
  133       }
  134   
  135       /**
  136        * Create a <code>DataHandler</code> instance referencing a URL.
  137        * The DataHandler internally creates a <code>URLDataSource</code>
  138        * instance to represent the URL.
  139        *
  140        * @param url       a URL object
  141        */
  142       public DataHandler(URL url) {
  143           dataSource = new URLDataSource(url);
  144           oldFactory = factory; // keep track of the factory
  145       }
  146   
  147       /**
  148        * Return the CommandMap for this instance of DataHandler.
  149        */
  150       private synchronized CommandMap getCommandMap() {
  151           if (currentCommandMap != null)
  152               return currentCommandMap;
  153           else
  154               return CommandMap.getDefaultCommandMap();
  155       }
  156   
  157       /**
  158        * Return the DataSource associated with this instance
  159        * of DataHandler.
  160        * <p>
  161        * For DataHandlers that have been instantiated with a DataSource,
  162        * this method returns the DataSource that was used to create the
  163        * DataHandler object. In other cases the DataHandler
  164        * constructs a DataSource from the data used to construct
  165        * the DataHandler. DataSources created for DataHandlers <b>not</b>
  166        * instantiated with a DataSource are cached for performance
  167        * reasons.
  168        *
  169        * @return  a valid DataSource object for this DataHandler
  170        */
  171       public DataSource getDataSource() {
  172           if (dataSource == null) {
  173               // create one on the fly
  174               if (objDataSource == null)
  175                   objDataSource = new DataHandlerDataSource(this);
  176               return objDataSource;
  177           }
  178           return dataSource;
  179       }
  180   
  181       /**
  182        * Return the name of the data object. If this DataHandler
  183        * was created with a DataSource, this method calls through
  184        * to the <code>DataSource.getName</code> method, otherwise it
  185        * returns <i>null</i>.
  186        *
  187        * @return  the name of the object
  188        */
  189       public String getName() {
  190           if (dataSource != null)
  191               return dataSource.getName();
  192           else
  193               return null;
  194       }
  195   
  196       /**
  197        * Return the MIME type of this object as retrieved from
  198        * the source object. Note that this is the <i>full</i>
  199        * type with parameters.
  200        *
  201        * @return  the MIME type
  202        */
  203       public String getContentType() {
  204           if (dataSource != null) // data source case
  205               return dataSource.getContentType();
  206           else
  207               return objectMimeType; // obj/type case
  208       }
  209   
  210       /**
  211        * Get the InputStream for this object. <p>
  212        *
  213        * For DataHandlers instantiated with a DataSource, the DataHandler
  214        * calls the <code>DataSource.getInputStream</code> method and
  215        * returns the result to the caller.
  216        * <p>
  217        * For DataHandlers instantiated with an Object, the DataHandler
  218        * first attempts to find a DataContentHandler for the Object. If
  219        * the DataHandler can not find a DataContentHandler for this MIME
  220        * type, it throws an UnsupportedDataTypeException.  If it is
  221        * successful, it creates a pipe and a thread.  The thread uses the
  222        * DataContentHandler's <code>writeTo</code> method to write the
  223        * stream data into one end of the pipe.  The other end of the pipe
  224        * is returned to the caller.  Because a thread is created to copy
  225        * the data, IOExceptions that may occur during the copy can not be
  226        * propagated back to the caller. The result is an empty stream.<p>
  227        *
  228        * @return  the InputStream representing this data
  229        * @exception IOException   if an I/O error occurs
  230        *
  231        * @see javax.activation.DataContentHandler#writeTo
  232        * @see javax.activation.UnsupportedDataTypeException
  233        */
  234       public InputStream getInputStream() throws IOException {
  235           InputStream ins = null;
  236   
  237           if (dataSource != null) {
  238               ins = dataSource.getInputStream();
  239           } else {
  240               DataContentHandler dch = getDataContentHandler();
  241               // we won't even try if we can't get a dch
  242               if (dch == null)
  243                   throw new UnsupportedDataTypeException(
  244                                   "no DCH for MIME type " + getBaseType());
  245   
  246               if (dch instanceof ObjectDataContentHandler) {
  247                   if (((ObjectDataContentHandler)dch).getDCH() == null)
  248                       throw new UnsupportedDataTypeException(
  249                                   "no object DCH for MIME type " + getBaseType());
  250               }
  251               // there is none but the default^^^^^^^^^^^^^^^^
  252               final DataContentHandler fdch = dch;
  253   
  254               // from bill s.
  255               // ce n'est pas une pipe!
  256               //
  257               // NOTE: This block of code needs to throw exceptions, but
  258               // can't because it is in another thread!!! ARG!
  259               //
  260               final PipedOutputStream pos = new PipedOutputStream();
  261               PipedInputStream pin = new PipedInputStream(pos);
  262               new Thread(
  263                          new Runnable() {
  264                   public void run() {
  265                       try {
  266                           fdch.writeTo(object, objectMimeType, pos);
  267                       } catch (IOException e) {
  268   
  269                       } finally {
  270                           try {
  271                               pos.close();
  272                           } catch (IOException ie) { }
  273                       }
  274                   }
  275               },
  276                         "DataHandler.getInputStream").start();
  277               ins = pin;
  278           }
  279   
  280           return ins;
  281       }
  282   
  283       /**
  284        * Write the data to an <code>OutputStream</code>.<p>
  285        *
  286        * If the DataHandler was created with a DataSource, writeTo
  287        * retrieves the InputStream and copies the bytes from the
  288        * InputStream to the OutputStream passed in.
  289        * <p>
  290        * If the DataHandler was created with an object, writeTo
  291        * retrieves the DataContentHandler for the object's type.
  292        * If the DataContentHandler was found, it calls the
  293        * <code>writeTo</code> method on the <code>DataContentHandler</code>.
  294        *
  295        * @param os        the OutputStream to write to
  296        * @exception IOException   if an I/O error occurs
  297        */
  298       public void writeTo(OutputStream os) throws IOException {
  299           // for the DataSource case
  300           if (dataSource != null) {
  301               InputStream is = null;
  302               byte data[] = new byte[8*1024];
  303               int bytes_read;
  304   
  305               is = dataSource.getInputStream();
  306   
  307               try {
  308                   while ((bytes_read = is.read(data)) > 0) {
  309                       os.write(data, 0, bytes_read);
  310                   }
  311               } finally {
  312                   is.close();
  313                   is = null;
  314               }
  315           } else { // for the Object case
  316               DataContentHandler dch = getDataContentHandler();
  317               dch.writeTo(object, objectMimeType, os);
  318           }
  319       }
  320   
  321       /**
  322        * Get an OutputStream for this DataHandler to allow overwriting
  323        * the underlying data.
  324        * If the DataHandler was created with a DataSource, the
  325        * DataSource's <code>getOutputStream</code> method is called.
  326        * Otherwise, <code>null</code> is returned.
  327        *
  328        * @return the OutputStream
  329        *
  330        * @see javax.activation.DataSource#getOutputStream
  331        * @see javax.activation.URLDataSource
  332        */
  333       public OutputStream getOutputStream() throws IOException {
  334           if (dataSource != null)
  335               return dataSource.getOutputStream();
  336           else
  337               return null;
  338       }
  339   
  340       /**
  341        * Return the DataFlavors in which this data is available. <p>
  342        *
  343        * Returns an array of DataFlavor objects indicating the flavors
  344        * the data can be provided in. The array is usually ordered
  345        * according to preference for providing the data, from most
  346        * richly descriptive to least richly descriptive.<p>
  347        *
  348        * The DataHandler attempts to find a DataContentHandler that
  349        * corresponds to the MIME type of the data. If one is located,
  350        * the DataHandler calls the DataContentHandler's
  351        * <code>getTransferDataFlavors</code> method. <p>
  352        *
  353        * If a DataContentHandler can <i>not</i> be located, and if the
  354        * DataHandler was created with a DataSource (or URL), one
  355        * DataFlavor is returned that represents this object's MIME type
  356        * and the <code>java.io.InputStream</code> class.  If the
  357        * DataHandler was created with an object and a MIME type,
  358        * getTransferDataFlavors returns one DataFlavor that represents
  359        * this object's MIME type and the object's class.
  360        *
  361        * @return  an array of data flavors in which this data can be transferred
  362        * @see javax.activation.DataContentHandler#getTransferDataFlavors
  363        */
  364       public synchronized DataFlavor[] getTransferDataFlavors() {
  365           if (factory != oldFactory) // if the factory has changed, clear cache
  366               transferFlavors = emptyFlavors;
  367   
  368           // if it's not set, set it...
  369           if (transferFlavors == emptyFlavors)
  370               transferFlavors = getDataContentHandler().getTransferDataFlavors();
  371           return transferFlavors;
  372       }
  373   
  374       /**
  375        * Returns whether the specified data flavor is supported
  376        * for this object.<p>
  377        *
  378        * This method iterates through the DataFlavors returned from
  379        * <code>getTransferDataFlavors</code>, comparing each with
  380        * the specified flavor.
  381        *
  382        * @param flavor    the requested flavor for the data
  383        * @return          true if the data flavor is supported
  384        * @see javax.activation.DataHandler#getTransferDataFlavors
  385        */
  386       public boolean isDataFlavorSupported(DataFlavor flavor) {
  387           DataFlavor[] lFlavors = getTransferDataFlavors();
  388   
  389           for (int i = 0; i < lFlavors.length; i++) {
  390               if (lFlavors[i].equals(flavor))
  391                   return true;
  392           }
  393           return false;
  394       }
  395   
  396       /**
  397        * Returns an object that represents the data to be
  398        * transferred. The class of the object returned is defined by the
  399        * representation class of the data flavor.<p>
  400        *
  401        * <b>For DataHandler's created with DataSources or URLs:</b><p>
  402        *
  403        * The DataHandler attempts to locate a DataContentHandler
  404        * for this MIME type. If one is found, the passed in DataFlavor
  405        * and the type of the data are passed to its <code>getTransferData</code>
  406        * method. If the DataHandler fails to locate a DataContentHandler
  407        * and the flavor specifies this object's MIME type and the
  408        * <code>java.io.InputStream</code> class, this object's InputStream
  409        * is returned.
  410        * Otherwise it throws an UnsupportedFlavorException. <p>
  411        *
  412        * <b>For DataHandler's created with Objects:</b><p>
  413        *
  414        * The DataHandler attempts to locate a DataContentHandler
  415        * for this MIME type. If one is found, the passed in DataFlavor
  416        * and the type of the data are passed to its getTransferData
  417        * method. If the DataHandler fails to locate a DataContentHandler
  418        * and the flavor specifies this object's MIME type and its class,
  419        * this DataHandler's referenced object is returned.
  420        * Otherwise it throws an UnsupportedFlavorException.
  421        *
  422        * @param flavor    the requested flavor for the data
  423        * @return          the object
  424        * @exception UnsupportedFlavorException    if the data could not be
  425        *                  converted to the requested flavor
  426        * @exception IOException   if an I/O error occurs
  427        * @see javax.activation.ActivationDataFlavor
  428        */
  429       public Object getTransferData(DataFlavor flavor)
  430                                   throws UnsupportedFlavorException, IOException {
  431           return getDataContentHandler().getTransferData(flavor, dataSource);
  432       }
  433   
  434       /**
  435        * Set the CommandMap for use by this DataHandler.
  436        * Setting it to <code>null</code> causes the CommandMap to revert
  437        * to the CommandMap returned by the
  438        * <code>CommandMap.getDefaultCommandMap</code> method.
  439        * Changing the CommandMap, or setting it to <code>null</code>,
  440        * clears out any data cached from the previous CommandMap.
  441        *
  442        * @param commandMap        the CommandMap to use in this DataHandler
  443        *
  444        * @see javax.activation.CommandMap#setDefaultCommandMap
  445        */
  446       public synchronized void setCommandMap(CommandMap commandMap) {
  447           if (commandMap != currentCommandMap || commandMap == null) {
  448               // clear cached values...
  449               transferFlavors = emptyFlavors;
  450               dataContentHandler = null;
  451   
  452               currentCommandMap = commandMap;
  453           }
  454       }
  455   
  456       /**
  457        * Return the <i>preferred</i> commands for this type of data.
  458        * This method calls the <code>getPreferredCommands</code> method
  459        * in the CommandMap associated with this instance of DataHandler.
  460        * This method returns an array that represents a subset of
  461        * available commands. In cases where multiple commands for the
  462        * MIME type represented by this DataHandler are present, the
  463        * installed CommandMap chooses the appropriate commands.
  464        *
  465        * @return  the CommandInfo objects representing the preferred commands
  466        *
  467        * @see javax.activation.CommandMap#getPreferredCommands
  468        */
  469       public CommandInfo[] getPreferredCommands() {
  470           if (dataSource != null)
  471               return getCommandMap().getPreferredCommands(getBaseType(),
  472                                                           dataSource);
  473           else
  474               return getCommandMap().getPreferredCommands(getBaseType());
  475       }
  476   
  477       /**
  478        * Return all the commands for this type of data.
  479        * This method returns an array containing all commands
  480        * for the type of data represented by this DataHandler. The
  481        * MIME type for the underlying data represented by this DataHandler
  482        * is used to call through to the <code>getAllCommands</code> method
  483        * of the CommandMap associated with this DataHandler.
  484        *
  485        * @return  the CommandInfo objects representing all the commands
  486        *
  487        * @see javax.activation.CommandMap#getAllCommands
  488        */
  489       public CommandInfo[] getAllCommands() {
  490           if (dataSource != null)
  491               return getCommandMap().getAllCommands(getBaseType(), dataSource);
  492           else
  493               return getCommandMap().getAllCommands(getBaseType());
  494       }
  495   
  496       /**
  497        * Get the command <i>cmdName</i>. Use the search semantics as
  498        * defined by the CommandMap installed in this DataHandler. The
  499        * MIME type for the underlying data represented by this DataHandler
  500        * is used to call through to the <code>getCommand</code> method
  501        * of the CommandMap associated with this DataHandler.
  502        *
  503        * @param cmdName   the command name
  504        * @return  the CommandInfo corresponding to the command
  505        *
  506        * @see javax.activation.CommandMap#getCommand
  507        */
  508       public CommandInfo getCommand(String cmdName) {
  509           if (dataSource != null)
  510               return getCommandMap().getCommand(getBaseType(), cmdName,
  511                                                                   dataSource);
  512           else
  513               return getCommandMap().getCommand(getBaseType(), cmdName);
  514       }
  515   
  516       /**
  517        * Return the data in its preferred Object form. <p>
  518        *
  519        * If the DataHandler was instantiated with an object, return
  520        * the object. <p>
  521        *
  522        * If the DataHandler was instantiated with a DataSource,
  523        * this method uses a DataContentHandler to return the content
  524        * object for the data represented by this DataHandler. If no
  525        * <code>DataContentHandler</code> can be found for the
  526        * the type of this data, the DataHandler returns an
  527        * InputStream for the data.
  528        *
  529        * @return the content.
  530        * @exception IOException if an IOException occurs during
  531        *                              this operation.
  532        */
  533       public Object getContent() throws IOException {
  534           if (object != null)
  535               return object;
  536           else
  537               return getDataContentHandler().getContent(getDataSource());
  538       }
  539   
  540       /**
  541        * A convenience method that takes a CommandInfo object
  542        * and instantiates the corresponding command, usually
  543        * a JavaBean component.
  544        * <p>
  545        * This method calls the CommandInfo's <code>getCommandObject</code>
  546        * method with the <code>ClassLoader</code> used to load
  547        * the <code>javax.activation.DataHandler</code> class itself.
  548        *
  549        * @param cmdinfo   the CommandInfo corresponding to a command
  550        * @return  the instantiated command object
  551        */
  552       public Object getBean(CommandInfo cmdinfo) {
  553           Object bean = null;
  554   
  555           try {
  556               // make the bean
  557               ClassLoader cld = null;
  558               // First try the "application's" class loader.
  559               cld = SecuritySupport.getContextClassLoader();
  560               if (cld == null)
  561                   cld = this.getClass().getClassLoader();
  562               bean = cmdinfo.getCommandObject(this, cld);
  563           } catch (IOException e) {
  564           } catch (ClassNotFoundException e) { }
  565   
  566           return bean;
  567       }
  568   
  569       /**
  570        * Get the DataContentHandler for this DataHandler: <p>
  571        *
  572        * If a DataContentHandlerFactory is set, use it.
  573        * Otherwise look for an object to serve DCH in the
  574        * following order: <p>
  575        *
  576        * 1) if a factory is set, use it <p>
  577        * 2) if a CommandMap is set, use it <p>
  578        * 3) use the default CommandMap <p>
  579        *
  580        * In any case, wrap the real DataContentHandler with one of our own
  581        * to handle any missing cases, fill in defaults, and to ensure that
  582        * we always have a non-null DataContentHandler.
  583        *
  584        * @return  the requested DataContentHandler
  585        */
  586       private synchronized DataContentHandler getDataContentHandler() {
  587   
  588           // make sure the factory didn't change
  589           if (factory != oldFactory) {
  590               oldFactory = factory;
  591               factoryDCH = null;
  592               dataContentHandler = null;
  593               transferFlavors = emptyFlavors;
  594           }
  595   
  596           if (dataContentHandler != null)
  597               return dataContentHandler;
  598   
  599           String simpleMT = getBaseType();
  600   
  601           if (factoryDCH == null && factory != null)
  602               factoryDCH = factory.createDataContentHandler(simpleMT);
  603   
  604           if (factoryDCH != null)
  605               dataContentHandler = factoryDCH;
  606   
  607           if (dataContentHandler == null) {
  608               if (dataSource != null)
  609                   dataContentHandler = getCommandMap().
  610                                   createDataContentHandler(simpleMT, dataSource);
  611               else
  612                   dataContentHandler = getCommandMap().
  613                                   createDataContentHandler(simpleMT);
  614           }
  615   
  616           // getDataContentHandler always uses these 'wrapper' handlers
  617           // to make sure it returns SOMETHING meaningful...
  618           if (dataSource != null)
  619               dataContentHandler = new DataSourceDataContentHandler(
  620                                                         dataContentHandler,
  621                                                         dataSource);
  622           else
  623               dataContentHandler = new ObjectDataContentHandler(
  624                                                         dataContentHandler,
  625                                                         object,
  626                                                         objectMimeType);
  627           return dataContentHandler;
  628       }
  629   
  630       /**
  631        * Use the MimeType class to extract the MIME type/subtype,
  632        * ignoring the parameters.  The type is cached.
  633        */
  634       private synchronized String getBaseType() {
  635           if (shortType == null) {
  636               String ct = getContentType();
  637               try {
  638                   MimeType mt = new MimeType(ct);
  639                   shortType = mt.getBaseType();
  640               } catch (MimeTypeParseException e) {
  641                   shortType = ct;
  642               }
  643           }
  644           return shortType;
  645       }
  646   
  647       /**
  648        * Sets the DataContentHandlerFactory.  The DataContentHandlerFactory
  649        * is called first to find DataContentHandlers.
  650        * The DataContentHandlerFactory can only be set once.
  651        * <p>
  652        * If the DataContentHandlerFactory has already been set,
  653        * this method throws an Error.
  654        *
  655        * @param newFactory        the DataContentHandlerFactory
  656        * @exception Error if the factory has already been defined.
  657        *
  658        * @see javax.activation.DataContentHandlerFactory
  659        */
  660       public static synchronized void setDataContentHandlerFactory(
  661                                            DataContentHandlerFactory newFactory) {
  662           if (factory != null)
  663               throw new Error("DataContentHandlerFactory already defined");
  664   
  665           SecurityManager security = System.getSecurityManager();
  666           if (security != null) {
  667               try {
  668                   // if it's ok with the SecurityManager, it's ok with me...
  669                   security.checkSetFactory();
  670               } catch (SecurityException ex) {
  671                   // otherwise, we also allow it if this code and the
  672                   // factory come from the same class loader (e.g.,
  673                   // the JAF classes were loaded with the applet classes).
  674                   if (DataHandler.class.getClassLoader() !=
  675                           newFactory.getClass().getClassLoader())
  676                       throw ex;
  677               }
  678           }
  679           factory = newFactory;
  680       }
  681   }
  682   
  683   /**
  684    * The DataHanderDataSource class implements the
  685    * DataSource interface when the DataHandler is constructed
  686    * with an Object and a mimeType string.
  687    */
  688   class DataHandlerDataSource implements DataSource {
  689       DataHandler dataHandler = null;
  690   
  691       /**
  692        * The constructor.
  693        */
  694       public DataHandlerDataSource(DataHandler dh) {
  695           this.dataHandler = dh;
  696       }
  697   
  698       /**
  699        * Returns an <code>InputStream</code> representing this object.
  700        * @return  the <code>InputStream</code>
  701        */
  702       public InputStream getInputStream() throws IOException {
  703           return dataHandler.getInputStream();
  704       }
  705   
  706       /**
  707        * Returns the <code>OutputStream</code> for this object.
  708        * @return  the <code>OutputStream</code>
  709        */
  710       public OutputStream getOutputStream() throws IOException {
  711           return dataHandler.getOutputStream();
  712       }
  713   
  714       /**
  715        * Returns the MIME type of the data represented by this object.
  716        * @return  the MIME type
  717        */
  718       public String getContentType() {
  719           return dataHandler.getContentType();
  720       }
  721   
  722       /**
  723        * Returns the name of this object.
  724        * @return  the name of this object
  725        */
  726       public String getName() {
  727           return dataHandler.getName(); // what else would it be?
  728       }
  729   }
  730   
  731   /*
  732    * DataSourceDataContentHandler
  733    *
  734    * This is a <i>private</i> DataContentHandler that wraps the real
  735    * DataContentHandler in the case where the DataHandler was instantiated
  736    * with a DataSource.
  737    */
  738   class DataSourceDataContentHandler implements DataContentHandler {
  739       private DataSource ds = null;
  740       private DataFlavor transferFlavors[] = null;
  741       private DataContentHandler dch = null;
  742   
  743       /**
  744        * The constructor.
  745        */
  746       public DataSourceDataContentHandler(DataContentHandler dch, DataSource ds) {
  747           this.ds = ds;
  748           this.dch = dch;
  749       }
  750   
  751       /**
  752        * Return the DataFlavors for this <code>DataContentHandler</code>.
  753        * @return  the DataFlavors
  754        */
  755       public DataFlavor[] getTransferDataFlavors() {
  756   
  757           if (transferFlavors == null) {
  758               if (dch != null) { // is there a dch?
  759                   transferFlavors = dch.getTransferDataFlavors();
  760               } else {
  761                   transferFlavors = new DataFlavor[1];
  762                   transferFlavors[0] =
  763                       new ActivationDataFlavor(ds.getContentType(),
  764                                                ds.getContentType());
  765               }
  766           }
  767           return transferFlavors;
  768       }
  769   
  770       /**
  771        * Return the Transfer Data of type DataFlavor from InputStream.
  772        * @param df        the DataFlavor
  773        * @param ds        the DataSource
  774        * @return          the constructed Object
  775        */
  776       public Object getTransferData(DataFlavor df, DataSource ds) throws
  777                                   UnsupportedFlavorException, IOException {
  778   
  779           if (dch != null)
  780               return dch.getTransferData(df, ds);
  781           else if (df.equals(getTransferDataFlavors()[0])) // only have one now
  782               return ds.getInputStream();
  783           else
  784               throw new UnsupportedFlavorException(df);
  785       }
  786   
  787       public Object getContent(DataSource ds) throws IOException {
  788   
  789           if (dch != null)
  790               return dch.getContent(ds);
  791           else
  792               return ds.getInputStream();
  793       }
  794   
  795       /**
  796        * Write the object to the output stream.
  797        */
  798       public void writeTo(Object obj, String mimeType, OutputStream os)
  799                                                   throws IOException {
  800           if (dch != null)
  801               dch.writeTo(obj, mimeType, os);
  802           else
  803               throw new UnsupportedDataTypeException(
  804                           "no DCH for content type " + ds.getContentType());
  805       }
  806   }
  807   
  808   /*
  809    * ObjectDataContentHandler
  810    *
  811    * This is a <i>private</i> DataContentHandler that wraps the real
  812    * DataContentHandler in the case where the DataHandler was instantiated
  813    * with an object.
  814    */
  815   class ObjectDataContentHandler implements DataContentHandler {
  816       private DataFlavor transferFlavors[] = null;
  817       private Object obj;
  818       private String mimeType;
  819       private DataContentHandler dch = null;
  820   
  821       /**
  822        * The constructor.
  823        */
  824       public ObjectDataContentHandler(DataContentHandler dch,
  825                                       Object obj, String mimeType) {
  826           this.obj = obj;
  827           this.mimeType = mimeType;
  828           this.dch = dch;
  829       }
  830   
  831       /**
  832        * Return the DataContentHandler for this object.
  833        * Used only by the DataHandler class.
  834        */
  835       public DataContentHandler getDCH() {
  836           return dch;
  837       }
  838   
  839       /**
  840        * Return the DataFlavors for this <code>DataContentHandler</code>.
  841        * @return  the DataFlavors
  842        */
  843       public synchronized DataFlavor[] getTransferDataFlavors() {
  844           if (transferFlavors == null) {
  845               if (dch != null) {
  846                   transferFlavors = dch.getTransferDataFlavors();
  847               } else {
  848                   transferFlavors = new DataFlavor[1];
  849                   transferFlavors[0] = new ActivationDataFlavor(obj.getClass(),
  850                                                mimeType, mimeType);
  851               }
  852           }
  853           return transferFlavors;
  854       }
  855   
  856       /**
  857        * Return the Transfer Data of type DataFlavor from InputStream.
  858        * @param df        the DataFlavor
  859        * @param ds        the DataSource
  860        * @return          the constructed Object
  861        */
  862       public Object getTransferData(DataFlavor df, DataSource ds)
  863                                   throws UnsupportedFlavorException, IOException {
  864   
  865           if (dch != null)
  866               return dch.getTransferData(df, ds);
  867           else if (df.equals(getTransferDataFlavors()[0])) // only have one now
  868               return obj;
  869           else
  870               throw new UnsupportedFlavorException(df);
  871   
  872       }
  873   
  874       public Object getContent(DataSource ds) {
  875           return obj;
  876       }
  877   
  878       /**
  879        * Write the object to the output stream.
  880        */
  881       public void writeTo(Object obj, String mimeType, OutputStream os)
  882                                                   throws IOException {
  883           if (dch != null)
  884               dch.writeTo(obj, mimeType, os);
  885           else if (obj instanceof byte[])
  886               os.write((byte[])obj);
  887           else if (obj instanceof String) {
  888               OutputStreamWriter osw = new OutputStreamWriter(os);
  889               osw.write((String)obj);
  890               osw.flush();
  891           } else throw new UnsupportedDataTypeException(
  892                   "no object DCH for MIME type " + this.mimeType);
  893       }
  894   }

Save This Page
Home » Open-JDK-6.b17-src » javax » activation » [javadoc | source]