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