Path: blob/master/src/java.desktop/windows/classes/sun/print/Win32PrintService.java
41152 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.print;2627import java.awt.GraphicsEnvironment;28import java.awt.Toolkit;29import java.awt.Window;30import java.awt.print.PrinterJob;31import java.io.File;32import java.net.URI;33import java.net.URISyntaxException;34import java.util.ArrayList;35import java.util.HashMap;36import javax.print.DocFlavor;37import javax.print.DocPrintJob;38import javax.print.PrintService;39import javax.print.ServiceUIFactory;40import javax.print.attribute.Attribute;41import javax.print.attribute.AttributeSet;42import javax.print.attribute.AttributeSetUtilities;43import javax.print.attribute.EnumSyntax;44import javax.print.attribute.HashAttributeSet;45import javax.print.attribute.PrintRequestAttributeSet;46import javax.print.attribute.PrintServiceAttribute;47import javax.print.attribute.PrintServiceAttributeSet;48import javax.print.attribute.HashPrintServiceAttributeSet;49import javax.print.attribute.standard.PrinterName;50import javax.print.attribute.standard.PrinterIsAcceptingJobs;51import javax.print.attribute.standard.QueuedJobCount;52import javax.print.attribute.standard.JobName;53import javax.print.attribute.standard.RequestingUserName;54import javax.print.attribute.standard.Chromaticity;55import javax.print.attribute.standard.Copies;56import javax.print.attribute.standard.CopiesSupported;57import javax.print.attribute.standard.Destination;58import javax.print.attribute.standard.DialogOwner;59import javax.print.attribute.standard.DialogTypeSelection;60import javax.print.attribute.standard.Fidelity;61import javax.print.attribute.standard.Media;62import javax.print.attribute.standard.MediaSizeName;63import javax.print.attribute.standard.MediaSize;64import javax.print.attribute.standard.MediaTray;65import javax.print.attribute.standard.MediaPrintableArea;66import javax.print.attribute.standard.OrientationRequested;67import javax.print.attribute.standard.PageRanges;68import javax.print.attribute.standard.PrinterState;69import javax.print.attribute.standard.PrinterStateReason;70import javax.print.attribute.standard.PrinterStateReasons;71import javax.print.attribute.standard.Severity;72import javax.print.attribute.standard.Sides;73import javax.print.attribute.standard.ColorSupported;74import javax.print.attribute.standard.PrintQuality;75import javax.print.attribute.standard.PrinterResolution;76import javax.print.attribute.standard.SheetCollate;77import javax.print.event.PrintServiceAttributeListener;78import sun.awt.windows.WPrinterJob;7980public class Win32PrintService implements PrintService, AttributeUpdater,81SunPrinterJobService {8283public static MediaSize[] predefMedia = Win32MediaSize.getPredefMedia();8485private static final DocFlavor[] supportedFlavors = {86DocFlavor.BYTE_ARRAY.GIF,87DocFlavor.INPUT_STREAM.GIF,88DocFlavor.URL.GIF,89DocFlavor.BYTE_ARRAY.JPEG,90DocFlavor.INPUT_STREAM.JPEG,91DocFlavor.URL.JPEG,92DocFlavor.BYTE_ARRAY.PNG,93DocFlavor.INPUT_STREAM.PNG,94DocFlavor.URL.PNG,95DocFlavor.SERVICE_FORMATTED.PAGEABLE,96DocFlavor.SERVICE_FORMATTED.PRINTABLE,97DocFlavor.BYTE_ARRAY.AUTOSENSE,98DocFlavor.URL.AUTOSENSE,99DocFlavor.INPUT_STREAM.AUTOSENSE100};101102/* let's try to support a few of these */103private static final Class<?>[] serviceAttrCats = {104PrinterName.class,105PrinterIsAcceptingJobs.class,106QueuedJobCount.class,107ColorSupported.class,108};109110/* it turns out to be inconvenient to store the other categories111* separately because many attributes are in multiple categories.112*/113private static Class<?>[] otherAttrCats = {114JobName.class,115RequestingUserName.class,116Copies.class,117Destination.class,118OrientationRequested.class,119PageRanges.class,120Media.class,121MediaPrintableArea.class,122Fidelity.class,123// We support collation on 2D printer jobs, even if the driver can't.124SheetCollate.class,125SunAlternateMedia.class,126Chromaticity.class127};128129130/*131* This table together with methods findWin32Media and132* findMatchingMediaSizeNameMM are declared public as these are also133* used in WPrinterJob.java.134*/135public static final MediaSizeName[] dmPaperToPrintService = {136MediaSizeName.NA_LETTER, MediaSizeName.NA_LETTER,137MediaSizeName.TABLOID, MediaSizeName.LEDGER,138MediaSizeName.NA_LEGAL, MediaSizeName.INVOICE,139MediaSizeName.EXECUTIVE, MediaSizeName.ISO_A3,140MediaSizeName.ISO_A4, MediaSizeName.ISO_A4,141MediaSizeName.ISO_A5, MediaSizeName.JIS_B4,142MediaSizeName.JIS_B5, MediaSizeName.FOLIO,143MediaSizeName.QUARTO, MediaSizeName.NA_10X14_ENVELOPE,144MediaSizeName.B, MediaSizeName.NA_LETTER,145MediaSizeName.NA_NUMBER_9_ENVELOPE, MediaSizeName.NA_NUMBER_10_ENVELOPE,146MediaSizeName.NA_NUMBER_11_ENVELOPE, MediaSizeName.NA_NUMBER_12_ENVELOPE,147MediaSizeName.NA_NUMBER_14_ENVELOPE, MediaSizeName.C,148MediaSizeName.D, MediaSizeName.E,149MediaSizeName.ISO_DESIGNATED_LONG, MediaSizeName.ISO_C5,150MediaSizeName.ISO_C3, MediaSizeName.ISO_C4,151MediaSizeName.ISO_C6, MediaSizeName.ITALY_ENVELOPE,152MediaSizeName.ISO_B4, MediaSizeName.ISO_B5,153MediaSizeName.ISO_B6, MediaSizeName.ITALY_ENVELOPE,154MediaSizeName.MONARCH_ENVELOPE, MediaSizeName.PERSONAL_ENVELOPE,155MediaSizeName.NA_10X15_ENVELOPE, MediaSizeName.NA_9X12_ENVELOPE,156MediaSizeName.FOLIO, MediaSizeName.ISO_B4,157MediaSizeName.JAPANESE_POSTCARD, MediaSizeName.NA_9X11_ENVELOPE,158};159160private static final MediaTray[] dmPaperBinToPrintService = {161MediaTray.TOP, MediaTray.BOTTOM, MediaTray.MIDDLE,162MediaTray.MANUAL, MediaTray.ENVELOPE, Win32MediaTray.ENVELOPE_MANUAL,163Win32MediaTray.AUTO, Win32MediaTray.TRACTOR,164Win32MediaTray.SMALL_FORMAT, Win32MediaTray.LARGE_FORMAT,165MediaTray.LARGE_CAPACITY, null, null,166MediaTray.MAIN, Win32MediaTray.FORMSOURCE,167};168169// from wingdi.h170private static int DM_PAPERSIZE = 0x2;171private static int DM_PRINTQUALITY = 0x400;172private static int DM_YRESOLUTION = 0x2000;173private static final int DMRES_MEDIUM = -3;174private static final int DMRES_HIGH = -4;175private static final int DMORIENT_LANDSCAPE = 2;176private static final int DMDUP_VERTICAL = 2;177private static final int DMDUP_HORIZONTAL = 3;178private static final int DMCOLLATE_TRUE = 1;179private static final int DMCOLOR_MONOCHROME = 1;180private static final int DMCOLOR_COLOR = 2;181182183// media sizes with indices above dmPaperToPrintService' length184private static final int DMPAPER_A2 = 66;185private static final int DMPAPER_A6 = 70;186private static final int DMPAPER_B6_JIS = 88;187188189// Bit settings for getPrinterCapabilities which matches that190// of native getCapabilities in WPrinterJob.cpp191private static final int DEVCAP_COLOR = 0x0001;192private static final int DEVCAP_DUPLEX = 0x0002;193private static final int DEVCAP_COLLATE = 0x0004;194private static final int DEVCAP_QUALITY = 0x0008;195private static final int DEVCAP_POSTSCRIPT = 0x0010;196197private String printer;198private PrinterName name;199private String port;200201private transient PrintServiceAttributeSet lastSet;202private transient ServiceNotifier notifier = null;203204private MediaSizeName[] mediaSizeNames;205private MediaPrintableArea[] mediaPrintables;206private MediaTray[] mediaTrays;207private PrinterResolution[] printRes;208private HashMap<MediaSizeName, MediaPrintableArea> mpaMap;209private int nCopies;210private int prnCaps;211private int[] defaultSettings;212213private boolean gotTrays;214private boolean gotCopies;215private boolean mediaInitialized;216private boolean mpaListInitialized;217218private ArrayList<Integer> idList;219private MediaSize[] mediaSizes;220221private boolean isInvalid;222223Win32PrintService(String name) {224if (name == null) {225throw new IllegalArgumentException("null printer name");226}227printer = name;228229// initialize flags230mediaInitialized = false;231gotTrays = false;232gotCopies = false;233isInvalid = false;234printRes = null;235prnCaps = 0;236defaultSettings = null;237port = null;238}239240public void invalidateService() {241isInvalid = true;242}243244public String getName() {245return printer;246}247248private PrinterName getPrinterName() {249if (name == null) {250name = new PrinterName(printer, null);251}252return name;253}254255public int findPaperID(MediaSizeName msn) {256if (msn instanceof Win32MediaSize) {257Win32MediaSize winMedia = (Win32MediaSize)msn;258return winMedia.getDMPaper();259} else {260for (int id=0; id<dmPaperToPrintService.length;id++) {261if (dmPaperToPrintService[id].equals(msn)) {262return id+1; // DMPAPER_LETTER == 1263}264}265if (msn.equals(MediaSizeName.ISO_A2)) {266return DMPAPER_A2;267}268else if (msn.equals(MediaSizeName.ISO_A6)) {269return DMPAPER_A6;270}271else if (msn.equals(MediaSizeName.JIS_B6)) {272return DMPAPER_B6_JIS;273}274}275276// If not found in predefined Windows ID, then we search through277// the returned IDs of the driver because they can define their own278// unique IDs.279initMedia();280281if ((idList != null) && (mediaSizes != null) &&282(idList.size() == mediaSizes.length)) {283for (int i=0; i< idList.size(); i++) {284if (mediaSizes[i].getMediaSizeName() == msn) {285return idList.get(i).intValue();286}287}288}289return 0;290}291292public int findTrayID(MediaTray tray) {293294getMediaTrays(); // make sure they are initialised.295296if (tray instanceof Win32MediaTray) {297Win32MediaTray winTray = (Win32MediaTray)tray;298return winTray.getDMBinID();299}300for (int id=0; id<dmPaperBinToPrintService.length; id++) {301if (tray.equals(dmPaperBinToPrintService[id])) {302return id+1; // DMBIN_FIRST = 1;303}304}305return 0; // didn't find the tray306}307308public MediaTray findMediaTray(int dmBin) {309if (dmBin >= 1 && dmBin <= dmPaperBinToPrintService.length) {310return dmPaperBinToPrintService[dmBin-1];311}312MediaTray[] trays = getMediaTrays();313if (trays != null) {314for (int i=0;i<trays.length;i++) {315if(trays[i] instanceof Win32MediaTray) {316Win32MediaTray win32Tray = (Win32MediaTray)trays[i];317if (win32Tray.winID == dmBin) {318return win32Tray;319}320}321}322}323return Win32MediaTray.AUTO;324}325326public MediaSizeName findWin32Media(int dmIndex) {327if (dmIndex >= 1 && dmIndex <= dmPaperToPrintService.length) {328return dmPaperToPrintService[dmIndex - 1];329}330switch(dmIndex) {331/* matching media sizes with indices beyond332dmPaperToPrintService's length */333case DMPAPER_A2:334return MediaSizeName.ISO_A2;335case DMPAPER_A6:336return MediaSizeName.ISO_A6;337case DMPAPER_B6_JIS:338return MediaSizeName.JIS_B6;339default:340return null;341}342}343344private boolean addToUniqueList(ArrayList<MediaSizeName> msnList,345MediaSizeName mediaName) {346MediaSizeName msn;347for (int i=0; i< msnList.size(); i++) {348msn = msnList.get(i);349if (msn == mediaName) {350return false;351}352}353msnList.add(mediaName);354return true;355}356357private synchronized void initMedia() {358if (mediaInitialized == true) {359return;360}361mediaInitialized = true;362int[] media = getAllMediaIDs(printer, getPort());363if (media == null) {364return;365}366367ArrayList<MediaSizeName> msnList = new ArrayList<>();368ArrayList<Win32MediaSize> trailingWmsList = new ArrayList<Win32MediaSize>();369MediaSizeName mediaName;370boolean added;371boolean queryFailure = false;372float[] prnArea;373374// Get all mediaSizes supported by the printer.375// We convert media to ArrayList idList and pass this to the376// function for getting mediaSizes.377// This is to ensure that mediaSizes and media IDs have 1-1 correspondence.378// We remove from ID list any invalid mediaSize. Though this is rare,379// it happens in HP 4050 German driver.380381idList = new ArrayList<>();382for (int i=0; i < media.length; i++) {383idList.add(Integer.valueOf(media[i]));384}385386ArrayList<String> dmPaperNameList = new ArrayList<String>();387mediaSizes = getMediaSizes(idList, media, dmPaperNameList);388for (int i = 0; i < idList.size(); i++) {389390// match Win ID with our predefined ID using table391mediaName = findWin32Media(idList.get(i).intValue());392// Verify that this standard size is the same size as that393// reported by the driver. This should be the case except when394// the driver is mis-using a standard windows paper ID.395if (mediaName != null &&396idList.size() == mediaSizes.length) {397MediaSize win32Size = MediaSize.getMediaSizeForName(mediaName);398MediaSize driverSize = mediaSizes[i];399int error = 2540; // == 1/10"400if (Math.abs(win32Size.getX(1)-driverSize.getX(1)) > error ||401Math.abs(win32Size.getY(1)-driverSize.getY(1)) > error)402{403mediaName = null;404}405}406boolean dmPaperIDMatched = (mediaName != null);407408// No match found, then we get the MediaSizeName out of the MediaSize409// This requires 1-1 correspondence, lengths must be checked.410if ((mediaName == null) && (idList.size() == mediaSizes.length)) {411mediaName = mediaSizes[i].getMediaSizeName();412}413414// Add mediaName to the msnList415added = false;416if (mediaName != null) {417added = addToUniqueList(msnList, mediaName);418}419if ((!dmPaperIDMatched || !added) && (idList.size() == dmPaperNameList.size())) {420/* The following block allows to add such media names to the list, whose sizes421* matched with media sizes predefined in JDK, while whose paper IDs did not,422* or whose sizes and paper IDs both did not match with any predefined in JDK.423*/424Win32MediaSize wms = Win32MediaSize.findMediaName(dmPaperNameList.get(i));425if ((wms == null) && (idList.size() == mediaSizes.length)) {426wms = new Win32MediaSize(dmPaperNameList.get(i), idList.get(i));427mediaSizes[i] = new MediaSize(mediaSizes[i].getX(MediaSize.MM),428mediaSizes[i].getY(MediaSize.MM), MediaSize.MM, wms);429}430if ((wms != null) && (wms != mediaName)) {431if (!added) {432added = addToUniqueList(msnList, mediaName = wms);433} else {434trailingWmsList.add(wms);435}436}437}438}439for (Win32MediaSize wms : trailingWmsList) {440added = addToUniqueList(msnList, wms);441}442443// init mediaSizeNames444mediaSizeNames = new MediaSizeName[msnList.size()];445msnList.toArray(mediaSizeNames);446}447448449/*450* Gets a list of MediaPrintableAreas using a call to native function.451* msn is MediaSizeName used to get a specific printable area. If null,452* it will get all the supported MediPrintableAreas.453*/454private synchronized MediaPrintableArea[] getMediaPrintables(MediaSizeName msn)455{456if (msn == null) {457if (mpaListInitialized == true) {458return mediaPrintables;459}460} else {461// get from cached mapping of MPAs462if (mpaMap != null && (mpaMap.get(msn) != null)) {463MediaPrintableArea[] mpaArr = new MediaPrintableArea[1];464mpaArr[0] = mpaMap.get(msn);465return mpaArr;466}467}468469initMedia();470471if ((mediaSizeNames == null) || (mediaSizeNames.length == 0)) {472return null;473}474475MediaSizeName[] loopNames;476if (msn != null) {477loopNames = new MediaSizeName[1];478loopNames[0] = msn;479} else {480loopNames = mediaSizeNames;481}482483if (mpaMap == null) {484mpaMap = new HashMap<>();485}486487for (int i=0; i < loopNames.length; i++) {488MediaSizeName mediaName = loopNames[i];489490if (mpaMap.get(mediaName) != null) {491continue;492}493494if (mediaName != null) {495int defPaper = findPaperID(mediaName);496float[] prnArea = (defPaper != 0) ? getMediaPrintableArea(printer, defPaper) : null;497MediaPrintableArea printableArea = null;498if (prnArea != null) {499try {500printableArea = new MediaPrintableArea(prnArea[0],501prnArea[1],502prnArea[2],503prnArea[3],504MediaPrintableArea.INCH);505506mpaMap.put(mediaName, printableArea);507}508catch (IllegalArgumentException e) {509}510} else {511// if getting MPA failed, we use MediaSize512MediaSize ms = MediaSize.getMediaSizeForName(mediaName);513514if (ms != null) {515try {516printableArea = new MediaPrintableArea(0, 0,517ms.getX(MediaSize.INCH),518ms.getY(MediaSize.INCH),519MediaPrintableArea.INCH);520mpaMap.put(mediaName, printableArea);521} catch (IllegalArgumentException e) {522}523}524}525} //mediaName != null526}527528if (mpaMap.size() == 0) {529return null;530}531532if (msn != null) {533if (mpaMap.get(msn) == null) {534return null;535}536MediaPrintableArea[] mpaArr = new MediaPrintableArea[1];537// by this time, we've already gotten the desired MPA538mpaArr[0] = mpaMap.get(msn);539return mpaArr;540} else {541mediaPrintables = mpaMap.values().toArray(new MediaPrintableArea[0]);542mpaListInitialized = true;543return mediaPrintables;544}545}546547548private synchronized MediaTray[] getMediaTrays() {549if (gotTrays == true && mediaTrays != null) {550return mediaTrays;551}552String prnPort = getPort();553int[] mediaTr = getAllMediaTrays(printer, prnPort);554String[] winMediaTrayNames = getAllMediaTrayNames(printer, prnPort);555556if ((mediaTr == null) || (winMediaTrayNames == null)){557return null;558}559560/* first count how many valid bins there are so we can allocate561* an array of the correct size562*/563int nTray = 0;564for (int i=0; i < mediaTr.length ; i++) {565if (mediaTr[i] > 0) nTray++;566}567568MediaTray[] arr = new MediaTray[nTray];569int dmBin;570571/* Some drivers in Win 7 don't have the same length for DC_BINS and572* DC_BINNAMES so there is no guarantee that lengths of mediaTr and573* winMediaTrayNames are equal. To avoid getting ArrayIndexOutOfBounds,574* we need to make sure we get the minimum of the two.575*/576577for (int i = 0, j=0; i < Math.min(mediaTr.length, winMediaTrayNames.length); i++) {578dmBin = mediaTr[i];579if (dmBin > 0) {580// check for unsupported DMBINs and create new Win32MediaTray581if ((dmBin > dmPaperBinToPrintService.length)582|| (dmPaperBinToPrintService[dmBin-1] == null)) {583arr[j++] = new Win32MediaTray(dmBin, winMediaTrayNames[i]);584} else {585arr[j++] = dmPaperBinToPrintService[dmBin-1];586}587}588// no else - For invalid ids, just ignore it because assigning a "default"589// value may result in duplicate trays.590}591mediaTrays = arr;592gotTrays = true;593return mediaTrays;594}595596private boolean isSameSize(float w1, float h1, float w2, float h2) {597float diffX = w1 - w2;598float diffY = h1 - h2;599// Get diff of reverse dimensions600// EPSON Stylus COLOR 860 reverses envelope's width & height601float diffXrev = w1 - h2;602float diffYrev = h1 - w2;603604if (((Math.abs(diffX)<=1) && (Math.abs(diffY)<=1)) ||605((Math.abs(diffXrev)<=1) && (Math.abs(diffYrev)<=1))){606return true;607} else {608return false;609}610}611612public MediaSizeName findMatchingMediaSizeNameMM (float w, float h){613if (predefMedia != null) {614for (int k=0; k<predefMedia.length;k++) {615if (predefMedia[k] == null) {616continue;617}618619if (isSameSize(predefMedia[k].getX(MediaSize.MM),620predefMedia[k].getY(MediaSize.MM),621w, h)) {622return predefMedia[k].getMediaSizeName();623}624}625}626return null;627}628629630private MediaSize[] getMediaSizes(ArrayList<Integer> idList, int[] media,631ArrayList<String> dmPaperNameList) {632if (dmPaperNameList == null) {633dmPaperNameList = new ArrayList<String>();634}635636String prnPort = getPort();637int[] mediaSz = getAllMediaSizes(printer, prnPort);638String[] winMediaNames = getAllMediaNames(printer, prnPort);639MediaSizeName msn = null;640MediaSize ms = null;641float wid, ht;642643if ((mediaSz == null) || (winMediaNames == null)) {644return null;645}646647int nMedia = mediaSz.length/2;648ArrayList<MediaSize> msList = new ArrayList<>();649650for (int i = 0; i < nMedia; i++, ms=null) {651wid = mediaSz[i*2]/10f;652ht = mediaSz[i*2+1]/10f;653654// Make sure to validate wid & ht.655// HP LJ 4050 (german) causes IAE in Sonderformat paper, wid & ht656// returned is not constant.657if ((wid <= 0) || (ht <= 0)) {658//Remove corresponding ID from list659if (nMedia == media.length) {660Integer remObj = Integer.valueOf(media[i]);661idList.remove(idList.indexOf(remObj));662}663continue;664}665// Find matching media using dimensions.666// This call matches only with our own predefined sizes.667msn = findMatchingMediaSizeNameMM(wid, ht);668if (msn != null) {669ms = MediaSize.getMediaSizeForName(msn);670}671672if (ms != null) {673msList.add(ms);674dmPaperNameList.add(winMediaNames[i]);675} else {676Win32MediaSize wms = Win32MediaSize.findMediaName(winMediaNames[i]);677if (wms == null) {678wms = new Win32MediaSize(winMediaNames[i], media[i]);679}680try {681ms = new MediaSize(wid, ht, MediaSize.MM, wms);682msList.add(ms);683dmPaperNameList.add(winMediaNames[i]);684} catch(IllegalArgumentException e) {685if (nMedia == media.length) {686Integer remObj = Integer.valueOf(media[i]);687idList.remove(idList.indexOf(remObj));688}689}690}691}692693MediaSize[] arr2 = new MediaSize[msList.size()];694msList.toArray(arr2);695696return arr2;697}698699private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {700if (getJobStatus(printer, 2) != 1) {701return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;702}703else {704return PrinterIsAcceptingJobs.ACCEPTING_JOBS;705}706}707708private PrinterState getPrinterState() {709if (isInvalid) {710return PrinterState.STOPPED;711} else {712return null;713}714}715716private PrinterStateReasons getPrinterStateReasons() {717if (isInvalid) {718PrinterStateReasons psr = new PrinterStateReasons();719psr.put(PrinterStateReason.SHUTDOWN, Severity.ERROR);720return psr;721} else {722return null;723}724}725726private QueuedJobCount getQueuedJobCount() {727728int count = getJobStatus(printer, 1);729if (count != -1) {730return new QueuedJobCount(count);731}732else {733return new QueuedJobCount(0);734}735}736737private boolean isSupportedCopies(Copies copies) {738synchronized (this) {739if (gotCopies == false) {740nCopies = getCopiesSupported(printer, getPort());741gotCopies = true;742}743}744int numCopies = copies.getValue();745return (numCopies > 0 && numCopies <= nCopies);746}747748private boolean isSupportedMedia(MediaSizeName msn) {749750initMedia();751752if (mediaSizeNames != null) {753for (int i=0; i<mediaSizeNames.length; i++) {754if (msn.equals(mediaSizeNames[i])) {755return true;756}757}758}759return false;760}761762private boolean isSupportedMediaPrintableArea(MediaPrintableArea mpa) {763764getMediaPrintables(null);765int units = MediaPrintableArea.INCH;766767if (mediaPrintables != null) {768for (int i=0; i<mediaPrintables.length; i++) {769if ((mpa.getX(units) >= mediaPrintables[i].getX(units)) &&770(mpa.getY(units) >= mediaPrintables[i].getY(units)) &&771(mpa.getX(units) + mpa.getWidth(units) <=772mediaPrintables[i].getX(units) +773mediaPrintables[i].getWidth(units)) &&774(mpa.getY(units) + mpa.getHeight(units) <=775mediaPrintables[i].getY(units) +776mediaPrintables[i].getHeight(units))) {777return true;778}779}780}781return false;782}783784private boolean isSupportedMediaTray(MediaTray msn) {785MediaTray[] trays = getMediaTrays();786787if (trays != null) {788for (int i=0; i<trays.length; i++) {789if (msn.equals(trays[i])) {790return true;791}792}793}794return false;795}796797private int getPrinterCapabilities() {798if (prnCaps == 0) {799prnCaps = getCapabilities(printer, getPort());800}801return prnCaps;802}803804private String getPort() {805if (port == null) {806port = getPrinterPort(printer);807}808return port;809}810811/*812* NOTE: defaults indices must match those in WPrinterJob.cpp813*/814private int[] getDefaultPrinterSettings() {815if (defaultSettings == null) {816defaultSettings = getDefaultSettings(printer, getPort());817}818return defaultSettings;819}820821private PrinterResolution[] getPrintResolutions() {822if (printRes == null) {823int[] prnRes = getAllResolutions(printer, getPort());824if (prnRes == null) {825printRes = new PrinterResolution[0];826} else {827int nRes = prnRes.length/2;828829ArrayList<PrinterResolution> arrList = new ArrayList<>();830PrinterResolution pr;831832for (int i=0; i<nRes; i++) {833try {834pr = new PrinterResolution(prnRes[i*2],835prnRes[i*2+1], PrinterResolution.DPI);836arrList.add(pr);837} catch (IllegalArgumentException e) {838}839}840841printRes = arrList.toArray(new PrinterResolution[arrList.size()]);842}843}844return printRes;845}846847private boolean isSupportedResolution(PrinterResolution res) {848PrinterResolution[] supportedRes = getPrintResolutions();849if (supportedRes != null) {850for (int i=0; i<supportedRes.length; i++) {851if (res.equals(supportedRes[i])) {852return true;853}854}855}856return false;857}858859public DocPrintJob createPrintJob() {860@SuppressWarnings("removal")861SecurityManager security = System.getSecurityManager();862if (security != null) {863security.checkPrintJobAccess();864}865return new Win32PrintJob(this);866}867868private PrintServiceAttributeSet getDynamicAttributes() {869PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();870attrs.add(getPrinterIsAcceptingJobs());871attrs.add(getQueuedJobCount());872return attrs;873}874875public PrintServiceAttributeSet getUpdatedAttributes() {876PrintServiceAttributeSet currSet = getDynamicAttributes();877if (lastSet == null) {878lastSet = currSet;879return AttributeSetUtilities.unmodifiableView(currSet);880} else {881PrintServiceAttributeSet updates =882new HashPrintServiceAttributeSet();883Attribute []attrs = currSet.toArray();884for (int i=0; i<attrs.length; i++) {885Attribute attr = attrs[i];886if (!lastSet.containsValue(attr)) {887updates.add(attr);888}889}890lastSet = currSet;891return AttributeSetUtilities.unmodifiableView(updates);892}893}894895public void wakeNotifier() {896synchronized (this) {897if (notifier != null) {898notifier.wake();899}900}901}902903public void addPrintServiceAttributeListener(PrintServiceAttributeListener904listener) {905synchronized (this) {906if (listener == null) {907return;908}909if (notifier == null) {910notifier = new ServiceNotifier(this);911}912notifier.addListener(listener);913}914}915916public void removePrintServiceAttributeListener(917PrintServiceAttributeListener listener) {918synchronized (this) {919if (listener == null || notifier == null ) {920return;921}922notifier.removeListener(listener);923if (notifier.isEmpty()) {924notifier.stopNotifier();925notifier = null;926}927}928}929930@SuppressWarnings("unchecked")931public <T extends PrintServiceAttribute> T932getAttribute(Class<T> category)933{934if (category == null) {935throw new NullPointerException("category");936}937if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {938throw new IllegalArgumentException("Not a PrintServiceAttribute");939}940if (category == ColorSupported.class) {941int caps = getPrinterCapabilities();942if ((caps & DEVCAP_COLOR) != 0) {943return (T)ColorSupported.SUPPORTED;944} else {945return (T)ColorSupported.NOT_SUPPORTED;946}947} else if (category == PrinterName.class) {948return (T)getPrinterName();949} else if (category == PrinterState.class) {950return (T)getPrinterState();951} else if (category == PrinterStateReasons.class) {952return (T)getPrinterStateReasons();953} else if (category == QueuedJobCount.class) {954return (T)getQueuedJobCount();955} else if (category == PrinterIsAcceptingJobs.class) {956return (T)getPrinterIsAcceptingJobs();957} else {958return null;959}960}961962public PrintServiceAttributeSet getAttributes() {963964PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();965attrs.add(getPrinterName());966attrs.add(getPrinterIsAcceptingJobs());967PrinterState prnState = getPrinterState();968if (prnState != null) {969attrs.add(prnState);970}971PrinterStateReasons prnStateReasons = getPrinterStateReasons();972if (prnStateReasons != null) {973attrs.add(prnStateReasons);974}975attrs.add(getQueuedJobCount());976int caps = getPrinterCapabilities();977if ((caps & DEVCAP_COLOR) != 0) {978attrs.add(ColorSupported.SUPPORTED);979} else {980attrs.add(ColorSupported.NOT_SUPPORTED);981}982983return AttributeSetUtilities.unmodifiableView(attrs);984}985986public DocFlavor[] getSupportedDocFlavors() {987int len = supportedFlavors.length;988DocFlavor[] supportedDocFlavors;989int caps = getPrinterCapabilities();990// doc flavors supported991// if PostScript is supported992if ((caps & DEVCAP_POSTSCRIPT) != 0) {993supportedDocFlavors = new DocFlavor[len+3];994System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len);995supportedDocFlavors[len] = DocFlavor.BYTE_ARRAY.POSTSCRIPT;996supportedDocFlavors[len+1] = DocFlavor.INPUT_STREAM.POSTSCRIPT;997supportedDocFlavors[len+2] = DocFlavor.URL.POSTSCRIPT;998} else {999supportedDocFlavors = new DocFlavor[len];1000System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len);1001}1002return supportedDocFlavors;1003}10041005public boolean isDocFlavorSupported(DocFlavor flavor) {1006/* To avoid a native query which may be time-consuming1007* do not invoke native unless postscript support is being queried.1008* Instead just check the ones we 'always' support1009*/1010DocFlavor[] supportedDocFlavors;1011if (isPostScriptFlavor(flavor)) {1012supportedDocFlavors = getSupportedDocFlavors();1013} else {1014supportedDocFlavors = supportedFlavors;1015}1016for (int f=0; f<supportedDocFlavors.length; f++) {1017if (flavor.equals(supportedDocFlavors[f])) {1018return true;1019}1020}1021return false;1022}10231024public Class<?>[] getSupportedAttributeCategories() {1025ArrayList<Class<?>> categList = new ArrayList<>(otherAttrCats.length+3);1026for (int i=0; i < otherAttrCats.length; i++) {1027categList.add(otherAttrCats[i]);1028}10291030int caps = getPrinterCapabilities();10311032if ((caps & DEVCAP_DUPLEX) != 0) {1033categList.add(Sides.class);1034}10351036if ((caps & DEVCAP_QUALITY) != 0) {1037int[] defaults = getDefaultPrinterSettings();1038// Added check: if supported, we should be able to get the default.1039if ((defaults[3] >= DMRES_HIGH) && (defaults[3] < 0)) {1040categList.add(PrintQuality.class);1041}1042}10431044PrinterResolution[] supportedRes = getPrintResolutions();1045if ((supportedRes!=null) && (supportedRes.length>0)) {1046categList.add(PrinterResolution.class);1047}10481049if (GraphicsEnvironment.isHeadless() == false) {1050categList.add(DialogOwner.class);1051categList.add(DialogTypeSelection.class);1052}1053return categList.toArray(new Class<?>[categList.size()]);1054}10551056public boolean1057isAttributeCategorySupported(Class<? extends Attribute> category)1058{10591060if (category == null) {1061throw new NullPointerException("null category");1062}10631064if (!(Attribute.class.isAssignableFrom(category))) {1065throw new IllegalArgumentException(category +1066" is not an Attribute");1067}10681069Class<?>[] classList = getSupportedAttributeCategories();1070for (int i = 0; i < classList.length; i++) {1071if (category.equals(classList[i])) {1072return true;1073}1074}10751076return false;1077}10781079public Object1080getDefaultAttributeValue(Class<? extends Attribute> category)1081{1082if (category == null) {1083throw new NullPointerException("null category");1084}1085if (!Attribute.class.isAssignableFrom(category)) {1086throw new IllegalArgumentException(category +1087" is not an Attribute");1088}10891090if (!isAttributeCategorySupported(category)) {1091return null;1092}10931094int[] defaults = getDefaultPrinterSettings();1095// indices must match those in WPrinterJob.cpp1096int defPaper = defaults[0];1097int defYRes = defaults[2];1098int defQuality = defaults[3];1099int defCopies = defaults[4];1100int defOrient = defaults[5];1101int defSides = defaults[6];1102int defCollate = defaults[7];1103int defColor = defaults[8];11041105if (category == Copies.class) {1106if (defCopies > 0) {1107return new Copies(defCopies);1108} else {1109return new Copies(1);1110}1111} else if (category == Chromaticity.class) {1112if (defColor == DMCOLOR_COLOR) {1113return Chromaticity.COLOR;1114} else {1115return Chromaticity.MONOCHROME;1116}1117} else if (category == JobName.class) {1118return new JobName("Java Printing", null);1119} else if (category == OrientationRequested.class) {1120if (defOrient == DMORIENT_LANDSCAPE) {1121return OrientationRequested.LANDSCAPE;1122} else {1123return OrientationRequested.PORTRAIT;1124}1125} else if (category == PageRanges.class) {1126return new PageRanges(1, Integer.MAX_VALUE);1127} else if (category == Media.class) {1128MediaSizeName msn = findWin32Media(defPaper);1129if (msn != null) {1130if (!isSupportedMedia(msn) && mediaSizeNames != null) {1131msn = mediaSizeNames[0];1132defPaper = findPaperID(msn);1133}1134return msn;1135} else {1136initMedia();1137if ((mediaSizeNames != null) && (mediaSizeNames.length > 0)) {1138// if 'mediaSizeNames' is not null, idList and mediaSizes1139// cannot be null but to be safe, add a check1140if ((idList != null) && (mediaSizes != null) &&1141(idList.size() == mediaSizes.length)) {1142Integer defIdObj = Integer.valueOf(defPaper);1143int index = idList.indexOf(defIdObj);1144if (index>=0 && index<mediaSizes.length) {1145return mediaSizes[index].getMediaSizeName();1146}1147}11481149return mediaSizeNames[0];1150}1151}1152} else if (category == MediaPrintableArea.class) {1153/* Verify defPaper */1154MediaSizeName msn = findWin32Media(defPaper);1155if (msn != null &&1156!isSupportedMedia(msn) && mediaSizeNames != null) {1157defPaper = findPaperID(mediaSizeNames[0]);1158}1159float[] prnArea = getMediaPrintableArea(printer, defPaper);1160if (prnArea != null) {1161MediaPrintableArea printableArea = null;1162try {1163printableArea = new MediaPrintableArea(prnArea[0],1164prnArea[1],1165prnArea[2],1166prnArea[3],1167MediaPrintableArea.INCH);1168} catch (IllegalArgumentException e) {1169}1170return printableArea;1171}1172return null;1173} else if (category == SunAlternateMedia.class) {1174return null;1175} else if (category == Destination.class) {1176try {1177return new Destination((new File("out.prn")).toURI());1178} catch (SecurityException se) {1179try {1180return new Destination(new URI("file:out.prn"));1181} catch (URISyntaxException e) {1182return null;1183}1184}1185} else if (category == Sides.class) {1186switch(defSides) {1187case DMDUP_VERTICAL :1188return Sides.TWO_SIDED_LONG_EDGE;1189case DMDUP_HORIZONTAL :1190return Sides.TWO_SIDED_SHORT_EDGE;1191default :1192return Sides.ONE_SIDED;1193}1194} else if (category == PrinterResolution.class) {1195int yRes = defYRes;1196int xRes = defQuality;1197if ((xRes < 0) || (yRes < 0)) {1198int res = (yRes > xRes) ? yRes : xRes;1199if (res > 0) {1200return new PrinterResolution(res, res, PrinterResolution.DPI);1201}1202}1203else {1204return new PrinterResolution(xRes, yRes, PrinterResolution.DPI);1205}1206} else if (category == ColorSupported.class) {1207int caps = getPrinterCapabilities();1208if ((caps & DEVCAP_COLOR) != 0) {1209return ColorSupported.SUPPORTED;1210} else {1211return ColorSupported.NOT_SUPPORTED;1212}1213} else if (category == PrintQuality.class) {1214if ((defQuality < 0) && (defQuality >= DMRES_HIGH)) {1215switch (defQuality) {1216case DMRES_HIGH:1217return PrintQuality.HIGH;1218case DMRES_MEDIUM:1219return PrintQuality.NORMAL;1220default:1221return PrintQuality.DRAFT;1222}1223}1224} else if (category == RequestingUserName.class) {1225String userName = "";1226try {1227userName = System.getProperty("user.name", "");1228} catch (SecurityException se) {1229}1230return new RequestingUserName(userName, null);1231} else if (category == SheetCollate.class) {1232if (defCollate == DMCOLLATE_TRUE) {1233return SheetCollate.COLLATED;1234} else {1235return SheetCollate.UNCOLLATED;1236}1237} else if (category == Fidelity.class) {1238return Fidelity.FIDELITY_FALSE;1239}1240return null;1241}12421243private boolean isPostScriptFlavor(DocFlavor flavor) {1244if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) ||1245flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||1246flavor.equals(DocFlavor.URL.POSTSCRIPT)) {1247return true;1248}1249else {1250return false;1251}1252}12531254private boolean isPSDocAttr(Class<?> category) {1255if (category == OrientationRequested.class || category == Copies.class) {1256return true;1257}1258else {1259return false;1260}1261}12621263private boolean isAutoSense(DocFlavor flavor) {1264if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) ||1265flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) ||1266flavor.equals(DocFlavor.URL.AUTOSENSE)) {1267return true;1268}1269else {1270return false;1271}1272}12731274public Object1275getSupportedAttributeValues(Class<? extends Attribute> category,1276DocFlavor flavor,1277AttributeSet attributes)1278{1279if (category == null) {1280throw new NullPointerException("null category");1281}1282if (!Attribute.class.isAssignableFrom(category)) {1283throw new IllegalArgumentException(category +1284" does not implement Attribute");1285}1286if (flavor != null) {1287if (!isDocFlavorSupported(flavor)) {1288throw new IllegalArgumentException(flavor +1289" is an unsupported flavor");1290// if postscript & category is already specified within the1291// PostScript data we return null1292} else if (isAutoSense(flavor) ||(isPostScriptFlavor(flavor) &&1293(isPSDocAttr(category)))){1294return null;1295}1296}1297if (!isAttributeCategorySupported(category)) {1298return null;1299}13001301if (category == JobName.class) {1302return new JobName("Java Printing", null);1303} else if (category == RequestingUserName.class) {1304String userName = "";1305try {1306userName = System.getProperty("user.name", "");1307} catch (SecurityException se) {1308}1309return new RequestingUserName(userName, null);1310} else if (category == ColorSupported.class) {1311int caps = getPrinterCapabilities();1312if ((caps & DEVCAP_COLOR) != 0) {1313return ColorSupported.SUPPORTED;1314} else {1315return ColorSupported.NOT_SUPPORTED;1316}1317} else if (category == Chromaticity.class) {1318if (flavor == null ||1319flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1320flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||1321flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||1322flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||1323flavor.equals(DocFlavor.URL.GIF) ||1324flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||1325flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||1326flavor.equals(DocFlavor.URL.JPEG) ||1327flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||1328flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||1329flavor.equals(DocFlavor.URL.PNG)) {1330int caps = getPrinterCapabilities();1331if ((caps & DEVCAP_COLOR) == 0) {1332Chromaticity []arr = new Chromaticity[1];1333arr[0] = Chromaticity.MONOCHROME;1334return (arr);1335} else {1336Chromaticity []arr = new Chromaticity[2];1337arr[0] = Chromaticity.MONOCHROME;1338arr[1] = Chromaticity.COLOR;1339return (arr);1340}1341} else {1342return null;1343}1344} else if (category == Destination.class) {1345try {1346return new Destination((new File("out.prn")).toURI());1347} catch (SecurityException se) {1348try {1349return new Destination(new URI("file:out.prn"));1350} catch (URISyntaxException e) {1351return null;1352}1353}1354} else if (category == OrientationRequested.class) {1355if (flavor == null ||1356flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1357flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||1358flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||1359flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||1360flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||1361flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||1362flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||1363flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||1364flavor.equals(DocFlavor.URL.GIF) ||1365flavor.equals(DocFlavor.URL.JPEG) ||1366flavor.equals(DocFlavor.URL.PNG)) {1367OrientationRequested []arr = new OrientationRequested[3];1368arr[0] = OrientationRequested.PORTRAIT;1369arr[1] = OrientationRequested.LANDSCAPE;1370arr[2] = OrientationRequested.REVERSE_LANDSCAPE;1371return arr;1372} else {1373return null;1374}1375} else if ((category == Copies.class) ||1376(category == CopiesSupported.class)) {1377synchronized (this) {1378if (gotCopies == false) {1379nCopies = getCopiesSupported(printer, getPort());1380gotCopies = true;1381}1382}1383return new CopiesSupported(1, nCopies);1384} else if (category == Media.class) {13851386initMedia();13871388int len = (mediaSizeNames == null) ? 0 : mediaSizeNames.length;13891390MediaTray[] trays = getMediaTrays();13911392len += (trays == null) ? 0 : trays.length;13931394Media []arr = new Media[len];1395if (mediaSizeNames != null) {1396System.arraycopy(mediaSizeNames, 0, arr,13970, mediaSizeNames.length);1398}1399if (trays != null) {1400System.arraycopy(trays, 0, arr,1401len - trays.length, trays.length);1402}1403return arr;1404} else if (category == MediaPrintableArea.class) {1405// if getting printable area for a specific media size1406Media mediaName = null;1407if ((attributes != null) &&1408((mediaName =1409(Media)attributes.get(Media.class)) != null)) {14101411if (!(mediaName instanceof MediaSizeName)) {1412// if an instance of MediaTray, fall thru returning1413// all MediaPrintableAreas1414mediaName = null;1415}1416}14171418MediaPrintableArea[] mpas =1419getMediaPrintables((MediaSizeName)mediaName);1420if (mpas != null) {1421MediaPrintableArea[] arr = new MediaPrintableArea[mpas.length];1422System.arraycopy(mpas, 0, arr, 0, mpas.length);1423return arr;1424} else {1425return null;1426}1427} else if (category == SunAlternateMedia.class) {1428return new SunAlternateMedia(1429(Media)getDefaultAttributeValue(Media.class));1430} else if (category == PageRanges.class) {1431if (flavor == null ||1432flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1433flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {1434PageRanges []arr = new PageRanges[1];1435arr[0] = new PageRanges(1, Integer.MAX_VALUE);1436return arr;1437} else {1438return null;1439}1440} else if (category == PrinterResolution.class) {1441PrinterResolution[] supportedRes = getPrintResolutions();1442if (supportedRes == null) {1443return null;1444}1445PrinterResolution []arr =1446new PrinterResolution[supportedRes.length];1447System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length);1448return arr;1449} else if (category == Sides.class) {1450if (flavor == null ||1451flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1452flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {1453Sides []arr = new Sides[3];1454arr[0] = Sides.ONE_SIDED;1455arr[1] = Sides.TWO_SIDED_LONG_EDGE;1456arr[2] = Sides.TWO_SIDED_SHORT_EDGE;1457return arr;1458} else {1459return null;1460}1461} else if (category == PrintQuality.class) {1462PrintQuality []arr = new PrintQuality[3];1463arr[0] = PrintQuality.DRAFT;1464arr[1] = PrintQuality.HIGH;1465arr[2] = PrintQuality.NORMAL;1466return arr;1467} else if (category == SheetCollate.class) {1468if (flavor == null ||1469(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1470flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {1471SheetCollate []arr = new SheetCollate[2];1472arr[0] = SheetCollate.COLLATED;1473arr[1] = SheetCollate.UNCOLLATED;1474return arr;1475} else {1476return null;1477}1478} else if (category == Fidelity.class) {1479Fidelity []arr = new Fidelity[2];1480arr[0] = Fidelity.FIDELITY_FALSE;1481arr[1] = Fidelity.FIDELITY_TRUE;1482return arr;1483} else {1484return null;1485}1486}14871488public boolean isAttributeValueSupported(Attribute attr,1489DocFlavor flavor,1490AttributeSet attributes) {14911492if (attr == null) {1493throw new NullPointerException("null attribute");1494}1495Class<? extends Attribute> category = attr.getCategory();1496if (flavor != null) {1497if (!isDocFlavorSupported(flavor)) {1498throw new IllegalArgumentException(flavor +1499" is an unsupported flavor");1500// if postscript & category is already specified within the PostScript data1501// we return false1502} else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) &&1503(isPSDocAttr(category)))) {1504return false;1505}1506}15071508if (!isAttributeCategorySupported(category)) {1509return false;1510}1511else if (category == Chromaticity.class) {1512if ((flavor == null) ||1513flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1514flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||1515flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||1516flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||1517flavor.equals(DocFlavor.URL.GIF) ||1518flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||1519flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||1520flavor.equals(DocFlavor.URL.JPEG) ||1521flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||1522flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||1523flavor.equals(DocFlavor.URL.PNG)) {1524int caps = getPrinterCapabilities();1525if ((caps & DEVCAP_COLOR) != 0) {1526return true;1527} else {1528return attr == Chromaticity.MONOCHROME;1529}1530} else {1531return false;1532}1533} else if (category == Copies.class) {1534return isSupportedCopies((Copies)attr);15351536} else if (category == Destination.class) {1537URI uri = ((Destination)attr).getURI();1538if ("file".equals(uri.getScheme()) &&1539!uri.getSchemeSpecificPart().isEmpty()) {1540return true;1541} else {1542return false;1543}15441545} else if (category == Media.class) {1546if (attr instanceof MediaSizeName) {1547return isSupportedMedia((MediaSizeName)attr);1548}1549if (attr instanceof MediaTray) {1550return isSupportedMediaTray((MediaTray)attr);1551}15521553} else if (category == MediaPrintableArea.class) {1554return isSupportedMediaPrintableArea((MediaPrintableArea)attr);15551556} else if (category == SunAlternateMedia.class) {1557Media media = ((SunAlternateMedia)attr).getMedia();1558return isAttributeValueSupported(media, flavor, attributes);15591560} else if (category == PageRanges.class ||1561category == SheetCollate.class ||1562category == Sides.class) {1563if (flavor != null &&1564!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1565flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {1566return false;1567}1568} else if (category == PrinterResolution.class) {1569if (attr instanceof PrinterResolution) {1570return isSupportedResolution((PrinterResolution)attr);1571}1572} else if (category == OrientationRequested.class) {1573if (attr == OrientationRequested.REVERSE_PORTRAIT ||1574(flavor != null) &&1575!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1576flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||1577flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||1578flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||1579flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||1580flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||1581flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||1582flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||1583flavor.equals(DocFlavor.URL.GIF) ||1584flavor.equals(DocFlavor.URL.JPEG) ||1585flavor.equals(DocFlavor.URL.PNG))) {1586return false;1587}15881589} else if (category == ColorSupported.class) {1590int caps = getPrinterCapabilities();1591boolean isColorSup = ((caps & DEVCAP_COLOR) != 0);1592if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) ||1593(isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) {1594return false;1595}1596} else if (category == DialogTypeSelection.class) {1597return true; // isHeadless was checked by category support1598} else if (category == DialogOwner.class) {1599DialogOwner owner = (DialogOwner)attr;1600DialogTypeSelection dts = (attributes == null) ? null :1601(DialogTypeSelection)attributes.get(DialogTypeSelection.class);1602if (dts == DialogTypeSelection.NATIVE) {1603return DialogOwnerAccessor.getID(owner) != 0;1604} else {1605if (DialogOwnerAccessor.getID(owner) != 0) {1606return false;1607} else if (owner.getOwner() != null) {1608return true;1609} else {1610return Toolkit.getDefaultToolkit().isAlwaysOnTopSupported();1611}1612}1613}1614return true;1615}16161617public AttributeSet getUnsupportedAttributes(DocFlavor flavor,1618AttributeSet attributes) {16191620if (flavor != null && !isDocFlavorSupported(flavor)) {1621throw new IllegalArgumentException("flavor " + flavor +1622" is not supported");1623}16241625if (attributes == null) {1626return null;1627}16281629Attribute attr;1630AttributeSet unsupp = new HashAttributeSet();1631Attribute []attrs = attributes.toArray();1632for (int i=0; i<attrs.length; i++) {1633try {1634attr = attrs[i];1635if (!isAttributeCategorySupported(attr.getCategory())) {1636unsupp.add(attr);1637}1638else if (!isAttributeValueSupported(attr, flavor, attributes)) {1639unsupp.add(attr);1640}1641} catch (ClassCastException e) {1642}1643}1644if (unsupp.isEmpty()) {1645return null;1646} else {1647return unsupp;1648}1649}16501651private Win32DocumentPropertiesUI docPropertiesUI = null;16521653private static class Win32DocumentPropertiesUI1654extends DocumentPropertiesUI {16551656Win32PrintService service;16571658private Win32DocumentPropertiesUI(Win32PrintService s) {1659service = s;1660}16611662public PrintRequestAttributeSet1663showDocumentProperties(PrinterJob job,1664Window owner,1665PrintService service,1666PrintRequestAttributeSet aset) {16671668if (!(job instanceof WPrinterJob)) {1669return null;1670}1671WPrinterJob wJob = (WPrinterJob)job;1672return wJob.showDocumentProperties(owner, service, aset);1673}1674}16751676private synchronized DocumentPropertiesUI getDocumentPropertiesUI() {1677return new Win32DocumentPropertiesUI(this);1678}16791680private static class Win32ServiceUIFactory extends ServiceUIFactory {16811682Win32PrintService service;16831684Win32ServiceUIFactory(Win32PrintService s) {1685service = s;1686}16871688public Object getUI(int role, String ui) {1689if (role <= ServiceUIFactory.MAIN_UIROLE) {1690return null;1691}1692if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE &&1693DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui))1694{1695return service.getDocumentPropertiesUI();1696}1697throw new IllegalArgumentException("Unsupported role");1698}16991700public String[] getUIClassNamesForRole(int role) {17011702if (role <= ServiceUIFactory.MAIN_UIROLE) {1703return null;1704}1705if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) {1706String[] names = new String[0];1707names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME;1708return names;1709}1710throw new IllegalArgumentException("Unsupported role");1711}1712}17131714private Win32ServiceUIFactory uiFactory = null;17151716public synchronized ServiceUIFactory getServiceUIFactory() {1717if (uiFactory == null) {1718uiFactory = new Win32ServiceUIFactory(this);1719}1720return uiFactory;1721}17221723public String toString() {1724return "Win32 Printer : " + getName();1725}17261727public boolean equals(Object obj) {1728return (obj == this ||1729(obj instanceof Win32PrintService &&1730((Win32PrintService)obj).getName().equals(getName())));1731}17321733public int hashCode() {1734return this.getClass().hashCode()+getName().hashCode();1735}17361737public boolean usesClass(Class<?> c) {1738return (c == sun.awt.windows.WPrinterJob.class);1739}17401741private native int[] getAllMediaIDs(String printerName, String port);1742private native int[] getAllMediaSizes(String printerName, String port);1743private native int[] getAllMediaTrays(String printerName, String port);1744private native float[] getMediaPrintableArea(String printerName,1745int paperSize);1746private native String[] getAllMediaNames(String printerName, String port);1747private native String[] getAllMediaTrayNames(String printerName, String port);1748private native int getCopiesSupported(String printerName, String port);1749private native int[] getAllResolutions(String printerName, String port);1750private native int getCapabilities(String printerName, String port);17511752private native int[] getDefaultSettings(String printerName, String port);1753private native int getJobStatus(String printerName, int type);1754private native String getPrinterPort(String printerName);1755}17561757@SuppressWarnings("serial") // JDK implementation class1758class Win32MediaSize extends MediaSizeName {1759private static ArrayList<String> winStringTable = new ArrayList<>();1760private static ArrayList<Win32MediaSize> winEnumTable = new ArrayList<>();1761private static MediaSize[] predefMedia;17621763private int dmPaperID; // driver ID for this paper.17641765private Win32MediaSize(int x) {1766super(x);17671768}17691770private static synchronized int nextValue(String name) {1771winStringTable.add(name);1772return (winStringTable.size()-1);1773}17741775public static synchronized Win32MediaSize findMediaName(String name) {1776int nameIndex = winStringTable.indexOf(name);1777if (nameIndex != -1) {1778return winEnumTable.get(nameIndex);1779}1780return null;1781}17821783public static MediaSize[] getPredefMedia() {1784return predefMedia;1785}17861787public Win32MediaSize(String name, int dmPaper) {1788super(nextValue(name));1789dmPaperID = dmPaper;1790winEnumTable.add(this);1791}17921793private MediaSizeName[] getSuperEnumTable() {1794return (MediaSizeName[])super.getEnumValueTable();1795}17961797static {1798/* initialize predefMedia */1799{1800Win32MediaSize winMedia = new Win32MediaSize(-1);18011802// cannot call getSuperEnumTable directly because of static context1803MediaSizeName[] enumMedia = winMedia.getSuperEnumTable();1804if (enumMedia != null) {1805predefMedia = new MediaSize[enumMedia.length];18061807for (int i=0; i<enumMedia.length; i++) {1808predefMedia[i] = MediaSize.getMediaSizeForName(enumMedia[i]);1809}1810}1811}1812}18131814int getDMPaper() {1815return dmPaperID;1816}18171818protected String[] getStringTable() {1819String[] nameTable = new String[winStringTable.size()];1820return winStringTable.toArray(nameTable);1821}18221823protected EnumSyntax[] getEnumValueTable() {1824MediaSizeName[] enumTable = new MediaSizeName[winEnumTable.size()];1825return winEnumTable.toArray(enumTable);1826}18271828}182918301831