src/share/jaf_classes/javax/activation/DataHandler.java

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

mercurial