Initial import.
[clinton/mirror/jspi/.git] / jspi / src / main / java / de / lohndirekt / print / Job.java
diff --git a/jspi/src/main/java/de/lohndirekt/print/Job.java b/jspi/src/main/java/de/lohndirekt/print/Job.java
new file mode 100644 (file)
index 0000000..a9b3188
--- /dev/null
@@ -0,0 +1,305 @@
+/**\r
+ * Copyright (C) 2003 <a href="http://www.lohndirekt.de/">lohndirekt.de</a>\r
+ *\r
+ * This library is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU Lesser General Public\r
+ * License as published by the Free Software Foundation; either\r
+ * version 2.1 of the License, or (at your option) any later version.\r
+ * \r
+ * This library is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\r
+ * Lesser General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU Lesser General Public\r
+ * License along with this library; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+ *  \r
+ */\r
+package de.lohndirekt.print;\r
+\r
+import java.io.IOException;\r
+import java.net.URI;\r
+import java.net.URISyntaxException;\r
+import java.util.ArrayList;\r
+import java.util.HashMap;\r
+import java.util.Iterator;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.logging.Level;\r
+import java.util.logging.Logger;\r
+\r
+import javax.print.Doc;\r
+import javax.print.DocPrintJob;\r
+import javax.print.PrintException;\r
+import javax.print.PrintService;\r
+import javax.print.attribute.Attribute;\r
+import javax.print.attribute.AttributeSet;\r
+import javax.print.attribute.HashAttributeSet;\r
+import javax.print.attribute.HashPrintJobAttributeSet;\r
+import javax.print.attribute.PrintJobAttribute;\r
+import javax.print.attribute.PrintJobAttributeSet;\r
+import javax.print.attribute.PrintRequestAttributeSet;\r
+import javax.print.event.PrintJobAttributeListener;\r
+import javax.print.event.PrintJobEvent;\r
+import javax.print.event.PrintJobListener;\r
+\r
+import de.lohndirekt.print.attribute.AttributeHelper;\r
+import de.lohndirekt.print.attribute.IppAttributeName;\r
+import de.lohndirekt.print.attribute.IppStatus;\r
+import de.lohndirekt.print.attribute.ipp.jobdesc.JobId;\r
+import de.lohndirekt.print.attribute.ipp.jobdesc.JobUri;\r
+import de.lohndirekt.print.attribute.ipp.printerdesc.supported.OperationsSupported;\r
+\r
+/**\r
+ * @author bpusch\r
+ *\r
+ */\r
+class Job implements DocPrintJob {\r
+       protected boolean ok = false;\r
+       protected Logger log = Logger.getLogger(this.getClass().getName());\r
+       protected IppPrintService printService;\r
+       private PrintJobAttributeSet jobAttributes;\r
+       protected JobUri jobUri;\r
+       private List jobListeners;\r
+       private Map attributeListeners;\r
+\r
+       /**\r
+        * @param service\r
+        */\r
+       public Job(IppPrintService service) {\r
+               this.printService = service;\r
+       }\r
+\r
+       /**\r
+        *\r
+        */\r
+       public PrintService getPrintService() {\r
+               return this.printService;\r
+       }\r
+\r
+       /**\r
+        *\r
+        */\r
+       public PrintJobAttributeSet getAttributes() {\r
+               return this.jobAttributes;\r
+       }\r
+\r
+       /**\r
+        *\r
+        */\r
+       public void print(Doc doc, PrintRequestAttributeSet attributes) throws PrintException {\r
+               IppRequest request = null;\r
+               request = this.printService.request(OperationsSupported.PRINT_JOB);\r
+               try {\r
+                       request.setData(doc.getStreamForBytes());\r
+               } catch (IOException e) {\r
+                       log.log(Level.SEVERE, e.getMessage(), e);\r
+                       throw new PrintException("Error getting document data (" + description(attributes) + "): " + e.getMessage());\r
+               }\r
+               //add the operation attributes\r
+               AttributeSet operationAttributes = new HashAttributeSet();\r
+               operationAttributes.addAll(AttributeHelper.jobOperationAttributes(attributes));\r
+               operationAttributes.addAll(AttributeHelper.docOperationAttributes(doc));\r
+               request.addOperationAttributes(operationAttributes);\r
+               //set the job template attributes\r
+               request.setJobAttributes(AttributeHelper.jobAttributes(attributes));\r
+               IppResponse response = null;\r
+               try {\r
+                       response = request.send();\r
+                       notifyJobListeners(PrintJobEvent.DATA_TRANSFER_COMPLETE);\r
+               } catch (IOException e) {\r
+                       log.log(Level.SEVERE, e.getMessage(), e);\r
+                       throw new PrintException("Error sending " + description(attributes) + " to IPP service: " + e.getMessage());\r
+               }\r
+               if (response != null && response.getStatus()!=null) {\r
+                       Map responseAttributes = response.getAttributes();\r
+                       updateAttributes(responseAttributes);\r
+                       if (response.getStatus().equals(IppStatus.SUCCESSFUL_OK)\r
+                               || response.getStatus().equals(IppStatus.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES)\r
+                               || response.getStatus().equals(IppStatus.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUTED_ATTRIBUTES)) {\r
+                               if (responseAttributes.containsKey(IppAttributeName.JOB_URI.getCategory())) {\r
+                                       Set jobUriList = (Set) responseAttributes.get(IppAttributeName.JOB_URI.getCategory());\r
+                                       this.jobUri = (JobUri) jobUriList.iterator().next();\r
+                               }\r
+                               notifyJobListeners(PrintJobEvent.JOB_COMPLETE);\r
+                               this.ok = true;\r
+                       } else {\r
+                               notifyJobListeners(PrintJobEvent.JOB_FAILED);\r
+                               this.ok = false;\r
+                       }\r
+               } else {\r
+                       notifyJobListeners(PrintJobEvent.JOB_FAILED);\r
+                       this.ok = false;\r
+               }\r
+               notifyJobListeners(PrintJobEvent.NO_MORE_EVENTS);\r
+               if (!this.ok){\r
+                   String msg = "Printing " + description(attributes) + "  failed";\r
+                   if (response != null && response.getStatus()!=null) {\r
+                       msg+=": Server status was '"+response.getStatus().getStatus()+" - "+response.getStatus().getText()+"'!";\r
+                   }\r
+                       throw new PrintException(msg);\r
+               }\r
+       }\r
+\r
+       \r
+\r
+       public void addPrintJobListener(PrintJobListener listener) {\r
+               if (listener != null) {\r
+                       if (jobListeners == null) {\r
+                               jobListeners = new ArrayList();\r
+                       }\r
+                       jobListeners.add(listener);\r
+               }\r
+       }\r
+\r
+       public void removePrintJobListener(PrintJobListener listener) {\r
+               if (listener != null) {\r
+                       jobListeners.remove(listener);\r
+               }\r
+       }\r
+\r
+       public void addPrintJobAttributeListener(PrintJobAttributeListener listener, PrintJobAttributeSet attributes) {\r
+               if (listener != null) {\r
+                       if (attributeListeners == null) {\r
+                               attributeListeners = new HashMap();\r
+                       }\r
+                       attributeListeners.put(listener, attributes);\r
+               }\r
+       }\r
+\r
+       public void removePrintJobAttributeListener(PrintJobAttributeListener listener) {\r
+               if (listener != null) {\r
+                       attributeListeners.remove(listener);\r
+               }\r
+       }\r
+\r
+       void notifyJobListeners(int eventType) {\r
+               if (jobListeners != null) {\r
+                       PrintJobEvent event = new PrintJobEvent(this, eventType);\r
+                       for (Iterator iter = jobListeners.iterator(); iter.hasNext();) {\r
+                               PrintJobListener listener = (PrintJobListener) iter.next();\r
+                               if (eventType == PrintJobEvent.DATA_TRANSFER_COMPLETE) {\r
+                                       listener.printDataTransferCompleted(event);\r
+                               } else if (eventType == PrintJobEvent.JOB_CANCELED) {\r
+                                       listener.printJobCanceled(event);\r
+                               } else if (eventType == PrintJobEvent.JOB_COMPLETE) {\r
+                                       listener.printJobCompleted(event);\r
+                               } else if (eventType == PrintJobEvent.JOB_FAILED) {\r
+                                       listener.printJobFailed(event);\r
+                               } else if (eventType == PrintJobEvent.NO_MORE_EVENTS) {\r
+                                       listener.printJobNoMoreEvents(event);\r
+                               } else if (eventType == PrintJobEvent.REQUIRES_ATTENTION) {\r
+                                       listener.printJobRequiresAttention(event);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       IppResponse sendRequest(OperationsSupported operation, AttributeSet operationAttributes) throws IOException {\r
+               IppRequest request = this.request(operation);\r
+               request.addOperationAttributes(operationAttributes);\r
+               IppResponse response = null;\r
+               response = request.send();\r
+               return response;\r
+       }\r
+\r
+       private IppRequest request(OperationsSupported operation) {\r
+               IppRequest request = IppRequestFactory.createIppRequest(this.jobUri.getURI(), operation, this.printService.getRequestingUserName(), this.printService.getRequestingUserPassword());\r
+               AttributeSet operationAttributes = new HashAttributeSet();\r
+               operationAttributes.add(this.jobUri);\r
+               request.addOperationAttributes(operationAttributes);\r
+               return request;\r
+       }\r
+\r
+       //  public methods which are not part of the JPS API\r
+       /**\r
+        * \r
+        * This method returns the Job with the given JobId that is held by \r
+        * the given PrintService.\r
+        * <br>\r
+        * This method might return a Job which is not hold by this PrintService\r
+        * but the same CUPS server \r
+        * \r
+        * @param service\r
+        * @param id\r
+        * @return the corresponding Job wihth the given JobId, or null if no such \r
+        *          Job exists\r
+        * @throws PrintException\r
+        */\r
+       static Job getJob(IppPrintService service, JobId id) throws PrintException {\r
+               Job job = new Job(service);\r
+               job.printService = service;\r
+               URI jobUri;\r
+               try {\r
+                       jobUri =\r
+                               new URI(\r
+                                       service.getUri().getScheme(),\r
+                                       service.getUri().getAuthority(),\r
+                                       "/jobs/" + id.getValue(),\r
+                                       service.getUri().getQuery(),\r
+                                       service.getUri().getFragment());\r
+               } catch (URISyntaxException e) {\r
+                       throw new PrintException("Internal bug.", e);\r
+               }\r
+               job.jobUri = new JobUri(jobUri);\r
+               try {\r
+                       job.updateAttributes();\r
+               } catch (IllegalStateException e) {\r
+                       job = null;\r
+               }\r
+               return job;\r
+       }\r
+       \r
+       /**\r
+        * @param responseAttributes\r
+        */\r
+       private void updateAttributes(Map responseAttributes) {\r
+               this.jobAttributes = new HashPrintJobAttributeSet();\r
+               for (Iterator iter = responseAttributes.values().iterator(); iter.hasNext();) {\r
+                       Set values = (Set) iter.next();\r
+                       for (Iterator listIter = values.iterator(); listIter.hasNext();) {\r
+                               Attribute attribute = (Attribute) listIter.next();\r
+                               if (attribute instanceof PrintJobAttribute)\r
+                                       this.jobAttributes.add(attribute);\r
+                       }\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Updates the Job's attributes to the current values.\r
+        * \r
+        * @throws PrintException\r
+        */\r
+       private void updateAttributes() throws PrintException {\r
+               try {\r
+                   AttributeSet operationAttributes = new HashAttributeSet();\r
+                       IppResponse response = sendRequest(OperationsSupported.GET_JOB_ATTRIBUTES, operationAttributes);\r
+                       if (!response.getStatus().equals(IppStatus.SUCCESSFUL_OK)\r
+                               && !response.getStatus().equals(IppStatus.SUCCESSFUL_OK_CONFLICTING_ATTRIBUTES)\r
+                               && !response.getStatus().equals(IppStatus.SUCCESSFUL_OK_IGNORED_OR_SUBSTITUTED_ATTRIBUTES)) {\r
+                               if (response.getStatus().equals(IppStatus.CLIENT_ERROR_NOT_FOUND)) {\r
+                                       throw new IllegalStateException("Job with uri '" + this.jobUri.toString() + "does not exist.");\r
+                               }\r
+                               throw new PrintException("Request not successful.");\r
+                       }\r
+                       Map attribsMap = response.getAttributes();\r
+                       updateAttributes(attribsMap);\r
+                       \r
+               } catch (IOException e) {\r
+                       throw new PrintException("Update failed.", e);\r
+               }\r
+       }\r
+       \r
+       private String description(PrintRequestAttributeSet attributes){\r
+               String description = "job";\r
+               if (attributes != null){\r
+                       Attribute jobName = attributes.get(IppAttributeName.JOB_NAME.getCategory());\r
+                       if (jobName != null){\r
+                               description += " " + jobName.toString();\r
+                       }\r
+               }\r
+               return description;\r
+       }\r
+}\r