diff -r 000000000000 -r 373ffda63c9a src/share/jaf_classes/javax/activation/DataHandler.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/jaf_classes/javax/activation/DataHandler.java Wed Apr 27 01:27:09 2016 +0800 @@ -0,0 +1,899 @@ +/* + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +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.
+ * + * DataHandler and the Transferable Interface
+ * 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.
+ * + * DataHandler and CommandMaps
+ * The DataHandler keeps track of the current CommandMap that it uses to
+ * service requests for commands (getCommand
,
+ * getAllCommands
, getPreferredCommands
).
+ * Each instance of a DataHandler may have a CommandMap associated with
+ * it using the setCommandMap
method. If a CommandMap was
+ * not set, DataHandler calls the getDefaultCommandMap
+ * method in CommandMap and uses the value it returns. See
+ * CommandMap for more information.
+ * + * DataHandler and URLs
+ * 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
+ *
+ * @since 1.6
+ */
+
+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 DataHandler
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 DataHandler
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 DataHandler
instance referencing a URL.
+ * The DataHandler internally creates a URLDataSource
+ * 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.
+ *
+ * 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 not
+ * 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 DataSource.getName
method, otherwise it
+ * returns null.
+ *
+ * @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 full
+ * 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.
+ *
+ * For DataHandlers instantiated with a DataSource, the DataHandler
+ * calls the DataSource.getInputStream
method and
+ * returns the result to the caller.
+ *
+ * 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 writeTo
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.
+ *
+ * @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 OutputStream
.
+ * + * If the DataHandler was created with a DataSource, writeTo + * retrieves the InputStream and copies the bytes from the + * InputStream to the OutputStream passed in. + *
+ * 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
+ * writeTo
method on the DataContentHandler
.
+ *
+ * @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 getOutputStream
method is called.
+ * Otherwise, null
is returned.
+ *
+ * @return 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.
+ * + * 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.
+ *
+ * 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
+ * getTransferDataFlavors
method.
+ *
+ * If a DataContentHandler can not 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 java.io.InputStream
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;
+ else
+ return transferFlavors.clone();
+
+ }
+
+ /**
+ * Returns whether the specified data flavor is supported
+ * for this object.
+ *
+ * This method iterates through the DataFlavors returned from
+ * getTransferDataFlavors
, 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.
+ * + * For DataHandler's created with DataSources or URLs:
+ *
+ * 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 the
+ * java.io.InputStream
class, this object's InputStream
+ * is returned.
+ * Otherwise it throws an UnsupportedFlavorException.
+ * + * For DataHandler's created with Objects:
+ *
+ * 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 null
causes the CommandMap to revert
+ * to the CommandMap returned by the
+ * CommandMap.getDefaultCommandMap
method.
+ * Changing the CommandMap, or setting it to null
,
+ * 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 preferred commands for this type of data.
+ * This method calls the getPreferredCommands
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 getAllCommands
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 cmdName. 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 getCommand
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.
+ * + * If the DataHandler was instantiated with an object, return + * the object.
+ *
+ * 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
+ * DataContentHandler
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.
+ *
+ * This method calls the CommandInfo's getCommandObject
+ * method with the ClassLoader
used to load
+ * the javax.activation.DataHandler
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:
+ * + * If a DataContentHandlerFactory is set, use it. + * Otherwise look for an object to serve DCH in the + * following order:
+ * + * 1) if a factory is set, use it
+ * 2) if a CommandMap is set, use it
+ * 3) use the default CommandMap
+ * + * 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. + *
+ * 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 InputStream
representing this object.
+ * @return the InputStream
+ */
+ public InputStream getInputStream() throws IOException {
+ return dataHandler.getInputStream();
+ }
+
+ /**
+ * Returns the OutputStream
for this object.
+ * @return the OutputStream
+ */
+ 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 private 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 DataContentHandler
.
+ * @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 private 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 DataContentHandler
.
+ * @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);
+ }
+}