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