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 } else { 1194 return new PrinterResolution(300, 300, PrinterResolution.DPI); 1195 } 1196 } 1197 else { 1198 return new PrinterResolution(xRes, yRes, PrinterResolution.DPI); 1199 } 1200 } else if (category == ColorSupported.class) { 1201 int caps = getPrinterCapabilities(); 1202 if ((caps & DEVCAP_COLOR) != 0) { 1203 return ColorSupported.SUPPORTED; 1204 } else { 1205 return ColorSupported.NOT_SUPPORTED; 1206 } 1207 } else if (category == PrintQuality.class) { 1208 if ((defQuality < 0) && (defQuality >= DMRES_HIGH)) { 1209 switch (defQuality) { 1210 case DMRES_HIGH: 1211 return PrintQuality.HIGH; 1212 case DMRES_MEDIUM: 1213 return PrintQuality.NORMAL; 1214 default: 1215 return PrintQuality.DRAFT; 1216 } 1217 } 1218 } else if (category == RequestingUserName.class) { 1219 String userName = ""; 1220 try { 1221 userName = System.getProperty("user.name", ""); 1222 } catch (SecurityException se) { 1223 } 1224 return new RequestingUserName(userName, null); 1225 } else if (category == SheetCollate.class) { 1226 if (defCollate == DMCOLLATE_TRUE) { 1227 return SheetCollate.COLLATED; 1228 } else { 1229 return SheetCollate.UNCOLLATED; 1230 } 1231 } else if (category == Fidelity.class) { 1232 return Fidelity.FIDELITY_FALSE; 1233 } 1234 return null; 1235 } 1236 1237 private boolean isPostScriptFlavor(DocFlavor flavor) { 1238 if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) || 1239 flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || 1240 flavor.equals(DocFlavor.URL.POSTSCRIPT)) { 1241 return true; 1242 } 1243 else { 1244 return false; 1245 } 1246 } 1247 1248 private boolean isPSDocAttr(Class<?> category) { 1249 if (category == OrientationRequested.class || category == Copies.class) { 1250 return true; 1251 } 1252 else { 1253 return false; 1254 } 1255 } 1256 1257 private boolean isAutoSense(DocFlavor flavor) { 1258 if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) || 1259 flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) || 1260 flavor.equals(DocFlavor.URL.AUTOSENSE)) { 1261 return true; 1262 } 1263 else { 1264 return false; 1265 } 1266 } 1267 1268 public Object 1269 getSupportedAttributeValues(Class<? extends Attribute> category, 1270 DocFlavor flavor, 1271 AttributeSet attributes) 1272 { 1273 if (category == null) { 1274 throw new NullPointerException("null category"); 1275 } 1276 if (!Attribute.class.isAssignableFrom(category)) { 1277 throw new IllegalArgumentException(category + 1278 " does not implement Attribute"); 1279 } 1280 if (flavor != null) { 1281 if (!isDocFlavorSupported(flavor)) { 1282 throw new IllegalArgumentException(flavor + 1283 " is an unsupported flavor"); 1284 // if postscript & category is already specified within the 1285 // PostScript data we return null 1286 } else if (isAutoSense(flavor) ||(isPostScriptFlavor(flavor) && 1287 (isPSDocAttr(category)))){ 1288 return null; 1289 } 1290 } 1291 if (!isAttributeCategorySupported(category)) { 1292 return null; 1293 } 1294 1295 if (category == JobName.class) { 1296 return new JobName("Java Printing", null); 1297 } else if (category == RequestingUserName.class) { 1298 String userName = ""; 1299 try { 1300 userName = System.getProperty("user.name", ""); 1301 } catch (SecurityException se) { 1302 } 1303 return new RequestingUserName(userName, null); 1304 } else if (category == ColorSupported.class) { 1305 int caps = getPrinterCapabilities(); 1306 if ((caps & DEVCAP_COLOR) != 0) { 1307 return ColorSupported.SUPPORTED; 1308 } else { 1309 return ColorSupported.NOT_SUPPORTED; 1310 } 1311 } else if (category == Chromaticity.class) { 1312 if (flavor == null || 1313 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1314 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1315 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1316 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1317 flavor.equals(DocFlavor.URL.GIF) || 1318 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1319 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1320 flavor.equals(DocFlavor.URL.JPEG) || 1321 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1322 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1323 flavor.equals(DocFlavor.URL.PNG)) { 1324 int caps = getPrinterCapabilities(); 1325 if ((caps & DEVCAP_COLOR) == 0) { 1326 Chromaticity []arr = new Chromaticity[1]; 1327 arr[0] = Chromaticity.MONOCHROME; 1328 return (arr); 1329 } else { 1330 Chromaticity []arr = new Chromaticity[2]; 1331 arr[0] = Chromaticity.MONOCHROME; 1332 arr[1] = Chromaticity.COLOR; 1333 return (arr); 1334 } 1335 } else { 1336 return null; 1337 } 1338 } else if (category == Destination.class) { 1339 try { 1340 return new Destination((new File("out.prn")).toURI()); 1341 } catch (SecurityException se) { 1342 try { 1343 return new Destination(new URI("file:out.prn")); 1344 } catch (URISyntaxException e) { 1345 return null; 1346 } 1347 } 1348 } else if (category == OrientationRequested.class) { 1349 if (flavor == null || 1350 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1351 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1352 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1353 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1354 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1355 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1356 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1357 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1358 flavor.equals(DocFlavor.URL.GIF) || 1359 flavor.equals(DocFlavor.URL.JPEG) || 1360 flavor.equals(DocFlavor.URL.PNG)) { 1361 OrientationRequested []arr = new OrientationRequested[3]; 1362 arr[0] = OrientationRequested.PORTRAIT; 1363 arr[1] = OrientationRequested.LANDSCAPE; 1364 arr[2] = OrientationRequested.REVERSE_LANDSCAPE; 1365 return arr; 1366 } else { 1367 return null; 1368 } 1369 } else if ((category == Copies.class) || 1370 (category == CopiesSupported.class)) { 1371 synchronized (this) { 1372 if (gotCopies == false) { 1373 nCopies = getCopiesSupported(printer, getPort()); 1374 gotCopies = true; 1375 } 1376 } 1377 return new CopiesSupported(1, nCopies); 1378 } else if (category == Media.class) { 1379 1380 initMedia(); 1381 1382 int len = (mediaSizeNames == null) ? 0 : mediaSizeNames.length; 1383 1384 MediaTray[] trays = getMediaTrays(); 1385 1386 len += (trays == null) ? 0 : trays.length; 1387 1388 Media []arr = new Media[len]; 1389 if (mediaSizeNames != null) { 1390 System.arraycopy(mediaSizeNames, 0, arr, 1391 0, mediaSizeNames.length); 1392 } 1393 if (trays != null) { 1394 System.arraycopy(trays, 0, arr, 1395 len - trays.length, trays.length); 1396 } 1397 return arr; 1398 } else if (category == MediaPrintableArea.class) { 1399 // if getting printable area for a specific media size 1400 Media mediaName = null; 1401 if ((attributes != null) && 1402 ((mediaName = 1403 (Media)attributes.get(Media.class)) != null)) { 1404 1405 if (!(mediaName instanceof MediaSizeName)) { 1406 // if an instance of MediaTray, fall thru returning 1407 // all MediaPrintableAreas 1408 mediaName = null; 1409 } 1410 } 1411 1412 MediaPrintableArea[] mpas = 1413 getMediaPrintables((MediaSizeName)mediaName); 1414 if (mpas != null) { 1415 MediaPrintableArea[] arr = new MediaPrintableArea[mpas.length]; 1416 System.arraycopy(mpas, 0, arr, 0, mpas.length); 1417 return arr; 1418 } else { 1419 return null; 1420 } 1421 } else if (category == SunAlternateMedia.class) { 1422 return new SunAlternateMedia( 1423 (Media)getDefaultAttributeValue(Media.class)); 1424 } else if (category == PageRanges.class) { 1425 if (flavor == null || 1426 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1427 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { 1428 PageRanges []arr = new PageRanges[1]; 1429 arr[0] = new PageRanges(1, Integer.MAX_VALUE); 1430 return arr; 1431 } else { 1432 return null; 1433 } 1434 } else if (category == PrinterResolution.class) { 1435 PrinterResolution[] supportedRes = getPrintResolutions(); 1436 if (supportedRes == null) { 1437 return null; 1438 } 1439 PrinterResolution []arr = 1440 new PrinterResolution[supportedRes.length]; 1441 System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length); 1442 return arr; 1443 } else if (category == Sides.class) { 1444 if (flavor == null || 1445 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1446 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { 1447 Sides []arr = new Sides[3]; 1448 arr[0] = Sides.ONE_SIDED; 1449 arr[1] = Sides.TWO_SIDED_LONG_EDGE; 1450 arr[2] = Sides.TWO_SIDED_SHORT_EDGE; 1451 return arr; 1452 } else { 1453 return null; 1454 } 1455 } else if (category == PrintQuality.class) { 1456 PrintQuality []arr = new PrintQuality[3]; 1457 arr[0] = PrintQuality.DRAFT; 1458 arr[1] = PrintQuality.HIGH; 1459 arr[2] = PrintQuality.NORMAL; 1460 return arr; 1461 } else if (category == SheetCollate.class) { 1462 if (flavor == null || 1463 (flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1464 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { 1465 SheetCollate []arr = new SheetCollate[2]; 1466 arr[0] = SheetCollate.COLLATED; 1467 arr[1] = SheetCollate.UNCOLLATED; 1468 return arr; 1469 } else { 1470 return null; 1471 } 1472 } else if (category == Fidelity.class) { 1473 Fidelity []arr = new Fidelity[2]; 1474 arr[0] = Fidelity.FIDELITY_FALSE; 1475 arr[1] = Fidelity.FIDELITY_TRUE; 1476 return arr; 1477 } else { 1478 return null; 1479 } 1480 } 1481 1482 public boolean isAttributeValueSupported(Attribute attr, 1483 DocFlavor flavor, 1484 AttributeSet attributes) { 1485 1486 if (attr == null) { 1487 throw new NullPointerException("null attribute"); 1488 } 1489 Class<? extends Attribute> category = attr.getCategory(); 1490 if (flavor != null) { 1491 if (!isDocFlavorSupported(flavor)) { 1492 throw new IllegalArgumentException(flavor + 1493 " is an unsupported flavor"); 1494 // if postscript & category is already specified within the PostScript data 1495 // we return false 1496 } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) && 1497 (isPSDocAttr(category)))) { 1498 return false; 1499 } 1500 } 1501 1502 if (!isAttributeCategorySupported(category)) { 1503 return false; 1504 } 1505 else if (category == Chromaticity.class) { 1506 if ((flavor == null) || 1507 flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1508 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1509 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1510 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1511 flavor.equals(DocFlavor.URL.GIF) || 1512 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1513 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1514 flavor.equals(DocFlavor.URL.JPEG) || 1515 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1516 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1517 flavor.equals(DocFlavor.URL.PNG)) { 1518 int caps = getPrinterCapabilities(); 1519 if ((caps & DEVCAP_COLOR) != 0) { 1520 return true; 1521 } else { 1522 return attr == Chromaticity.MONOCHROME; 1523 } 1524 } else { 1525 return false; 1526 } 1527 } else if (category == Copies.class) { 1528 return isSupportedCopies((Copies)attr); 1529 1530 } else if (category == Destination.class) { 1531 URI uri = ((Destination)attr).getURI(); 1532 if ("file".equals(uri.getScheme()) && 1533 !(uri.getSchemeSpecificPart().equals(""))) { 1534 return true; 1535 } else { 1536 return false; 1537 } 1538 1539 } else if (category == Media.class) { 1540 if (attr instanceof MediaSizeName) { 1541 return isSupportedMedia((MediaSizeName)attr); 1542 } 1543 if (attr instanceof MediaTray) { 1544 return isSupportedMediaTray((MediaTray)attr); 1545 } 1546 1547 } else if (category == MediaPrintableArea.class) { 1548 return isSupportedMediaPrintableArea((MediaPrintableArea)attr); 1549 1550 } else if (category == SunAlternateMedia.class) { 1551 Media media = ((SunAlternateMedia)attr).getMedia(); 1552 return isAttributeValueSupported(media, flavor, attributes); 1553 1554 } else if (category == PageRanges.class || 1555 category == SheetCollate.class || 1556 category == Sides.class) { 1557 if (flavor != null && 1558 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1559 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { 1560 return false; 1561 } 1562 } else if (category == PrinterResolution.class) { 1563 if (attr instanceof PrinterResolution) { 1564 return isSupportedResolution((PrinterResolution)attr); 1565 } 1566 } else if (category == OrientationRequested.class) { 1567 if (attr == OrientationRequested.REVERSE_PORTRAIT || 1568 (flavor != null) && 1569 !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || 1570 flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || 1571 flavor.equals(DocFlavor.INPUT_STREAM.GIF) || 1572 flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || 1573 flavor.equals(DocFlavor.INPUT_STREAM.PNG) || 1574 flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || 1575 flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || 1576 flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || 1577 flavor.equals(DocFlavor.URL.GIF) || 1578 flavor.equals(DocFlavor.URL.JPEG) || 1579 flavor.equals(DocFlavor.URL.PNG))) { 1580 return false; 1581 } 1582 1583 } else if (category == ColorSupported.class) { 1584 int caps = getPrinterCapabilities(); 1585 boolean isColorSup = ((caps & DEVCAP_COLOR) != 0); 1586 if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) || 1587 (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) { 1588 return false; 1589 } 1590 } 1591 return true; 1592 } 1593 1594 public AttributeSet getUnsupportedAttributes(DocFlavor flavor, 1595 AttributeSet attributes) { 1596 1597 if (flavor != null && !isDocFlavorSupported(flavor)) { 1598 throw new IllegalArgumentException("flavor " + flavor + 1599 " is not supported"); 1600 } 1601 1602 if (attributes == null) { 1603 return null; 1604 } 1605 1606 Attribute attr; 1607 AttributeSet unsupp = new HashAttributeSet(); 1608 Attribute []attrs = attributes.toArray(); 1609 for (int i=0; i<attrs.length; i++) { 1610 try { 1611 attr = attrs[i]; 1612 if (!isAttributeCategorySupported(attr.getCategory())) { 1613 unsupp.add(attr); 1614 } 1615 else if (!isAttributeValueSupported(attr, flavor, attributes)) { 1616 unsupp.add(attr); 1617 } 1618 } catch (ClassCastException e) { 1619 } 1620 } 1621 if (unsupp.isEmpty()) { 1622 return null; 1623 } else { 1624 return unsupp; 1625 } 1626 } 1627 1628 private Win32DocumentPropertiesUI docPropertiesUI = null; 1629 1630 private static class Win32DocumentPropertiesUI 1631 extends DocumentPropertiesUI { 1632 1633 Win32PrintService service; 1634 1635 private Win32DocumentPropertiesUI(Win32PrintService s) { 1636 service = s; 1637 } 1638 1639 public PrintRequestAttributeSet 1640 showDocumentProperties(PrinterJob job, 1641 Window owner, 1642 PrintService service, 1643 PrintRequestAttributeSet aset) { 1644 1645 if (!(job instanceof WPrinterJob)) { 1646 return null; 1647 } 1648 WPrinterJob wJob = (WPrinterJob)job; 1649 return wJob.showDocumentProperties(owner, service, aset); 1650 } 1651 } 1652 1653 private synchronized DocumentPropertiesUI getDocumentPropertiesUI() { 1654 return new Win32DocumentPropertiesUI(this); 1655 } 1656 1657 private static class Win32ServiceUIFactory extends ServiceUIFactory { 1658 1659 Win32PrintService service; 1660 1661 Win32ServiceUIFactory(Win32PrintService s) { 1662 service = s; 1663 } 1664 1665 public Object getUI(int role, String ui) { 1666 if (role <= ServiceUIFactory.MAIN_UIROLE) { 1667 return null; 1668 } 1669 if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE && 1670 DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui)) 1671 { 1672 return service.getDocumentPropertiesUI(); 1673 } 1674 throw new IllegalArgumentException("Unsupported role"); 1675 } 1676 1677 public String[] getUIClassNamesForRole(int role) { 1678 1679 if (role <= ServiceUIFactory.MAIN_UIROLE) { 1680 return null; 1681 } 1682 if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) { 1683 String[] names = new String[0]; 1684 names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME; 1685 return names; 1686 } 1687 throw new IllegalArgumentException("Unsupported role"); 1688 } 1689 } 1690 1691 private Win32ServiceUIFactory uiFactory = null; 1692 1693 public synchronized ServiceUIFactory getServiceUIFactory() { 1694 if (uiFactory == null) { 1695 uiFactory = new Win32ServiceUIFactory(this); 1696 } 1697 return uiFactory; 1698 } 1699 1700 public String toString() { 1701 return "Win32 Printer : " + getName(); 1702 } 1703 1704 public boolean equals(Object obj) { 1705 return (obj == this || 1706 (obj instanceof Win32PrintService && 1707 ((Win32PrintService)obj).getName().equals(getName()))); 1708 } 1709 1710 public int hashCode() { 1711 return this.getClass().hashCode()+getName().hashCode(); 1712 } 1713 1714 public boolean usesClass(Class<?> c) { 1715 return (c == sun.awt.windows.WPrinterJob.class); 1716 } 1717 1718 private native int[] getAllMediaIDs(String printerName, String port); 1719 private native int[] getAllMediaSizes(String printerName, String port); 1720 private native int[] getAllMediaTrays(String printerName, String port); 1721 private native float[] getMediaPrintableArea(String printerName, 1722 int paperSize); 1723 private native String[] getAllMediaNames(String printerName, String port); 1724 private native String[] getAllMediaTrayNames(String printerName, String port); 1725 private native int getCopiesSupported(String printerName, String port); 1726 private native int[] getAllResolutions(String printerName, String port); 1727 private native int getCapabilities(String printerName, String port); 1728 1729 private native int[] getDefaultSettings(String printerName, String port); 1730 private native int getJobStatus(String printerName, int type); 1731 private native String getPrinterPort(String printerName); 1732 } 1733 1734 @SuppressWarnings("serial") // JDK implementation class 1735 class Win32MediaSize extends MediaSizeName { 1736 private static ArrayList<String> winStringTable = new ArrayList<>(); 1737 private static ArrayList<Win32MediaSize> winEnumTable = new ArrayList<>(); 1738 private static MediaSize[] predefMedia; 1739 1740 private int dmPaperID; // driver ID for this paper. 1741 1742 private Win32MediaSize(int x) { 1743 super(x); 1744 1745 } 1746 1747 private static synchronized int nextValue(String name) { 1748 winStringTable.add(name); 1749 return (winStringTable.size()-1); 1750 } 1751 1752 public static synchronized Win32MediaSize findMediaName(String name) { 1753 int nameIndex = winStringTable.indexOf(name); 1754 if (nameIndex != -1) { 1755 return winEnumTable.get(nameIndex); 1756 } 1757 return null; 1758 } 1759 1760 public static MediaSize[] getPredefMedia() { 1761 return predefMedia; 1762 } 1763 1764 public Win32MediaSize(String name, int dmPaper) { 1765 super(nextValue(name)); 1766 dmPaperID = dmPaper; 1767 winEnumTable.add(this); 1768 } 1769 1770 private MediaSizeName[] getSuperEnumTable() { 1771 return (MediaSizeName[])super.getEnumValueTable(); 1772 } 1773 1774 static { 1775 /* initialize predefMedia */ 1776 { 1777 Win32MediaSize winMedia = new Win32MediaSize(-1); 1778 1779 // cannot call getSuperEnumTable directly because of static context 1780 MediaSizeName[] enumMedia = winMedia.getSuperEnumTable(); 1781 if (enumMedia != null) { 1782 predefMedia = new MediaSize[enumMedia.length]; 1783 1784 for (int i=0; i<enumMedia.length; i++) { 1785 predefMedia[i] = MediaSize.getMediaSizeForName(enumMedia[i]); 1786 } 1787 } 1788 } 1789 } 1790 1791 int getDMPaper() { 1792 return dmPaperID; 1793 } 1794 1795 protected String[] getStringTable() { 1796 String[] nameTable = new String[winStringTable.size()]; 1797 return winStringTable.toArray(nameTable); 1798 } 1799 1800 protected EnumSyntax[] getEnumValueTable() { 1801 MediaSizeName[] enumTable = new MediaSizeName[winEnumTable.size()]; 1802 return winEnumTable.toArray(enumTable); 1803 } 1804 1805 }