--- /dev/null
+/**\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