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 int units = MediaPrintableArea.INCH; 763 764 if (mediaPrintables != null) { 765 for (int i=0; i<mediaPrintables.length; i++) { 766 if ((mpa.getX(units) > mediaPrintables[i].getX(units)) && 767 (mpa.getY(units) > mediaPrintables[i].getY(units)) && 768 (mpa.getX(units) + mpa.getWidth(units) < 769 mediaPrintables[i].getX(units) + 770 mediaPrintables[i].getWidth(units)) && 771 (mpa.getY(units) + mpa.getHeight(units) < 772 mediaPrintables[i].getY(units) + 773 mediaPrintables[i].getHeight(units))) { 774 return true; 775 } 776 } 777 } 778 return false; 779 } 780 781 private boolean isSupportedMediaTray(MediaTray msn) { 782 MediaTray[] trays = getMediaTrays(); 783 784 if (trays != null) { 785 for (int i=0; i<trays.length; i++) { 786 if (msn.equals(trays[i])) { 787 return true; 788 } 789 } 790 } 791 return false; 792 } 793 794 private int getPrinterCapabilities() { 795 if (prnCaps == 0) { 796 prnCaps = getCapabilities(printer, getPort()); 797 } 798 return prnCaps; 799 } 800 801 private String getPort() { 802 if (port == null) { 803 port = getPrinterPort(printer); 804 } 805 return port; 806 } 807 808 /* 809 * NOTE: defaults indices must match those in WPrinterJob.cpp 810 */ 811 private int[] getDefaultPrinterSettings() { 812 if (defaultSettings == null) { 813 defaultSettings = getDefaultSettings(printer, getPort()); 814 } 815 return defaultSettings; 816 } 817 818 private PrinterResolution[] getPrintResolutions() { 819 if (printRes == null) { 820 int[] prnRes = getAllResolutions(printer, getPort()); 821 if (prnRes == null) { 822 printRes = new PrinterResolution[0]; 823 } else { 824 int nRes = prnRes.length/2; 825 826 ArrayList<PrinterResolution> arrList = new ArrayList<>(); 827 PrinterResolution pr; 828 829 for (int i=0; i<nRes; i++) { 830 try { 831 pr = new PrinterResolution(prnRes[i*2], 832 prnRes[i*2+1], PrinterResolution.DPI); 833 arrList.add(pr); 834 } catch (IllegalArgumentException e) { 835 } 836 } 837 838 printRes = arrList.toArray(new PrinterResolution[arrList.size()]); 839 } 840 } 841 return printRes; 842 } 843 844 private boolean isSupportedResolution(PrinterResolution res) { 845 PrinterResolution[] supportedRes = getPrintResolutions(); 846 if (supportedRes != null) { 847 for (int i=0; i<supportedRes.length; i++) { 848 if (res.equals(supportedRes[i])) { 849 return true; 850 } 851 } 852 } 853 return false; 854 } 855 856 public DocPrintJob createPrintJob() { 857 SecurityManager security = System.getSecurityManager(); 858 if (security != null) { 859 security.checkPrintJobAccess(); 860 } 861 return new Win32PrintJob(this); 862 } 863 864 private PrintServiceAttributeSet getDynamicAttributes() { 865 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); 866 attrs.add(getPrinterIsAcceptingJobs()); 867 attrs.add(getQueuedJobCount()); 868 return attrs; 869 } 870 871 public PrintServiceAttributeSet getUpdatedAttributes() { 872 PrintServiceAttributeSet currSet = getDynamicAttributes(); 873 if (lastSet == null) { 874 lastSet = currSet; 875 return AttributeSetUtilities.unmodifiableView(currSet); 876 } else { 877 PrintServiceAttributeSet updates = 878 new HashPrintServiceAttributeSet(); 879 Attribute []attrs = currSet.toArray(); 880 for (int i=0; i<attrs.length; i++) { 881 Attribute attr = attrs[i]; 882 if (!lastSet.containsValue(attr)) { 883 updates.add(attr); 884 } 885 } 886 lastSet = currSet; 887 return AttributeSetUtilities.unmodifiableView(updates); 888 } 889 } 890 891 public void wakeNotifier() { 892 synchronized (this) { 893 if (notifier != null) { 894 notifier.wake(); 895 } 896 } 897 } 898 899 public void addPrintServiceAttributeListener(PrintServiceAttributeListener 900 listener) { 901 synchronized (this) { 902 if (listener == null) { 903 return; 904 } 905 if (notifier == null) { 906 notifier = new ServiceNotifier(this); 907 } 908 notifier.addListener(listener); 909 } 910 } 911 912 public void removePrintServiceAttributeListener( 913 PrintServiceAttributeListener listener) { 914 synchronized (this) { 915 if (listener == null || notifier == null ) { 916 return; 917 } 918 notifier.removeListener(listener); 919 if (notifier.isEmpty()) { 920 notifier.stopNotifier(); 921 notifier = null; 922 } 923 } 924 } 925 926 @SuppressWarnings("unchecked") 927 public <T extends PrintServiceAttribute> T 928 getAttribute(Class<T> category) 929 { 930 if (category == null) { 931 throw new NullPointerException("category"); 932 } 933 if (!(PrintServiceAttribute.class.isAssignableFrom(category))) { 934 throw new IllegalArgumentException("Not a PrintServiceAttribute"); 935 } 936 if (category == ColorSupported.class) { 937 int caps = getPrinterCapabilities(); 938 if ((caps & DEVCAP_COLOR) != 0) { 939 return (T)ColorSupported.SUPPORTED; 940 } else { 941 return (T)ColorSupported.NOT_SUPPORTED; 942 } 943 } else if (category == PrinterName.class) { 944 return (T)getPrinterName(); 945 } else if (category == PrinterState.class) { 946 return (T)getPrinterState(); 947 } else if (category == PrinterStateReasons.class) { 948 return (T)getPrinterStateReasons(); 949 } else if (category == QueuedJobCount.class) { 950 return (T)getQueuedJobCount(); 951 } else if (category == PrinterIsAcceptingJobs.class) { 952 return (T)getPrinterIsAcceptingJobs(); 953 } else { 954 return null; 955 } 956 } 957 958 public PrintServiceAttributeSet getAttributes() { 959 960 PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); 961 attrs.add(getPrinterName()); 962 attrs.add(getPrinterIsAcceptingJobs()); 963 PrinterState prnState = getPrinterState(); 964 if (prnState != null) { 965 attrs.add(prnState); 966 } 967 PrinterStateReasons prnStateReasons = getPrinterStateReasons(); 968 if (prnStateReasons != null) { 969 attrs.add(prnStateReasons); 970 } 971 attrs.add(getQueuedJobCount()); 972 int caps = getPrinterCapabilities(); 973 if ((caps & DEVCAP_COLOR) != 0) { 974 attrs.add(ColorSupported.SUPPORTED); 975 } else { 976 attrs.add(ColorSupported.NOT_SUPPORTED); 977 } 978 979 return AttributeSetUtilities.unmodifiableView(attrs); 980 } 981 982 public DocFlavor[] getSupportedDocFlavors() { 983 int len = supportedFlavors.length; 984 DocFlavor[] supportedDocFlavors; 985 int caps = getPrinterCapabilities(); 986 // doc flavors supported 987 // if PostScript is supported 988 if ((caps & DEVCAP_POSTSCRIPT) != 0) { 989 supportedDocFlavors = new DocFlavor[len+3]; 990 System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len); 991 supportedDocFlavors[len] = DocFlavor.BYTE_ARRAY.POSTSCRIPT; 992 supportedDocFlavors[len+1] = DocFlavor.INPUT_STREAM.POSTSCRIPT; 993 supportedDocFlavors[len+2] = DocFlavor.URL.POSTSCRIPT; 994 } else { 995 supportedDocFlavors = new DocFlavor[len]; 996 System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len); 997 } 998 return supportedDocFlavors; 999 } 1000 1001 public boolean isDocFlavorSupported(DocFlavor flavor) { 1002 /* To avoid a native query which may be time-consuming 1003 * do not invoke native unless postscript support is being queried. 1004 * Instead just check the ones we 'always' support 1005 */ 1006 DocFlavor[] supportedDocFlavors; 1007 if (isPostScriptFlavor(flavor)) { 1008 supportedDocFlavors = getSupportedDocFlavors(); 1009 } else { 1010 supportedDocFlavors = supportedFlavors; 1011 } 1012 for (int f=0; f<supportedDocFlavors.length; f++) { 1013 if (flavor.equals(supportedDocFlavors[f])) { 1014 return true; 1015 } 1016 } 1017 return false; 1018 } 1019 1020 public Class<?>[] getSupportedAttributeCategories() { 1021 ArrayList<Class<?>> categList = new ArrayList<>(otherAttrCats.length+3); 1022 for (int i=0; i < otherAttrCats.length; i++) { 1023 categList.add(otherAttrCats[i]); 1024 } 1025 1026 int caps = getPrinterCapabilities(); 1027 1028 if ((caps & DEVCAP_DUPLEX) != 0) { 1029 categList.add(Sides.class); 1030 } 1031 1032 if ((caps & DEVCAP_QUALITY) != 0) { 1033 int[] defaults = getDefaultPrinterSettings(); 1034 // Added check: if supported, we should be able to get the default. 1035 if ((defaults[3] >= DMRES_HIGH) && (defaults[3] < 0)) { 1036 categList.add(PrintQuality.class); 1037 } 1038 } 1039 1040 PrinterResolution[] supportedRes = getPrintResolutions(); 1041 if ((supportedRes!=null) && (supportedRes.length>0)) { 1042 categList.add(PrinterResolution.class); 1043 } 1044 1045 return categList.toArray(new Class<?>[categList.size()]); 1046 } 1047 1048 public boolean 1049 isAttributeCategorySupported(Class<? extends Attribute> category) 1050 { 1051 1052 if (category == null) { 1053 throw new NullPointerException("null category"); 1054 } 1055 1056 if (!(Attribute.class.isAssignableFrom(category))) { 1057 throw new IllegalArgumentException(category + 1058 " is not an Attribute"); 1059 } 1060 1061 Class<?>[] classList = getSupportedAttributeCategories(); 1062 for (int i = 0; i < classList.length; i++) { 1063 if (category.equals(classList[i])) { 1064 return true; 1065 } 1066 } 1067 1068 return false; 1069 } 1070 1071 public Object 1072 getDefaultAttributeValue(Class<? extends Attribute> category) 1073 { 1074 if (category == null) { 1075 throw new NullPointerException("null category"); 1076 } 1077 if (!Attribute.class.isAssignableFrom(category)) { 1078 throw new IllegalArgumentException(category + 1079 " is not an Attribute"); 1080 } 1081 1082 if (!isAttributeCategorySupported(category)) { 1083 return null; 1084 } 1085 1086 int[] defaults = getDefaultPrinterSettings(); 1087 // indices must match those in WPrinterJob.cpp 1088 int defPaper = defaults[0]; 1089 int defYRes = defaults[2]; 1090 int defQuality = defaults[3]; 1091 int defCopies = defaults[4]; 1092 int defOrient = defaults[5]; 1093 int defSides = defaults[6]; 1094 int defCollate = defaults[7]; 1095 int defColor = defaults[8]; 1096 1097 if (category == Copies.class) { 1098 if (defCopies > 0) { 1099 return new Copies(defCopies); 1100 } else { 1101 return new Copies(1); 1102 } 1103 } else if (category == Chromaticity.class) { 1104 if (defColor == DMCOLOR_COLOR) { 1105 return Chromaticity.COLOR; 1106 } else { 1107 return Chromaticity.MONOCHROME; 1108 } 1109 } else if (category == JobName.class) { 1110 return new JobName("Java Printing", null); 1111 } else if (category == OrientationRequested.class) { 1112 if (defOrient == DMORIENT_LANDSCAPE) { 1113 return OrientationRequested.LANDSCAPE; 1114 } else { 1115 return OrientationRequested.PORTRAIT; 1116 } 1117 } else if (category == PageRanges.class) { 1118 return new PageRanges(1, Integer.MAX_VALUE); 1119 } else if (category == Media.class) { 1120 MediaSizeName msn = findWin32Media(defPaper); 1121 if (msn != null) { 1122 if (!isSupportedMedia(msn) && mediaSizeNames != null) { 1123 msn = mediaSizeNames[0]; 1124 defPaper = findPaperID(msn); 1125 } 1126 return msn; 1127 } else { 1128 initMedia(); 1129 if ((mediaSizeNames != null) && (mediaSizeNames.length > 0)) { 1130 // if 'mediaSizeNames' is not null, idList and mediaSizes 1131 // cannot be null but to be safe, add a check 1132 if ((idList != null) && (mediaSizes != null) && 1133 (idList.size() == mediaSizes.length)) { 1134 Integer defIdObj = Integer.valueOf(defPaper); 1135 int index = idList.indexOf(defIdObj); 1136 if (index>=0 && index<mediaSizes.length) { 1137 return mediaSizes[index].getMediaSizeName(); 1138 } 1139 } 1140 1141 return mediaSizeNames[0]; 1142 } 1143 } 1144 } else if (category == MediaPrintableArea.class) { 1145 /* Verify defPaper */ 1146 MediaSizeName msn = findWin32Media(defPaper); 1147 if (msn != null && 1148 !isSupportedMedia(msn) && mediaSizeNames != null) { 1149 defPaper = findPaperID(mediaSizeNames[0]); 1150 } 1151 float[] prnArea = getMediaPrintableArea(printer, defPaper); 1152 if (prnArea != null) { 1153 MediaPrintableArea printableArea = null; 1154 try { 1155 printableArea = new MediaPrintableArea(prnArea[0], 1156 prnArea[1], 1157 prnArea[2], 1158 prnArea[3], 1159 MediaPrintableArea.INCH); 1160 } catch (IllegalArgumentException e) { 1161 } 1162 return printableArea; 1163 } 1164 return null; 1165 } else if (category == SunAlternateMedia.class) { 1166 return null; 1167 } else if (category == Destination.class) { 1168 try { 1169 return new Destination((new File("out.prn")).toURI()); 1170 } catch (SecurityException se) { 1171 try { 1172 return new Destination(new URI("file:out.prn")); 1173 } catch (URISyntaxException e) { 1174 return null; 1175 } 1176 } 1177 } else if (category == Sides.class) { 1178 switch(defSides) { 1179 case DMDUP_VERTICAL : 1180 return Sides.TWO_SIDED_LONG_EDGE; 1181 case DMDUP_HORIZONTAL : 1182 return Sides.TWO_SIDED_SHORT_EDGE; 1183 default : 1184 return Sides.ONE_SIDED; 1185 } 1186 } else if (category == PrinterResolution.class) { 1187 int yRes = defYRes; 1188 int xRes = defQuality; 1189 if ((xRes < 0) || (yRes < 0)) { 1190 int res = (yRes > xRes) ? yRes : xRes; 1191 if (res > 0) { 1192 return new PrinterResolution(res, res, PrinterResolution.DPI); 1193 } 1194 } 1195 else { 1196 return new PrinterResolution(xRes, yRes, PrinterResolution.DPI); 1197 } 1198 } else if (category == ColorSupported.class) { 1199 int caps = getPrinterCapabilities(); 1200 if ((caps & DEVCAP_COLOR) != 0) { 1201 return ColorSupported.SUPPORTED; 1202 } else { 1203 return ColorSupported.NOT_SUPPORTED; 1204 } 1205 } else if (category == PrintQuality.class) { 1206 if ((defQuality < 0) && (defQuality >= DMRES_HIGH)) { 1207 switch (defQuality) { 1208 case DMRES_HIGH: 1209 return PrintQuality.HIGH; 1210 case DMRES_MEDIUM: 1211 return PrintQuality.NORMAL; 1212 default: 1213 return PrintQuality.DRAFT; 1214 } 1215 } 1216 } else if (category == RequestingUserName.class) { 1217 String userName = ""; 1218 try { 1219 userName = System.getProperty("user.name", ""); 1220 } catch (SecurityException se) { 1221 } 1222 return new RequestingUserName(userName, null); 1223 } else if (category == SheetCollate.class) { 1224 if (defCollate == DMCOLLATE_TRUE) { 1225 return SheetCollate.COLLATED; 1226 } else { 1227 return SheetCollate.UNCOLLATED; 1228 } 1229 } else if (category == Fidelity.class) { 1230 return Fidelity.FIDELITY_FALSE; 1231 } 1232 return null; 1233 } 1234 1235 private boolean isPostScriptFlavor(DocFlavor flavor) { 1236 if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) || 1237 flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || 1238 flavor.equals(DocFlavor.URL.POSTSCRIPT)) { 1239 return true; 1240 } 1241 else { 1242 return false; 1243 } 1244 } 1245 1246 private boolean isPSDocAttr(Class<?> category) { 1247 if (category == OrientationRequested.class || category == Copies.class) { 1248 return true; 1249 } 1250 else { 1251 return false; 1252 } 1253 } 1254 1255 private boolean isAutoSense(DocFlavor flavor) { 1256 if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) || 1257 flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) || 1258 flavor.equals(DocFlavor.URL.AUTOSENSE)) { 1259 return true; 1260 } 1261 else { 1262 return false; 1263 } 1264 } 1265 1266 public Object 1267 getSupportedAttributeValues(Class<? extends Attribute> category, 1268 DocFlavor flavor, 1269 AttributeSet attributes) 1270 { 1271 if (category == null) { 1272 throw new NullPointerException("null category"); 1273 } 1274 if (!Attribute.class.isAssignableFrom(category)) { 1275 throw new IllegalArgumentException(category + 1276 " does not implement Attribute"); 1277 } 1278 if (flavor != null) { 1279 if (!isDocFlavorSupported(flavor)) { 1280 throw new IllegalArgumentException(flavor + 1281 " is an unsupported flavor"); 1282 // if postscript & category is already specified within the 1283 // PostScript data we return null 1284 } else if (isAutoSense(flavor) ||(isPostScriptFlavor(flavor) && 1285 (isPSDocAttr(category)))){ 1286 return null; 1287 } 1288 } 1289 if (!isAttributeCategorySupported(category)) { 1290 return null; 1291 } 1292 1293 if (category == JobName.class) { 1294 return new JobName("Java Printing", null); 1295 } else if (category == RequestingUserName.class) { 1296 String userName = ""; 1297 try { 1298 userName = System.getProperty("user.name", ""); 1299 } catch (SecurityException se) { 1300 } 1301 return new RequestingUserName(userName, null); 1302 } else if (category == ColorSupported.class) { 1303 int caps = getPrinterCapabilities(); 1304 if ((caps & DEVCAP_COLOR) != 0) { 1305 return ColorSupported.SUPPORTED; 1306 } else { 1307 return ColorSupported.NOT_SUPPORTED; 1308 } 1309 } else if (category == Chromaticity.class) { 1310 if (flavor == null || 1311 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1312 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1313 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1314 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1315 flavor.equals(DocFlavor.URL.GIF) || 1316 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1317 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1318 flavor.equals(DocFlavor.URL.JPEG) || 1319 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1320 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1321 flavor.equals(DocFlavor.URL.PNG)) { 1322 int caps = getPrinterCapabilities(); 1323 if ((caps & DEVCAP_COLOR) == 0) { 1324 Chromaticity []arr = new Chromaticity[1]; 1325 arr[0] = Chromaticity.MONOCHROME; 1326 return (arr); 1327 } else { 1328 Chromaticity []arr = new Chromaticity[2]; 1329 arr[0] = Chromaticity.MONOCHROME; 1330 arr[1] = Chromaticity.COLOR; 1331 return (arr); 1332 } 1333 } else { 1334 return null; 1335 } 1336 } else if (category == Destination.class) { 1337 try { 1338 return new Destination((new File("out.prn")).toURI()); 1339 } catch (SecurityException se) { 1340 try { 1341 return new Destination(new URI("file:out.prn")); 1342 } catch (URISyntaxException e) { 1343 return null; 1344 } 1345 } 1346 } else if (category == OrientationRequested.class) { 1347 if (flavor == null || 1348 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1349 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1350 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1351 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1352 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1353 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1354 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1355 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1356 flavor.equals(DocFlavor.URL.GIF) || 1357 flavor.equals(DocFlavor.URL.JPEG) || 1358 flavor.equals(DocFlavor.URL.PNG)) { 1359 OrientationRequested []arr = new OrientationRequested[3]; 1360 arr[0] = OrientationRequested.PORTRAIT; 1361 arr[1] = OrientationRequested.LANDSCAPE; 1362 arr[2] = OrientationRequested.REVERSE_LANDSCAPE; 1363 return arr; 1364 } else { 1365 return null; 1366 } 1367 } else if ((category == Copies.class) || 1368 (category == CopiesSupported.class)) { 1369 synchronized (this) { 1370 if (gotCopies == false) { 1371 nCopies = getCopiesSupported(printer, getPort()); 1372 gotCopies = true; 1373 } 1374 } 1375 return new CopiesSupported(1, nCopies); 1376 } else if (category == Media.class) { 1377 1378 initMedia(); 1379 1380 int len = (mediaSizeNames == null) ? 0 : mediaSizeNames.length; 1381 1382 MediaTray[] trays = getMediaTrays(); 1383 1384 len += (trays == null) ? 0 : trays.length; 1385 1386 Media []arr = new Media[len]; 1387 if (mediaSizeNames != null) { 1388 System.arraycopy(mediaSizeNames, 0, arr, 1389 0, mediaSizeNames.length); 1390 } 1391 if (trays != null) { 1392 System.arraycopy(trays, 0, arr, 1393 len - trays.length, trays.length); 1394 } 1395 return arr; 1396 } else if (category == MediaPrintableArea.class) { 1397 // if getting printable area for a specific media size 1398 Media mediaName = null; 1399 if ((attributes != null) && 1400 ((mediaName = 1401 (Media)attributes.get(Media.class)) != null)) { 1402 1403 if (!(mediaName instanceof MediaSizeName)) { 1404 // if an instance of MediaTray, fall thru returning 1405 // all MediaPrintableAreas 1406 mediaName = null; 1407 } 1408 } 1409 1410 MediaPrintableArea[] mpas = 1411 getMediaPrintables((MediaSizeName)mediaName); 1412 if (mpas != null) { 1413 MediaPrintableArea[] arr = new MediaPrintableArea[mpas.length]; 1414 System.arraycopy(mpas, 0, arr, 0, mpas.length); 1415 return arr; 1416 } else { 1417 return null; 1418 } 1419 } else if (category == SunAlternateMedia.class) { 1420 return new SunAlternateMedia( 1421 (Media)getDefaultAttributeValue(Media.class)); 1422 } else if (category == PageRanges.class) { 1423 if (flavor == null || 1424 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1425 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { 1426 PageRanges []arr = new PageRanges[1]; 1427 arr[0] = new PageRanges(1, Integer.MAX_VALUE); 1428 return arr; 1429 } else { 1430 return null; 1431 } 1432 } else if (category == PrinterResolution.class) { 1433 PrinterResolution[] supportedRes = getPrintResolutions(); 1434 if (supportedRes == null) { 1435 return null; 1436 } 1437 PrinterResolution []arr = 1438 new PrinterResolution[supportedRes.length]; 1439 System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length); 1440 return arr; 1441 } else if (category == Sides.class) { 1442 if (flavor == null || 1443 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1444 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { 1445 Sides []arr = new Sides[3]; 1446 arr[0] = Sides.ONE_SIDED; 1447 arr[1] = Sides.TWO_SIDED_LONG_EDGE; 1448 arr[2] = Sides.TWO_SIDED_SHORT_EDGE; 1449 return arr; 1450 } else { 1451 return null; 1452 } 1453 } else if (category == PrintQuality.class) { 1454 PrintQuality []arr = new PrintQuality[3]; 1455 arr[0] = PrintQuality.DRAFT; 1456 arr[1] = PrintQuality.HIGH; 1457 arr[2] = PrintQuality.NORMAL; 1458 return arr; 1459 } else if (category == SheetCollate.class) { 1460 if (flavor == null || 1461 (flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1462 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { 1463 SheetCollate []arr = new SheetCollate[2]; 1464 arr[0] = SheetCollate.COLLATED; 1465 arr[1] = SheetCollate.UNCOLLATED; 1466 return arr; 1467 } else { 1468 return null; 1469 } 1470 } else if (category == Fidelity.class) { 1471 Fidelity []arr = new Fidelity[2]; 1472 arr[0] = Fidelity.FIDELITY_FALSE; 1473 arr[1] = Fidelity.FIDELITY_TRUE; 1474 return arr; 1475 } else { 1476 return null; 1477 } 1478 } 1479 1480 public boolean isAttributeValueSupported(Attribute attr, 1481 DocFlavor flavor, 1482 AttributeSet attributes) { 1483 1484 if (attr == null) { 1485 throw new NullPointerException("null attribute"); 1486 } 1487 Class<? extends Attribute> category = attr.getCategory(); 1488 if (flavor != null) { 1489 if (!isDocFlavorSupported(flavor)) { 1490 throw new IllegalArgumentException(flavor + 1491 " is an unsupported flavor"); 1492 // if postscript & category is already specified within the PostScript data 1493 // we return false 1494 } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) && 1495 (isPSDocAttr(category)))) { 1496 return false; 1497 } 1498 } 1499 1500 if (!isAttributeCategorySupported(category)) { 1501 return false; 1502 } 1503 else if (category == Chromaticity.class) { 1504 if ((flavor == null) || 1505 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1506 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1507 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1508 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1509 flavor.equals(DocFlavor.URL.GIF) || 1510 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1511 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1512 flavor.equals(DocFlavor.URL.JPEG) || 1513 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1514 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1515 flavor.equals(DocFlavor.URL.PNG)) { 1516 int caps = getPrinterCapabilities(); 1517 if ((caps & DEVCAP_COLOR) != 0) { 1518 return true; 1519 } else { 1520 return attr == Chromaticity.MONOCHROME; 1521 } 1522 } else { 1523 return false; 1524 } 1525 } else if (category == Copies.class) { 1526 return isSupportedCopies((Copies)attr); 1527 1528 } else if (category == Destination.class) { 1529 URI uri = ((Destination)attr).getURI(); 1530 if ("file".equals(uri.getScheme()) && 1531 !(uri.getSchemeSpecificPart().equals(""))) { 1532 return true; 1533 } else { 1534 return false; 1535 } 1536 1537 } else if (category == Media.class) { 1538 if (attr instanceof MediaSizeName) { 1539 return isSupportedMedia((MediaSizeName)attr); 1540 } 1541 if (attr instanceof MediaTray) { 1542 return isSupportedMediaTray((MediaTray)attr); 1543 } 1544 1545 } else if (category == MediaPrintableArea.class) { 1546 return isSupportedMediaPrintableArea((MediaPrintableArea)attr); 1547 1548 } else if (category == SunAlternateMedia.class) { 1549 Media media = ((SunAlternateMedia)attr).getMedia(); 1550 return isAttributeValueSupported(media, flavor, attributes); 1551 1552 } else if (category == PageRanges.class || 1553 category == SheetCollate.class || 1554 category == Sides.class) { 1555 if (flavor != null && 1556 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1557 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { 1558 return false; 1559 } 1560 } else if (category == PrinterResolution.class) { 1561 if (attr instanceof PrinterResolution) { 1562 return isSupportedResolution((PrinterResolution)attr); 1563 } 1564 } else if (category == OrientationRequested.class) { 1565 if (attr == OrientationRequested.REVERSE_PORTRAIT || 1566 (flavor != null) && 1567 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1568 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1569 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1570 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1571 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1572 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1573 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1574 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1575 flavor.equals(DocFlavor.URL.GIF) || 1576 flavor.equals(DocFlavor.URL.JPEG) || 1577 flavor.equals(DocFlavor.URL.PNG))) { 1578 return false; 1579 } 1580 1581 } else if (category == ColorSupported.class) { 1582 int caps = getPrinterCapabilities(); 1583 boolean isColorSup = ((caps & DEVCAP_COLOR) != 0); 1584 if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) || 1585 (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) { 1586 return false; 1587 } 1588 } 1589 return true; 1590 } 1591 1592 public AttributeSet getUnsupportedAttributes(DocFlavor flavor, 1593 AttributeSet attributes) { 1594 1595 if (flavor != null && !isDocFlavorSupported(flavor)) { 1596 throw new IllegalArgumentException("flavor " + flavor + 1597 " is not supported"); 1598 } 1599 1600 if (attributes == null) { 1601 return null; 1602 } 1603 1604 Attribute attr; 1605 AttributeSet unsupp = new HashAttributeSet(); 1606 Attribute []attrs = attributes.toArray(); 1607 for (int i=0; i<attrs.length; i++) { 1608 try { 1609 attr = attrs[i]; 1610 if (!isAttributeCategorySupported(attr.getCategory())) { 1611 unsupp.add(attr); 1612 } 1613 else if (!isAttributeValueSupported(attr, flavor, attributes)) { 1614 unsupp.add(attr); 1615 } 1616 } catch (ClassCastException e) { 1617 } 1618 } 1619 if (unsupp.isEmpty()) { 1620 return null; 1621 } else { 1622 return unsupp; 1623 } 1624 } 1625 1626 private Win32DocumentPropertiesUI docPropertiesUI = null; 1627 1628 private static class Win32DocumentPropertiesUI 1629 extends DocumentPropertiesUI { 1630 1631 Win32PrintService service; 1632 1633 private Win32DocumentPropertiesUI(Win32PrintService s) { 1634 service = s; 1635 } 1636 1637 public PrintRequestAttributeSet 1638 showDocumentProperties(PrinterJob job, 1639 Window owner, 1640 PrintService service, 1641 PrintRequestAttributeSet aset) { 1642 1643 if (!(job instanceof WPrinterJob)) { 1644 return null; 1645 } 1646 WPrinterJob wJob = (WPrinterJob)job; 1647 return wJob.showDocumentProperties(owner, service, aset); 1648 } 1649 } 1650 1651 private synchronized DocumentPropertiesUI getDocumentPropertiesUI() { 1652 return new Win32DocumentPropertiesUI(this); 1653 } 1654 1655 private static class Win32ServiceUIFactory extends ServiceUIFactory { 1656 1657 Win32PrintService service; 1658 1659 Win32ServiceUIFactory(Win32PrintService s) { 1660 service = s; 1661 } 1662 1663 public Object getUI(int role, String ui) { 1664 if (role <= ServiceUIFactory.MAIN_UIROLE) { 1665 return null; 1666 } 1667 if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE && 1668 DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui)) 1669 { 1670 return service.getDocumentPropertiesUI(); 1671 } 1672 throw new IllegalArgumentException("Unsupported role"); 1673 } 1674 1675 public String[] getUIClassNamesForRole(int role) { 1676 1677 if (role <= ServiceUIFactory.MAIN_UIROLE) { 1678 return null; 1679 } 1680 if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) { 1681 String[] names = new String[0]; 1682 names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME; 1683 return names; 1684 } 1685 throw new IllegalArgumentException("Unsupported role"); 1686 } 1687 } 1688 1689 private Win32ServiceUIFactory uiFactory = null; 1690 1691 public synchronized ServiceUIFactory getServiceUIFactory() { 1692 if (uiFactory == null) { 1693 uiFactory = new Win32ServiceUIFactory(this); 1694 } 1695 return uiFactory; 1696 } 1697 1698 public String toString() { 1699 return "Win32 Printer : " + getName(); 1700 } 1701 1702 public boolean equals(Object obj) { 1703 return (obj == this || 1704 (obj instanceof Win32PrintService && 1705 ((Win32PrintService)obj).getName().equals(getName()))); 1706 } 1707 1708 public int hashCode() { 1709 return this.getClass().hashCode()+getName().hashCode(); 1710 } 1711 1712 public boolean usesClass(Class<?> c) { 1713 return (c == sun.awt.windows.WPrinterJob.class); 1714 } 1715 1716 private native int[] getAllMediaIDs(String printerName, String port); 1717 private native int[] getAllMediaSizes(String printerName, String port); 1718 private native int[] getAllMediaTrays(String printerName, String port); 1719 private native float[] getMediaPrintableArea(String printerName, 1720 int paperSize); 1721 private native String[] getAllMediaNames(String printerName, String port); 1722 private native String[] getAllMediaTrayNames(String printerName, String port); 1723 private native int getCopiesSupported(String printerName, String port); 1724 private native int[] getAllResolutions(String printerName, String port); 1725 private native int getCapabilities(String printerName, String port); 1726 1727 private native int[] getDefaultSettings(String printerName, String port); 1728 private native int getJobStatus(String printerName, int type); 1729 private native String getPrinterPort(String printerName); 1730 } 1731 1732 @SuppressWarnings("serial") // JDK implementation class 1733 class Win32MediaSize extends MediaSizeName { 1734 private static ArrayList<String> winStringTable = new ArrayList<>(); 1735 private static ArrayList<Win32MediaSize> winEnumTable = new ArrayList<>(); 1736 private static MediaSize[] predefMedia; 1737 1738 private int dmPaperID; // driver ID for this paper. 1739 1740 private Win32MediaSize(int x) { 1741 super(x); 1742 1743 } 1744 1745 private static synchronized int nextValue(String name) { 1746 winStringTable.add(name); 1747 return (winStringTable.size()-1); 1748 } 1749 1750 public static synchronized Win32MediaSize findMediaName(String name) { 1751 int nameIndex = winStringTable.indexOf(name); 1752 if (nameIndex != -1) { 1753 return winEnumTable.get(nameIndex); 1754 } 1755 return null; 1756 } 1757 1758 public static MediaSize[] getPredefMedia() { 1759 return predefMedia; 1760 } 1761 1762 public Win32MediaSize(String name, int dmPaper) { 1763 super(nextValue(name)); 1764 dmPaperID = dmPaper; 1765 winEnumTable.add(this); 1766 } 1767 1768 private MediaSizeName[] getSuperEnumTable() { 1769 return (MediaSizeName[])super.getEnumValueTable(); 1770 } 1771 1772 static { 1773 /* initialize predefMedia */ 1774 { 1775 Win32MediaSize winMedia = new Win32MediaSize(-1); 1776 1777 // cannot call getSuperEnumTable directly because of static context 1778 MediaSizeName[] enumMedia = winMedia.getSuperEnumTable(); 1779 if (enumMedia != null) { 1780 predefMedia = new MediaSize[enumMedia.length]; 1781 1782 for (int i=0; i<enumMedia.length; i++) { 1783 predefMedia[i] = MediaSize.getMediaSizeForName(enumMedia[i]); 1784 } 1785 } 1786 } 1787 } 1788 1789 int getDMPaper() { 1790 return dmPaperID; 1791 } 1792 1793 protected String[] getStringTable() { 1794 String[] nameTable = new String[winStringTable.size()]; 1795 return winStringTable.toArray(nameTable); 1796 } 1797 1798 protected EnumSyntax[] getEnumValueTable() { 1799 MediaSizeName[] enumTable = new MediaSizeName[winEnumTable.size()]; 1800 return winEnumTable.toArray(enumTable); 1801 } 1802 1803 }