Initial import.
[clinton/mirror/jspi/.git] / jspi / src / main / java / de / lohndirekt / print / Job.java
1 /**
2 * Copyright (C) 2003 <a href="http://www.lohndirekt.de/">lohndirekt.de</a>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 */
19 package de.lohndirekt.print;
20
21 import java.io.IOException;
22 import java.net.URI;
23 import java.net.URISyntaxException;
24 import java.util.ArrayList;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Set;
30 import java.util.logging.Level;
31 import java.util.logging.Logger;
32
33 import javax.print.Doc;
34 import javax.print.DocPrintJob;
35 import javax.print.PrintException;
36 import javax.print.PrintService;
37 import javax.print.attribute.Attribute;
38 import javax.print.attribute.AttributeSet;
39 import javax.print.attribute.HashAttributeSet;
40 import javax.print.attribute.HashPrintJobAttributeSet;
41 import javax.print.attribute.PrintJobAttribute;
42 import javax.print.attribute.PrintJobAttributeSet;
43 import javax.print.attribute.PrintRequestAttributeSet;
44 import javax.print.event.PrintJobAttributeListener;
45 import javax.print.event.PrintJobEvent;
46 import javax.print.event.PrintJobListener;
47
48 import de.lohndirekt.print.attribute.AttributeHelper;
49 import de.lohndirekt.print.attribute.IppAttributeName;
50 import de.lohndirekt.print.attribute.IppStatus;
51 import de.lohndirekt.print.attribute.ipp.jobdesc.JobId;
52 import de.lohndirekt.print.attribute.ipp.jobdesc.JobUri;
53 import de.lohndirekt.print.attribute.ipp.printerdesc.supported.OperationsSupported;
54
55 /**
56 * @author bpusch
57 *
58 */
59 class Job implements DocPrintJob {
60 protected boolean ok = false;
61 protected Logger log = Logger.getLogger(this.getClass().getName());
62 protected IppPrintService printService;
63 private PrintJobAttributeSet jobAttributes;
64 protected JobUri jobUri;
65 private List jobListeners;
66 private Map attributeListeners;
67
68 /**
69 * @param service
70 */
71 public Job(IppPrintService service) {
72 this.printService = service;
73 }
74
75 /**
76 *
77 */
78 public PrintService getPrintService() {
79 return this.printService;
80 }
81
82 /**
83 *
84 */
85 public PrintJobAttributeSet getAttributes() {
86 return this.jobAttributes;
87 }
88
89 /**
90 *
91 */
92 public void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException {
93 IppRequest request = null;
94 request = this.printService.request(OperationsSupported.PRINT_JOB);
95 try {
96 request.setData(doc.getStreamForBytes());
97 } catch (IOException e) {
98 log.log(Level.SEVERE, e.getMessage(), e);
99 throw new PrintException("Error getting document data (" + description(attributes) + "): " + e.getMessage());
100 }
101 //add the operation attributes
102 AttributeSet operationAttributes = new HashAttributeSet();
103 operationAttributes.addAll(AttributeHelper.jobOperationAttributes(attributes));
104 operationAttributes.addAll(AttributeHelper.docOperationAttributes(doc));
105 request.addOperationAttributes(operationAttributes);
106 //set the job template attributes
107 request.setJobAttributes(AttributeHelper.jobAttributes(attributes));
108 IppResponse response = null;
109 try {
110 response = request.send();
111 notifyJobListeners(PrintJobEvent.DATA_TRANSFER_COMPLETE);
112 } catch (IOException e) {
113 log.log(Level.SEVERE, e.getMessage(), e);
114 throw new PrintException("Error sending " + description(attributes) + " to IPP service: " + e.getMessage());
115 }
116 if (response != null && response.getStatus()!=null) {
117 Map responseAttributes = response.getAttributes();
118 updateAttributes(responseAttributes);
119 if (response.getStatus().equals(IppStatus.SUCCESSFUL_OK)
120 || response.getStatus().equals(IppStatus.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES)
121 || response.getStatus().equals(IppStatus.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUTED_ATTRIBUTES)) {
122 if (responseAttributes.containsKey(IppAttributeName.JOB_URI.getCategory())) {
123 Set jobUriList = (Set) responseAttributes.get(IppAttributeName.JOB_URI.getCategory());
124 this.jobUri = (JobUri) jobUriList.iterator().next();
125 }
126 notifyJobListeners(PrintJobEvent.JOB_COMPLETE);
127 this.ok = true;
128 } else {
129 notifyJobListeners(PrintJobEvent.JOB_FAILED);
130 this.ok = false;
131 }
132 } else {
133 notifyJobListeners(PrintJobEvent.JOB_FAILED);
134 this.ok = false;
135 }
136 notifyJobListeners(PrintJobEvent.NO_MORE_EVENTS);
137 if (!this.ok){
138 String msg = "Printing " + description(attributes) + " failed";
139 if (response != null && response.getStatus()!=null) {
140 msg+=": Server status was '"+response.getStatus().getStatus()+" - "+response.getStatus().getText()+"'!";
141 }
142 throw new PrintException(msg);
143 }
144 }
145
146
147
148 public void addPrintJobListener(PrintJobListener listener) {
149 if (listener != null) {
150 if (jobListeners == null) {
151 jobListeners = new ArrayList();
152 }
153 jobListeners.add(listener);
154 }
155 }
156
157 public void removePrintJobListener(PrintJobListener listener) {
158 if (listener != null) {
159 jobListeners.remove(listener);
160 }
161 }
162
163 public void addPrintJobAttributeListener(PrintJobAttributeListener listener, PrintJobAttributeSet attributes) {
164 if (listener != null) {
165 if (attributeListeners == null) {
166 attributeListeners = new HashMap();
167 }
168 attributeListeners.put(listener, attributes);
169 }
170 }
171
172 public void removePrintJobAttributeListener(PrintJobAttributeListener listener) {
173 if (listener != null) {
174 attributeListeners.remove(listener);
175 }
176 }
177
178 void notifyJobListeners(int eventType) {
179 if (jobListeners != null) {
180 PrintJobEvent event = new PrintJobEvent(this, eventType);
181 for (Iterator iter = jobListeners.iterator(); iter.hasNext();) {
182 PrintJobListener listener = (PrintJobListener) iter.next();
183 if (eventType == PrintJobEvent.DATA_TRANSFER_COMPLETE) {
184 listener.printDataTransferCompleted(event);
185 } else if (eventType == PrintJobEvent.JOB_CANCELED) {
186 listener.printJobCanceled(event);
187 } else if (eventType == PrintJobEvent.JOB_COMPLETE) {
188 listener.printJobCompleted(event);
189 } else if (eventType == PrintJobEvent.JOB_FAILED) {
190 listener.printJobFailed(event);
191 } else if (eventType == PrintJobEvent.NO_MORE_EVENTS) {
192 listener.printJobNoMoreEvents(event);
193 } else if (eventType == PrintJobEvent.REQUIRES_ATTENTION) {
194 listener.printJobRequiresAttention(event);
195 }
196 }
197 }
198 }
199
200 IppResponse sendRequest(OperationsSupported operation, AttributeSet operationAttributes) throws IOException {
201 IppRequest request = this.request(operation);
202 request.addOperationAttributes(operationAttributes);
203 IppResponse response = null;
204 response = request.send();
205 return response;
206 }
207
208 private IppRequest request(OperationsSupported operation) {
209 IppRequest request = IppRequestFactory.createIppRequest(this.jobUri.getURI(), operation, this.printService.getRequestingUserName(), this.printService.getRequestingUserPassword());
210 AttributeSet operationAttributes = new HashAttributeSet();
211 operationAttributes.add(this.jobUri);
212 request.addOperationAttributes(operationAttributes);
213 return request;
214 }
215
216 // public methods which are not part of the JPS API
217 /**
218 *
219 * This method returns the Job with the given JobId that is held by
220 * the given PrintService.
221 * <br>
222 * This method might return a Job which is not hold by this PrintService
223 * but the same CUPS server
224 *
225 * @param service
226 * @param id
227 * @return the corresponding Job wihth the given JobId, or null if no such
228 * Job exists
229 * @throws PrintException
230 */
231 static Job getJob(IppPrintService service, JobId id) throws PrintException {
232 Job job = new Job(service);
233 job.printService = service;
234 URI jobUri;
235 try {
236 jobUri =
237 new URI(
238 service.getUri().getScheme(),
239 service.getUri().getAuthority(),
240 "/jobs/" + id.getValue(),
241 service.getUri().getQuery(),
242 service.getUri().getFragment());
243 } catch (URISyntaxException e) {
244 throw new PrintException("Internal bug.", e);
245 }
246 job.jobUri = new JobUri(jobUri);
247 try {
248 job.updateAttributes();
249 } catch (IllegalStateException e) {
250 job = null;
251 }
252 return job;
253 }
254
255 /**
256 * @param responseAttributes
257 */
258 private void updateAttributes(Map responseAttributes) {
259 this.jobAttributes = new HashPrintJobAttributeSet();
260 for (Iterator iter = responseAttributes.values().iterator(); iter.hasNext();) {
261 Set values = (Set) iter.next();
262 for (Iterator listIter = values.iterator(); listIter.hasNext();) {
263 Attribute attribute = (Attribute) listIter.next();
264 if (attribute instanceof PrintJobAttribute)
265 this.jobAttributes.add(attribute);
266 }
267 }
268 }
269
270 /**
271 * Updates the Job's attributes to the current values.
272 *
273 * @throws PrintException
274 */
275 private void updateAttributes() throws PrintException {
276 try {
277 AttributeSet operationAttributes = new HashAttributeSet();
278 IppResponse response = sendRequest(OperationsSupported.GET_JOB_ATTRIBUTES, operationAttributes);
279 if (!response.getStatus().equals(IppStatus.SUCCESSFUL_OK)
280 && !response.getStatus().equals(IppStatus.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES)
281 && !response.getStatus().equals(IppStatus.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUTED_ATTRIBUTES)) {
282 if (response.getStatus().equals(IppStatus.CLIENT_ERROR_NOT_FOUND)) {
283 throw new IllegalStateException("Job with uri '" + this.jobUri.toString() + "does not exist.");
284 }
285 throw new PrintException("Request not successful.");
286 }
287 Map attribsMap = response.getAttributes();
288 updateAttributes(attribsMap);
289
290 } catch (IOException e) {
291 throw new PrintException("Update failed.", e);
292 }
293 }
294
295 private String description(PrintRequestAttributeSet attributes){
296 String description = "job";
297 if (attributes != null){
298 Attribute jobName = attributes.get(IppAttributeName.JOB_NAME.getCategory());
299 if (jobName != null){
300 description += " " + jobName.toString();
301 }
302 }
303 return description;
304 }
305 }