FileDocCategorySizeDatePackage
DataHandler.javaAPI DocGlassfish v2 API30759Mon May 14 15:29:52 BST 2007javax.activation

DataHandler

public class DataHandler extends Object implements Transferable
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

Fields Summary
private DataSource
dataSource
private DataSource
objDataSource
private Object
object
private String
objectMimeType
private CommandMap
currentCommandMap
private static final DataFlavor[]
emptyFlavors
private DataFlavor[]
transferFlavors
private DataContentHandler
dataContentHandler
private DataContentHandler
factoryDCH
private static DataContentHandlerFactory
factory
private DataContentHandlerFactory
oldFactory
private String
shortType
Constructors Summary
public DataHandler(DataSource ds)
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


                                 	      
       
	// save a reference to the incoming DS
	dataSource = ds;
	oldFactory = factory; // keep track of the factory
    
public DataHandler(Object obj, String mimeType)
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

	object = obj;
	objectMimeType = mimeType;
	oldFactory = factory; // keep track of the factory
    
public DataHandler(URL url)
Create a DataHandler instance referencing a URL. The DataHandler internally creates a URLDataSource instance to represent the URL.

param
url a URL object

	dataSource = new URLDataSource(url);
	oldFactory = factory; // keep track of the factory
    
Methods Summary
public javax.activation.CommandInfo[]getAllCommands()
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

	if (dataSource != null)
	    return getCommandMap().getAllCommands(getBaseType(), dataSource);
	else
	    return getCommandMap().getAllCommands(getBaseType());
    
private synchronized java.lang.StringgetBaseType()
Use the MimeType class to extract the MIME type/subtype, ignoring the parameters. The type is cached.

	if (shortType == null) {
	    String ct = getContentType();
	    try {
		MimeType mt = new MimeType(ct);
		shortType = mt.getBaseType();
	    } catch (MimeTypeParseException e) {
		shortType = ct;
	    }
	}
	return shortType;
    
public java.lang.ObjectgetBean(javax.activation.CommandInfo cmdinfo)
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

	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;
    
public javax.activation.CommandInfogetCommand(java.lang.String cmdName)
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

	if (dataSource != null)
	    return getCommandMap().getCommand(getBaseType(), cmdName,
								dataSource);
	else
	    return getCommandMap().getCommand(getBaseType(), cmdName);
    
private synchronized javax.activation.CommandMapgetCommandMap()
Return the CommandMap for this instance of DataHandler.

	if (currentCommandMap != null)
	    return currentCommandMap;
	else
	    return CommandMap.getDefaultCommandMap();
    
public java.lang.ObjectgetContent()
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.

	if (object != null)
	    return object;
	else
	    return getDataContentHandler().getContent(getDataSource());
    
public java.lang.StringgetContentType()
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

	if (dataSource != null) // data source case
	    return dataSource.getContentType();
	else
	    return objectMimeType; // obj/type case
    
private synchronized javax.activation.DataContentHandlergetDataContentHandler()
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


	// 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;
    
public javax.activation.DataSourcegetDataSource()
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

	if (dataSource == null) {
	    // create one on the fly
	    if (objDataSource == null)
		objDataSource = new DataHandlerDataSource(this);
	    return objDataSource;
	}
	return dataSource;
    
public java.io.InputStreamgetInputStream()
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

	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;
    
public java.lang.StringgetName()
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

	if (dataSource != null)
	    return dataSource.getName();
	else
	    return null;
    
public java.io.OutputStreamgetOutputStream()
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

	if (dataSource != null)
	    return dataSource.getOutputStream();
	else
	    return null;
    
public javax.activation.CommandInfo[]getPreferredCommands()
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

	if (dataSource != null)
	    return getCommandMap().getPreferredCommands(getBaseType(),
							dataSource);
	else
	    return getCommandMap().getPreferredCommands(getBaseType());
    
public java.lang.ObjectgetTransferData(java.awt.datatransfer.DataFlavor flavor)
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

	return getDataContentHandler().getTransferData(flavor, dataSource);
    
public synchronized java.awt.datatransfer.DataFlavor[]getTransferDataFlavors()
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

	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();
	return transferFlavors;
    
public booleanisDataFlavorSupported(java.awt.datatransfer.DataFlavor flavor)
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

	DataFlavor[] lFlavors = getTransferDataFlavors();

	for (int i = 0; i < lFlavors.length; i++) {
	    if (lFlavors[i].equals(flavor))
		return true;
	}
	return false;
    
public synchronized voidsetCommandMap(javax.activation.CommandMap commandMap)
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

	if (commandMap != currentCommandMap || commandMap == null) {
	    // clear cached values...
	    transferFlavors = emptyFlavors;
	    dataContentHandler = null;

	    currentCommandMap = commandMap;
	}
    
public static synchronized voidsetDataContentHandlerFactory(javax.activation.DataContentHandlerFactory newFactory)
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

	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;
    
public voidwriteTo(java.io.OutputStream os)
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

	// 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);
	}