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