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