]> git.ipfire.org Git - thirdparty/cups.git/blob - scripting/java/src/com/easysw/cups/Cups.java
Load cups into easysw/current.
[thirdparty/cups.git] / scripting / java / src / com / easysw / cups / Cups.java
1 package com.easysw.cups;
2
3 /**
4 * @version 1.2 26-FEB-2006
5 * @author Apple Inc.
6 *
7 * Internet Printing Protocol definitions for the Common UNIX Printing
8 * System (CUPS).
9 *
10 * Copyright 2007 by Apple Inc.
11 * Copyright 1997-2006 by Easy Software Products.
12 *
13 * These coded instructions, statements, and computer programs are the
14 * property of Apple Inc. and are protected by Federal copyright
15 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
16 * which should have been included with this file. If this file is
17 * file is missing or damaged, see the license at "http://www.cups.org/".
18 */
19
20 /**
21 * An <code>Cups</code> object is used for connecting to servers,
22 * reading and writing data, and performing common CUPS operations.
23 *
24 * @author TDB
25 * @version 1.2
26 * @since JDK1.3
27 */
28
29 import java.io.*;
30 import java.util.*;
31 import java.net.*;
32
33 public class Cups
34 {
35
36 static final int REQ_STATE_CREATE_HTTP = 0;
37 static final int REQ_STATE_WRITE_HTTP_HEADER = 1;
38 static final int REQ_STATE_WRITE_IPP_HEADER = 2;
39 static final int REQ_STATE_WRITE_IPP_ATTRS = 3;
40 static final int REQ_STATE_FINISH_IPP_ATTRS = 4;
41 static final int REQ_STATE_READ_RESPONSE = 5;
42 static final int REQ_STATE_DONE = 6;
43 static final String[] req_state_names =
44 { "Create HTTP",
45 "Write Http Header",
46 "Write IPP Header",
47 "Write IPP Attrs",
48 "Finish IPP Attrs",
49 "Read Response",
50 "Done"
51 };
52
53
54 static final int FILEREQ_STATE_CREATE_HTTP = 0;
55 static final int FILEREQ_STATE_WRITE_HTTP_HEADER = 1;
56 static final int FILEREQ_STATE_WRITE_IPP_HEADER = 2;
57 static final int FILEREQ_STATE_WRITE_IPP_ATTRS = 3;
58 static final int FILEREQ_STATE_FINISH_IPP_ATTRS = 4;
59 static final int FILEREQ_STATE_WRITE_FILE_DATA = 5;
60 static final int FILEREQ_STATE_READ_RESPONSE = 6;
61 static final int FILEREQ_STATE_DONE = 7;
62 static final String[] filereq_state_names =
63 { "Create HTTP",
64 "Write Http Header",
65 "Write IPP Header",
66 "Write IPP Attrs",
67 "Finish IPP Attrs",
68 "Write File Data",
69 "Read Response",
70 "Done"
71 };
72
73
74 IPP ipp; // IPP Request
75 IPPHttp http; // Connection to server
76
77
78 String protocol; // Protocol name
79 String address; // address/name of server
80 int port; // Port #
81 String path; // Path ....
82 String dest; // Name of destination printer
83 String instance; // Instance of printer
84
85 //
86 // encrypt, user, and passwd are not fully implemented!
87 //
88 boolean encrypt; // Open encrypted connection.
89 String user; // User to login as.
90 String passwd; // Password if needed.
91
92 String site; // URL of site.
93
94 int last_error; // Last error #
95 String error_text; // Text for error
96
97 /**
98 * Void constructor.
99 */
100 public Cups()
101 {
102 http = null;
103 ipp = null;
104
105 protocol = "http";
106 address = "localhost";
107 port = 631;
108 path = "/";
109 site = "http://localhost:631/";
110 dest = "";
111 instance = "";
112 user = "";
113 passwd = "";
114 encrypt = false;
115 }
116
117 /**
118 * Constructor using a <code>URL</code>.
119 *
120 * @param <code>p_url</code> A <code>URL</code> object.
121 */
122 public Cups( URL p_url )
123 {
124 http = null;
125 ipp = null;
126
127 protocol = p_url.getProtocol() + "://";
128 address = p_url.getHost();
129 port = p_url.getPort();
130 path = p_url.getPath();
131
132 site = protocol + address;
133 if (port > 0)
134 site = site + ":" + port;
135
136 if (path.length() > 0)
137 site = site + path;
138
139 dest = "";
140 instance = "";
141 user = "";
142 passwd = "";
143 encrypt = false;
144 }
145
146
147 /**
148 * Set the value of the <code>protocol</code> member. Valid values
149 * are ipp or http.
150 *
151 * @param <code>p_protocol</code> String with protocol.
152 */
153 public void setProtocol( String p_protocol )
154 {
155 protocol = p_protocol;
156 site = protocol + "://" + address + ":" + port + path;
157 }
158
159 /**
160 * Set the value of the <code>server</code> member. This is an
161 * IP address or a hostname.
162 *
163 * @param <code>p_server</code> IP address or hostname.
164 */
165 public void setServer( String p_server )
166 {
167 address = p_server;
168 site = protocol + "://" + address + ":" + port + path;
169 }
170
171
172 /**
173 * Set the value of the <code>port</code> member.
174 *
175 * @param <code>p_port</code> Port number.
176 */
177 public void setPort( int p_port )
178 {
179 port = p_port;
180 site = protocol + "://" + address + ":" + port + path;
181 }
182
183
184 /**
185 * Set the value of the <code>user</code> member.
186 *
187 * @param <code>p_user</code> User name.
188 */
189 public void setUser( String p_user )
190 {
191 user = p_user;
192 }
193
194
195 /**
196 * Set the value of the <code>passwd</code> member.
197 *
198 * @param <code>p_passwd</code> Password.
199 */
200 public void setPasswd( String p_passwd )
201 {
202 passwd = p_passwd;
203 }
204
205
206 /**
207 * Set the value of the <code>dest</code> member.
208 *
209 * @param <code>p_dest</code> Destination.
210 */
211 public void setDest( String p_dest )
212 {
213 dest = p_dest;
214 }
215
216
217 /**
218 * Set the value of the <code>instance</code> member.
219 *
220 * @param <code>p_instance</code> Instance.
221 */
222 public void setInstance( String p_instance)
223 {
224 instance = p_instance;
225 }
226
227
228 /**
229 * Set the value of the <code>encrypt</code> member.
230 *
231 * @param <code>p_enrypt</code> Yes or no.
232 */
233 public void setEncrypt( boolean p_encrypt )
234 {
235 encrypt = p_encrypt;
236 }
237
238
239 /**
240 * Get the value of the <code>encrypt</code> member.
241 *
242 * @return <code>boolean</code> Encryption on or off.
243 */
244 public boolean getEncrypt()
245 {
246 return(encrypt);
247 }
248
249
250 /**
251 * Set the value of the <code>path</code> member. This is the
252 * path that will be used in the POST method.
253 *
254 * @param <code>p_path</code> Path on server.
255 */
256 public void setPath( String p_path )
257 {
258 path = p_path;
259 site = protocol + "://" + address + ":" + port + path;
260 }
261
262
263
264 public boolean doRequest(String from) throws IOException
265 {
266 // System.out.println("doRequest From: " + from );
267 return(doRequest());
268 }
269
270
271
272 /**
273 * Do a CUPS request to the server.
274 *
275 * @param <code>p_dest</code> Destination name.
276 * @return <code>boolean</code> True on success, false otherwise
277 * @throw <code>IOException</code>
278 */
279 public boolean doRequest() throws IOException
280 {
281 IPPAttribute attr;
282 int state = REQ_STATE_CREATE_HTTP;
283 int errors = 0;
284
285 while (true)
286 {
287 switch( state )
288 {
289
290 case REQ_STATE_CREATE_HTTP:
291 String url_str = site + dest;
292
293 try
294 {
295 if (user.length() > 0 && passwd.length() > 0)
296 http = new IPPHttp(url_str, "", user, passwd );
297 else
298 http = new IPPHttp(url_str);
299 state++;
300 }
301 catch (IOException e)
302 {
303 throw(e);
304 }
305 break;
306
307
308
309 case REQ_STATE_WRITE_HTTP_HEADER:
310 //
311 // Send the HTTP header.
312 //
313 switch( http.writeHeader( http.path, ipp.sizeInBytes() ))
314 {
315 case IPPHttp.HTTP_FORBIDDEN:
316 case IPPHttp.HTTP_NOT_FOUND:
317 case IPPHttp.HTTP_BAD_REQUEST:
318 case IPPHttp.HTTP_METHOD_NOT_ALLOWED:
319 case IPPHttp.HTTP_PAYMENT_REQUIRED:
320 case IPPHttp.HTTP_UPGRADE_REQUIRED:
321 case IPPHttp.HTTP_ERROR:
322 case IPPHttp.HTTP_UNAUTHORIZED:
323 errors++;
324 if (errors < 5)
325 {
326 if (!http.reConnect())
327 {
328 System.out.println("Could not reConnect(0)!");
329 return(false);
330 }
331 }
332 else
333 {
334 return(false);
335 }
336 break;
337
338 default: state++;
339 }
340 break;
341
342
343
344 case REQ_STATE_WRITE_IPP_HEADER:
345 //
346 // Send the request header.
347 //
348 byte[] header = new byte[8];
349 header[0] = (byte)1;
350 header[1] = (byte)1;
351 header[2] = (byte)((ipp.request.operation_id & 0xff00) >> 8);
352 header[3] = (byte)(ipp.request.operation_id & 0xff);
353 header[4] = (byte)((ipp.request.request_id & 0xff000000) >> 24);
354 header[5] = (byte)((ipp.request.request_id & 0xff0000) >> 16);
355 header[6] = (byte)((ipp.request.request_id & 0xff00) >> 8);
356 header[7] = (byte)(ipp.request.request_id & 0xff);
357 http.write( header );
358 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
359 {
360 errors++;
361 if (errors < 5)
362 {
363 if (http.reConnect())
364 state = REQ_STATE_WRITE_HTTP_HEADER;
365 else
366 {
367 System.out.println("Could not reConnect(1)\n");
368 return(false);
369 }
370 }
371 else
372 {
373 return(false);
374 }
375 }
376 else state++;
377 break;
378
379
380 case REQ_STATE_WRITE_IPP_ATTRS:
381 //
382 // Send the attributes list.
383 //
384 byte[] bytes;
385 int sz;
386 int last_group = -1;
387 boolean auth_error = false;
388 for (int i=0; i < ipp.attrs.size() && !auth_error; i++)
389 {
390 attr = (IPPAttribute)ipp.attrs.get(i);
391 sz = attr.sizeInBytes(last_group);
392 bytes = attr.getBytes(sz,last_group);
393 last_group = attr.group_tag;
394 http.write(bytes);
395
396 //
397 // Check for server response between each attribute.
398 //
399 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
400 {
401 errors++;
402 if (errors < 5)
403 {
404 if (!http.reConnect())
405 {
406 System.out.println("Could not reConnect(2)");
407 return(false);
408 }
409 state = REQ_STATE_WRITE_HTTP_HEADER;
410 auth_error = true;
411 }
412 else
413 {
414 return(false);
415 }
416 }
417
418 }
419 if (!auth_error)
420 state++;
421 break;
422
423
424
425 case REQ_STATE_FINISH_IPP_ATTRS:
426 //
427 // Send the end of attributes tag.
428 //
429 byte[] footer = new byte[1];
430 footer[0] = (byte)IPPDefs.TAG_END;
431 http.write( footer );
432
433 //
434 // Keep checking .....
435 //
436 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
437 {
438 errors++;
439 if (errors < 5)
440 {
441 if (!http.reConnect())
442 {
443 System.out.println("Could not reConnect(3)");
444 return(false);
445 }
446 state = REQ_STATE_WRITE_HTTP_HEADER;
447 }
448 else
449 {
450 return(false);
451 }
452 }
453 else state++;
454 break;
455
456
457
458 case REQ_STATE_READ_RESPONSE:
459 //
460 // Now read back response
461 //
462 int read_length;
463 read_length = http.read_header();
464 switch( http.status )
465 {
466 case IPPHttp.HTTP_OK:
467 break;
468
469 case IPPHttp.HTTP_UNAUTHORIZED:
470 http.reConnect();
471 state = REQ_STATE_WRITE_HTTP_HEADER;
472 errors = 0;
473 break;
474
475 default:
476 errors++;
477 if (errors < 5)
478 {
479 if (!http.reConnect())
480 {
481 System.out.println("Could not reConnect(4)");
482 return(false);
483 }
484 state = REQ_STATE_WRITE_HTTP_HEADER;
485 }
486 else
487 {
488 System.out.println("Too many errors: " + errors );
489 return(false);
490 }
491 break;
492 }
493
494 if ((read_length > 0) && (state == REQ_STATE_READ_RESPONSE))
495 {
496 http.read_buffer = http.read(read_length);
497 ipp = http.processResponse();
498 state++;
499 }
500 break;
501
502 case REQ_STATE_DONE:
503 //
504 // success.
505 //
506 http.conn.close();
507 http = null;
508 return(true);
509 }
510 }
511
512 } // End of doRequest
513
514
515
516 /**
517 * Send a FILE to the CUPS server.
518 *
519 * @param <code>file</code> File to send.
520 * @return <code>boolean</code> True on success, false otherwise
521 * @throw <code>IOException</code>
522 */
523 public boolean doRequest(File file) throws IOException
524 {
525 IPPAttribute attr;
526 int state = FILEREQ_STATE_CREATE_HTTP;
527 int errors = 0;
528 FileInputStream fis = null;
529
530 while (true)
531 {
532 switch( state )
533 {
534
535 case FILEREQ_STATE_CREATE_HTTP:
536 String url_str = site + dest;
537 try
538 {
539 if (user.length() > 0 && passwd.length() > 0)
540 http = new IPPHttp(url_str, "", user, passwd );
541 else
542 http = new IPPHttp(url_str);
543 state++;
544 }
545 catch (IOException e)
546 {
547 throw(e);
548 }
549 break;
550
551
552
553 case FILEREQ_STATE_WRITE_HTTP_HEADER:
554
555 if (fis != null)
556 {
557 fis.close();
558 }
559
560 //
561 // Open an input stream to the file.
562 //
563 try
564 {
565 fis = new FileInputStream(file);
566 }
567 catch (IOException e)
568 {
569 last_error = -1;
570 error_text = "Error opening file input stream.";
571 throw(e);
572 }
573
574 //
575 // Send the HTTP header.
576 //
577 int ippSz = ipp.sizeInBytes() + (int)file.length();
578 switch( http.writeHeader( http.path, ippSz ))
579 {
580 case IPPHttp.HTTP_FORBIDDEN:
581 case IPPHttp.HTTP_NOT_FOUND:
582 case IPPHttp.HTTP_BAD_REQUEST:
583 case IPPHttp.HTTP_METHOD_NOT_ALLOWED:
584 case IPPHttp.HTTP_PAYMENT_REQUIRED:
585 case IPPHttp.HTTP_UPGRADE_REQUIRED:
586 case IPPHttp.HTTP_ERROR:
587 case IPPHttp.HTTP_UNAUTHORIZED:
588 errors++;
589 if (errors < 5)
590 {
591 http.reConnect();
592 }
593 else
594 return(false);
595 break;
596
597 default: state++;
598 }
599 break;
600
601
602
603 case FILEREQ_STATE_WRITE_IPP_HEADER:
604 //
605 // Send the request header.
606 //
607 byte[] header = new byte[8];
608 header[0] = (byte)1;
609 header[1] = (byte)1;
610 header[2] = (byte)((ipp.request.operation_id & 0xff00) >> 8);
611 header[3] = (byte)(ipp.request.operation_id & 0xff);
612 header[4] = (byte)((ipp.request.request_id & 0xff000000) >> 24);
613 header[5] = (byte)((ipp.request.request_id & 0xff0000) >> 16);
614 header[6] = (byte)((ipp.request.request_id & 0xff00) >> 8);
615 header[7] = (byte)(ipp.request.request_id & 0xff);
616 http.write( header );
617 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
618 {
619 errors++;
620 if (errors < 5)
621 {
622 http.reConnect();
623 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
624 }
625 else
626 return(false);
627 }
628 else state++;
629 break;
630
631
632 case FILEREQ_STATE_WRITE_IPP_ATTRS:
633 //
634 // Send the attributes list.
635 //
636 byte[] bytes;
637 int sz;
638 int last_group = -1;
639 boolean auth_error = false;
640 for (int i=0; i < ipp.attrs.size() && !auth_error; i++)
641 {
642 attr = (IPPAttribute)ipp.attrs.get(i);
643 sz = attr.sizeInBytes(last_group);
644 bytes = attr.getBytes(sz,last_group);
645 last_group = attr.group_tag;
646 http.write(bytes);
647
648 //
649 // Check for server response between each attribute.
650 //
651 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
652 {
653 errors++;
654 if (errors < 5)
655 {
656 http.reConnect();
657 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
658 auth_error = true;
659 }
660 else
661 return(false);
662 }
663
664 }
665 if (!auth_error)
666 state++;
667 break;
668
669
670
671 case FILEREQ_STATE_FINISH_IPP_ATTRS:
672 //
673 // Send the end of attributes tag.
674 //
675 byte[] footer = new byte[1];
676 footer[0] = (byte)IPPDefs.TAG_END;
677 http.write( footer );
678
679 //
680 // Keep checking .....
681 //
682 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
683 {
684 errors++;
685 if (errors < 5)
686 {
687 http.reConnect();
688 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
689 }
690 else
691 return(false);
692 }
693 else state++;
694 break;
695
696
697
698 case FILEREQ_STATE_WRITE_FILE_DATA:
699 //
700 // Send the file data - this could be improved on ALOT.
701 //
702 int count;
703 byte[] b = new byte[1024];
704 while ((state == FILEREQ_STATE_WRITE_FILE_DATA) &&
705 ((count = fis.read(b)) != -1))
706 {
707 //
708 // Keep checking .....
709 //
710 if (http.checkForResponse() >= IPPHttp.HTTP_BAD_REQUEST)
711 {
712 errors++;
713 if (errors < 5)
714 {
715 http.reConnect();
716 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
717 }
718 else
719 {
720 return(false);
721 }
722 }
723 else
724 {
725 if (count > 0)
726 http.write( b, count );
727 }
728
729 } // while
730
731 if (state == FILEREQ_STATE_WRITE_FILE_DATA)
732 {
733 fis.close();
734 fis = null;
735 state++;
736 }
737 break;
738
739
740
741 case FILEREQ_STATE_READ_RESPONSE:
742 //
743 // Now read back response
744 //
745 int read_length;
746 read_length = http.read_header();
747 switch( http.status )
748 {
749 case IPPHttp.HTTP_OK:
750 break;
751
752 case IPPHttp.HTTP_UNAUTHORIZED:
753 http.reConnect();
754 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
755 errors = 0;
756 break;
757
758 default:
759 errors++;
760 if (errors < 5)
761 {
762 http.reConnect();
763 state = FILEREQ_STATE_WRITE_HTTP_HEADER;
764 }
765 else
766 {
767 return(false);
768 }
769 break;
770 }
771
772 if ((read_length > 0) && (state == FILEREQ_STATE_READ_RESPONSE))
773 {
774 http.read_buffer = http.read(read_length);
775 ipp = http.processResponse();
776 state++;
777 }
778 break;
779
780 case FILEREQ_STATE_DONE:
781 //
782 // success.
783 //
784 http.conn.close();
785 http = null;
786 return(true);
787 }
788 }
789
790 } // End of doRequest(file)
791
792
793
794
795
796
797
798 /**
799 * Get a list of jobs.
800 *
801 * @param <code>showMyJobs</code> Show only jobs for user.
802 * @param <code>showCompleted</code> Show completed OR active jobs.
803 *
804 * @return <code>CupsJob[]</code> Array of job objects, or null.
805 * @throw <code>IOException</code>
806 */
807 public CupsJob[] cupsGetJobs( boolean showMyJobs, boolean showCompleted )
808 throws IOException
809 {
810
811 IPPAttribute a;
812
813 String req_attrs[] = /* Requested attributes */
814 {
815 "job-id",
816 "job-priority",
817 "job-k-octets",
818 "job-state",
819 "time-at-completed",
820 "time-at-creation",
821 "time-at-processing",
822 "job-printer-uri",
823 "document-format",
824 "job-name",
825 "job-originating-user-name"
826 };
827
828
829 ipp = new IPP();
830 ipp.request = new IPPRequest( 1, (short)IPPDefs.GET_JOBS );
831
832 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
833 "attributes-charset" );
834 a.addString( "", "iso-8859-1" );
835 ipp.addAttribute(a);
836
837
838 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
839 "attributes-natural-language" );
840 a.addString( "", "en" );
841 ipp.addAttribute(a);
842
843
844 //
845 // Add the printer uri
846 //
847 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
848 "printer-uri" );
849
850 if (site != null)
851 a.addString( "", site );
852 else
853 a.addString( "", "ipp://localhost/jobs" ); // Default ...
854 // a.dump_values();
855 ipp.addAttribute(a);
856
857
858 //
859 // Add the requesting user name
860 // **FIX** This should be fixed to use the user member.
861 //
862 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
863 "requesting-user-name" );
864 a.addString( "", "root" );
865 ipp.addAttribute(a);
866
867 //
868 // Show only my jobs?
869 //
870 if (showMyJobs)
871 {
872 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_BOOLEAN,
873 "my-jobs" );
874 a.addBoolean( true );
875 ipp.addAttribute(a);
876 }
877
878 //
879 // Show completed jobs?
880 //
881 if (showCompleted)
882 {
883 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_KEYWORD,
884 "which-jobs" );
885 a.addString( "", "completed" );
886 ipp.addAttribute(a);
887 }
888
889 //
890 // Get ALL attributes - to get only listed ones,
891 // uncomment this and fill in req_attrs.
892 //
893 // a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_KEYWORD,
894 // "requested-attributes" );
895 // a.addStrings( "", req_attrs );
896 // ipp.addAttribute(a);
897
898 //
899 // Do the request and process the response.
900 //
901 if (doRequest("cupsGetJobs"))
902 {
903
904
905 //
906 // First we have to figure out how many jobs there are
907 // so we can create the array.
908 //
909
910 //
911 // Skip past leading attributes
912 //
913 int i = 0;
914 int group_tag = -1;
915 while ((i < ipp.attrs.size()) && (group_tag != IPPDefs.TAG_JOB))
916 {
917 a = (IPPAttribute)ipp.attrs.get(i);
918 group_tag = a.group_tag;
919 if (group_tag != IPPDefs.TAG_JOB)
920 i++;
921 }
922
923 int num_jobs = 0;
924 group_tag = IPPDefs.TAG_JOB;
925 while ((i < ipp.attrs.size()) && (group_tag == IPPDefs.TAG_JOB))
926 {
927 a = (IPPAttribute)ipp.attrs.get(i++);
928 if ((a != null) && (a.name.compareTo("job-id") == 0))
929 num_jobs++;
930 // a.dump_values();
931 }
932
933 if (num_jobs < 1)
934 return(null);
935
936
937 //
938 // Now create the array of the proper size.
939 //
940 int n = 0;
941 CupsJob[] jobs = new CupsJob[num_jobs];
942 for (n=0; n < num_jobs; n++)
943 {
944 jobs[n] = new CupsJob();
945 }
946
947
948
949
950 //
951 // Skip past leading attributes
952 //
953 group_tag = -1;
954 i = 0;
955 while ((i < ipp.attrs.size()) && (group_tag != IPPDefs.TAG_JOB))
956 {
957 a = (IPPAttribute)ipp.attrs.get(i);
958 group_tag = a.group_tag;
959 if (group_tag != IPPDefs.TAG_JOB)
960 i++;
961 }
962
963 //
964 // Now we actually fill the array with the job data.
965 //
966 n = 0;
967 for (;i < ipp.attrs.size(); i++)
968 {
969 a = (IPPAttribute)ipp.attrs.get(i);
970
971 if (a.group_tag == IPPDefs.TAG_ZERO)
972 {
973 n++;
974 continue;
975 }
976 else
977 {
978 try
979 {
980 jobs[n].updateAttribute( a );
981 }
982 catch (ArrayIndexOutOfBoundsException e)
983 {
984 return(jobs);
985 }
986 }
987 }
988 return( jobs );
989 }
990 return(null);
991
992 } // End of cupsGetJobs
993
994
995
996 /**
997 * Get a list of printers.
998 *
999 * @return <code>String[]</code> Array of printers, or null.
1000 * @throw <code>IOException</code>
1001 */
1002 public String[] cupsGetPrinters()
1003 throws IOException
1004 {
1005
1006 IPPAttribute a;
1007
1008 ipp = new IPP();
1009
1010 //
1011 // Fill in the required attributes
1012 //
1013 ipp.request = new IPPRequest( 1, (short)IPPDefs.CUPS_GET_PRINTERS );
1014
1015 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1016 "attributes-charset" );
1017 a.addString( "", "iso-8859-1" );
1018 ipp.addAttribute(a);
1019
1020
1021 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1022 "attributes-natural-language" );
1023 a.addString( "", "en" );
1024 ipp.addAttribute(a);
1025
1026
1027 if (doRequest("cupsGetPrinters"))
1028 {
1029 int num_printers = 0;
1030 for (int i=0; i < ipp.attrs.size(); i++)
1031 {
1032 a = (IPPAttribute)ipp.attrs.get(i);
1033 if ((a.name.compareTo("printer-name") == 0) &&
1034 (a.value_tag == IPPDefs.TAG_NAME))
1035 {
1036 num_printers++;
1037 }
1038 }
1039 if (num_printers < 1)
1040 return(null);
1041
1042 String[] printers = new String[num_printers];
1043 IPPValue val;
1044 int n = 0;
1045 for (int i=0; i < ipp.attrs.size(); i++)
1046 {
1047 a = (IPPAttribute)ipp.attrs.get(i);
1048 if (a.group_tag < 2)
1049 continue;
1050
1051 if ((a.name.compareTo("printer-name") == 0) &&
1052 (a.value_tag == IPPDefs.TAG_NAME))
1053 {
1054 val = (IPPValue)a.values.get(0);
1055 if (val != null)
1056 {
1057 printers[n] = val.text;
1058 n++;
1059 }
1060 }
1061 }
1062 return( printers );
1063
1064 } // if doRequest ...
1065
1066 return(null);
1067
1068 } // End of cupsGetPrinters
1069
1070
1071
1072
1073 /**
1074 * Get default destination.
1075 *
1076 * @return <code>String</code> Name of default printer, or null.
1077 * @throw <code>IOException</code>
1078 */
1079 public String cupsGetDefault()
1080 throws IOException
1081 {
1082
1083 IPPAttribute a;
1084
1085
1086 ipp = new IPP();
1087 //
1088 // Fill in the required attributes
1089 //
1090 ipp.request = new IPPRequest( 1, (short)IPPDefs.CUPS_GET_DEFAULT);
1091
1092 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1093 "attributes-charset" );
1094 a.addString( "", "iso-8859-1" );
1095 ipp.addAttribute(a);
1096
1097
1098 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1099 "attributes-natural-language" );
1100 a.addString( "", "en" );
1101 ipp.addAttribute(a);
1102
1103
1104 if (doRequest("cupsGetDefault"))
1105 {
1106 if ((ipp == null) || (ipp.attrs == null))
1107 return(null);
1108
1109 int num_printers = 0;
1110 for (int i=0; i < ipp.attrs.size(); i++)
1111 {
1112 a = (IPPAttribute)ipp.attrs.get(i);
1113 if ((a.name.compareTo("printer-name") == 0) &&
1114 (a.value_tag == IPPDefs.TAG_NAME))
1115 {
1116 IPPValue val = (IPPValue)a.values.get(0);
1117 if (val != null)
1118 {
1119 return( val.text );
1120 }
1121 }
1122 }
1123 } // if doRequest ...
1124
1125 return(null);
1126
1127 } // End of cupsGetDefault
1128
1129
1130
1131
1132
1133
1134 /**
1135 * Get printer attributes
1136 *
1137 * @param <code>printer_name</code> Name of printer to get info for.
1138 * @return <code>List</code> List of attributes.
1139 * @throw <code>IOException</code>
1140 *
1141 * @see <code>CupsPrinter</code>
1142 */
1143 public List cupsGetPrinterAttributes( String printer_name )
1144 throws IOException
1145 {
1146
1147 IPPAttribute a;
1148
1149 ipp = new IPP();
1150
1151 //
1152 // Fill in the required attributes
1153 //
1154 ipp.request = new IPPRequest( 1, (short)IPPDefs.GET_PRINTER_ATTRIBUTES );
1155
1156 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1157 "attributes-charset" );
1158 a.addString( "", "iso-8859-1" );
1159 ipp.addAttribute(a);
1160
1161
1162 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1163 "attributes-natural-language" );
1164 a.addString( "", "en" );
1165 ipp.addAttribute(a);
1166
1167 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
1168 "printer-uri" );
1169 String p_uri = "ipp://" + address + ":" +
1170 port + "/printers/" + printer_name;
1171 a.addString( "", p_uri );
1172 ipp.addAttribute(a);
1173
1174 if (doRequest("cupsGetPrinterAttributes"))
1175 {
1176 return(ipp.attrs);
1177 }
1178
1179 return(null);
1180
1181 } // End of cupsGetPrinterAttributes
1182
1183
1184
1185
1186 /**
1187 * Print a file.
1188 *
1189 * @param <code>p_filename</code> Path of file to print.
1190 * @param <code>p_attrs[]</code> Array of print job attributes.
1191 *
1192 * @return <code>CupsJob</code> Object with job info.
1193 *
1194 * @throw <code>IOException</code>
1195 *
1196 * @see <code>CupsJob</code>
1197 */
1198 public CupsJob cupsPrintFile( String p_filename,
1199 IPPAttribute p_attrs[] )
1200 throws IOException
1201 {
1202
1203 CupsJob job;
1204 IPPAttribute a;
1205 File file;
1206
1207
1208 file = new File(p_filename);
1209 if (!file.exists())
1210 {
1211 last_error = -1;
1212 error_text = "File does not exist.";
1213 return(null);
1214 }
1215
1216 if (!file.canRead())
1217 {
1218 last_error = -1;
1219 error_text = "File cannot be read.";
1220 return(null);
1221 }
1222
1223
1224 ipp = new IPP();
1225 //
1226 // Fill in the required attributes
1227 //
1228 ipp.request = new IPPRequest( 1, (short)IPPDefs.PRINT_JOB );
1229
1230 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1231 "attributes-charset" );
1232 a.addString( "", "iso-8859-1" );
1233 ipp.addAttribute(a);
1234
1235 // ------------
1236 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1237 "attributes-natural-language" );
1238 a.addString( "", "en" );
1239 ipp.addAttribute(a);
1240
1241 // ------------
1242 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
1243 "printer-uri" );
1244 a.addString( "", site + dest );
1245 ipp.addAttribute(a);
1246
1247 // ------------
1248 // **FIX** Fix this later.
1249 /*
1250 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
1251 "requesting-user-name" );
1252 // a.addString( "", p_username );
1253 a.addString( "", "root");
1254 ipp.addAttribute(a);
1255 */
1256
1257 // ------------
1258 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
1259 "job-name" );
1260 a.addString( "", file.getName() );
1261 ipp.addAttribute(a);
1262
1263 if (p_attrs != null)
1264 {
1265 for (int i=0; i < p_attrs.length; i++)
1266 {
1267 a = p_attrs[i];
1268 ipp.addAttribute(a);
1269 }
1270 }
1271
1272 if (doRequest(file))
1273 {
1274 job = new CupsJob();
1275 for (int i=0; i < ipp.attrs.size(); i++)
1276 {
1277 a = (IPPAttribute)ipp.attrs.get(i);
1278 job.updateAttribute(a);
1279 }
1280 return(job);
1281
1282 } // if doRequest ...
1283
1284 return(null);
1285
1286 } // End of cupsPrintFile
1287
1288
1289
1290
1291
1292 /**
1293 * Cancel a job - send a job cancel request to the server.
1294 *
1295 * @param <code>printer_name</code> Destination.
1296 * @param <code>p_job_id</code> ID of job.
1297 * @param <code>p_user_name</code> Requesting user name.
1298 *
1299 * @throw <code>IOException</code>
1300 */
1301 public int cupsCancelJob( String printer_name,
1302 int p_job_id,
1303 String p_user_name )
1304 throws IOException
1305 {
1306
1307 IPPAttribute a;
1308
1309 ipp = new IPP();
1310
1311 //
1312 // Fill in the required attributes
1313 //
1314 ipp.request = new IPPRequest( 1, (short)IPPDefs.CANCEL_JOB );
1315
1316 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1317 "attributes-charset" );
1318 a.addString( "", "iso-8859-1" );
1319 ipp.addAttribute(a);
1320
1321 // ------------
1322 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1323 "attributes-natural-language" );
1324 a.addString( "", "en" );
1325 ipp.addAttribute(a);
1326
1327 // ------------
1328 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
1329 "printer-uri" );
1330 a.addString( "", site + dest );
1331 ipp.addAttribute(a);
1332
1333 // ------------
1334 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_INTEGER,
1335 "job-id" );
1336 a.addInteger( p_job_id );
1337 ipp.addAttribute(a);
1338
1339 // ------------
1340 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_NAME,
1341 "requesting-user-name" );
1342 a.addString( "", p_user_name );
1343 ipp.addAttribute(a);
1344
1345 if (doRequest("cupsCancelJob"))
1346 {
1347 for (int i=0; i < ipp.attrs.size(); i++)
1348 {
1349 a = (IPPAttribute)ipp.attrs.get(i);
1350 a.dump_values();
1351 }
1352 return(0);
1353
1354 } // if doRequest ...
1355
1356 return(0);
1357
1358 } // End of cupsCancelJob
1359
1360
1361
1362
1363 public List cupsGetPrinterStatus(String printer_name)
1364 throws IOException
1365 {
1366 IPPAttribute a;
1367 String p_uri;
1368
1369 ipp = new IPP();
1370
1371 //
1372 // Fill in the required attributes
1373 //
1374 ipp.request = new IPPRequest(1,(short)IPPDefs.GET_PRINTER_ATTRIBUTES);
1375
1376 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_CHARSET,
1377 "attributes-charset" );
1378 a.addString( "", "iso-8859-1" );
1379 ipp.addAttribute(a);
1380
1381
1382 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_LANGUAGE,
1383 "attributes-natural-language" );
1384 a.addString( "", "en" );
1385 ipp.addAttribute(a);
1386
1387 a = new IPPAttribute( IPPDefs.TAG_OPERATION, IPPDefs.TAG_URI,
1388 "printer-uri" );
1389 p_uri = "ipp://" + address + ":" +
1390 port + "/printers/" + printer_name;
1391 a.addString( "", p_uri );
1392 ipp.addAttribute(a);
1393
1394 if (doRequest("cupsGetPrinterStatus"))
1395 {
1396 return(ipp.attrs);
1397 }
1398 return(null);
1399 }
1400
1401
1402
1403
1404
1405 } // End of Cups class
1406