/*
* Copyright (c) 1997, 2017, 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 Also: Since: 1.6
/**
* 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, getAllCommands,
* getPreferredCommands}).
* Each instance of a DataHandler may have a CommandMap associated with
* it using the {@code setCommandMap} method. If a CommandMap was
* not set, DataHandler calls the {@code getDefaultCommandMap}
* 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
*
* @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. Params: - ds – the DataSource
/**
* Create a {@code 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. Params: - obj – the Java Object
- mimeType – the MIME type of the object
/**
* Create a {@code 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. Params: - url – a URL object
/**
* Create a {@code DataHandler} instance referencing a URL.
* The DataHandler internally creates a {@code 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.
/**
* 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.
Returns: a valid DataSource object for this DataHandler
/**
* 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 DataSource.getName
method, otherwise it returns null.
Returns: the name of the object
/**
* Return the name of the data object. If this DataHandler
* was created with a DataSource, this method calls through
* to the {@code DataSource.getName} 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 full
type with parameters.
Returns: the MIME type
/**
* 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. 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.
Throws: - IOException – if an I/O error occurs
See Also: Returns: the InputStream representing this data
/**
* Get the InputStream for this object. <p>
*
* For DataHandlers instantiated with a DataSource, the DataHandler
* calls the {@code DataSource.getInputStream} 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} 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
.
Params: - os – the OutputStream to write to
Throws: - IOException – if an I/O error occurs
/**
* Write the data to an {@code OutputStream}.<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} method on the {@code 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. Throws: - IOException – for failures creating the OutputStream
See Also: Returns: the OutputStream
/**
* 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} method is called.
* Otherwise, {@code null} 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.
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.
See Also: Returns: an array of data flavors in which this data can be transferred
/**
* 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} 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} 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.
Params: - flavor – the requested flavor for the data
See Also: Returns: true if the data flavor is supported
/**
* Returns whether the specified data flavor is supported
* for this object.<p>
*
* This method iterates through the DataFlavors returned from
* {@code 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.
Params: - flavor – the requested flavor for the data
Throws: - UnsupportedFlavorException – if the data could not be
converted to the requested flavor
- IOException – if an I/O error occurs
See Also: Returns: the object
/**
* 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}
* method. If the DataHandler fails to locate a DataContentHandler
* and the flavor specifies this object's MIME type and the
* {@code java.io.InputStream} 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 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. Params: - commandMap – the CommandMap to use in this DataHandler
See Also:
/**
* Set the CommandMap for use by this DataHandler.
* Setting it to {@code null} causes the CommandMap to revert
* to the CommandMap returned by the
* {@code CommandMap.getDefaultCommandMap} method.
* Changing the CommandMap, or setting it to {@code 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. See Also: Returns: the CommandInfo objects representing the preferred commands
/**
* Return the <i>preferred</i> commands for this type of data.
* This method calls the {@code 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. See Also: Returns: the CommandInfo objects representing all the commands
/**
* 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} 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. Params: - cmdName – the command name
See Also: Returns: the CommandInfo corresponding to the command
/**
* 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} 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.
Throws: - IOException – if an IOException occurs during
this operation.
Returns: the content.
/**
* 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} 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.
Params: - cmdinfo – the CommandInfo corresponding to a command
Returns: the instantiated command object
/**
* 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}
* method with the {@code ClassLoader} used to load
* the {@code 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.
Returns: the requested DataContentHandler
/**
* 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.
/**
* 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.
Params: - newFactory – the DataContentHandlerFactory
Throws: - Error – if the factory has already been defined.
See Also:
/**
* 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.
/**
* 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.
/**
* The constructor.
*/
public DataHandlerDataSource(DataHandler dh) {
this.dataHandler = dh;
}
Returns an InputStream
representing this object. Returns: the InputStream
/**
* Returns an {@code InputStream} representing this object.
* @return the {@code InputStream}
*/
public InputStream getInputStream() throws IOException {
return dataHandler.getInputStream();
}
Returns the OutputStream
for this object. Returns: the OutputStream
/**
* Returns the {@code OutputStream} for this object.
* @return the {@code OutputStream}
*/
public OutputStream getOutputStream() throws IOException {
return dataHandler.getOutputStream();
}
Returns the MIME type of the data represented by this object.
Returns: the MIME type
/**
* 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.
Returns: the name of this object
/**
* 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.
/**
* The constructor.
*/
public DataSourceDataContentHandler(DataContentHandler dch, DataSource ds) {
this.ds = ds;
this.dch = dch;
}
Return the DataFlavors for this DataContentHandler
. Returns: the DataFlavors
/**
* Return the DataFlavors for this {@code 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.
Params: - df – the DataFlavor
- ds – the DataSource
Returns: the constructed Object
/**
* 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.
/**
* 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.
/**
* 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.
/**
* Return the DataContentHandler for this object.
* Used only by the DataHandler class.
*/
public DataContentHandler getDCH() {
return dch;
}
Return the DataFlavors for this DataContentHandler
. Returns: the DataFlavors
/**
* Return the DataFlavors for this {@code 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.
Params: - df – the DataFlavor
- ds – the DataSource
Returns: the constructed Object
/**
* 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.
/**
* 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);
}
}