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 |
19 | package de.lohndirekt.print;\r |
20 | \r |
21 | import java.io.IOException;\r |
22 | import java.net.URI;\r |
23 | import java.net.URISyntaxException;\r |
24 | import java.util.ArrayList;\r |
25 | import java.util.HashMap;\r |
26 | import java.util.Iterator;\r |
27 | import java.util.List;\r |
28 | import java.util.Map;\r |
29 | import java.util.Set;\r |
30 | import java.util.logging.Level;\r |
31 | import java.util.logging.Logger;\r |
32 | \r |
33 | import javax.print.Doc;\r |
34 | import javax.print.DocPrintJob;\r |
35 | import javax.print.PrintException;\r |
36 | import javax.print.PrintService;\r |
37 | import javax.print.attribute.Attribute;\r |
38 | import javax.print.attribute.AttributeSet;\r |
39 | import javax.print.attribute.HashAttributeSet;\r |
40 | import javax.print.attribute.HashPrintJobAttributeSet;\r |
41 | import javax.print.attribute.PrintJobAttribute;\r |
42 | import javax.print.attribute.PrintJobAttributeSet;\r |
43 | import javax.print.attribute.PrintRequestAttributeSet;\r |
44 | import javax.print.event.PrintJobAttributeListener;\r |
45 | import javax.print.event.PrintJobEvent;\r |
46 | import javax.print.event.PrintJobListener;\r |
47 | \r |
48 | import de.lohndirekt.print.attribute.AttributeHelper;\r |
49 | import de.lohndirekt.print.attribute.IppAttributeName;\r |
50 | import de.lohndirekt.print.attribute.IppStatus;\r |
51 | import de.lohndirekt.print.attribute.ipp.jobdesc.JobId;\r |
52 | import de.lohndirekt.print.attribute.ipp.jobdesc.JobUri;\r |
53 | import de.lohndirekt.print.attribute.ipp.printerdesc.supported.OperationsSupported;\r |
54 | \r |
55 | /**\r |
56 | * @author bpusch\r |
57 | *\r |
58 | */\r |
59 | class 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 |