2 * Copyright (C) 2003 <a href="http://www.lohndirekt.de/">lohndirekt.de</a>
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.
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.
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
19 package de
.lohndirekt
.print
;
21 import java
.io
.IOException
;
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
;
30 import java
.util
.logging
.Level
;
31 import java
.util
.logging
.Logger
;
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
;
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
;
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
;
71 public Job(IppPrintService service
) {
72 this.printService
= service
;
78 public PrintService
getPrintService() {
79 return this.printService
;
85 public PrintJobAttributeSet
getAttributes() {
86 return this.jobAttributes
;
92 public void print(Doc doc
, PrintRequestAttributeSet attributes
) throws PrintException
{
93 IppRequest request
= null;
94 request
= this.printService
.request(OperationsSupported
.PRINT_JOB
);
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());
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;
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());
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();
126 notifyJobListeners(PrintJobEvent
.JOB_COMPLETE
);
129 notifyJobListeners(PrintJobEvent
.JOB_FAILED
);
133 notifyJobListeners(PrintJobEvent
.JOB_FAILED
);
136 notifyJobListeners(PrintJobEvent
.NO_MORE_EVENTS
);
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()+"'!";
142 throw new PrintException(msg
);
148 public void addPrintJobListener(PrintJobListener listener
) {
149 if (listener
!= null) {
150 if (jobListeners
== null) {
151 jobListeners
= new ArrayList();
153 jobListeners
.add(listener
);
157 public void removePrintJobListener(PrintJobListener listener
) {
158 if (listener
!= null) {
159 jobListeners
.remove(listener
);
163 public void addPrintJobAttributeListener(PrintJobAttributeListener listener
, PrintJobAttributeSet attributes
) {
164 if (listener
!= null) {
165 if (attributeListeners
== null) {
166 attributeListeners
= new HashMap();
168 attributeListeners
.put(listener
, attributes
);
172 public void removePrintJobAttributeListener(PrintJobAttributeListener listener
) {
173 if (listener
!= null) {
174 attributeListeners
.remove(listener
);
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
);
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();
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
);
216 // public methods which are not part of the JPS API
219 * This method returns the Job with the given JobId that is held by
220 * the given PrintService.
222 * This method might return a Job which is not hold by this PrintService
223 * but the same CUPS server
227 * @return the corresponding Job wihth the given JobId, or null if no such
229 * @throws PrintException
231 static Job
getJob(IppPrintService service
, JobId id
) throws PrintException
{
232 Job job
= new Job(service
);
233 job
.printService
= service
;
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
);
246 job
.jobUri
= new JobUri(jobUri
);
248 job
.updateAttributes();
249 } catch (IllegalStateException e
) {
256 * @param responseAttributes
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
);
271 * Updates the Job's attributes to the current values.
273 * @throws PrintException
275 private void updateAttributes() throws PrintException
{
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.");
285 throw new PrintException("Request not successful.");
287 Map attribsMap
= response
.getAttributes();
288 updateAttributes(attribsMap
);
290 } catch (IOException e
) {
291 throw new PrintException("Update failed.", e
);
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();