Merge from mainline.
[official-gcc.git] / libjava / classpath / gnu / javax / print / ipp / DocPrintJobImpl.java
blobd391afc7e1af0c3b920fd7471a54ea5472ad9a59
1 /* DocPrintJobImpl.java -- Implementation of DocPrintJob.
2 Copyright (C) 2006 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
39 package gnu.javax.print.ipp;
41 import gnu.javax.print.PrintFlavorException;
42 import gnu.javax.print.ipp.attribute.job.JobId;
43 import gnu.javax.print.ipp.attribute.job.JobUri;
44 import gnu.javax.print.ipp.attribute.printer.DocumentFormat;
45 import gnu.javax.print.ipp.attribute.supported.OperationsSupported;
47 import java.io.IOException;
48 import java.io.InputStream;
49 import java.io.UnsupportedEncodingException;
50 import java.net.URI;
51 import java.net.URISyntaxException;
52 import java.net.URL;
53 import java.util.ArrayList;
54 import java.util.HashSet;
55 import java.util.Iterator;
56 import java.util.List;
57 import java.util.Map;
59 import javax.print.CancelablePrintJob;
60 import javax.print.Doc;
61 import javax.print.DocFlavor;
62 import javax.print.DocPrintJob;
63 import javax.print.PrintException;
64 import javax.print.PrintService;
65 import javax.print.attribute.AttributeSetUtilities;
66 import javax.print.attribute.DocAttributeSet;
67 import javax.print.attribute.HashAttributeSet;
68 import javax.print.attribute.HashPrintJobAttributeSet;
69 import javax.print.attribute.PrintJobAttributeSet;
70 import javax.print.attribute.PrintRequestAttributeSet;
71 import javax.print.attribute.standard.JobName;
72 import javax.print.attribute.standard.PrinterURI;
73 import javax.print.attribute.standard.RequestingUserName;
74 import javax.print.event.PrintJobAttributeListener;
75 import javax.print.event.PrintJobEvent;
76 import javax.print.event.PrintJobListener;
78 /**
79 * Implementation of the DocPrintJob interface. Implementation is
80 * specific to the <code>IppPrintService</code> implementation.
82 * @author Wolfgang Baer (WBaer@gmx.de)
84 public class DocPrintJobImpl implements CancelablePrintJob
86 /** The print service this job is bound to. */
87 private IppPrintService service;
89 /** The set of print job listeners. */
90 private HashSet printJobListener = new HashSet();
92 /** The print job attributes listeners. */
93 private ArrayList attributesListener = new ArrayList();
94 /** The print job attributes listeners associated attribute set. */
95 private ArrayList attributesListenerAttributes = new ArrayList();
97 /** The username. */
98 private String username;
99 /** The password of the user. */
100 private String password;
102 /** Returned job uri. */
103 private JobUri jobUri = null;
104 /** Returned job id. */
105 private JobId jobId = null;
107 /** The requesting-username for later canceling */
108 private RequestingUserName requestingUser;
110 /** The print job sets. */
111 private PrintJobAttributeSet oldSet = new HashPrintJobAttributeSet();
112 private PrintJobAttributeSet currentSet = new HashPrintJobAttributeSet();
114 /**
115 * State variable if we already started printing.
117 private boolean printing = false;
119 // TODO Implement complete PrintJobListener notification
120 // TODO Implement PrintJobAttributeListener notification
123 * Constructs a DocPrintJobImpl instance bound to the given print service.
125 * @param service the print service instance.
126 * @param user the user of this print service.
127 * @param passwd the password of the user.
129 public DocPrintJobImpl(IppPrintService service, String user, String passwd)
131 this.service = service;
132 username = user;
133 password = passwd;
137 * @see DocPrintJob#addPrintJobAttributeListener(PrintJobAttributeListener, PrintJobAttributeSet)
139 public void addPrintJobAttributeListener(PrintJobAttributeListener listener,
140 PrintJobAttributeSet attributes)
142 if (listener == null)
143 return;
145 attributesListener.add(listener);
146 attributesListenerAttributes.add(attributes);
150 * @see DocPrintJob#addPrintJobListener(PrintJobListener)
152 public void addPrintJobListener(PrintJobListener listener)
154 if (listener == null)
155 return;
157 printJobListener.add(listener);
161 * @see javax.print.DocPrintJob#getAttributes()
163 public PrintJobAttributeSet getAttributes()
165 return AttributeSetUtilities.unmodifiableView(currentSet);
169 * @see javax.print.DocPrintJob#getPrintService()
171 public PrintService getPrintService()
173 return service;
177 * @see DocPrintJob#print(Doc, PrintRequestAttributeSet)
179 public void print(Doc doc, PrintRequestAttributeSet attributes)
180 throws PrintException
182 if (printing)
183 throw new PrintException("already printing");
185 printing = true;
187 DocAttributeSet docAtts = doc.getAttributes();
188 DocFlavor flavor = doc.getDocFlavor();
190 if (flavor == null || (!service.isDocFlavorSupported(flavor)))
192 notifyPrintJobListeners(new PrintJobEvent(this, PrintJobEvent.JOB_FAILED));
193 throw new PrintFlavorException("Invalid flavor", new DocFlavor[] {flavor});
196 // merge attributes as doc attributes take precendence
197 // over the print request attributes
198 HashAttributeSet mergedAtts = new HashAttributeSet();
200 if (attributes != null)
201 mergedAtts.addAll(attributes);
202 if (docAtts != null)
203 mergedAtts.addAll(docAtts);
205 // check for requesting-user-name -add the
206 // executing username if no other is specified
207 // save user name so we can make a cancel operation under same user
208 if (! mergedAtts.containsKey(RequestingUserName.class))
210 mergedAtts.add(IppPrintService.REQUESTING_USER_NAME);
211 requestingUser = IppPrintService.REQUESTING_USER_NAME;
213 else
215 requestingUser = (RequestingUserName)
216 mergedAtts.get(RequestingUserName.class);
219 // same for job-name
220 if (! mergedAtts.containsKey(JobName.class))
221 mergedAtts.add(IppPrintService.JOB_NAME);
223 IppResponse response = null;
227 PrinterURI printerUri = service.getPrinterURI();
228 String printerUriStr = "http" + printerUri.toString().substring(3);
230 URI uri = null;
233 uri = new URI(printerUriStr);
235 catch (URISyntaxException e)
237 // does not happen
240 IppRequest request =
241 new IppRequest(uri, username, password);
243 request.setOperationID( (short) OperationsSupported.PRINT_JOB.getValue());
244 request.setOperationAttributeDefaults();
245 request.addOperationAttribute(printerUri);
247 if (mergedAtts != null)
249 request.addAndFilterJobOperationAttributes(mergedAtts);
250 request.addAndFilterJobTemplateAttributes(mergedAtts);
253 // DocFlavor getMimeType returns charset quoted
254 DocumentFormat format = DocumentFormat.createDocumentFormat(flavor);
255 request.addOperationAttribute(format);
257 // Get and set the printdata based on the
258 // representation classname
259 String className = flavor.getRepresentationClassName();
261 if (className.equals("[B"))
263 request.setData((byte[]) doc.getPrintData());
264 response = request.send();
266 else if (className.equals("java.io.InputStream"))
268 InputStream stream = (InputStream) doc.getPrintData();
269 request.setData(stream);
270 response = request.send();
271 stream.close();
273 else if (className.equals("[C"))
277 // CUPS only supports UTF-8 currently so we convert
278 // We also assume that char[] is always utf-16 - correct ?
279 String str = new String((char[]) doc.getPrintData());
280 request.setData(str.getBytes("utf-16"));
281 response = request.send();
283 catch (UnsupportedEncodingException e)
285 notifyPrintJobListeners(new PrintJobEvent(this, PrintJobEvent.JOB_FAILED));
286 throw new PrintFlavorException("Invalid charset of flavor", e, new DocFlavor[] {flavor});
289 else if (className.equals("java.io.Reader"))
293 // FIXME Implement
294 // Convert a Reader into a InputStream properly encoded
295 response = request.send();
296 throw new UnsupportedEncodingException("not supported yet");
298 catch (UnsupportedEncodingException e)
300 notifyPrintJobListeners(new PrintJobEvent(this, PrintJobEvent.JOB_FAILED));
301 throw new PrintFlavorException("Invalid charset of flavor", e, new DocFlavor[] {flavor});
304 else if (className.equals("java.lang.String"))
308 // CUPS only supports UTF-8 currently so we convert
309 // We also assume that String is always utf-16 - correct ?
310 String str = (String) doc.getPrintData();
311 request.setData(str.getBytes("utf-16"));
312 response = request.send();
314 catch (UnsupportedEncodingException e)
316 notifyPrintJobListeners(new PrintJobEvent(this, PrintJobEvent.JOB_FAILED));
317 throw new PrintFlavorException("Invalid charset of flavor", e, new DocFlavor[] {flavor});
320 else if (className.equals("java.net.URL"))
322 URL url = (URL) doc.getPrintData();
323 InputStream stream = url.openStream();
324 request.setData(stream);
325 response = request.send();
326 stream.close();
328 else if (className.equals("java.awt.image.renderable.RenderableImage")
329 || className.equals("java.awt.print.Printable")
330 || className.equals("java.awt.print.Pageable"))
332 // For the future :-)
333 throw new PrintException("Not yet supported.");
335 else
337 // should not happen - however
338 notifyPrintJobListeners(new PrintJobEvent(this, PrintJobEvent.JOB_FAILED));
339 throw new PrintFlavorException("Invalid flavor", new DocFlavor[] {flavor});
342 // at this point the data is transfered
343 notifyPrintJobListeners(new PrintJobEvent(
344 this, PrintJobEvent.DATA_TRANSFER_COMPLETE));
346 catch (IOException e)
348 throw new PrintException("IOException occured.", e);
351 int status = response.getStatusCode();
352 if (! (status == IppStatusCode.SUCCESSFUL_OK
353 || status == IppStatusCode.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUED_ATTRIBUTES
354 || status == IppStatusCode.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES) )
356 notifyPrintJobListeners(new PrintJobEvent(
357 this, PrintJobEvent.JOB_FAILED));
358 throw new PrintException("Printing failed - received statuscode " + Integer.toHexString(status));
360 // TODO maybe specific status codes may require to throw a specific
361 // detailed attribute exception
363 else
365 // start print job progress monitoring thread
366 // FIXME Implement
368 // for now we just notify as finished
369 notifyPrintJobListeners(
370 new PrintJobEvent(this, PrintJobEvent.JOB_COMPLETE));
373 List jobAtts = response.getJobAttributes();
375 // extract the uri and id of job for canceling and further monitoring
376 Map jobAttributes = (Map) jobAtts.get(0);
377 jobUri = (JobUri) ((HashSet)jobAttributes.get(JobUri.class)).toArray()[0];
378 jobId = (JobId) ((HashSet)jobAttributes.get(JobId.class)).toArray()[0];
382 * @see DocPrintJob#removePrintJobAttributeListener(PrintJobAttributeListener)
384 public void removePrintJobAttributeListener(PrintJobAttributeListener listener)
386 if (listener == null)
387 return;
389 int index = attributesListener.indexOf(listener);
390 if (index != -1)
392 attributesListener.remove(index);
393 attributesListenerAttributes.remove(index);
398 * @see DocPrintJob#removePrintJobListener(PrintJobListener)
400 public void removePrintJobListener(PrintJobListener listener)
402 if (listener == null)
403 return;
405 printJobListener.remove(listener);
409 * @see CancelablePrintJob#cancel()
411 public void cancel() throws PrintException
413 if (jobUri == null)
415 throw new PrintException("print job is not yet send");
418 IppResponse response = null;
422 IppRequest request = new IppRequest(jobUri.getURI(), username, password);
423 request.setOperationID( (short) OperationsSupported.CANCEL_JOB.getValue());
424 request.setOperationAttributeDefaults();
425 request.addOperationAttribute(jobUri);
426 request.addOperationAttribute(requestingUser);
427 response = request.send();
429 catch (IOException e)
431 throw new IppException("IOException occured during cancel request.", e);
434 int status = response.getStatusCode();
435 if (! (status == IppStatusCode.SUCCESSFUL_OK
436 || status == IppStatusCode.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUED_ATTRIBUTES
437 || status == IppStatusCode.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES) )
439 notifyPrintJobListeners(new PrintJobEvent(
440 this, PrintJobEvent.JOB_FAILED));
441 throw new PrintException("Canceling failed - received statuscode " + Integer.toHexString(status));
443 else
445 notifyPrintJobListeners(new PrintJobEvent(
446 this, PrintJobEvent.JOB_CANCELED));
450 private void notifyPrintJobListeners(PrintJobEvent e)
452 Iterator it = printJobListener.iterator();
453 while (it.hasNext())
455 PrintJobListener l = (PrintJobListener) it.next();
456 if (e.getPrintEventType() == PrintJobEvent.DATA_TRANSFER_COMPLETE)
457 l.printDataTransferCompleted(e);
458 else if (e.getPrintEventType() == PrintJobEvent.JOB_CANCELED)
459 l.printJobCanceled(e);
460 else if (e.getPrintEventType() == PrintJobEvent.JOB_COMPLETE)
461 l.printJobCompleted(e);
462 else if (e.getPrintEventType() == PrintJobEvent.JOB_FAILED)
463 l.printJobFailed(e);
464 else if (e.getPrintEventType() == PrintJobEvent.NO_MORE_EVENTS)
465 l.printJobNoMoreEvents(e);
466 else
467 l.printJobRequiresAttention(e);