/* * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.print; import java.awt.Window; import java.awt.print.PrinterJob; import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.HashMap; import javax.print.DocFlavor; import javax.print.DocPrintJob; import javax.print.PrintService; import javax.print.ServiceUIFactory; import javax.print.attribute.Attribute; import javax.print.attribute.AttributeSet; import javax.print.attribute.AttributeSetUtilities; import javax.print.attribute.EnumSyntax; import javax.print.attribute.HashAttributeSet; import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.PrintServiceAttributeSet; import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.standard.PrinterName; import javax.print.attribute.standard.PrinterIsAcceptingJobs; import javax.print.attribute.standard.QueuedJobCount; import javax.print.attribute.standard.JobName; import javax.print.attribute.standard.RequestingUserName; import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.CopiesSupported; import javax.print.attribute.standard.Destination; import javax.print.attribute.standard.Fidelity; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaSizeName; import javax.print.attribute.standard.MediaSize; import javax.print.attribute.standard.MediaTray; import javax.print.attribute.standard.MediaPrintableArea; import javax.print.attribute.standard.OrientationRequested; import javax.print.attribute.standard.PageRanges; import javax.print.attribute.standard.PrinterState; import javax.print.attribute.standard.PrinterStateReason; import javax.print.attribute.standard.PrinterStateReasons; import javax.print.attribute.standard.Severity; import javax.print.attribute.standard.Sides; import javax.print.attribute.standard.ColorSupported; import javax.print.attribute.standard.PrintQuality; import javax.print.attribute.standard.PrinterResolution; import javax.print.attribute.standard.SheetCollate; import javax.print.event.PrintServiceAttributeListener; import sun.awt.windows.WPrinterJob; public class Win32PrintService implements PrintService, AttributeUpdater, SunPrinterJobService { public static MediaSize[] predefMedia = Win32MediaSize.getPredefMedia(); private static final DocFlavor[] supportedFlavors = { DocFlavor.BYTE_ARRAY.GIF, DocFlavor.INPUT_STREAM.GIF, DocFlavor.URL.GIF, DocFlavor.BYTE_ARRAY.JPEG, DocFlavor.INPUT_STREAM.JPEG, DocFlavor.URL.JPEG, DocFlavor.BYTE_ARRAY.PNG, DocFlavor.INPUT_STREAM.PNG, DocFlavor.URL.PNG, DocFlavor.SERVICE_FORMATTED.PAGEABLE, DocFlavor.SERVICE_FORMATTED.PRINTABLE, DocFlavor.BYTE_ARRAY.AUTOSENSE, DocFlavor.URL.AUTOSENSE, DocFlavor.INPUT_STREAM.AUTOSENSE }; /* let's try to support a few of these */ private static final Class[] serviceAttrCats = { PrinterName.class, PrinterIsAcceptingJobs.class, QueuedJobCount.class, ColorSupported.class, }; /* it turns out to be inconvenient to store the other categories * separately because many attributes are in multiple categories. */ private static Class[] otherAttrCats = { JobName.class, RequestingUserName.class, Copies.class, Destination.class, OrientationRequested.class, PageRanges.class, Media.class, MediaPrintableArea.class, Fidelity.class, // We support collation on 2D printer jobs, even if the driver can't. SheetCollate.class, SunAlternateMedia.class, Chromaticity.class }; /* * This table together with methods findWin32Media and * findMatchingMediaSizeNameMM are declared public as these are also * used in WPrinterJob.java. */ public static final MediaSizeName[] dmPaperToPrintService = { MediaSizeName.NA_LETTER, MediaSizeName.NA_LETTER, MediaSizeName.TABLOID, MediaSizeName.LEDGER, MediaSizeName.NA_LEGAL, MediaSizeName.INVOICE, MediaSizeName.EXECUTIVE, MediaSizeName.ISO_A3, MediaSizeName.ISO_A4, MediaSizeName.ISO_A4, MediaSizeName.ISO_A5, MediaSizeName.JIS_B4, MediaSizeName.JIS_B5, MediaSizeName.FOLIO, MediaSizeName.QUARTO, MediaSizeName.NA_10X14_ENVELOPE, MediaSizeName.B, MediaSizeName.NA_LETTER, MediaSizeName.NA_NUMBER_9_ENVELOPE, MediaSizeName.NA_NUMBER_10_ENVELOPE, MediaSizeName.NA_NUMBER_11_ENVELOPE, MediaSizeName.NA_NUMBER_12_ENVELOPE, MediaSizeName.NA_NUMBER_14_ENVELOPE, MediaSizeName.C, MediaSizeName.D, MediaSizeName.E, MediaSizeName.ISO_DESIGNATED_LONG, MediaSizeName.ISO_C5, MediaSizeName.ISO_C3, MediaSizeName.ISO_C4, MediaSizeName.ISO_C6, MediaSizeName.ITALY_ENVELOPE, MediaSizeName.ISO_B4, MediaSizeName.ISO_B5, MediaSizeName.ISO_B6, MediaSizeName.ITALY_ENVELOPE, MediaSizeName.MONARCH_ENVELOPE, MediaSizeName.PERSONAL_ENVELOPE, MediaSizeName.NA_10X15_ENVELOPE, MediaSizeName.NA_9X12_ENVELOPE, MediaSizeName.FOLIO, MediaSizeName.ISO_B4, MediaSizeName.JAPANESE_POSTCARD, MediaSizeName.NA_9X11_ENVELOPE, }; private static final MediaTray[] dmPaperBinToPrintService = { MediaTray.TOP, MediaTray.BOTTOM, MediaTray.MIDDLE, MediaTray.MANUAL, MediaTray.ENVELOPE, Win32MediaTray.ENVELOPE_MANUAL, Win32MediaTray.AUTO, Win32MediaTray.TRACTOR, Win32MediaTray.SMALL_FORMAT, Win32MediaTray.LARGE_FORMAT, MediaTray.LARGE_CAPACITY, null, null, MediaTray.MAIN, Win32MediaTray.FORMSOURCE, }; // from wingdi.h private static int DM_PAPERSIZE = 0x2; private static int DM_PRINTQUALITY = 0x400; private static int DM_YRESOLUTION = 0x2000; private static final int DMRES_MEDIUM = -3; private static final int DMRES_HIGH = -4; private static final int DMORIENT_LANDSCAPE = 2; private static final int DMDUP_VERTICAL = 2; private static final int DMDUP_HORIZONTAL = 3; private static final int DMCOLLATE_TRUE = 1; private static final int DMCOLOR_MONOCHROME = 1; private static final int DMCOLOR_COLOR = 2; // media sizes with indices above dmPaperToPrintService' length private static final int DMPAPER_A2 = 66; private static final int DMPAPER_A6 = 70; private static final int DMPAPER_B6_JIS = 88; // Bit settings for getPrinterCapabilities which matches that // of native getCapabilities in WPrinterJob.cpp private static final int DEVCAP_COLOR = 0x0001; private static final int DEVCAP_DUPLEX = 0x0002; private static final int DEVCAP_COLLATE = 0x0004; private static final int DEVCAP_QUALITY = 0x0008; private static final int DEVCAP_POSTSCRIPT = 0x0010; private String printer; private PrinterName name; private String port; transient private PrintServiceAttributeSet lastSet; transient private ServiceNotifier notifier = null; private MediaSizeName[] mediaSizeNames; private MediaPrintableArea[] mediaPrintables; private MediaTray[] mediaTrays; private PrinterResolution[] printRes; private HashMap mpaMap; private int nCopies; private int prnCaps; private int[] defaultSettings; private boolean gotTrays; private boolean gotCopies; private boolean mediaInitialized; private boolean mpaListInitialized; private ArrayList idList; private MediaSize[] mediaSizes; private boolean isInvalid; Win32PrintService(String name) { if (name == null) { throw new IllegalArgumentException("null printer name"); } printer = name; // initialize flags mediaInitialized = false; gotTrays = false; gotCopies = false; isInvalid = false; printRes = null; prnCaps = 0; defaultSettings = null; port = null; } public void invalidateService() { isInvalid = true; } public String getName() { return printer; } private PrinterName getPrinterName() { if (name == null) { name = new PrinterName(printer, null); } return name; } public int findPaperID(MediaSizeName msn) { if (msn instanceof Win32MediaSize) { Win32MediaSize winMedia = (Win32MediaSize)msn; return winMedia.getDMPaper(); } else { for (int id=0; id= 1 && dmBin <= dmPaperBinToPrintService.length) { return dmPaperBinToPrintService[dmBin-1]; } MediaTray[] trays = getMediaTrays(); if (trays != null) { for (int i=0;i= 1 && dmIndex <= dmPaperToPrintService.length) { return dmPaperToPrintService[dmIndex - 1]; } switch(dmIndex) { /* matching media sizes with indices beyond dmPaperToPrintService's length */ case DMPAPER_A2: return MediaSizeName.ISO_A2; case DMPAPER_A6: return MediaSizeName.ISO_A6; case DMPAPER_B6_JIS: return MediaSizeName.JIS_B6; default: return null; } } private boolean addToUniqueList(ArrayList msnList, MediaSizeName mediaName) { MediaSizeName msn; for (int i=0; i< msnList.size(); i++) { msn = (MediaSizeName)msnList.get(i); if (msn == mediaName) { return false; } } msnList.add(mediaName); return true; } private synchronized void initMedia() { if (mediaInitialized == true) { return; } mediaInitialized = true; int[] media = getAllMediaIDs(printer, getPort()); if (media == null) { return; } ArrayList msnList = new ArrayList(); ArrayList trailingWmsList = new ArrayList(); ArrayList printableList = new ArrayList(); MediaSizeName mediaName; boolean added; boolean queryFailure = false; float[] prnArea; // Get all mediaSizes supported by the printer. // We convert media to ArrayList idList and pass this to the // function for getting mediaSizes. // This is to ensure that mediaSizes and media IDs have 1-1 correspondence. // We remove from ID list any invalid mediaSize. Though this is rare, // it happens in HP 4050 German driver. idList = new ArrayList(); for (int i=0; i < media.length; i++) { idList.add(Integer.valueOf(media[i])); } ArrayList dmPaperNameList = new ArrayList(); mediaSizes = getMediaSizes(idList, media, dmPaperNameList); for (int i = 0; i < idList.size(); i++) { // match Win ID with our predefined ID using table mediaName = findWin32Media(((Integer)idList.get(i)).intValue()); // Verify that this standard size is the same size as that // reported by the driver. This should be the case except when // the driver is mis-using a standard windows paper ID. if (mediaName != null && idList.size() == mediaSizes.length) { MediaSize win32Size = MediaSize.getMediaSizeForName(mediaName); MediaSize driverSize = mediaSizes[i]; int error = 2540; // == 1/10" if (Math.abs(win32Size.getX(1)-driverSize.getX(1)) > error || Math.abs(win32Size.getY(1)-driverSize.getY(1)) > error) { mediaName = null; } } boolean dmPaperIDMatched = (mediaName != null); // No match found, then we get the MediaSizeName out of the MediaSize // This requires 1-1 correspondence, lengths must be checked. if ((mediaName == null) && (idList.size() == mediaSizes.length)) { mediaName = mediaSizes[i].getMediaSizeName(); } // Add mediaName to the msnList added = false; if (mediaName != null) { added = addToUniqueList(msnList, mediaName); } if ((!dmPaperIDMatched || !added) && (idList.size() == dmPaperNameList.size())) { /* The following block allows to add such media names to the list, whose sizes * matched with media sizes predefined in JDK, while whose paper IDs did not, * or whose sizes and paper IDs both did not match with any predefined in JDK. */ Win32MediaSize wms = Win32MediaSize.findMediaName(dmPaperNameList.get(i)); if ((wms == null) && (idList.size() == mediaSizes.length)) { wms = new Win32MediaSize(dmPaperNameList.get(i), (Integer)idList.get(i)); mediaSizes[i] = new MediaSize(mediaSizes[i].getX(MediaSize.MM), mediaSizes[i].getY(MediaSize.MM), MediaSize.MM, wms); } if ((wms != null) && (wms != mediaName)) { if (!added) { added = addToUniqueList(msnList, mediaName = wms); } else { trailingWmsList.add(wms); } } } } for (Win32MediaSize wms : trailingWmsList) { added = addToUniqueList(msnList, wms); } // init mediaSizeNames mediaSizeNames = new MediaSizeName[msnList.size()]; msnList.toArray(mediaSizeNames); } /* * Gets a list of MediaPrintableAreas using a call to native function. * msn is MediaSizeName used to get a specific printable area. If null, * it will get all the supported MediPrintableAreas. */ private synchronized MediaPrintableArea[] getMediaPrintables(MediaSizeName msn) { if (msn == null) { if (mpaListInitialized == true) { return mediaPrintables; } } else { // get from cached mapping of MPAs if (mpaMap != null && (mpaMap.get(msn) != null)) { MediaPrintableArea[] mpaArr = new MediaPrintableArea[1]; mpaArr[0] = (MediaPrintableArea)mpaMap.get(msn); return mpaArr; } } initMedia(); if ((mediaSizeNames == null) || (mediaSizeNames.length == 0)) { return null; } MediaSizeName[] loopNames; if (msn != null) { loopNames = new MediaSizeName[1]; loopNames[0] = msn; } else { loopNames = mediaSizeNames; } if (mpaMap == null) { mpaMap = new HashMap(); } for (int i=0; i < loopNames.length; i++) { MediaSizeName mediaName = loopNames[i]; if (mpaMap.get(mediaName) != null) { continue; } if (mediaName != null) { int defPaper = findPaperID(mediaName); float[] prnArea = (defPaper != 0) ? getMediaPrintableArea(printer, defPaper) : null; MediaPrintableArea printableArea = null; if (prnArea != null) { try { printableArea = new MediaPrintableArea(prnArea[0], prnArea[1], prnArea[2], prnArea[3], MediaPrintableArea.INCH); mpaMap.put(mediaName, printableArea); } catch (IllegalArgumentException e) { } } else { // if getting MPA failed, we use MediaSize MediaSize ms = MediaSize.getMediaSizeForName((MediaSizeName)mediaName); if (ms != null) { try { printableArea = new MediaPrintableArea(0, 0, ms.getX(MediaSize.INCH), ms.getY(MediaSize.INCH), MediaPrintableArea.INCH); mpaMap.put(mediaName, printableArea); } catch (IllegalArgumentException e) { } } } } //mediaName != null } if (mpaMap.size() == 0) { return null; } if (msn != null) { if (mpaMap.get(msn) == null) { return null; } MediaPrintableArea[] mpaArr = new MediaPrintableArea[1]; // by this time, we've already gotten the desired MPA mpaArr[0] = (MediaPrintableArea)mpaMap.get(msn); return mpaArr; } else { mediaPrintables = (MediaPrintableArea[])mpaMap.values().toArray(new MediaPrintableArea[0]); mpaListInitialized = true; return mediaPrintables; } } private synchronized MediaTray[] getMediaTrays() { if (gotTrays == true && mediaTrays != null) { return mediaTrays; } String prnPort = getPort(); int[] mediaTr = getAllMediaTrays(printer, prnPort); String[] winMediaTrayNames = getAllMediaTrayNames(printer, prnPort); if ((mediaTr == null) || (winMediaTrayNames == null)){ return null; } /* first count how many valid bins there are so we can allocate * an array of the correct size */ int nTray = 0; for (int i=0; i < mediaTr.length ; i++) { if (mediaTr[i] > 0) nTray++; } MediaTray[] arr = new MediaTray[nTray]; int dmBin; /* Some drivers in Win 7 don't have the same length for DC_BINS and * DC_BINNAMES so there is no guarantee that lengths of mediaTr and * winMediaTrayNames are equal. To avoid getting ArrayIndexOutOfBounds, * we need to make sure we get the minimum of the two. */ for (int i = 0, j=0; i < Math.min(mediaTr.length, winMediaTrayNames.length); i++) { dmBin = mediaTr[i]; if (dmBin > 0) { // check for unsupported DMBINs and create new Win32MediaTray if ((dmBin > dmPaperBinToPrintService.length) || (dmPaperBinToPrintService[dmBin-1] == null)) { arr[j++] = new Win32MediaTray(dmBin, winMediaTrayNames[i]); } else { arr[j++] = dmPaperBinToPrintService[dmBin-1]; } } // no else - For invalid ids, just ignore it because assigning a "default" // value may result in duplicate trays. } mediaTrays = arr; gotTrays = true; return mediaTrays; } private boolean isSameSize(float w1, float h1, float w2, float h2) { float diffX = w1 - w2; float diffY = h1 - h2; // Get diff of reverse dimensions // EPSON Stylus COLOR 860 reverses envelope's width & height float diffXrev = w1 - h2; float diffYrev = h1 - w2; if (((Math.abs(diffX)<=1) && (Math.abs(diffY)<=1)) || ((Math.abs(diffXrev)<=1) && (Math.abs(diffYrev)<=1))){ return true; } else { return false; } } public MediaSizeName findMatchingMediaSizeNameMM (float w, float h){ if (predefMedia != null) { for (int k=0; k dmPaperNameList) { if (dmPaperNameList == null) { dmPaperNameList = new ArrayList(); } String prnPort = getPort(); int[] mediaSz = getAllMediaSizes(printer, prnPort); String[] winMediaNames = getAllMediaNames(printer, prnPort); MediaSizeName msn = null; MediaSize ms = null; float wid, ht; if ((mediaSz == null) || (winMediaNames == null)) { return null; } int nMedia = mediaSz.length/2; ArrayList msList = new ArrayList(); for (int i = 0; i < nMedia; i++, ms=null) { wid = mediaSz[i*2]/10f; ht = mediaSz[i*2+1]/10f; // Make sure to validate wid & ht. // HP LJ 4050 (german) causes IAE in Sonderformat paper, wid & ht // returned is not constant. if ((wid <= 0) || (ht <= 0)) { //Remove corresponding ID from list if (nMedia == media.length) { Integer remObj = Integer.valueOf(media[i]); idList.remove(idList.indexOf(remObj)); } continue; } // Find matching media using dimensions. // This call matches only with our own predefined sizes. msn = findMatchingMediaSizeNameMM(wid, ht); if (msn != null) { ms = MediaSize.getMediaSizeForName(msn); } if (ms != null) { msList.add(ms); dmPaperNameList.add(winMediaNames[i]); } else { Win32MediaSize wms = Win32MediaSize.findMediaName(winMediaNames[i]); if (wms == null) { wms = new Win32MediaSize(winMediaNames[i], media[i]); } try { ms = new MediaSize(wid, ht, MediaSize.MM, wms); msList.add(ms); dmPaperNameList.add(winMediaNames[i]); } catch(IllegalArgumentException e) { if (nMedia == media.length) { Integer remObj = Integer.valueOf(media[i]); idList.remove(idList.indexOf(remObj)); } } } } MediaSize[] arr2 = new MediaSize[msList.size()]; msList.toArray(arr2); return arr2; } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() { if (getJobStatus(printer, 2) != 1) { return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS; } else { return PrinterIsAcceptingJobs.ACCEPTING_JOBS; } } private PrinterState getPrinterState() { if (isInvalid) { return PrinterState.STOPPED; } else { return null; } } private PrinterStateReasons getPrinterStateReasons() { if (isInvalid) { PrinterStateReasons psr = new PrinterStateReasons(); psr.put(PrinterStateReason.SHUTDOWN, Severity.ERROR); return psr; } else { return null; } } private QueuedJobCount getQueuedJobCount() { int count = getJobStatus(printer, 1); if (count != -1) { return new QueuedJobCount(count); } else { return new QueuedJobCount(0); } } private boolean isSupportedCopies(Copies copies) { synchronized (this) { if (gotCopies == false) { nCopies = getCopiesSupported(printer, getPort()); gotCopies = true; } } int numCopies = copies.getValue(); return (numCopies > 0 && numCopies <= nCopies); } private boolean isSupportedMedia(MediaSizeName msn) { initMedia(); if (mediaSizeNames != null) { for (int i=0; i T getAttribute(Class category) { if (category == null) { throw new NullPointerException("category"); } if (!(PrintServiceAttribute.class.isAssignableFrom(category))) { throw new IllegalArgumentException("Not a PrintServiceAttribute"); } if (category == ColorSupported.class) { int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) != 0) { return (T)ColorSupported.SUPPORTED; } else { return (T)ColorSupported.NOT_SUPPORTED; } } else if (category == PrinterName.class) { return (T)getPrinterName(); } else if (category == PrinterState.class) { return (T)getPrinterState(); } else if (category == PrinterStateReasons.class) { return (T)getPrinterStateReasons(); } else if (category == QueuedJobCount.class) { return (T)getQueuedJobCount(); } else if (category == PrinterIsAcceptingJobs.class) { return (T)getPrinterIsAcceptingJobs(); } else { return null; } } public PrintServiceAttributeSet getAttributes() { PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); attrs.add(getPrinterName()); attrs.add(getPrinterIsAcceptingJobs()); PrinterState prnState = getPrinterState(); if (prnState != null) { attrs.add(prnState); } PrinterStateReasons prnStateReasons = getPrinterStateReasons(); if (prnStateReasons != null) { attrs.add(prnStateReasons); } attrs.add(getQueuedJobCount()); int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) != 0) { attrs.add(ColorSupported.SUPPORTED); } else { attrs.add(ColorSupported.NOT_SUPPORTED); } return AttributeSetUtilities.unmodifiableView(attrs); } public DocFlavor[] getSupportedDocFlavors() { int len = supportedFlavors.length; DocFlavor[] supportedDocFlavors; int caps = getPrinterCapabilities(); // doc flavors supported // if PostScript is supported if ((caps & DEVCAP_POSTSCRIPT) != 0) { supportedDocFlavors = new DocFlavor[len+3]; System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len); supportedDocFlavors[len] = DocFlavor.BYTE_ARRAY.POSTSCRIPT; supportedDocFlavors[len+1] = DocFlavor.INPUT_STREAM.POSTSCRIPT; supportedDocFlavors[len+2] = DocFlavor.URL.POSTSCRIPT; } else { supportedDocFlavors = new DocFlavor[len]; System.arraycopy(supportedFlavors, 0, supportedDocFlavors, 0, len); } return supportedDocFlavors; } public boolean isDocFlavorSupported(DocFlavor flavor) { /* To avoid a native query which may be time-consuming * do not invoke native unless postscript support is being queried. * Instead just check the ones we 'always' support */ DocFlavor[] supportedDocFlavors; if (isPostScriptFlavor(flavor)) { supportedDocFlavors = getSupportedDocFlavors(); } else { supportedDocFlavors = supportedFlavors; } for (int f=0; f[] getSupportedAttributeCategories() { ArrayList categList = new ArrayList(otherAttrCats.length+3); for (int i=0; i < otherAttrCats.length; i++) { categList.add(otherAttrCats[i]); } int caps = getPrinterCapabilities(); if ((caps & DEVCAP_DUPLEX) != 0) { categList.add(Sides.class); } if ((caps & DEVCAP_QUALITY) != 0) { int[] defaults = getDefaultPrinterSettings(); // Added check: if supported, we should be able to get the default. if ((defaults[3] >= DMRES_HIGH) && (defaults[3] < 0)) { categList.add(PrintQuality.class); } } PrinterResolution[] supportedRes = getPrintResolutions(); if ((supportedRes!=null) && (supportedRes.length>0)) { categList.add(PrinterResolution.class); } return (Class[])categList.toArray(new Class[categList.size()]); } public boolean isAttributeCategorySupported(Class category) { if (category == null) { throw new NullPointerException("null category"); } if (!(Attribute.class.isAssignableFrom(category))) { throw new IllegalArgumentException(category + " is not an Attribute"); } Class[] classList = getSupportedAttributeCategories(); for (int i = 0; i < classList.length; i++) { if (category.equals(classList[i])) { return true; } } return false; } public Object getDefaultAttributeValue(Class category) { if (category == null) { throw new NullPointerException("null category"); } if (!Attribute.class.isAssignableFrom(category)) { throw new IllegalArgumentException(category + " is not an Attribute"); } if (!isAttributeCategorySupported(category)) { return null; } int[] defaults = getDefaultPrinterSettings(); // indices must match those in WPrinterJob.cpp int defPaper = defaults[0]; int defYRes = defaults[2]; int defQuality = defaults[3]; int defCopies = defaults[4]; int defOrient = defaults[5]; int defSides = defaults[6]; int defCollate = defaults[7]; int defColor = defaults[8]; if (category == Copies.class) { if (defCopies > 0) { return new Copies(defCopies); } else { return new Copies(1); } } else if (category == Chromaticity.class) { if (defColor == DMCOLOR_COLOR) { return Chromaticity.COLOR; } else { return Chromaticity.MONOCHROME; } } else if (category == JobName.class) { return new JobName("Java Printing", null); } else if (category == OrientationRequested.class) { if (defOrient == DMORIENT_LANDSCAPE) { return OrientationRequested.LANDSCAPE; } else { return OrientationRequested.PORTRAIT; } } else if (category == PageRanges.class) { return new PageRanges(1, Integer.MAX_VALUE); } else if (category == Media.class) { MediaSizeName msn = findWin32Media(defPaper); if (msn != null) { if (!isSupportedMedia(msn) && mediaSizeNames != null) { msn = mediaSizeNames[0]; defPaper = findPaperID(msn); } return msn; } else { initMedia(); if ((mediaSizeNames != null) && (mediaSizeNames.length > 0)) { // if 'mediaSizeNames' is not null, idList and mediaSizes // cannot be null but to be safe, add a check if ((idList != null) && (mediaSizes != null) && (idList.size() == mediaSizes.length)) { Integer defIdObj = Integer.valueOf(defPaper); int index = idList.indexOf(defIdObj); if (index>=0 && index xRes) ? yRes : xRes; if (res > 0) { return new PrinterResolution(res, res, PrinterResolution.DPI); } } else { return new PrinterResolution(xRes, yRes, PrinterResolution.DPI); } } else if (category == ColorSupported.class) { int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) != 0) { return ColorSupported.SUPPORTED; } else { return ColorSupported.NOT_SUPPORTED; } } else if (category == PrintQuality.class) { if ((defQuality < 0) && (defQuality >= DMRES_HIGH)) { switch (defQuality) { case DMRES_HIGH: return PrintQuality.HIGH; case DMRES_MEDIUM: return PrintQuality.NORMAL; default: return PrintQuality.DRAFT; } } } else if (category == RequestingUserName.class) { String userName = ""; try { userName = System.getProperty("user.name", ""); } catch (SecurityException se) { } return new RequestingUserName(userName, null); } else if (category == SheetCollate.class) { if (defCollate == DMCOLLATE_TRUE) { return SheetCollate.COLLATED; } else { return SheetCollate.UNCOLLATED; } } else if (category == Fidelity.class) { return Fidelity.FIDELITY_FALSE; } return null; } private boolean isPostScriptFlavor(DocFlavor flavor) { if (flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT) || flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || flavor.equals(DocFlavor.URL.POSTSCRIPT)) { return true; } else { return false; } } private boolean isPSDocAttr(Class category) { if (category == OrientationRequested.class || category == Copies.class) { return true; } else { return false; } } private boolean isAutoSense(DocFlavor flavor) { if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) || flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) || flavor.equals(DocFlavor.URL.AUTOSENSE)) { return true; } else { return false; } } public Object getSupportedAttributeValues(Class category, DocFlavor flavor, AttributeSet attributes) { if (category == null) { throw new NullPointerException("null category"); } if (!Attribute.class.isAssignableFrom(category)) { throw new IllegalArgumentException(category + " does not implement Attribute"); } if (flavor != null) { if (!isDocFlavorSupported(flavor)) { throw new IllegalArgumentException(flavor + " is an unsupported flavor"); // if postscript & category is already specified within the // PostScript data we return null } else if (isAutoSense(flavor) ||(isPostScriptFlavor(flavor) && (isPSDocAttr(category)))){ return null; } } if (!isAttributeCategorySupported(category)) { return null; } if (category == JobName.class) { return new JobName("Java Printing", null); } else if (category == RequestingUserName.class) { String userName = ""; try { userName = System.getProperty("user.name", ""); } catch (SecurityException se) { } return new RequestingUserName(userName, null); } else if (category == ColorSupported.class) { int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) != 0) { return ColorSupported.SUPPORTED; } else { return ColorSupported.NOT_SUPPORTED; } } else if (category == Chromaticity.class) { if (flavor == null || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || flavor.equals(DocFlavor.URL.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.URL.PNG)) { int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) == 0) { Chromaticity []arr = new Chromaticity[1]; arr[0] = Chromaticity.MONOCHROME; return (arr); } else { Chromaticity []arr = new Chromaticity[2]; arr[0] = Chromaticity.MONOCHROME; arr[1] = Chromaticity.COLOR; return (arr); } } else { return null; } } else if (category == Destination.class) { try { return new Destination((new File("out.prn")).toURI()); } catch (SecurityException se) { try { return new Destination(new URI("file:out.prn")); } catch (URISyntaxException e) { return null; } } } else if (category == OrientationRequested.class) { if (flavor == null || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.URL.JPEG) || flavor.equals(DocFlavor.URL.PNG)) { OrientationRequested []arr = new OrientationRequested[3]; arr[0] = OrientationRequested.PORTRAIT; arr[1] = OrientationRequested.LANDSCAPE; arr[2] = OrientationRequested.REVERSE_LANDSCAPE; return arr; } else { return null; } } else if ((category == Copies.class) || (category == CopiesSupported.class)) { synchronized (this) { if (gotCopies == false) { nCopies = getCopiesSupported(printer, getPort()); gotCopies = true; } } return new CopiesSupported(1, nCopies); } else if (category == Media.class) { initMedia(); int len = (mediaSizeNames == null) ? 0 : mediaSizeNames.length; MediaTray[] trays = getMediaTrays(); len += (trays == null) ? 0 : trays.length; Media []arr = new Media[len]; if (mediaSizeNames != null) { System.arraycopy(mediaSizeNames, 0, arr, 0, mediaSizeNames.length); } if (trays != null) { System.arraycopy(trays, 0, arr, len - trays.length, trays.length); } return arr; } else if (category == MediaPrintableArea.class) { // if getting printable area for a specific media size Media mediaName = null; if ((attributes != null) && ((mediaName = (Media)attributes.get(Media.class)) != null)) { if (!(mediaName instanceof MediaSizeName)) { // if an instance of MediaTray, fall thru returning // all MediaPrintableAreas mediaName = null; } } MediaPrintableArea[] mpas = getMediaPrintables((MediaSizeName)mediaName); if (mpas != null) { MediaPrintableArea[] arr = new MediaPrintableArea[mpas.length]; System.arraycopy(mpas, 0, arr, 0, mpas.length); return arr; } else { return null; } } else if (category == SunAlternateMedia.class) { return new SunAlternateMedia( (Media)getDefaultAttributeValue(Media.class)); } else if (category == PageRanges.class) { if (flavor == null || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { PageRanges []arr = new PageRanges[1]; arr[0] = new PageRanges(1, Integer.MAX_VALUE); return arr; } else { return null; } } else if (category == PrinterResolution.class) { PrinterResolution[] supportedRes = getPrintResolutions(); if (supportedRes == null) { return null; } PrinterResolution []arr = new PrinterResolution[supportedRes.length]; System.arraycopy(supportedRes, 0, arr, 0, supportedRes.length); return arr; } else if (category == Sides.class) { if (flavor == null || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) { Sides []arr = new Sides[3]; arr[0] = Sides.ONE_SIDED; arr[1] = Sides.TWO_SIDED_LONG_EDGE; arr[2] = Sides.TWO_SIDED_SHORT_EDGE; return arr; } else { return null; } } else if (category == PrintQuality.class) { PrintQuality []arr = new PrintQuality[3]; arr[0] = PrintQuality.DRAFT; arr[1] = PrintQuality.HIGH; arr[2] = PrintQuality.NORMAL; return arr; } else if (category == SheetCollate.class) { if (flavor == null || (flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { SheetCollate []arr = new SheetCollate[2]; arr[0] = SheetCollate.COLLATED; arr[1] = SheetCollate.UNCOLLATED; return arr; } else { return null; } } else if (category == Fidelity.class) { Fidelity []arr = new Fidelity[2]; arr[0] = Fidelity.FIDELITY_FALSE; arr[1] = Fidelity.FIDELITY_TRUE; return arr; } else { return null; } } public boolean isAttributeValueSupported(Attribute attr, DocFlavor flavor, AttributeSet attributes) { if (attr == null) { throw new NullPointerException("null attribute"); } Class category = attr.getCategory(); if (flavor != null) { if (!isDocFlavorSupported(flavor)) { throw new IllegalArgumentException(flavor + " is an unsupported flavor"); // if postscript & category is already specified within the PostScript data // we return false } else if (isAutoSense(flavor) || (isPostScriptFlavor(flavor) && (isPSDocAttr(category)))) { return false; } } if (!isAttributeCategorySupported(category)) { return false; } else if (category == Chromaticity.class) { if ((flavor == null) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || flavor.equals(DocFlavor.URL.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.URL.PNG)) { int caps = getPrinterCapabilities(); if ((caps & DEVCAP_COLOR) != 0) { return true; } else { return attr == Chromaticity.MONOCHROME; } } else { return false; } } else if (category == Copies.class) { return isSupportedCopies((Copies)attr); } else if (category == Destination.class) { URI uri = ((Destination)attr).getURI(); if ("file".equals(uri.getScheme()) && !(uri.getSchemeSpecificPart().equals(""))) { return true; } else { return false; } } else if (category == Media.class) { if (attr instanceof MediaSizeName) { return isSupportedMedia((MediaSizeName)attr); } if (attr instanceof MediaTray) { return isSupportedMediaTray((MediaTray)attr); } } else if (category == MediaPrintableArea.class) { return isSupportedMediaPrintableArea((MediaPrintableArea)attr); } else if (category == SunAlternateMedia.class) { Media media = ((SunAlternateMedia)attr).getMedia(); return isAttributeValueSupported(media, flavor, attributes); } else if (category == PageRanges.class || category == SheetCollate.class || category == Sides.class) { if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { return false; } } else if (category == PrinterResolution.class) { if (attr instanceof PrinterResolution) { return isSupportedResolution((PrinterResolution)attr); } } else if (category == OrientationRequested.class) { if (attr == OrientationRequested.REVERSE_PORTRAIT || (flavor != null) && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) || flavor.equals(DocFlavor.INPUT_STREAM.GIF) || flavor.equals(DocFlavor.INPUT_STREAM.JPEG) || flavor.equals(DocFlavor.INPUT_STREAM.PNG) || flavor.equals(DocFlavor.BYTE_ARRAY.GIF) || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) || flavor.equals(DocFlavor.BYTE_ARRAY.PNG) || flavor.equals(DocFlavor.URL.GIF) || flavor.equals(DocFlavor.URL.JPEG) || flavor.equals(DocFlavor.URL.PNG))) { return false; } } else if (category == ColorSupported.class) { int caps = getPrinterCapabilities(); boolean isColorSup = ((caps & DEVCAP_COLOR) != 0); if ((!isColorSup && (attr == ColorSupported.SUPPORTED)) || (isColorSup && (attr == ColorSupported.NOT_SUPPORTED))) { return false; } } return true; } public AttributeSet getUnsupportedAttributes(DocFlavor flavor, AttributeSet attributes) { if (flavor != null && !isDocFlavorSupported(flavor)) { throw new IllegalArgumentException("flavor " + flavor + "is not supported"); } if (attributes == null) { return null; } Attribute attr; AttributeSet unsupp = new HashAttributeSet(); Attribute []attrs = attributes.toArray(); for (int i=0; i