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

Save This Page
Home » glassfish-v2ur2-b04-src » javax » activation » [javadoc | source]