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