blob: ea5771b3ad28b58e4d8fdb1635796c9ef66658e4 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.print;
27
28import java.io.File;
29import java.net.URI;
30import java.net.URISyntaxException;
31import java.net.URL;
32
33import java.util.Vector;
34
35import javax.print.DocFlavor;
36import javax.print.DocPrintJob;
37import javax.print.PrintService;
38import javax.print.ServiceUIFactory;
39import javax.print.attribute.Attribute;
40import javax.print.attribute.AttributeSet;
41import javax.print.attribute.AttributeSetUtilities;
42import javax.print.attribute.EnumSyntax;
43import javax.print.attribute.HashAttributeSet;
44import javax.print.attribute.PrintServiceAttribute;
45import javax.print.attribute.PrintServiceAttributeSet;
46import javax.print.attribute.HashPrintServiceAttributeSet;
47import javax.print.attribute.standard.PrinterName;
48import javax.print.attribute.standard.PrinterIsAcceptingJobs;
49import javax.print.attribute.standard.QueuedJobCount;
50import javax.print.attribute.standard.JobName;
51import javax.print.attribute.standard.RequestingUserName;
52import javax.print.attribute.standard.Chromaticity;
53import javax.print.attribute.standard.Copies;
54import javax.print.attribute.standard.CopiesSupported;
55import javax.print.attribute.standard.Destination;
56import javax.print.attribute.standard.Fidelity;
57import javax.print.attribute.standard.Media;
58import javax.print.attribute.standard.MediaSizeName;
59import javax.print.attribute.standard.MediaSize;
60import javax.print.attribute.standard.MediaTray;
61import javax.print.attribute.standard.MediaPrintableArea;
62import javax.print.attribute.standard.OrientationRequested;
63import javax.print.attribute.standard.PageRanges;
64import javax.print.attribute.standard.PrinterState;
65import javax.print.attribute.standard.PrinterStateReason;
66import javax.print.attribute.standard.PrinterStateReasons;
67import javax.print.attribute.standard.Severity;
68import javax.print.attribute.standard.Sides;
69import javax.print.attribute.standard.ColorSupported;
70import javax.print.attribute.standard.PrintQuality;
71import javax.print.attribute.ResolutionSyntax;
72import javax.print.attribute.standard.PrinterResolution;
73import javax.print.attribute.standard.SheetCollate;
74import javax.print.event.PrintServiceAttributeListener;
75import java.util.ArrayList;
76
77import sun.print.SunPrinterJobService;
78
79public class Win32PrintService implements PrintService, AttributeUpdater,
80 SunPrinterJobService {
81
82 public static MediaSize[] predefMedia;
83
84 static {
85 Class c = Win32MediaSize.class;
86 }
87
88 private static final DocFlavor[] supportedFlavors = {
89 DocFlavor.BYTE_ARRAY.GIF,
90 DocFlavor.INPUT_STREAM.GIF,
91 DocFlavor.URL.GIF,
92 DocFlavor.BYTE_ARRAY.JPEG,
93 DocFlavor.INPUT_STREAM.JPEG,
94 DocFlavor.URL.JPEG,
95 DocFlavor.BYTE_ARRAY.PNG,
96 DocFlavor.INPUT_STREAM.PNG,
97 DocFlavor.URL.PNG,
98 DocFlavor.SERVICE_FORMATTED.PAGEABLE,
99 DocFlavor.SERVICE_FORMATTED.PRINTABLE,
100 DocFlavor.BYTE_ARRAY.AUTOSENSE,
101 DocFlavor.URL.AUTOSENSE,
102 DocFlavor.INPUT_STREAM.AUTOSENSE
103 };
104
105 /* let's try to support a few of these */
106 private static final Class[] serviceAttrCats = {
107 PrinterName.class,
108 PrinterIsAcceptingJobs.class,
109 QueuedJobCount.class,
110 ColorSupported.class,
111 };
112
113 /* it turns out to be inconvenient to store the other categories
114 * separately because many attributes are in multiple categories.
115 */
116 private static Class[] otherAttrCats = {
117 JobName.class,
118 RequestingUserName.class,
119 Copies.class,
120 Destination.class,
121 OrientationRequested.class,
122 PageRanges.class,
123 Media.class,
124 MediaPrintableArea.class,
125 Fidelity.class,
126 // We support collation on 2D printer jobs, even if the driver can't.
127 SheetCollate.class,
128 SunAlternateMedia.class,
129 Chromaticity.class
130 };
131
132
133 /*
134 * This table together with methods findWin32Media and
135 * findMatchingMediaSizeNameMM are declared public as these are also
136 * used in WPrinterJob.java.
137 */
138 public static final MediaSizeName[] dmPaperToPrintService = {
139 MediaSizeName.NA_LETTER, MediaSizeName.NA_LETTER,
140 MediaSizeName.TABLOID, MediaSizeName.LEDGER,
141 MediaSizeName.NA_LEGAL, MediaSizeName.INVOICE,
142 MediaSizeName.EXECUTIVE, MediaSizeName.ISO_A3,
143 MediaSizeName.ISO_A4, MediaSizeName.ISO_A4,
144 MediaSizeName.ISO_A5, MediaSizeName.JIS_B4,
145 MediaSizeName.JIS_B5, MediaSizeName.FOLIO,
146 MediaSizeName.QUARTO, MediaSizeName.NA_10X14_ENVELOPE,
147 MediaSizeName.B, MediaSizeName.NA_LETTER,
148 MediaSizeName.NA_NUMBER_9_ENVELOPE, MediaSizeName.NA_NUMBER_10_ENVELOPE,
149 MediaSizeName.NA_NUMBER_11_ENVELOPE, MediaSizeName.NA_NUMBER_12_ENVELOPE,
150 MediaSizeName.NA_NUMBER_14_ENVELOPE, MediaSizeName.C,
151 MediaSizeName.D, MediaSizeName.E,
152 MediaSizeName.ISO_DESIGNATED_LONG, MediaSizeName.ISO_C5,
153 MediaSizeName.ISO_C3, MediaSizeName.ISO_C4,
154 MediaSizeName.ISO_C6, MediaSizeName.ITALY_ENVELOPE,
155 MediaSizeName.ISO_B4, MediaSizeName.ISO_B5,
156 MediaSizeName.ISO_B6, MediaSizeName.ITALY_ENVELOPE,
157 MediaSizeName.MONARCH_ENVELOPE, MediaSizeName.PERSONAL_ENVELOPE,
158 MediaSizeName.NA_10X15_ENVELOPE, MediaSizeName.NA_9X12_ENVELOPE,
159 MediaSizeName.FOLIO, MediaSizeName.ISO_B4,
160 MediaSizeName.JAPANESE_POSTCARD, MediaSizeName.NA_9X11_ENVELOPE,
161 };
162
163 private static final MediaTray[] dmPaperBinToPrintService = {
164 MediaTray.TOP, MediaTray.BOTTOM, MediaTray.MIDDLE,
165 MediaTray.MANUAL, MediaTray.ENVELOPE, Win32MediaTray.ENVELOPE_MANUAL,
166 Win32MediaTray.AUTO, Win32MediaTray.TRACTOR,
167 Win32MediaTray.SMALL_FORMAT, Win32MediaTray.LARGE_FORMAT,
168 MediaTray.LARGE_CAPACITY, null, null,
169 MediaTray.MAIN, Win32MediaTray.FORMSOURCE,
170 };
171
172 // from wingdi.h
173 private static int DM_PAPERSIZE = 0x2;
174 private static int DM_PRINTQUALITY = 0x400;
175 private static int DM_YRESOLUTION = 0x2000;
176 private static final int DMRES_MEDIUM = -3;
177 private static final int DMRES_HIGH = -4;
178 private static final int DMORIENT_LANDSCAPE = 2;
179 private static final int DMDUP_VERTICAL = 2;
180 private static final int DMDUP_HORIZONTAL = 3;
181 private static final int DMCOLLATE_TRUE = 1;
182
183 // media sizes with indices above dmPaperToPrintService' length
184 private static final int DMPAPER_A2 = 66;
185 private static final int DMPAPER_A6 = 70;
186 private static final int DMPAPER_B6_JIS = 88;
187
188
189 // Bit settings for getPrinterCapabilities which matches that
190 // of native getCapabilities in WPrinterJob.cpp
191 private static final int DEVCAP_COLOR = 0x0001;
192 private static final int DEVCAP_DUPLEX = 0x0002;
193 private static final int DEVCAP_COLLATE = 0x0004;
194 private static final int DEVCAP_QUALITY = 0x0008;
195 private static final int DEVCAP_POSTSCRIPT = 0x0010;
196
197 private String printer;
198 private PrinterName name;
199 private String port;
200
201 transient private PrintServiceAttributeSet lastSet;
202 transient private ServiceNotifier notifier = null;
203
204 private MediaSizeName[] mediaSizeNames;
205 private MediaPrintableArea[] mediaPrintables;
206 private MediaTray[] mediaTrays;
207 private PrinterResolution[] printRes;
208 private int nCopies;
209 private int prnCaps;
210 private int[] defaultSettings;
211
212 private boolean gotTrays;
213 private boolean gotCopies;
214 private boolean mediaInitialized;
215
216 private ArrayList idList;
217 private MediaSize[] mediaSizes;
218
219 private boolean isInvalid;
220
221 Win32PrintService(String name) {
222 if (name == null) {
223 throw new IllegalArgumentException("null printer name");
224 }
225 printer = name;
226
227 // initialize flags
228 mediaInitialized = false;
229 gotTrays = false;
230 gotCopies = false;
231 isInvalid = false;
232 printRes = null;
233 prnCaps = 0;
234 defaultSettings = null;
235 port = null;
236 }
237
238 public void invalidateService() {
239 isInvalid = true;
240 }
241
242 public String getName() {
243 return printer;
244 }
245
246 private PrinterName getPrinterName() {
247 if (name == null) {
248 name = new PrinterName(printer, null);
249 }
250 return name;
251 }
252
253 public int findPaperID(MediaSizeName msn) {
254 if (msn instanceof Win32MediaSize) {
255 Win32MediaSize winMedia = (Win32MediaSize)msn;
256 return winMedia.getDMPaper();
257 } else {
258 for (int id=0; id<dmPaperToPrintService.length;id++) {
259 if (dmPaperToPrintService[id].equals(msn)) {
260 return id+1; // DMPAPER_LETTER == 1
261 }
262 }
263 if (msn.equals(MediaSizeName.ISO_A2)) {
264 return DMPAPER_A2;
265 }
266 else if (msn.equals(MediaSizeName.ISO_A6)) {
267 return DMPAPER_A6;
268 }
269 else if (msn.equals(MediaSizeName.JIS_B6)) {
270 return DMPAPER_B6_JIS;
271 }
272 }
273 return 0;
274 }
275
276 public MediaTray findMediaTray(int dmBin) {
277 if (dmBin >= 1 && dmBin <= dmPaperBinToPrintService.length) {
278 return dmPaperBinToPrintService[dmBin-1];
279 }
280 MediaTray[] trays = getMediaTrays();
281 if (trays != null) {
282 for (int i=0;i<trays.length;i++) {
283 if(trays[i] instanceof Win32MediaTray) {
284 Win32MediaTray win32Tray = (Win32MediaTray)trays[i];
285 if (win32Tray.winID == dmBin) {
286 return win32Tray;
287 }
288 }
289 }
290 }
291 return Win32MediaTray.AUTO;
292 }
293
294 public MediaSizeName findWin32Media(int dmIndex) {
295 if (dmIndex >= 1 && dmIndex <= dmPaperToPrintService.length) {
296 switch(dmIndex) {
297 /* matching media sizes with indices beyond
298 dmPaperToPrintService's length */
299 case DMPAPER_A2:
300 return MediaSizeName.ISO_A2;
301 case DMPAPER_A6:
302 return MediaSizeName.ISO_A6;
303 case DMPAPER_B6_JIS:
304 return MediaSizeName.JIS_B6;
305 default:
306 return dmPaperToPrintService[dmIndex - 1];
307 }
308 }
309
310 return null;
311 }
312
313 private boolean addToUniqueList(ArrayList msnList, MediaSizeName mediaName) {
314 MediaSizeName msn;
315 for (int i=0; i< msnList.size(); i++) {
316 msn = (MediaSizeName)msnList.get(i);
317 if (msn == mediaName) {
318 return false;
319 }
320 }
321 msnList.add(mediaName);
322 return true;
323 }
324
325 private synchronized void initMedia() {
326 if (mediaInitialized == true) {
327 return;
328 }
329 mediaInitialized = true;
330 int[] media = getAllMediaIDs(printer, getPort());
331 if (media == null) {
332 return;
333 }
334
335 ArrayList msnList = new ArrayList();
336 ArrayList printableList = new ArrayList();
337 MediaSizeName mediaName;
338 boolean added;
339 boolean queryFailure = false;
340 float[] prnArea;
341
342 // Get all mediaSizes supported by the printer.
343 // We convert media to ArrayList idList and pass this to the
344 // function for getting mediaSizes.
345 // This is to ensure that mediaSizes and media IDs have 1-1 correspondence.
346 // We remove from ID list any invalid mediaSize. Though this is rare,
347 // it happens in HP 4050 German driver.
348
349 idList = new ArrayList();
350 for (int i=0; i < media.length; i++) {
351 idList.add(new Integer(media[i]));
352 }
353
354 mediaSizes = getMediaSizes(idList, media);
355 for (int i = 0; i < idList.size(); i++) {
356
357 // match Win ID with our predefined ID using table
358 mediaName = findWin32Media(((Integer)idList.get(i)).intValue());
359 // Verify that this standard size is the same size as that
360 // reported by the driver. This should be the case except when
361 // the driver is mis-using a standard windows paper ID.
362 if (mediaName != null &&
363 idList.size() == mediaSizes.length) {
364 MediaSize win32Size = MediaSize.getMediaSizeForName(mediaName);
365 MediaSize driverSize = mediaSizes[i];
366 int error = 2540; // == 1/10"
367 if (Math.abs(win32Size.getX(1)-driverSize.getX(1)) > error ||
368 Math.abs(win32Size.getY(1)-driverSize.getY(1)) > error)
369 {
370 mediaName = null;
371 }
372 }
373
374 // No match found, then we get the MediaSizeName out of the MediaSize
375 // This requires 1-1 correspondence, lengths must be checked.
376 if ((mediaName == null) && (idList.size() == mediaSizes.length)) {
377 mediaName = mediaSizes[i].getMediaSizeName();
378 }
379
380 // Add mediaName to the msnList
381 if (mediaName != null) {
382 added = addToUniqueList(msnList, mediaName);
383
384 // get MediaPrintableArea only for supported MediaSizeName ?
385 if (added && !queryFailure) {
386 prnArea=getMediaPrintableArea(printer,
387 ((Integer)idList.get(i)).intValue());
388 if (prnArea != null) {
389 try {
390 MediaPrintableArea mpa =
391 new MediaPrintableArea(prnArea[0],
392 prnArea[1],
393 prnArea[2],
394 prnArea[3],
395 MediaPrintableArea.INCH);
396 printableList.add(mpa);
397 } catch (IllegalArgumentException iae) {
398 }
399 } else {
400 // Calling getMediaPrintableArea causes
401 // much overhead so if first attempt failed, we should
402 // just bail out.
403 if (i==0) {
404 queryFailure = true;
405 }
406 }
407 }
408 }
409 }
410
411 // init mediaSizeNames
412 mediaSizeNames = new MediaSizeName[msnList.size()];
413 msnList.toArray(mediaSizeNames);
414
415 // init mediaPrintables
416 mediaPrintables = new MediaPrintableArea[printableList.size()];
417 printableList.toArray(mediaPrintables);
418 }
419
420 private synchronized MediaTray[] getMediaTrays() {
421 if (gotTrays == true && mediaTrays != null) {
422 return mediaTrays;
423 }
424 String prnPort = getPort();
425 int[] mediaTr = getAllMediaTrays(printer, prnPort);
426 String[] winMediaTrayNames = getAllMediaTrayNames(printer, prnPort);
427
428 if ((mediaTr == null) || (winMediaTrayNames == null)){
429 return null;
430 }
431
432 /* first count how many valid bins there are so we can allocate
433 * an array of the correct size
434 */
435 int nTray = 0;
436 for (int i=0; i < mediaTr.length ; i++) {
437 if (mediaTr[i] > 0) nTray++;
438 }
439
440 MediaTray[] arr = new MediaTray[nTray];
441 int dmBin;
442 for (int i = 0, j=0; i < mediaTr.length; i++) {
443 dmBin = mediaTr[i];
444 if (dmBin > 0) {
445 // check for unsupported DMBINs and create new Win32MediaTray
446 if ((dmBin > dmPaperBinToPrintService.length)
447 || (dmPaperBinToPrintService[dmBin-1] == null)) {
448 arr[j++] = new Win32MediaTray(dmBin, winMediaTrayNames[i]);
449 } else {
450 arr[j++] = dmPaperBinToPrintService[dmBin-1];
451 }
452 }
453 // no else - For invalid ids, just ignore it because assigning a "default"
454 // value may result in duplicate trays.
455 }
456 mediaTrays = arr;
457 gotTrays = true;
458 return mediaTrays;
459 }
460
461 private boolean isSameSize(float w1, float h1, float w2, float h2) {
462 float diffX = w1 - w2;
463 float diffY = h1 - h2;
464 // Get diff of reverse dimensions
465 // EPSON Stylus COLOR 860 reverses envelope's width & height
466 float diffXrev = w1 - h2;
467 float diffYrev = h1 - w2;
468
469 if (((Math.abs(diffX)<=1) && (Math.abs(diffY)<=1)) ||
470 ((Math.abs(diffXrev)<=1) && (Math.abs(diffYrev)<=1))){
471 return true;
472 } else {
473 return false;
474 }
475 }
476
477 public MediaSizeName findMatchingMediaSizeNameMM (float w, float h){
478 if (predefMedia != null) {
479 for (int k=0; k<predefMedia.length;k++) {
480 if (predefMedia[k] == null) {
481 continue;
482 }
483
484 if (isSameSize(predefMedia[k].getX(MediaSize.MM),
485 predefMedia[k].getY(MediaSize.MM),
486 w, h)) {
487 return predefMedia[k].getMediaSizeName();
488 }
489 }
490 }
491 return null;
492 }
493
494
495 private MediaSize[] getMediaSizes(ArrayList idList, int[] media) {
496 String prnPort = getPort();
497 int[] mediaSz = getAllMediaSizes(printer, prnPort);
498 String[] winMediaNames = getAllMediaNames(printer, prnPort);
499 MediaSizeName msn = null;
500 MediaSize ms = null;
501 float wid, ht;
502
503 if ((mediaSz == null) || (winMediaNames == null)) {
504 return null;
505 }
506
507 int nMedia = mediaSz.length/2;
508 ArrayList msList = new ArrayList();
509
510 for (int i = 0; i < nMedia; i++, ms=null) {
511 wid = mediaSz[i*2]/10f;
512 ht = mediaSz[i*2+1]/10f;
513
514 // Make sure to validate wid & ht.
515 // HP LJ 4050 (german) causes IAE in Sonderformat paper, wid & ht
516 // returned is not constant.
517 if ((wid <= 0) || (ht <= 0)) {
518 //Remove corresponding ID from list
519 if (nMedia == media.length) {
520 Integer remObj = new Integer(media[i]);
521 idList.remove(idList.indexOf(remObj));
522 }
523 continue;
524 }
525 // Find matching media using dimensions.
526 // This call matches only with our own predefined sizes.
527 msn = findMatchingMediaSizeNameMM(wid, ht);
528 if (msn != null) {
529 ms = MediaSize.getMediaSizeForName(msn);
530 }
531
532 if (ms != null) {
533 msList.add(ms);
534 } else {
535 Win32MediaSize wms =
536 new Win32MediaSize(winMediaNames[i], media[i]);
537 try {
538 ms = new MediaSize(wid, ht, MediaSize.MM, wms);
539 msList.add(ms);
540 } catch(IllegalArgumentException e) {
541 if (nMedia == media.length) {
542 Integer remObj = new Integer(media[i]);
543 idList.remove(idList.indexOf(remObj));
544 }
545 }
546 }
547
548 }
549
550 MediaSize[] arr2 = new MediaSize[msList.size()];
551 msList.toArray(arr2);
552
553 return arr2;
554 }
555
556
557 private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
558 if (getJobStatus(printer, 2) != 1) {
559 return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
560 }
561 else {
562 return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
563 }
564 }
565
566 private PrinterState getPrinterState() {
567 if (isInvalid) {
568 return PrinterState.STOPPED;
569 } else {
570 return null;
571 }
572 }
573
574 private PrinterStateReasons getPrinterStateReasons() {
575 if (isInvalid) {
576 PrinterStateReasons psr = new PrinterStateReasons();
577 psr.put(PrinterStateReason.SHUTDOWN, Severity.ERROR);
578 return psr;
579 } else {
580 return null;
581 }
582 }
583
584 private QueuedJobCount getQueuedJobCount() {
585
586 int count = getJobStatus(printer, 1);
587 if (count != -1) {
588 return new QueuedJobCount(count);
589 }
590 else {
591 return new QueuedJobCount(0);
592 }
593 }
594
595 private boolean isSupportedCopies(Copies copies) {
596 synchronized (this) {
597 if (gotCopies == false) {
598 nCopies = getCopiesSupported(printer, getPort());
599 gotCopies = true;
600 }
601 }
602 int numCopies = copies.getValue();
603 return (numCopies > 0 && numCopies <= nCopies);
604 }
605
606 private boolean isSupportedMedia(MediaSizeName msn) {
607
608 initMedia();
609
610 if (mediaSizeNames != null) {
611 for (int i=0; i<mediaSizeNames.length; i++) {
612 if (msn.equals(mediaSizeNames[i])) {
613 return true;
614 }
615 }
616 }
617 return false;
618 }
619
620 private boolean isSupportedMediaPrintableArea(MediaPrintableArea mpa) {
621
622 initMedia();
623
624 if (mediaPrintables != null) {
625 for (int i=0; i<mediaPrintables.length; i++) {
626 if (mpa.equals(mediaPrintables[i])) {
627 return true;
628 }
629 }
630 }
631 return false;
632 }
633
634 private boolean isSupportedMediaTray(MediaTray msn) {
635 MediaTray[] trays = getMediaTrays();
636
637 if (trays != null) {
638 for (int i=0; i<trays.length; i++) {
639 if (msn.equals(trays[i])) {
640 return true;
641 }
642 }
643 }
644 return false;
645 }
646
647 private int getPrinterCapabilities() {
648 if (prnCaps == 0) {
649 prnCaps = getCapabilities(printer, getPort());
650 }
651 return prnCaps;
652 }
653
654 private String getPort() {
655 if (port == null) {
656 port = getPrinterPort(printer);
657 }
658 return port;
659 }
660
661 /*
662 * NOTE: defaults indices must match those in WPrinterJob.cpp
663 */
664 private int[] getDefaultPrinterSettings() {
665 if (defaultSettings == null) {
666 defaultSettings = getDefaultSettings(printer, getPort());
667 }
668 return defaultSettings;
669 }
670
671 private PrinterResolution[] getPrintResolutions() {
672 if (printRes == null) {
673 int[] prnRes = getAllResolutions(printer, getPort());
674 if (prnRes == null) {
675 printRes = new PrinterResolution[0];
676 } else {
677 int nRes = prnRes.length/2;
678
679 ArrayList arrList = new ArrayList();
680 PrinterResolution pr;
681
682 for (int i=0; i<nRes; i++) {
683 try {
684 pr = new PrinterResolution(prnRes[i*2],
685 prnRes[i*2+1], PrinterResolution.DPI);
686 arrList.add(pr);
687 } catch (IllegalArgumentException e) {
688 }
689 }
690
691 printRes = (PrinterResolution[])arrList.toArray(
692 new PrinterResolution[arrList.size()]);
693 }
694 }
695 return printRes;
696 }
697
698 private boolean isSupportedResolution(PrinterResolution res) {
699 PrinterResolution[] supportedRes = getPrintResolutions();
700 if (supportedRes != null) {
701 for (int i=0; i<supportedRes.length; i++) {
702 if (res.equals(supportedRes[i])) {
703 return true;
704 }
705 }
706 }
707 return false;
708 }
709
710 public DocPrintJob createPrintJob() {
711 SecurityManager security = System.getSecurityManager();
712 if (security != null) {
713 security.checkPrintJobAccess();
714 }
715 return new Win32PrintJob(this);
716 }
717
718 private PrintServiceAttributeSet getDynamicAttributes() {
719 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
720 attrs.add(getPrinterIsAcceptingJobs());
721 attrs.add(getQueuedJobCount());
722 return attrs;
723 }
724
725 public PrintServiceAttributeSet getUpdatedAttributes() {
726 PrintServiceAttributeSet currSet = getDynamicAttributes();
727 if (lastSet == null) {
728 lastSet = currSet;
729 return AttributeSetUtilities.unmodifiableView(currSet);
730 } else {
731 PrintServiceAttributeSet updates =
732 new HashPrintServiceAttributeSet();
733 Attribute []attrs = currSet.toArray();
734 for (int i=0; i<attrs.length; i++) {
735 Attribute attr = attrs[i];
736 if (!lastSet.containsValue(attr)) {
737 updates.add(attr);
738 }
739 }
740 lastSet = currSet;
741 return AttributeSetUtilities.unmodifiableView(updates);
742 }
743 }
744
745 public void wakeNotifier() {
746 synchronized (this) {
747 if (notifier != null) {
748 notifier.wake();
749 }
750 }
751 }
752
753 public void addPrintServiceAttributeListener(PrintServiceAttributeListener
754 listener) {
755 synchronized (this) {
756 if (listener == null) {
757 return;
758 }
759 if (notifier == null) {
760 notifier = new ServiceNotifier(this);
761 }
762 notifier.addListener(listener);
763 }
764 }
765
766 public void removePrintServiceAttributeListener(
767 PrintServiceAttributeListener listener) {
768 synchronized (this) {
769 if (listener == null || notifier == null ) {
770 return;
771 }
772 notifier.removeListener(listener);
773 if (notifier.isEmpty()) {
774 notifier.stopNotifier();
775 notifier = null;
776 }
777 }
778 }
779
780 public <T extends PrintServiceAttribute> T
781 getAttribute(Class<T> category)
782 {
783 if (category == null) {
784 throw new NullPointerException("category");
785 }
786 if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {
787 throw new IllegalArgumentException("Not a PrintServiceAttribute");
788 }
789 if (category == ColorSupported.class) {
790 int caps = getPrinterCapabilities();
791 if ((caps & DEVCAP_COLOR) != 0) {
792 return (T)ColorSupported.SUPPORTED;
793 } else {
794 return (T)ColorSupported.NOT_SUPPORTED;
795 }
796 } else if (category == PrinterName.class) {
797 return (T)getPrinterName();
798 } else if (category == PrinterState.class) {
799 return (T)getPrinterState();
800 } else if (category == PrinterStateReasons.class) {
801 return (T)getPrinterStateReasons();
802 } else if (category == QueuedJobCount.class) {
803 return (T)getQueuedJobCount();
804 } else if (category == PrinterIsAcceptingJobs.class) {
805 return (T)getPrinterIsAcceptingJobs();
806 } else {
807 return null;
808 }
809 }
810
811 public PrintServiceAttributeSet getAttributes() {
812
813 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
814 attrs.add(getPrinterName());
815 attrs.add(getPrinterIsAcceptingJobs());
816 PrinterState prnState = getPrinterState();
817 if (prnState != null) {
818 attrs.add(prnState);
819 }
820 PrinterStateReasons prnStateReasons = getPrinterStateReasons();
821 if (prnStateReasons != null) {
822 attrs.add(prnStateReasons);
823 }
824 attrs.add(getQueuedJobCount());
825 int caps = getPrinterCapabilities();
826 if ((caps & DEVCAP_COLOR) != 0) {
827 attrs.add(ColorSupported.SUPPORTED);
828 } else {
829 attrs.add(ColorSupported.NOT_SUPPORTED);
830 }
831
832 return AttributeSetUtilities.unmodifiableView(attrs);
833 }
834
835 public DocFlavor[] getSupportedDocFlavors() {
836 int len = supportedFlavors.length;
837 DocFlavor[] supportedDocFlavors;
838 int caps = getPrinterCapabilities();
839 // doc flavors supported
840 // if PostScript is supported
841 if ((caps & DEVCAP_POSTSCRIPT) != 0) {
842 supportedDocFlavors = new DocFlavor[len+3];
843 System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len);
844 supportedDocFlavors[len] = DocFlavor.BYTE_ARRAY.POSTSCRIPT;
845 supportedDocFlavors[len+1] = DocFlavor.INPUT_STREAM.POSTSCRIPT;
846 supportedDocFlavors[len+2] = DocFlavor.URL.POSTSCRIPT;
847 } else {
848 supportedDocFlavors = new DocFlavor[len];
849 System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len);
850 }
851 return supportedDocFlavors;
852 }
853
854 public boolean isDocFlavorSupported(DocFlavor flavor) {
855 /* To avoid a native query which may be time-consuming
856 * do not invoke native unless postscript support is being queried.
857 * Instead just check the ones we 'always' support
858 */
859 DocFlavor[] supportedDocFlavors;
860 if (isPostScriptFlavor(flavor)) {
861 supportedDocFlavors = getSupportedDocFlavors();
862 } else {
863 supportedDocFlavors = supportedFlavors;
864 }
865 for (int f=0; f<supportedDocFlavors.length; f++) {
866 if (flavor.equals(supportedDocFlavors[f])) {
867 return true;
868 }
869 }
870 return false;
871 }
872
873 public Class<?>[] getSupportedAttributeCategories() {
874 ArrayList categList = new ArrayList(otherAttrCats.length+3);
875 for (int i=0; i < otherAttrCats.length; i++) {
876 categList.add(otherAttrCats[i]);
877 }
878
879 int caps = getPrinterCapabilities();
880
881 if ((caps & DEVCAP_DUPLEX) != 0) {
882 categList.add(Sides.class);
883 }
884
885 if ((caps & DEVCAP_QUALITY) != 0) {
886 int[] defaults = getDefaultPrinterSettings();
887 // Added check: if supported, we should be able to get the default.
888 if ((defaults[3] >= DMRES_HIGH) && (defaults[3] < 0)) {
889 categList.add(PrintQuality.class);
890 }
891 }
892
893 PrinterResolution[] supportedRes = getPrintResolutions();
894 if ((supportedRes!=null) && (supportedRes.length>0)) {
895 categList.add(PrinterResolution.class);
896 }
897
898 return (Class[])categList.toArray(new Class[categList.size()]);
899 }
900
901 public boolean
902 isAttributeCategorySupported(Class<? extends Attribute> category)
903 {
904
905 if (category == null) {
906 throw new NullPointerException("null category");
907 }
908
909 if (!(Attribute.class.isAssignableFrom(category))) {
910 throw new IllegalArgumentException(category +
911 " is not an Attribute");
912 }
913
914 Class[] classList = getSupportedAttributeCategories();
915 for (int i = 0; i < classList.length; i++) {
916 if (category.equals(classList[i])) {
917 return true;
918 }
919 }
920
921 return false;
922 }
923
924 public Object
925 getDefaultAttributeValue(Class<? extends Attribute> category)
926 {
927 if (category == null) {
928 throw new NullPointerException("null category");
929 }
930 if (!Attribute.class.isAssignableFrom(category)) {
931 throw new IllegalArgumentException(category +
932 " is not an Attribute");
933 }
934
935 if (!isAttributeCategorySupported(category)) {
936 return null;
937 }
938
939 int[] defaults = getDefaultPrinterSettings();
940 // indices must match those in WPrinterJob.cpp
941 int defPaper = defaults[0];
942 int defYRes = defaults[2];
943 int defQuality = defaults[3];
944 int defCopies = defaults[4];
945 int defOrient = defaults[5];
946 int defSides = defaults[6];
947 int defCollate = defaults[7];
948
949 if (category == Copies.class) {
950 if (defCopies > 0) {
951 return new Copies(defCopies);
952 } else {
953 return new Copies(1);
954 }
955 } else if (category == Chromaticity.class) {
956 int caps = getPrinterCapabilities();
957 if ((caps & DEVCAP_COLOR) == 0) {
958 return Chromaticity.MONOCHROME;
959 } else {
960 return Chromaticity.COLOR;
961 }
962 } else if (category == JobName.class) {
963 return new JobName("Java Printing", null);
964 } else if (category == OrientationRequested.class) {
965 if (defOrient == DMORIENT_LANDSCAPE) {
966 return OrientationRequested.LANDSCAPE;
967 } else {
968 return OrientationRequested.PORTRAIT;
969 }
970 } else if (category == PageRanges.class) {
971 return new PageRanges(1, Integer.MAX_VALUE);
972 } else if (category == Media.class) {
973 MediaSizeName msn = findWin32Media(defPaper);
974 if (msn != null) {
975 if (!isSupportedMedia(msn) && mediaSizeNames != null) {
976 msn = mediaSizeNames[0];
977 defPaper = findPaperID(msn);
978 }
979 return msn;
980 } else {
981 initMedia();
982 if ((mediaSizeNames != null) && (mediaSizeNames.length > 0)) {
983 // if 'mediaSizeNames' is not null, idList and mediaSizes
984 // cannot be null but to be safe, add a check
985 if ((idList != null) && (mediaSizes != null) &&
986 (idList.size() == mediaSizes.length)) {
987 Integer defIdObj = new Integer(defPaper);
988 int index = idList.indexOf(defIdObj);
989 if (index>=0 && index<mediaSizes.length) {
990 return mediaSizes[index].getMediaSizeName();
991 }
992 }
993
994 return mediaSizeNames[0];
995 }
996 }
997 } else if (category == MediaPrintableArea.class) {
998 /* Verify defPaper */
999 MediaSizeName msn = findWin32Media(defPaper);
1000 if (msn != null &&
1001 !isSupportedMedia(msn) && mediaSizeNames != null) {
1002 defPaper = findPaperID(mediaSizeNames[0]);
1003 }
1004 float[] prnArea = getMediaPrintableArea(printer, defPaper);
1005 if (prnArea != null) {
1006 MediaPrintableArea printableArea = null;
1007 try {
1008 printableArea = new MediaPrintableArea(prnArea[0],
1009 prnArea[1],
1010 prnArea[2],
1011 prnArea[3],
1012 MediaPrintableArea.INCH);
1013 } catch (IllegalArgumentException e) {
1014 }
1015 return printableArea;
1016 }
1017 return null;
1018 } else if (category == SunAlternateMedia.class) {
1019 return null;
1020 } else if (category == Destination.class) {
1021 try {
1022 return new Destination((new File("out.prn")).toURI());
1023 } catch (SecurityException se) {
1024 try {
1025 return new Destination(new URI("file:out.prn"));
1026 } catch (URISyntaxException e) {
1027 return null;
1028 }
1029 }
1030 } else if (category == Sides.class) {
1031 switch(defSides) {
1032 case DMDUP_VERTICAL :
1033 return Sides.TWO_SIDED_LONG_EDGE;
1034 case DMDUP_HORIZONTAL :
1035 return Sides.TWO_SIDED_SHORT_EDGE;
1036 default :
1037 return Sides.ONE_SIDED;
1038 }
1039 } else if (category == PrinterResolution.class) {
1040 int yRes = defYRes;
1041 int xRes = defQuality;
1042 if ((xRes < 0) || (yRes < 0)) {
1043 int res = (yRes > xRes) ? yRes : xRes;
1044 if (res > 0) {
1045 return new PrinterResolution(res, res, PrinterResolution.DPI);
1046 }
1047 }
1048 else {
1049 return new PrinterResolution(xRes, yRes, PrinterResolution.DPI);
1050 }
1051 } else if (category == ColorSupported.class) {
1052 int caps = getPrinterCapabilities();
1053 if ((caps & DEVCAP_COLOR) != 0) {
1054 return ColorSupported.SUPPORTED;
1055 } else {
1056 return ColorSupported.NOT_SUPPORTED;
1057 }
1058 } else if (category == PrintQuality.class) {
1059 if ((defQuality < 0) && (defQuality >= DMRES_HIGH)) {
1060 switch (defQuality) {
1061 case DMRES_HIGH:
1062 return PrintQuality.HIGH;
1063 case DMRES_MEDIUM:
1064 return PrintQuality.NORMAL;
1065 default:
1066 return PrintQuality.DRAFT;
1067 }
1068 }
1069 } else if (category == RequestingUserName.class) {
1070 String userName = "";
1071 try {
1072 userName = System.getProperty("user.name", "");
1073 } catch (SecurityException se) {
1074 }
1075 return new RequestingUserName(userName, null);
1076 } else if (category == SheetCollate.class) {
1077 if (defCollate == DMCOLLATE_TRUE) {
1078 return SheetCollate.COLLATED;
1079 } else {
1080 return SheetCollate.UNCOLLATED;
1081 }
1082 } else if (category == Fidelity.class) {
1083 return Fidelity.FIDELITY_FALSE;
1084 }
1085 return null;
1086 }
1087
1088 private boolean isPostScriptFlavor(DocFlavor flavor) {
1089 if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) ||
1090 flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||
1091 flavor.equals(DocFlavor.URL.POSTSCRIPT)) {
1092 return true;
1093 }
1094 else {
1095 return false;
1096 }
1097 }
1098
1099 private boolean isPSDocAttr(Class category) {
1100 if (category == OrientationRequested.class || category == Copies.class) {
1101 return true;
1102 }
1103 else {
1104 return false;
1105 }
1106 }
1107
1108 private boolean isAutoSense(DocFlavor flavor) {
1109 if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) ||
1110 flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) ||
1111 flavor.equals(DocFlavor.URL.AUTOSENSE)) {
1112 return true;
1113 }
1114 else {
1115 return false;
1116 }
1117 }
1118
1119 public Object
1120 getSupportedAttributeValues(Class<? extends Attribute> category,
1121 DocFlavor flavor,
1122 AttributeSet attributes)
1123 {
1124 if (category == null) {
1125 throw new NullPointerException("null category");
1126 }
1127 if (!Attribute.class.isAssignableFrom(category)) {
1128 throw new IllegalArgumentException(category +
1129 " does not implement Attribute");
1130 }
1131 if (flavor != null) {
1132 if (!isDocFlavorSupported(flavor)) {
1133 throw new IllegalArgumentException(flavor +
1134 " is an unsupported flavor");
1135 // if postscript & category is already specified within the
1136 // PostScript data we return null
1137 } else if (isAutoSense(flavor) ||(isPostScriptFlavor(flavor) &&
1138 (isPSDocAttr(category)))){
1139 return null;
1140 }
1141 }
1142 if (!isAttributeCategorySupported(category)) {
1143 return null;
1144 }
1145
1146 if (category == JobName.class) {
1147 return new JobName("Java Printing", null);
1148 } else if (category == RequestingUserName.class) {
1149 String userName = "";
1150 try {
1151 userName = System.getProperty("user.name", "");
1152 } catch (SecurityException se) {
1153 }
1154 return new RequestingUserName(userName, null);
1155 } else if (category == ColorSupported.class) {
1156 int caps = getPrinterCapabilities();
1157 if ((caps & DEVCAP_COLOR) != 0) {
1158 return ColorSupported.SUPPORTED;
1159 } else {
1160 return ColorSupported.NOT_SUPPORTED;
1161 }
1162 } else if (category == Chromaticity.class) {
1163 if (flavor == null ||
1164 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1165 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1166 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
1167 flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
1168 flavor.equals(DocFlavor.URL.GIF) ||
1169 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
1170 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
1171 flavor.equals(DocFlavor.URL.JPEG) ||
1172 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
1173 flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
1174 flavor.equals(DocFlavor.URL.PNG)) {
1175 int caps = getPrinterCapabilities();
1176 if ((caps & DEVCAP_COLOR) == 0) {
1177 Chromaticity []arr = new Chromaticity[1];
1178 arr[0] = Chromaticity.MONOCHROME;
1179 return (arr);
1180 } else {
1181 Chromaticity []arr = new Chromaticity[2];
1182 arr[0] = Chromaticity.MONOCHROME;
1183 arr[1] = Chromaticity.COLOR;
1184 return (arr);
1185 }
1186 } else {
1187 return null;
1188 }
1189 } else if (category == Destination.class) {
1190 try {
1191 return new Destination((new File("out.prn")).toURI());
1192 } catch (SecurityException se) {
1193 try {
1194 return new Destination(new URI("file:out.prn"));
1195 } catch (URISyntaxException e) {
1196 return null;
1197 }
1198 }
1199 } else if (category == OrientationRequested.class) {
1200 if (flavor == null ||
1201 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1202 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1203 flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
1204 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
1205 flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
1206 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
1207 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
1208 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
1209 flavor.equals(DocFlavor.URL.GIF) ||
1210 flavor.equals(DocFlavor.URL.JPEG) ||
1211 flavor.equals(DocFlavor.URL.PNG)) {
1212 OrientationRequested []arr = new OrientationRequested[3];
1213 arr[0] = OrientationRequested.PORTRAIT;
1214 arr[1] = OrientationRequested.LANDSCAPE;
1215 arr[2] = OrientationRequested.REVERSE_LANDSCAPE;
1216 return arr;
1217 } else {
1218 return null;
1219 }
1220 } else if ((category == Copies.class) ||
1221 (category == CopiesSupported.class)) {
1222 synchronized (this) {
1223 if (gotCopies == false) {
1224 nCopies = getCopiesSupported(printer, getPort());
1225 gotCopies = true;
1226 }
1227 }
1228 return new CopiesSupported(1, nCopies);
1229 } else if (category == Media.class) {
1230
1231 initMedia();
1232
1233 int len = (mediaSizeNames == null) ? 0 : mediaSizeNames.length;
1234
1235 MediaTray[] trays = getMediaTrays();
1236
1237 len += (trays == null) ? 0 : trays.length;
1238
1239 Media []arr = new Media[len];
1240 if (mediaSizeNames != null) {
1241 System.arraycopy(mediaSizeNames, 0, arr,
1242 0, mediaSizeNames.length);
1243 }
1244 if (trays != null) {
1245 System.arraycopy(trays, 0, arr,
1246 mediaSizeNames.length, trays.length);
1247 }
1248 return arr;
1249 } else if (category == MediaPrintableArea.class) {
1250 initMedia();
1251
1252 if (mediaPrintables == null) {
1253 return null;
1254 }
1255
1256 // if getting printable area for a specific media size
1257 Media mediaName;
1258 if ((attributes != null) &&
1259 ((mediaName =
1260 (Media)attributes.get(Media.class)) != null)) {
1261
1262 if (mediaName instanceof MediaSizeName) {
1263 MediaPrintableArea []arr = new MediaPrintableArea[1];
1264
1265 if (mediaSizeNames.length == mediaPrintables.length) {
1266
1267 for (int j=0; j < mediaSizeNames.length; j++) {
1268
1269 if (mediaName.equals(mediaSizeNames[j])) {
1270 arr[0] = mediaPrintables[j];
1271 return arr;
1272 }
1273 }
1274 }
1275
1276 MediaSize ms =
1277 MediaSize.getMediaSizeForName((MediaSizeName)mediaName);
1278
1279 if (ms != null) {
1280 arr[0] = new MediaPrintableArea(0, 0,
1281 ms.getX(MediaSize.INCH),
1282 ms.getY(MediaSize.INCH),
1283 MediaPrintableArea.INCH);
1284 return arr;
1285 } else {
1286 return null;
1287 }
1288 }
1289 // else an instance of MediaTray, fall thru returning
1290 // all MediaPrintableAreas
1291 }
1292
1293 MediaPrintableArea []arr =
1294 new MediaPrintableArea[mediaPrintables.length];
1295 System.arraycopy(mediaPrintables, 0, arr, 0, mediaPrintables.length);
1296 return arr;
1297 } else if (category == SunAlternateMedia.class) {
1298 return new SunAlternateMedia(
1299 (Media)getDefaultAttributeValue(Media.class));
1300 } else if (category == PageRanges.class) {
1301 if (flavor == null ||
1302 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1303 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
1304 PageRanges []arr = new PageRanges[1];
1305 arr[0] = new PageRanges(1, Integer.MAX_VALUE);
1306 return arr;
1307 } else {
1308 return null;
1309 }
1310 } else if (category == PrinterResolution.class) {
1311 PrinterResolution[] supportedRes = getPrintResolutions();
1312 if (supportedRes == null) {
1313 return null;
1314 }
1315 PrinterResolution []arr =
1316 new PrinterResolution[supportedRes.length];
1317 System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length);
1318 return arr;
1319 } else if (category == Sides.class) {
1320 if (flavor == null ||
1321 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1322 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
1323 Sides []arr = new Sides[3];
1324 arr[0] = Sides.ONE_SIDED;
1325 arr[1] = Sides.TWO_SIDED_LONG_EDGE;
1326 arr[2] = Sides.TWO_SIDED_SHORT_EDGE;
1327 return arr;
1328 } else {
1329 return null;
1330 }
1331 } else if (category == PrintQuality.class) {
1332 PrintQuality []arr = new PrintQuality[3];
1333 arr[0] = PrintQuality.DRAFT;
1334 arr[1] = PrintQuality.HIGH;
1335 arr[2] = PrintQuality.NORMAL;
1336 return arr;
1337 } else if (category == SheetCollate.class) {
1338 if (flavor == null ||
1339 (flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1340 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1341 SheetCollate []arr = new SheetCollate[2];
1342 arr[0] = SheetCollate.COLLATED;
1343 arr[1] = SheetCollate.UNCOLLATED;
1344 return arr;
1345 } else {
1346 return null;
1347 }
1348 } else if (category == Fidelity.class) {
1349 Fidelity []arr = new Fidelity[2];
1350 arr[0] = Fidelity.FIDELITY_FALSE;
1351 arr[1] = Fidelity.FIDELITY_TRUE;
1352 return arr;
1353 } else {
1354 return null;
1355 }
1356 }
1357
1358 public boolean isAttributeValueSupported(Attribute attr,
1359 DocFlavor flavor,
1360 AttributeSet attributes) {
1361
1362 if (attr == null) {
1363 throw new NullPointerException("null attribute");
1364 }
1365 Class category = attr.getCategory();
1366 if (flavor != null) {
1367 if (!isDocFlavorSupported(flavor)) {
1368 throw new IllegalArgumentException(flavor +
1369 " is an unsupported flavor");
1370 // if postscript & category is already specified within the PostScript data
1371 // we return false
1372 } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) &&
1373 (isPSDocAttr(category)))) {
1374 return false;
1375 }
1376 }
1377
1378 if (!isAttributeCategorySupported(category)) {
1379 return false;
1380 }
1381 else if (category == Chromaticity.class) {
1382 if ((flavor == null) ||
1383 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1384 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1385 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
1386 flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
1387 flavor.equals(DocFlavor.URL.GIF) ||
1388 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
1389 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
1390 flavor.equals(DocFlavor.URL.JPEG) ||
1391 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
1392 flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
1393 flavor.equals(DocFlavor.URL.PNG)) {
1394 int caps = getPrinterCapabilities();
1395 if ((caps & DEVCAP_COLOR) != 0) {
1396 return true;
1397 } else {
1398 return attr == Chromaticity.MONOCHROME;
1399 }
1400 } else {
1401 return false;
1402 }
1403 } else if (category == Copies.class) {
1404 return isSupportedCopies((Copies)attr);
1405
1406 } else if (category == Destination.class) {
1407 URI uri = ((Destination)attr).getURI();
1408 if ("file".equals(uri.getScheme()) &&
1409 !(uri.getSchemeSpecificPart().equals(""))) {
1410 return true;
1411 } else {
1412 return false;
1413 }
1414
1415 } else if (category == Media.class) {
1416 if (attr instanceof MediaSizeName) {
1417 return isSupportedMedia((MediaSizeName)attr);
1418 }
1419 if (attr instanceof MediaTray) {
1420 return isSupportedMediaTray((MediaTray)attr);
1421 }
1422
1423 } else if (category == MediaPrintableArea.class) {
1424 return isSupportedMediaPrintableArea((MediaPrintableArea)attr);
1425
1426 } else if (category == SunAlternateMedia.class) {
1427 Media media = ((SunAlternateMedia)attr).getMedia();
1428 return isAttributeValueSupported(media, flavor, attributes);
1429
1430 } else if (category == PageRanges.class ||
1431 category == SheetCollate.class ||
1432 category == Sides.class) {
1433 if (flavor != null &&
1434 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1435 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
1436 return false;
1437 }
1438 } else if (category == PrinterResolution.class) {
1439 if (attr instanceof PrinterResolution) {
1440 return isSupportedResolution((PrinterResolution)attr);
1441 }
1442 } else if (category == OrientationRequested.class) {
1443 if (attr == OrientationRequested.REVERSE_PORTRAIT ||
1444 (flavor != null) &&
1445 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||
1446 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||
1447 flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||
1448 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||
1449 flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||
1450 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||
1451 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||
1452 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||
1453 flavor.equals(DocFlavor.URL.GIF) ||
1454 flavor.equals(DocFlavor.URL.JPEG) ||
1455 flavor.equals(DocFlavor.URL.PNG))) {
1456 return false;
1457 }
1458
1459 } else if (category == ColorSupported.class) {
1460 int caps = getPrinterCapabilities();
1461 boolean isColorSup = ((caps & DEVCAP_COLOR) != 0);
1462 if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) ||
1463 (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) {
1464 return false;
1465 }
1466 }
1467 return true;
1468 }
1469
1470 public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
1471 AttributeSet attributes) {
1472
1473 if (flavor != null && !isDocFlavorSupported(flavor)) {
1474 throw new IllegalArgumentException("flavor " + flavor +
1475 "is not supported");
1476 }
1477
1478 if (attributes == null) {
1479 return null;
1480 }
1481
1482 Attribute attr;
1483 AttributeSet unsupp = new HashAttributeSet();
1484 Attribute []attrs = attributes.toArray();
1485 for (int i=0; i<attrs.length; i++) {
1486 try {
1487 attr = attrs[i];
1488 if (!isAttributeCategorySupported(attr.getCategory())) {
1489 unsupp.add(attr);
1490 }
1491 else if (!isAttributeValueSupported(attr, flavor, attributes)) {
1492 unsupp.add(attr);
1493 }
1494 } catch (ClassCastException e) {
1495 }
1496 }
1497 if (unsupp.isEmpty()) {
1498 return null;
1499 } else {
1500 return unsupp;
1501 }
1502 }
1503
1504 public ServiceUIFactory getServiceUIFactory() {
1505 return null;
1506 }
1507
1508 public String toString() {
1509 return "Win32 Printer : " + getName();
1510 }
1511
1512 public boolean equals(Object obj) {
1513 return (obj == this ||
1514 (obj instanceof Win32PrintService &&
1515 ((Win32PrintService)obj).getName().equals(getName())));
1516 }
1517
1518 public int hashCode() {
1519 return this.getClass().hashCode()+getName().hashCode();
1520 }
1521
1522 public boolean usesClass(Class c) {
1523 return (c == sun.awt.windows.WPrinterJob.class);
1524 }
1525
1526 private native int[] getAllMediaIDs(String printerName, String port);
1527 private native int[] getAllMediaSizes(String printerName, String port);
1528 private native int[] getAllMediaTrays(String printerName, String port);
1529 private native float[] getMediaPrintableArea(String printerName,
1530 int paperSize);
1531 private native String[] getAllMediaNames(String printerName, String port);
1532 private native String[] getAllMediaTrayNames(String printerName, String port);
1533 private native int getCopiesSupported(String printerName, String port);
1534 private native int[] getAllResolutions(String printerName, String port);
1535 private native int getCapabilities(String printerName, String port);
1536
1537 private native int[] getDefaultSettings(String printerName, String port);
1538 private native int getJobStatus(String printerName, int type);
1539 private native String getPrinterPort(String printerName);
1540}
1541
1542
1543class Win32MediaSize extends MediaSizeName {
1544 private static ArrayList winStringTable = new ArrayList();
1545 private static ArrayList winEnumTable = new ArrayList();
1546
1547 private int dmPaperID; // driver ID for this paper.
1548
1549 private Win32MediaSize(int x) {
1550 super(x);
1551
1552 }
1553
1554 private synchronized static int nextValue(String name) {
1555 winStringTable.add(name);
1556 return (winStringTable.size()-1);
1557 }
1558
1559 public Win32MediaSize(String name, int dmPaper) {
1560 super(nextValue(name));
1561 dmPaperID = dmPaper;
1562 winEnumTable.add(this);
1563 }
1564
1565 private MediaSizeName[] getSuperEnumTable() {
1566 return (MediaSizeName[])super.getEnumValueTable();
1567 }
1568
1569 static {
1570 /* initialize Win32PrintService.predefMedia */
1571 {
1572 Win32MediaSize winMedia = new Win32MediaSize(-1);
1573
1574 // cannot call getSuperEnumTable directly because of static context
1575 MediaSizeName[] enumMedia = winMedia.getSuperEnumTable();
1576 if (enumMedia != null) {
1577 Win32PrintService.predefMedia = new MediaSize[enumMedia.length];
1578
1579 for (int i=0; i<enumMedia.length; i++) {
1580 Win32PrintService.predefMedia[i] =
1581 MediaSize.getMediaSizeForName(enumMedia[i]);
1582 }
1583 }
1584 }
1585 }
1586
1587 int getDMPaper() {
1588 return dmPaperID;
1589 }
1590
1591 protected String[] getStringTable() {
1592 String[] nameTable = new String[winStringTable.size()];
1593 return (String[])winStringTable.toArray(nameTable);
1594 }
1595
1596 protected EnumSyntax[] getEnumValueTable() {
1597 MediaSizeName[] enumTable = new MediaSizeName[winEnumTable.size()];
1598 return (MediaSizeName[])winEnumTable.toArray(enumTable);
1599 }
1600
1601}