1. /*
  2. * @(#)SimpleDoc.java 1.4 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.print;
  8. import java.io.ByteArrayInputStream;
  9. import java.io.CharArrayReader;
  10. import java.io.StringReader;
  11. import java.io.InputStream;
  12. import java.io.IOException;
  13. import java.io.Reader;
  14. import javax.print.attribute.AttributeSetUtilities;
  15. import javax.print.attribute.DocAttributeSet;
  16. /**
  17. * This class is an implementation of interface <code>Doc</code> that can
  18. * be used in many common printing requests.
  19. * It can handle all of the presently defined "pre-defined" doc flavors
  20. * defined as static variables in the DocFlavor class.
  21. * <p>
  22. * In particular this class implements certain required semantics of the
  23. * Doc specification as follows:
  24. * <ul>
  25. * <li>constructs a stream for the service if requested and appropriate.
  26. * <li>ensures the same object is returned for each call on a method.
  27. * <li>ensures multiple threads can access the Doc
  28. * <li>performs some validation of that the data matches the doc flavor.
  29. * </ul>
  30. * Clients who want to re-use the doc object in other jobs,
  31. * or need a MultiDoc will not want to use this class.
  32. * <p>
  33. * If the print data is a stream, or a print job requests data as a
  34. * stream, then <code>SimpleDoc</code> does not monitor if the service
  35. * properly closes the stream after data transfer completion or job
  36. * termination.
  37. * Clients may prefer to use provide their own implementation of doc that
  38. * adds a listener to monitor job completion and to validate that
  39. * resources such as streams are freed (ie closed).
  40. */
  41. public final class SimpleDoc implements Doc {
  42. private DocFlavor flavor;
  43. private DocAttributeSet attributes;
  44. private Object printData;
  45. private Reader reader;
  46. private InputStream inStream;
  47. /**
  48. * Constructs a <code>SimpleDoc</code> with the specified
  49. * print data, doc flavor and doc attribute set.
  50. * @param printData the print data object
  51. * @param flavor the <code>DocFlavor</code> object
  52. * @param attributes a <code>DocAttributeSet</code>, which can
  53. * be <code>null</code>
  54. * @throws IllegalArgumentException if <code>flavor</code> or
  55. * <code>printData</code> is <code>null</code>, or the
  56. * <code>printData</code> does not correspond
  57. * to the specified doc flavor--for example, the data is
  58. * not of the type specified as the representation in the
  59. * <code>DocFlavor</code>.
  60. */
  61. public SimpleDoc(Object printData,
  62. DocFlavor flavor, DocAttributeSet attributes) {
  63. if (flavor == null || printData == null) {
  64. throw new IllegalArgumentException("null argument(s)");
  65. }
  66. Class repClass = null;
  67. try {
  68. repClass = Class.forName(flavor.getRepresentationClassName());
  69. } catch (Throwable e) {
  70. throw new IllegalArgumentException("unknown representation class");
  71. }
  72. if (!repClass.isInstance(printData)) {
  73. throw new IllegalArgumentException("data is not of declared type");
  74. }
  75. this.flavor = flavor;
  76. if (attributes != null) {
  77. this.attributes = AttributeSetUtilities.unmodifiableView(attributes);
  78. }
  79. this.printData = printData;
  80. }
  81. /**
  82. * Determines the doc flavor in which this doc object will supply its
  83. * piece of print data.
  84. *
  85. * @return Doc flavor.
  86. */
  87. public DocFlavor getDocFlavor() {
  88. return flavor;
  89. }
  90. /**
  91. * Obtains the set of printing attributes for this doc object. If the
  92. * returned attribute set includes an instance of a particular attribute
  93. * <I>X,</I> the printer must use that attribute value for this doc,
  94. * overriding any value of attribute <I>X</I> in the job's attribute set.
  95. * If the returned attribute set does not include an instance
  96. * of a particular attribute <I>X</I> or if null is returned, the printer
  97. * must consult the job's attribute set to obtain the value for
  98. * attribute <I>X,</I> and if not found there, the printer must use an
  99. * implementation-dependent default value. The returned attribute set is
  100. * unmodifiable.
  101. *
  102. * @return Unmodifiable set of printing attributes for this doc, or null
  103. * to obtain all attribute values from the job's attribute
  104. * set.
  105. */
  106. public DocAttributeSet getAttributes() {
  107. return attributes;
  108. }
  109. /*
  110. * Obtains the print data representation object that contains this doc
  111. * object's piece of print data in the format corresponding to the
  112. * supported doc flavor.
  113. * The <CODE>getPrintData()</CODE> method returns an instance of
  114. * the representation class whose name is given by
  115. * {@link DocFlavor#getRepresentationClassName() getRepresentationClassName},
  116. * and the return value can be cast
  117. * from class Object to that representation class.
  118. *
  119. * @return Print data representation object.
  120. *
  121. * @exception IOException if the representation class is a stream and
  122. * there was an I/O error while constructing the stream.
  123. */
  124. public Object getPrintData() throws IOException {
  125. return printData;
  126. }
  127. /**
  128. * Obtains a reader for extracting character print data from this doc.
  129. * The <code>Doc</code> implementation is required to support this
  130. * method if the <code>DocFlavor</code> has one of the following print
  131. * data representation classes, and return <code>null</code>
  132. * otherwise:
  133. * <UL>
  134. * <LI> <code>char[]</code>
  135. * <LI> <code>java.lang.String</code>
  136. * <LI> <code>java.io.Reader</code>
  137. * </UL>
  138. * The doc's print data representation object is used to construct and
  139. * return a <code>Reader</code> for reading the print data as a stream
  140. * of characters from the print data representation object.
  141. * However, if the print data representation object is itself a
  142. * <code>Reader</code> then the print data representation object is
  143. * simply returned.
  144. * <P>
  145. * @return a <code>Reader</code> for reading the print data
  146. * characters from this doc.
  147. * If a reader cannot be provided because this doc does not meet
  148. * the criteria stated above, <code>null</code> is returned.
  149. *
  150. * @exception IOException if there was an I/O error while creating
  151. * the reader.
  152. */
  153. public Reader getReaderForText() throws IOException {
  154. if (printData instanceof Reader) {
  155. return (Reader)printData;
  156. }
  157. synchronized (this) {
  158. if (reader != null) {
  159. return reader;
  160. }
  161. if (printData instanceof char[]) {
  162. reader = new CharArrayReader((char[])printData);
  163. }
  164. else if (printData instanceof String) {
  165. reader = new StringReader((String)printData);
  166. }
  167. }
  168. return reader;
  169. }
  170. /**
  171. * Obtains an input stream for extracting byte print data from
  172. * this doc.
  173. * The <code>Doc</code> implementation is required to support this
  174. * method if the <code>DocFlavor</code> has one of the following print
  175. * data representation classes; otherwise this method
  176. * returns <code>null</code>:
  177. * <UL>
  178. * <LI> <code>byte[]</code>
  179. * <LI> <code>java.io.InputStream</code>
  180. * </UL>
  181. * The doc's print data representation object is obtained. Then, an
  182. * input stream for reading the print data
  183. * from the print data representation object as a stream of bytes is
  184. * created and returned.
  185. * However, if the print data representation object is itself an
  186. * input stream then the print data representation object is simply
  187. * returned.
  188. * <P>
  189. * @return an <code>InputStream</code> for reading the print data
  190. * bytes from this doc. If an input stream cannot be
  191. * provided because this doc does not meet
  192. * the criteria stated above, <code>null</code> is returned.
  193. *
  194. * @exception IOException
  195. * if there was an I/O error while creating the input stream.
  196. */
  197. public InputStream getStreamForBytes() throws IOException {
  198. if (printData instanceof InputStream) {
  199. return (InputStream)printData;
  200. }
  201. synchronized (this) {
  202. if (inStream != null) {
  203. return inStream;
  204. }
  205. if (printData instanceof byte[]) {
  206. inStream = new ByteArrayInputStream((byte[])printData);
  207. }
  208. }
  209. return inStream;
  210. }
  211. }