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