| /* |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. |
| * |
| * Copyright (c) 1997-2017 Oracle and/or its affiliates. All rights reserved. |
| * |
| * The contents of this file are subject to the terms of either the GNU |
| * General Public License Version 2 only ("GPL") or the Common Development |
| * and Distribution License("CDDL") (collectively, the "License"). You |
| * may not use this file except in compliance with the License. You can |
| * obtain a copy of the License at |
| * https://oss.oracle.com/licenses/CDDL+GPL-1.1 |
| * or LICENSE.txt. See the License for the specific |
| * language governing permissions and limitations under the License. |
| * |
| * When distributing the software, include this License Header Notice in each |
| * file and include the License file at LICENSE.txt. |
| * |
| * GPL Classpath Exception: |
| * Oracle designates this particular file as subject to the "Classpath" |
| * exception as provided by Oracle in the GPL Version 2 section of the License |
| * file that accompanied this code. |
| * |
| * Modifications: |
| * If applicable, add the following below the License Header, with the fields |
| * enclosed by brackets [] replaced by your own identifying information: |
| * "Portions Copyright [year] [name of copyright owner]" |
| * |
| * Contributor(s): |
| * If you wish your version of this file to be governed by only the CDDL or |
| * only the GPL Version 2, indicate your decision by adding "[Contributor] |
| * elects to include this software in this distribution under the [CDDL or GPL |
| * Version 2] license." If you don't indicate a single choice of license, a |
| * recipient has the option to distribute your version of this file under |
| * either the CDDL, the GPL Version 2 or to extend the choice of license to |
| * its licensees as provided above. However, if you add GPL Version 2 code |
| * and therefore, elected the GPL Version 2 license, then the option applies |
| * only if the new code is made subject to such option by the copyright |
| * holder. |
| */ |
| |
| package javax.activation; |
| |
| import java.io.InputStream; |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PipedInputStream; |
| import java.io.PipedOutputStream; |
| import java.io.OutputStreamWriter; |
| import java.net.URL; |
| import java.awt.datatransfer.Transferable; |
| import java.awt.datatransfer.DataFlavor; |
| import java.awt.datatransfer.UnsupportedFlavorException; |
| |
| /** |
| * The DataHandler class provides a consistent interface to data |
| * available in many different sources and formats. |
| * It manages simple stream to string conversions and related operations |
| * using DataContentHandlers. |
| * It provides access to commands that can operate on the data. |
| * The commands are found using a CommandMap. <p> |
| * |
| * <b>DataHandler and the Transferable Interface</b><p> |
| * DataHandler implements the Transferable interface so that data can |
| * be used in AWT data transfer operations, such as cut and paste and |
| * drag and drop. The implementation of the Transferable interface |
| * relies on the availability of an installed DataContentHandler |
| * object corresponding to the MIME type of the data represented in |
| * the specific instance of the DataHandler.<p> |
| * |
| * <b>DataHandler and CommandMaps</b><p> |
| * The DataHandler keeps track of the current CommandMap that it uses to |
| * service requests for commands (<code>getCommand</code>, |
| * <code>getAllCommands</code>, <code>getPreferredCommands</code>). |
| * Each instance of a DataHandler may have a CommandMap associated with |
| * it using the <code>setCommandMap</code> method. If a CommandMap was |
| * not set, DataHandler calls the <code>getDefaultCommandMap</code> |
| * method in CommandMap and uses the value it returns. See |
| * <i>CommandMap</i> for more information. <p> |
| * |
| * <b>DataHandler and URLs</b><p> |
| * The current DataHandler implementation creates a private |
| * instance of URLDataSource when it is constructed with a URL. |
| * |
| * @see javax.activation.CommandMap |
| * @see javax.activation.DataContentHandler |
| * @see javax.activation.DataSource |
| * @see javax.activation.URLDataSource |
| */ |
| |
| public class DataHandler implements Transferable { |
| |
| // Use the datasource to indicate whether we were started via the |
| // DataSource constructor or the object constructor. |
| private DataSource dataSource = null; |
| private DataSource objDataSource = null; |
| |
| // The Object and mimetype from the constructor (if passed in). |
| // object remains null if it was instantiated with a |
| // DataSource. |
| private Object object = null; |
| private String objectMimeType = null; |
| |
| // Keep track of the CommandMap |
| private CommandMap currentCommandMap = null; |
| |
| // our transfer flavors |
| private static final DataFlavor emptyFlavors[] = new DataFlavor[0]; |
| private DataFlavor transferFlavors[] = emptyFlavors; |
| |
| // our DataContentHandler |
| private DataContentHandler dataContentHandler = null; |
| private DataContentHandler factoryDCH = null; |
| |
| // our DataContentHandlerFactory |
| private static DataContentHandlerFactory factory = null; |
| private DataContentHandlerFactory oldFactory = null; |
| // the short representation of the ContentType (sans params) |
| private String shortType = null; |
| |
| /** |
| * Create a <code>DataHandler</code> instance referencing the |
| * specified DataSource. The data exists in a byte stream form. |
| * The DataSource will provide an InputStream to access the data. |
| * |
| * @param ds the DataSource |
| */ |
| public DataHandler(DataSource ds) { |
| // save a reference to the incoming DS |
| dataSource = ds; |
| oldFactory = factory; // keep track of the factory |
| } |
| |
| /** |
| * Create a <code>DataHandler</code> instance representing an object |
| * of this MIME type. This constructor is |
| * used when the application already has an in-memory representation |
| * of the data in the form of a Java Object. |
| * |
| * @param obj the Java Object |
| * @param mimeType the MIME type of the object |
| */ |
| public DataHandler(Object obj, String mimeType) { |
| object = obj; |
| objectMimeType = mimeType; |
| oldFactory = factory; // keep track of the factory |
| } |
| |
| /** |
| * Create a <code>DataHandler</code> instance referencing a URL. |
| * The DataHandler internally creates a <code>URLDataSource</code> |
| * instance to represent the URL. |
| * |
| * @param url a URL object |
| */ |
| public DataHandler(URL url) { |
| dataSource = new URLDataSource(url); |
| oldFactory = factory; // keep track of the factory |
| } |
| |
| /** |
| * Return the CommandMap for this instance of DataHandler. |
| */ |
| private synchronized CommandMap getCommandMap() { |
| if (currentCommandMap != null) |
| return currentCommandMap; |
| else |
| return CommandMap.getDefaultCommandMap(); |
| } |
| |
| /** |
| * Return the DataSource associated with this instance |
| * of DataHandler. |
| * <p> |
| * For DataHandlers that have been instantiated with a DataSource, |
| * this method returns the DataSource that was used to create the |
| * DataHandler object. In other cases the DataHandler |
| * constructs a DataSource from the data used to construct |
| * the DataHandler. DataSources created for DataHandlers <b>not</b> |
| * instantiated with a DataSource are cached for performance |
| * reasons. |
| * |
| * @return a valid DataSource object for this DataHandler |
| */ |
| public DataSource getDataSource() { |
| if (dataSource == null) { |
| // create one on the fly |
| if (objDataSource == null) |
| objDataSource = new DataHandlerDataSource(this); |
| return objDataSource; |
| } |
| return dataSource; |
| } |
| |
| /** |
| * Return the name of the data object. If this DataHandler |
| * was created with a DataSource, this method calls through |
| * to the <code>DataSource.getName</code> method, otherwise it |
| * returns <i>null</i>. |
| * |
| * @return the name of the object |
| */ |
| public String getName() { |
| if (dataSource != null) |
| return dataSource.getName(); |
| else |
| return null; |
| } |
| |
| /** |
| * Return the MIME type of this object as retrieved from |
| * the source object. Note that this is the <i>full</i> |
| * type with parameters. |
| * |
| * @return the MIME type |
| */ |
| public String getContentType() { |
| if (dataSource != null) // data source case |
| return dataSource.getContentType(); |
| else |
| return objectMimeType; // obj/type case |
| } |
| |
| /** |
| * Get the InputStream for this object. <p> |
| * |
| * For DataHandlers instantiated with a DataSource, the DataHandler |
| * calls the <code>DataSource.getInputStream</code> method and |
| * returns the result to the caller. |
| * <p> |
| * For DataHandlers instantiated with an Object, the DataHandler |
| * first attempts to find a DataContentHandler for the Object. If |
| * the DataHandler can not find a DataContentHandler for this MIME |
| * type, it throws an UnsupportedDataTypeException. If it is |
| * successful, it creates a pipe and a thread. The thread uses the |
| * DataContentHandler's <code>writeTo</code> method to write the |
| * stream data into one end of the pipe. The other end of the pipe |
| * is returned to the caller. Because a thread is created to copy |
| * the data, IOExceptions that may occur during the copy can not be |
| * propagated back to the caller. The result is an empty stream.<p> |
| * |
| * @return the InputStream representing this data |
| * @exception IOException if an I/O error occurs |
| * |
| * @see javax.activation.DataContentHandler#writeTo |
| * @see javax.activation.UnsupportedDataTypeException |
| */ |
| public InputStream getInputStream() throws IOException { |
| InputStream ins = null; |
| |
| if (dataSource != null) { |
| ins = dataSource.getInputStream(); |
| } else { |
| DataContentHandler dch = getDataContentHandler(); |
| // we won't even try if we can't get a dch |
| if (dch == null) |
| throw new UnsupportedDataTypeException( |
| "no DCH for MIME type " + getBaseType()); |
| |
| if (dch instanceof ObjectDataContentHandler) { |
| if (((ObjectDataContentHandler)dch).getDCH() == null) |
| throw new UnsupportedDataTypeException( |
| "no object DCH for MIME type " + getBaseType()); |
| } |
| // there is none but the default^^^^^^^^^^^^^^^^ |
| final DataContentHandler fdch = dch; |
| |
| // from bill s. |
| // ce n'est pas une pipe! |
| // |
| // NOTE: This block of code needs to throw exceptions, but |
| // can't because it is in another thread!!! ARG! |
| // |
| final PipedOutputStream pos = new PipedOutputStream(); |
| PipedInputStream pin = new PipedInputStream(pos); |
| new Thread( |
| new Runnable() { |
| public void run() { |
| try { |
| fdch.writeTo(object, objectMimeType, pos); |
| } catch (IOException e) { |
| |
| } finally { |
| try { |
| pos.close(); |
| } catch (IOException ie) { } |
| } |
| } |
| }, |
| "DataHandler.getInputStream").start(); |
| ins = pin; |
| } |
| |
| return ins; |
| } |
| |
| /** |
| * Write the data to an <code>OutputStream</code>.<p> |
| * |
| * If the DataHandler was created with a DataSource, writeTo |
| * retrieves the InputStream and copies the bytes from the |
| * InputStream to the OutputStream passed in. |
| * <p> |
| * If the DataHandler was created with an object, writeTo |
| * retrieves the DataContentHandler for the object's type. |
| * If the DataContentHandler was found, it calls the |
| * <code>writeTo</code> method on the <code>DataContentHandler</code>. |
| * |
| * @param os the OutputStream to write to |
| * @exception IOException if an I/O error occurs |
| */ |
| public void writeTo(OutputStream os) throws IOException { |
| // for the DataSource case |
| if (dataSource != null) { |
| InputStream is = null; |
| byte data[] = new byte[8*1024]; |
| int bytes_read; |
| |
| is = dataSource.getInputStream(); |
| |
| try { |
| while ((bytes_read = is.read(data)) > 0) { |
| os.write(data, 0, bytes_read); |
| } |
| } finally { |
| is.close(); |
| is = null; |
| } |
| } else { // for the Object case |
| DataContentHandler dch = getDataContentHandler(); |
| dch.writeTo(object, objectMimeType, os); |
| } |
| } |
| |
| /** |
| * Get an OutputStream for this DataHandler to allow overwriting |
| * the underlying data. |
| * If the DataHandler was created with a DataSource, the |
| * DataSource's <code>getOutputStream</code> method is called. |
| * Otherwise, <code>null</code> is returned. |
| * |
| * @return the OutputStream |
| * @exception IOException for failures creating the OutputStream |
| * |
| * @see javax.activation.DataSource#getOutputStream |
| * @see javax.activation.URLDataSource |
| */ |
| public OutputStream getOutputStream() throws IOException { |
| if (dataSource != null) |
| return dataSource.getOutputStream(); |
| else |
| return null; |
| } |
| |
| /** |
| * Return the DataFlavors in which this data is available. <p> |
| * |
| * Returns an array of DataFlavor objects indicating the flavors |
| * the data can be provided in. The array is usually ordered |
| * according to preference for providing the data, from most |
| * richly descriptive to least richly descriptive.<p> |
| * |
| * The DataHandler attempts to find a DataContentHandler that |
| * corresponds to the MIME type of the data. If one is located, |
| * the DataHandler calls the DataContentHandler's |
| * <code>getTransferDataFlavors</code> method. <p> |
| * |
| * If a DataContentHandler can <i>not</i> be located, and if the |
| * DataHandler was created with a DataSource (or URL), one |
| * DataFlavor is returned that represents this object's MIME type |
| * and the <code>java.io.InputStream</code> class. If the |
| * DataHandler was created with an object and a MIME type, |
| * getTransferDataFlavors returns one DataFlavor that represents |
| * this object's MIME type and the object's class. |
| * |
| * @return an array of data flavors in which this data can be transferred |
| * @see javax.activation.DataContentHandler#getTransferDataFlavors |
| */ |
| public synchronized DataFlavor[] getTransferDataFlavors() { |
| if (factory != oldFactory) // if the factory has changed, clear cache |
| transferFlavors = emptyFlavors; |
| |
| // if it's not set, set it... |
| if (transferFlavors == emptyFlavors) |
| transferFlavors = getDataContentHandler().getTransferDataFlavors(); |
| if (transferFlavors == emptyFlavors) |
| return transferFlavors; // no need to clone an empty array |
| else |
| return transferFlavors.clone(); |
| } |
| |
| /** |
| * Returns whether the specified data flavor is supported |
| * for this object.<p> |
| * |
| * This method iterates through the DataFlavors returned from |
| * <code>getTransferDataFlavors</code>, comparing each with |
| * the specified flavor. |
| * |
| * @param flavor the requested flavor for the data |
| * @return true if the data flavor is supported |
| * @see javax.activation.DataHandler#getTransferDataFlavors |
| */ |
| public boolean isDataFlavorSupported(DataFlavor flavor) { |
| DataFlavor[] lFlavors = getTransferDataFlavors(); |
| |
| for (int i = 0; i < lFlavors.length; i++) { |
| if (lFlavors[i].equals(flavor)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Returns an object that represents the data to be |
| * transferred. The class of the object returned is defined by the |
| * representation class of the data flavor.<p> |
| * |
| * <b>For DataHandler's created with DataSources or URLs:</b><p> |
| * |
| * The DataHandler attempts to locate a DataContentHandler |
| * for this MIME type. If one is found, the passed in DataFlavor |
| * and the type of the data are passed to its <code>getTransferData</code> |
| * method. If the DataHandler fails to locate a DataContentHandler |
| * and the flavor specifies this object's MIME type and the |
| * <code>java.io.InputStream</code> class, this object's InputStream |
| * is returned. |
| * Otherwise it throws an UnsupportedFlavorException. <p> |
| * |
| * <b>For DataHandler's created with Objects:</b><p> |
| * |
| * The DataHandler attempts to locate a DataContentHandler |
| * for this MIME type. If one is found, the passed in DataFlavor |
| * and the type of the data are passed to its getTransferData |
| * method. If the DataHandler fails to locate a DataContentHandler |
| * and the flavor specifies this object's MIME type and its class, |
| * this DataHandler's referenced object is returned. |
| * Otherwise it throws an UnsupportedFlavorException. |
| * |
| * @param flavor the requested flavor for the data |
| * @return the object |
| * @exception UnsupportedFlavorException if the data could not be |
| * converted to the requested flavor |
| * @exception IOException if an I/O error occurs |
| * @see javax.activation.ActivationDataFlavor |
| */ |
| public Object getTransferData(DataFlavor flavor) |
| throws UnsupportedFlavorException, IOException { |
| return getDataContentHandler().getTransferData(flavor, dataSource); |
| } |
| |
| /** |
| * Set the CommandMap for use by this DataHandler. |
| * Setting it to <code>null</code> causes the CommandMap to revert |
| * to the CommandMap returned by the |
| * <code>CommandMap.getDefaultCommandMap</code> method. |
| * Changing the CommandMap, or setting it to <code>null</code>, |
| * clears out any data cached from the previous CommandMap. |
| * |
| * @param commandMap the CommandMap to use in this DataHandler |
| * |
| * @see javax.activation.CommandMap#setDefaultCommandMap |
| */ |
| public synchronized void setCommandMap(CommandMap commandMap) { |
| if (commandMap != currentCommandMap || commandMap == null) { |
| // clear cached values... |
| transferFlavors = emptyFlavors; |
| dataContentHandler = null; |
| |
| currentCommandMap = commandMap; |
| } |
| } |
| |
| /** |
| * Return the <i>preferred</i> commands for this type of data. |
| * This method calls the <code>getPreferredCommands</code> method |
| * in the CommandMap associated with this instance of DataHandler. |
| * This method returns an array that represents a subset of |
| * available commands. In cases where multiple commands for the |
| * MIME type represented by this DataHandler are present, the |
| * installed CommandMap chooses the appropriate commands. |
| * |
| * @return the CommandInfo objects representing the preferred commands |
| * |
| * @see javax.activation.CommandMap#getPreferredCommands |
| */ |
| public CommandInfo[] getPreferredCommands() { |
| if (dataSource != null) |
| return getCommandMap().getPreferredCommands(getBaseType(), |
| dataSource); |
| else |
| return getCommandMap().getPreferredCommands(getBaseType()); |
| } |
| |
| /** |
| * Return all the commands for this type of data. |
| * This method returns an array containing all commands |
| * for the type of data represented by this DataHandler. The |
| * MIME type for the underlying data represented by this DataHandler |
| * is used to call through to the <code>getAllCommands</code> method |
| * of the CommandMap associated with this DataHandler. |
| * |
| * @return the CommandInfo objects representing all the commands |
| * |
| * @see javax.activation.CommandMap#getAllCommands |
| */ |
| public CommandInfo[] getAllCommands() { |
| if (dataSource != null) |
| return getCommandMap().getAllCommands(getBaseType(), dataSource); |
| else |
| return getCommandMap().getAllCommands(getBaseType()); |
| } |
| |
| /** |
| * Get the command <i>cmdName</i>. Use the search semantics as |
| * defined by the CommandMap installed in this DataHandler. The |
| * MIME type for the underlying data represented by this DataHandler |
| * is used to call through to the <code>getCommand</code> method |
| * of the CommandMap associated with this DataHandler. |
| * |
| * @param cmdName the command name |
| * @return the CommandInfo corresponding to the command |
| * |
| * @see javax.activation.CommandMap#getCommand |
| */ |
| public CommandInfo getCommand(String cmdName) { |
| if (dataSource != null) |
| return getCommandMap().getCommand(getBaseType(), cmdName, |
| dataSource); |
| else |
| return getCommandMap().getCommand(getBaseType(), cmdName); |
| } |
| |
| /** |
| * Return the data in its preferred Object form. <p> |
| * |
| * If the DataHandler was instantiated with an object, return |
| * the object. <p> |
| * |
| * If the DataHandler was instantiated with a DataSource, |
| * this method uses a DataContentHandler to return the content |
| * object for the data represented by this DataHandler. If no |
| * <code>DataContentHandler</code> can be found for the |
| * the type of this data, the DataHandler returns an |
| * InputStream for the data. |
| * |
| * @return the content. |
| * @exception IOException if an IOException occurs during |
| * this operation. |
| */ |
| public Object getContent() throws IOException { |
| if (object != null) |
| return object; |
| else |
| return getDataContentHandler().getContent(getDataSource()); |
| } |
| |
| /** |
| * A convenience method that takes a CommandInfo object |
| * and instantiates the corresponding command, usually |
| * a JavaBean component. |
| * <p> |
| * This method calls the CommandInfo's <code>getCommandObject</code> |
| * method with the <code>ClassLoader</code> used to load |
| * the <code>javax.activation.DataHandler</code> class itself. |
| * |
| * @param cmdinfo the CommandInfo corresponding to a command |
| * @return the instantiated command object |
| */ |
| public Object getBean(CommandInfo cmdinfo) { |
| Object bean = null; |
| |
| try { |
| // make the bean |
| ClassLoader cld = null; |
| // First try the "application's" class loader. |
| cld = SecuritySupport.getContextClassLoader(); |
| if (cld == null) |
| cld = this.getClass().getClassLoader(); |
| bean = cmdinfo.getCommandObject(this, cld); |
| } catch (IOException e) { |
| } catch (ClassNotFoundException e) { } |
| |
| return bean; |
| } |
| |
| /** |
| * Get the DataContentHandler for this DataHandler: <p> |
| * |
| * If a DataContentHandlerFactory is set, use it. |
| * Otherwise look for an object to serve DCH in the |
| * following order: <p> |
| * |
| * 1) if a factory is set, use it <p> |
| * 2) if a CommandMap is set, use it <p> |
| * 3) use the default CommandMap <p> |
| * |
| * In any case, wrap the real DataContentHandler with one of our own |
| * to handle any missing cases, fill in defaults, and to ensure that |
| * we always have a non-null DataContentHandler. |
| * |
| * @return the requested DataContentHandler |
| */ |
| private synchronized DataContentHandler getDataContentHandler() { |
| |
| // make sure the factory didn't change |
| if (factory != oldFactory) { |
| oldFactory = factory; |
| factoryDCH = null; |
| dataContentHandler = null; |
| transferFlavors = emptyFlavors; |
| } |
| |
| if (dataContentHandler != null) |
| return dataContentHandler; |
| |
| String simpleMT = getBaseType(); |
| |
| if (factoryDCH == null && factory != null) |
| factoryDCH = factory.createDataContentHandler(simpleMT); |
| |
| if (factoryDCH != null) |
| dataContentHandler = factoryDCH; |
| |
| if (dataContentHandler == null) { |
| if (dataSource != null) |
| dataContentHandler = getCommandMap(). |
| createDataContentHandler(simpleMT, dataSource); |
| else |
| dataContentHandler = getCommandMap(). |
| createDataContentHandler(simpleMT); |
| } |
| |
| // getDataContentHandler always uses these 'wrapper' handlers |
| // to make sure it returns SOMETHING meaningful... |
| if (dataSource != null) |
| dataContentHandler = new DataSourceDataContentHandler( |
| dataContentHandler, |
| dataSource); |
| else |
| dataContentHandler = new ObjectDataContentHandler( |
| dataContentHandler, |
| object, |
| objectMimeType); |
| return dataContentHandler; |
| } |
| |
| /** |
| * Use the MimeType class to extract the MIME type/subtype, |
| * ignoring the parameters. The type is cached. |
| */ |
| private synchronized String getBaseType() { |
| if (shortType == null) { |
| String ct = getContentType(); |
| try { |
| MimeType mt = new MimeType(ct); |
| shortType = mt.getBaseType(); |
| } catch (MimeTypeParseException e) { |
| shortType = ct; |
| } |
| } |
| return shortType; |
| } |
| |
| /** |
| * Sets the DataContentHandlerFactory. The DataContentHandlerFactory |
| * is called first to find DataContentHandlers. |
| * The DataContentHandlerFactory can only be set once. |
| * <p> |
| * If the DataContentHandlerFactory has already been set, |
| * this method throws an Error. |
| * |
| * @param newFactory the DataContentHandlerFactory |
| * @exception Error if the factory has already been defined. |
| * |
| * @see javax.activation.DataContentHandlerFactory |
| */ |
| public static synchronized void setDataContentHandlerFactory( |
| DataContentHandlerFactory newFactory) { |
| if (factory != null) |
| throw new Error("DataContentHandlerFactory already defined"); |
| |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| try { |
| // if it's ok with the SecurityManager, it's ok with me... |
| security.checkSetFactory(); |
| } catch (SecurityException ex) { |
| // otherwise, we also allow it if this code and the |
| // factory come from the same class loader (e.g., |
| // the JAF classes were loaded with the applet classes). |
| if (DataHandler.class.getClassLoader() != |
| newFactory.getClass().getClassLoader()) |
| throw ex; |
| } |
| } |
| factory = newFactory; |
| } |
| } |
| |
| /** |
| * The DataHanderDataSource class implements the |
| * DataSource interface when the DataHandler is constructed |
| * with an Object and a mimeType string. |
| */ |
| class DataHandlerDataSource implements DataSource { |
| DataHandler dataHandler = null; |
| |
| /** |
| * The constructor. |
| */ |
| public DataHandlerDataSource(DataHandler dh) { |
| this.dataHandler = dh; |
| } |
| |
| /** |
| * Returns an <code>InputStream</code> representing this object. |
| * @return the <code>InputStream</code> |
| */ |
| public InputStream getInputStream() throws IOException { |
| return dataHandler.getInputStream(); |
| } |
| |
| /** |
| * Returns the <code>OutputStream</code> for this object. |
| * @return the <code>OutputStream</code> |
| */ |
| public OutputStream getOutputStream() throws IOException { |
| return dataHandler.getOutputStream(); |
| } |
| |
| /** |
| * Returns the MIME type of the data represented by this object. |
| * @return the MIME type |
| */ |
| public String getContentType() { |
| return dataHandler.getContentType(); |
| } |
| |
| /** |
| * Returns the name of this object. |
| * @return the name of this object |
| */ |
| public String getName() { |
| return dataHandler.getName(); // what else would it be? |
| } |
| } |
| |
| /* |
| * DataSourceDataContentHandler |
| * |
| * This is a <i>private</i> DataContentHandler that wraps the real |
| * DataContentHandler in the case where the DataHandler was instantiated |
| * with a DataSource. |
| */ |
| class DataSourceDataContentHandler implements DataContentHandler { |
| private DataSource ds = null; |
| private DataFlavor transferFlavors[] = null; |
| private DataContentHandler dch = null; |
| |
| /** |
| * The constructor. |
| */ |
| public DataSourceDataContentHandler(DataContentHandler dch, DataSource ds) { |
| this.ds = ds; |
| this.dch = dch; |
| } |
| |
| /** |
| * Return the DataFlavors for this <code>DataContentHandler</code>. |
| * @return the DataFlavors |
| */ |
| public DataFlavor[] getTransferDataFlavors() { |
| |
| if (transferFlavors == null) { |
| if (dch != null) { // is there a dch? |
| transferFlavors = dch.getTransferDataFlavors(); |
| } else { |
| transferFlavors = new DataFlavor[1]; |
| transferFlavors[0] = |
| new ActivationDataFlavor(ds.getContentType(), |
| ds.getContentType()); |
| } |
| } |
| return transferFlavors; |
| } |
| |
| /** |
| * Return the Transfer Data of type DataFlavor from InputStream. |
| * @param df the DataFlavor |
| * @param ds the DataSource |
| * @return the constructed Object |
| */ |
| public Object getTransferData(DataFlavor df, DataSource ds) throws |
| UnsupportedFlavorException, IOException { |
| |
| if (dch != null) |
| return dch.getTransferData(df, ds); |
| else if (df.equals(getTransferDataFlavors()[0])) // only have one now |
| return ds.getInputStream(); |
| else |
| throw new UnsupportedFlavorException(df); |
| } |
| |
| public Object getContent(DataSource ds) throws IOException { |
| |
| if (dch != null) |
| return dch.getContent(ds); |
| else |
| return ds.getInputStream(); |
| } |
| |
| /** |
| * Write the object to the output stream. |
| */ |
| public void writeTo(Object obj, String mimeType, OutputStream os) |
| throws IOException { |
| if (dch != null) |
| dch.writeTo(obj, mimeType, os); |
| else |
| throw new UnsupportedDataTypeException( |
| "no DCH for content type " + ds.getContentType()); |
| } |
| } |
| |
| /* |
| * ObjectDataContentHandler |
| * |
| * This is a <i>private</i> DataContentHandler that wraps the real |
| * DataContentHandler in the case where the DataHandler was instantiated |
| * with an object. |
| */ |
| class ObjectDataContentHandler implements DataContentHandler { |
| private DataFlavor transferFlavors[] = null; |
| private Object obj; |
| private String mimeType; |
| private DataContentHandler dch = null; |
| |
| /** |
| * The constructor. |
| */ |
| public ObjectDataContentHandler(DataContentHandler dch, |
| Object obj, String mimeType) { |
| this.obj = obj; |
| this.mimeType = mimeType; |
| this.dch = dch; |
| } |
| |
| /** |
| * Return the DataContentHandler for this object. |
| * Used only by the DataHandler class. |
| */ |
| public DataContentHandler getDCH() { |
| return dch; |
| } |
| |
| /** |
| * Return the DataFlavors for this <code>DataContentHandler</code>. |
| * @return the DataFlavors |
| */ |
| public synchronized DataFlavor[] getTransferDataFlavors() { |
| if (transferFlavors == null) { |
| if (dch != null) { |
| transferFlavors = dch.getTransferDataFlavors(); |
| } else { |
| transferFlavors = new DataFlavor[1]; |
| transferFlavors[0] = new ActivationDataFlavor(obj.getClass(), |
| mimeType, mimeType); |
| } |
| } |
| return transferFlavors; |
| } |
| |
| /** |
| * Return the Transfer Data of type DataFlavor from InputStream. |
| * @param df the DataFlavor |
| * @param ds the DataSource |
| * @return the constructed Object |
| */ |
| public Object getTransferData(DataFlavor df, DataSource ds) |
| throws UnsupportedFlavorException, IOException { |
| |
| if (dch != null) |
| return dch.getTransferData(df, ds); |
| else if (df.equals(getTransferDataFlavors()[0])) // only have one now |
| return obj; |
| else |
| throw new UnsupportedFlavorException(df); |
| |
| } |
| |
| public Object getContent(DataSource ds) { |
| return obj; |
| } |
| |
| /** |
| * Write the object to the output stream. |
| */ |
| public void writeTo(Object obj, String mimeType, OutputStream os) |
| throws IOException { |
| if (dch != null) |
| dch.writeTo(obj, mimeType, os); |
| else if (obj instanceof byte[]) |
| os.write((byte[])obj); |
| else if (obj instanceof String) { |
| OutputStreamWriter osw = new OutputStreamWriter(os); |
| osw.write((String)obj); |
| osw.flush(); |
| } else |
| throw new UnsupportedDataTypeException( |
| "no object DCH for MIME type " + this.mimeType); |
| } |
| } |