/* * Copyright (c) 2000, 2019, 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.io.File; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Locale; import java.awt.GraphicsEnvironment; import java.awt.Toolkit; 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.HashAttributeSet; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.PrintServiceAttributeSet; import javax.print.attribute.HashPrintServiceAttributeSet; import javax.print.attribute.Size2DSyntax; 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.JobSheets; import javax.print.attribute.standard.RequestingUserName; import javax.print.attribute.standard.Chromaticity; import javax.print.attribute.standard.ColorSupported; import javax.print.attribute.standard.Copies; import javax.print.attribute.standard.CopiesSupported; import javax.print.attribute.standard.Destination; import javax.print.attribute.standard.DialogOwner; import javax.print.attribute.standard.DialogTypeSelection; import javax.print.attribute.standard.Fidelity; import javax.print.attribute.standard.Media; import javax.print.attribute.standard.MediaPrintableArea; import javax.print.attribute.standard.MediaSize; import javax.print.attribute.standard.MediaSizeName; 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.SheetCollate; import javax.print.attribute.standard.Sides; import javax.print.event.PrintServiceAttributeListener; public class UnixPrintService implements PrintService, AttributeUpdater, SunPrinterJobService { /* define doc flavors for text types in the default encoding of * this platform since we can always read those. */ private static String encoding = "ISO8859_1"; private static DocFlavor textByteFlavor; private static DocFlavor[] supportedDocFlavors = null; private static final DocFlavor[] supportedDocFlavorsInit = { DocFlavor.BYTE_ARRAY.POSTSCRIPT, DocFlavor.INPUT_STREAM.POSTSCRIPT, DocFlavor.URL.POSTSCRIPT, 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.CHAR_ARRAY.TEXT_PLAIN, DocFlavor.READER.TEXT_PLAIN, DocFlavor.STRING.TEXT_PLAIN, DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8, DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16, DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE, DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE, DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII, DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8, DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16, DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE, DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE, DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII, DocFlavor.URL.TEXT_PLAIN_UTF_8, DocFlavor.URL.TEXT_PLAIN_UTF_16, DocFlavor.URL.TEXT_PLAIN_UTF_16BE, DocFlavor.URL.TEXT_PLAIN_UTF_16LE, DocFlavor.URL.TEXT_PLAIN_US_ASCII, DocFlavor.SERVICE_FORMATTED.PAGEABLE, DocFlavor.SERVICE_FORMATTED.PRINTABLE, DocFlavor.BYTE_ARRAY.AUTOSENSE, DocFlavor.URL.AUTOSENSE, DocFlavor.INPUT_STREAM.AUTOSENSE }; private static final DocFlavor[] supportedHostDocFlavors = { DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST, DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST, DocFlavor.URL.TEXT_PLAIN_HOST }; String[] lpcStatusCom = { "", "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $2, $3}'" }; String[] lpcQueueCom = { "", "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $4}'" }; static { encoding = java.security.AccessController.doPrivileged( new sun.security.action.GetPropertyAction("file.encoding")); } /* let's try to support a few of these */ private static final Class[] serviceAttrCats = { PrinterName.class, PrinterIsAcceptingJobs.class, QueuedJobCount.class, }; /* it turns out to be inconvenient to store the other categories * separately because many attributes are in multiple categories. */ private static final Class[] otherAttrCats = { Chromaticity.class, Copies.class, Destination.class, Fidelity.class, JobName.class, JobSheets.class, Media.class, /* have to support this somehow ... */ MediaPrintableArea.class, OrientationRequested.class, PageRanges.class, RequestingUserName.class, SheetCollate.class, Sides.class, }; private static int MAXCOPIES = 1000; private static final MediaSizeName[] mediaSizes = { MediaSizeName.NA_LETTER, MediaSizeName.TABLOID, MediaSizeName.LEDGER, MediaSizeName.NA_LEGAL, MediaSizeName.EXECUTIVE, MediaSizeName.ISO_A3, MediaSizeName.ISO_A4, MediaSizeName.ISO_A5, MediaSizeName.ISO_B4, MediaSizeName.ISO_B5, }; private String printer; private PrinterName name; private boolean isInvalid; private transient PrintServiceAttributeSet lastSet; private transient ServiceNotifier notifier = null; UnixPrintService(String name) { if (name == null) { throw new IllegalArgumentException("null printer name"); } printer = name; isInvalid = false; } public void invalidateService() { isInvalid = true; } public String getName() { return printer; } private PrinterName getPrinterName() { if (name == null) { name = new PrinterName(printer, null); } return name; } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() { if (PrintServiceLookupProvider.cmdIndex == PrintServiceLookupProvider.UNINITIALIZED) { PrintServiceLookupProvider.cmdIndex = PrintServiceLookupProvider.getBSDCommandIndex(); } String command = "/usr/sbin/lpc status " + printer + lpcStatusCom[PrintServiceLookupProvider.cmdIndex]; String[] results= PrintServiceLookupProvider.execCmd(command); if (results != null && results.length > 0) { if (PrintServiceLookupProvider.cmdIndex == PrintServiceLookupProvider.BSD_LPD_NG) { if (results[0].startsWith("enabled enabled")) { return PrinterIsAcceptingJobs.ACCEPTING_JOBS ; } } else { if ((results[1].trim().startsWith("queuing is enabled") && results[2].trim().startsWith("printing is enabled")) || (results.length >= 4 && results[2].trim().startsWith("queuing is enabled") && results[3].trim().startsWith("printing is enabled"))) { return PrinterIsAcceptingJobs.ACCEPTING_JOBS ; } } } return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ; } // Filter the list of possible AIX Printers and remove header lines // and extra lines which have been added for remote printers. // 'protected' because this method is also used from PrintServiceLookupProvider. protected static String[] filterPrinterNamesAIX(String[] posPrinters) { ArrayList printers = new ArrayList<>(); String [] splitPart; for(int i = 0; i < posPrinters.length; i++) { // Remove the header lines if (posPrinters[i].startsWith("---") || posPrinters[i].startsWith("Queue") || posPrinters[i].isEmpty()) continue; // Check if there is a ":" in the end of the first colomn. // This means that it is not a valid printer definition. splitPart = posPrinters[i].split(" "); if(splitPart.length >= 1 && !splitPart[0].trim().endsWith(":")) { printers.add(posPrinters[i]); } } return printers.toArray(new String[printers.size()]); } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsAIX() { // On AIX there should not be a blank after '-a'. String command = "/usr/bin/lpstat -a" + printer; String[] results= PrintServiceLookupProvider.execCmd(command); // Remove headers and bogus entries added by remote printers. results = filterPrinterNamesAIX(results); if (results != null && results.length > 0) { for (int i = 0; i < results.length; i++) { if (results[i].contains("READY") || results[i].contains("RUNNING")) { return PrinterIsAcceptingJobs.ACCEPTING_JOBS; } } } return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS; } private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() { if (PrintServiceLookupProvider.isBSD()) { return getPrinterIsAcceptingJobsBSD(); } else if (PrintServiceLookupProvider.isAIX()) { return getPrinterIsAcceptingJobsAIX(); } 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 getQueuedJobCountBSD() { if (PrintServiceLookupProvider.cmdIndex == PrintServiceLookupProvider.UNINITIALIZED) { PrintServiceLookupProvider.cmdIndex = PrintServiceLookupProvider.getBSDCommandIndex(); } int qlen = 0; String command = "/usr/sbin/lpc status " + printer + lpcQueueCom[PrintServiceLookupProvider.cmdIndex]; String[] results = PrintServiceLookupProvider.execCmd(command); if (results != null && results.length > 0) { String queued; if (PrintServiceLookupProvider.cmdIndex == PrintServiceLookupProvider.BSD_LPD_NG) { queued = results[0]; } else { queued = results[3].trim(); if (queued.startsWith("no")) { return new QueuedJobCount(0); } else { queued = queued.substring(0, queued.indexOf(' ')); } } try { qlen = Integer.parseInt(queued); } catch (NumberFormatException e) { } } return new QueuedJobCount(qlen); } private QueuedJobCount getQueuedJobCountAIX() { // On AIX there should not be a blank after '-a'. String command = "/usr/bin/lpstat -a" + printer; String[] results= PrintServiceLookupProvider.execCmd(command); // Remove headers and bogus entries added by remote printers. results = filterPrinterNamesAIX(results); int qlen = 0; if (results != null && results.length > 0){ for (int i = 0; i < results.length; i++) { if (results[i].contains("QUEUED")){ qlen ++; } } } return new QueuedJobCount(qlen); } private QueuedJobCount getQueuedJobCount() { if (PrintServiceLookupProvider.isBSD()) { return getQueuedJobCountBSD(); } else if (PrintServiceLookupProvider.isAIX()) { return getQueuedJobCountAIX(); } else { return new QueuedJobCount(0); } } private PrintServiceAttributeSet getBSDServiceAttributes() { PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); attrs.add(getQueuedJobCountBSD()); attrs.add(getPrinterIsAcceptingJobsBSD()); return attrs; } private PrintServiceAttributeSet getAIXServiceAttributes() { PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet(); attrs.add(getQueuedJobCountAIX()); attrs.add(getPrinterIsAcceptingJobsAIX()); return attrs; } private boolean isSupportedCopies(Copies copies) { int numCopies = copies.getValue(); return (numCopies > 0 && numCopies < MAXCOPIES); } private boolean isSupportedMedia(MediaSizeName msn) { 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 == 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()); return AttributeSetUtilities.unmodifiableView(attrs); } private void initSupportedDocFlavors() { String hostEnc = DocFlavor.hostEncoding.toLowerCase(Locale.ENGLISH); if (!hostEnc.equals("utf-8") && !hostEnc.equals("utf-16") && !hostEnc.equals("utf-16be") && !hostEnc.equals("utf-16le") && !hostEnc.equals("us-ascii")) { int len = supportedDocFlavorsInit.length; DocFlavor[] flavors = new DocFlavor[len + supportedHostDocFlavors.length]; // copy host encoding flavors System.arraycopy(supportedHostDocFlavors, 0, flavors, len, supportedHostDocFlavors.length); System.arraycopy(supportedDocFlavorsInit, 0, flavors, 0, len); supportedDocFlavors = flavors; } else { supportedDocFlavors = supportedDocFlavorsInit; } } public DocFlavor[] getSupportedDocFlavors() { if (supportedDocFlavors == null) { initSupportedDocFlavors(); } int len = supportedDocFlavors.length; DocFlavor[] flavors = new DocFlavor[len]; System.arraycopy(supportedDocFlavors, 0, flavors, 0, len); return flavors; } public boolean isDocFlavorSupported(DocFlavor flavor) { if (supportedDocFlavors == null) { initSupportedDocFlavors(); } for (int f=0; f[] getSupportedAttributeCategories() { ArrayList> categList = new ArrayList<>(otherAttrCats.length); for (Class c : otherAttrCats) { categList.add(c); } if (GraphicsEnvironment.isHeadless() == false) { categList.add(DialogOwner.class); categList.add(DialogTypeSelection.class); } return 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"); } for (int i=0;i 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; } if (category == Copies.class) { return new Copies(1); } else if (category == Chromaticity.class) { return Chromaticity.COLOR; } else if (category == Destination.class) { try { return new Destination((new File("out.ps")).toURI()); } catch (SecurityException se) { try { return new Destination(new URI("file:out.ps")); } catch (URISyntaxException e) { return null; } } } else if (category == Fidelity.class) { return Fidelity.FIDELITY_FALSE; } else if (category == JobName.class) { return new JobName("Java Printing", null); } else if (category == JobSheets.class) { return JobSheets.STANDARD; } else if (category == Media.class) { String defaultCountry = Locale.getDefault().getCountry(); if (defaultCountry != null && (defaultCountry.isEmpty() || defaultCountry.equals(Locale.US.getCountry()) || defaultCountry.equals(Locale.CANADA.getCountry()))) { return MediaSizeName.NA_LETTER; } else { return MediaSizeName.ISO_A4; } } else if (category == MediaPrintableArea.class) { String defaultCountry = Locale.getDefault().getCountry(); float iw, ih; if (defaultCountry != null && (defaultCountry.isEmpty() || defaultCountry.equals(Locale.US.getCountry()) || defaultCountry.equals(Locale.CANADA.getCountry()))) { iw = MediaSize.NA.LETTER.getX(Size2DSyntax.INCH) - 0.5f; ih = MediaSize.NA.LETTER.getY(Size2DSyntax.INCH) - 0.5f; } else { iw = MediaSize.ISO.A4.getX(Size2DSyntax.INCH) - 0.5f; ih = MediaSize.ISO.A4.getY(Size2DSyntax.INCH) - 0.5f; } return new MediaPrintableArea(0.25f, 0.25f, iw, ih, MediaPrintableArea.INCH); } else if (category == OrientationRequested.class) { return OrientationRequested.PORTRAIT; } else if (category == PageRanges.class) { return new PageRanges(1, Integer.MAX_VALUE); } 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) { return SheetCollate.UNCOLLATED; } else if (category == Sides.class) { return Sides.ONE_SIDED; } else return null; } 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"); } else if (isAutoSense(flavor)) { return null; } } if (!isAttributeCategorySupported(category)) { return null; } if (category == Chromaticity.class) { if (flavor == null || isServiceFormattedFlavor(flavor)) { Chromaticity[]arr = new Chromaticity[1]; arr[0] = Chromaticity.COLOR; return (arr); } else { return null; } } else if (category == Destination.class) { try { return new Destination((new File("out.ps")).toURI()); } catch (SecurityException se) { try { return new Destination(new URI("file:out.ps")); } catch (URISyntaxException e) { return null; } } } else if (category == JobName.class) { return new JobName("Java Printing", null); } else if (category == JobSheets.class) { JobSheets[] arr = new JobSheets[2]; arr[0] = JobSheets.NONE; arr[1] = JobSheets.STANDARD; return arr; } else if (category == RequestingUserName.class) { String userName = ""; try { userName = System.getProperty("user.name", ""); } catch (SecurityException se) { } return new RequestingUserName(userName, null); } else if (category == OrientationRequested.class) { if (flavor == null || isServiceFormattedFlavor(flavor)) { 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)) { if (flavor == null || !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || flavor.equals(DocFlavor.URL.POSTSCRIPT) || flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) { return new CopiesSupported(1, MAXCOPIES); } else { return null; } } else if (category == Media.class) { Media []arr = new Media[mediaSizes.length]; System.arraycopy(mediaSizes, 0, arr, 0, mediaSizes.length); return arr; } else if (category == Fidelity.class) { Fidelity []arr = new Fidelity[2]; arr[0] = Fidelity.FIDELITY_FALSE; arr[1] = Fidelity.FIDELITY_TRUE; return arr; } else if (category == MediaPrintableArea.class) { /* The code below implements the behaviour that if no Media or * MediaSize attribute is specified, return an array of * MediaPrintableArea, one for each supported Media. * If a MediaSize is specified, return a MPA consistent for that, * and if a Media is specified locate its MediaSize and return * its MPA, and if none is found, return an MPA for the default * Media for this service. */ if (attributes == null) { return getAllPrintableAreas(); } MediaSize mediaSize = (MediaSize)attributes.get(MediaSize.class); Media media = (Media)attributes.get(Media.class); MediaPrintableArea []arr = new MediaPrintableArea[1]; if (mediaSize == null) { if (media instanceof MediaSizeName) { MediaSizeName msn = (MediaSizeName)media; mediaSize = MediaSize.getMediaSizeForName(msn); if (mediaSize == null) { /* try to get a size from the default media */ media = (Media)getDefaultAttributeValue(Media.class); if (media instanceof MediaSizeName) { msn = (MediaSizeName)media; mediaSize = MediaSize.getMediaSizeForName(msn); } if (mediaSize == null) { /* shouldn't happen, return a default */ arr[0] = new MediaPrintableArea(0.25f, 0.25f, 8f, 10.5f, MediaSize.INCH); return arr; } } } else { return getAllPrintableAreas(); } } /* If reach here MediaSize is non-null */ assert mediaSize != null; arr[0] = new MediaPrintableArea(0.25f, 0.25f, mediaSize.getX(MediaSize.INCH)-0.5f, mediaSize.getY(MediaSize.INCH)-0.5f, MediaSize.INCH); return arr; } 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 == 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.UNCOLLATED; arr[1] = SheetCollate.COLLATED; return arr; } else { return null; } } 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 { return null; } } private static MediaPrintableArea[] mpas = null; private MediaPrintableArea[] getAllPrintableAreas() { if (mpas == null) { Media[] media = (Media[])getSupportedAttributeValues(Media.class, null, null); mpas = new MediaPrintableArea[media.length]; for (int i=0; i< mpas.length; i++) { if (media[i] instanceof MediaSizeName) { MediaSizeName msn = (MediaSizeName)media[i]; MediaSize mediaSize = MediaSize.getMediaSizeForName(msn); if (mediaSize == null) { mpas[i] = (MediaPrintableArea) getDefaultAttributeValue(MediaPrintableArea.class); } else { mpas[i] = new MediaPrintableArea(0.25f, 0.25f, mediaSize.getX(MediaSize.INCH)-0.5f, mediaSize.getY(MediaSize.INCH)-0.5f, MediaSize.INCH); } } } } MediaPrintableArea[] mpasCopy = new MediaPrintableArea[mpas.length]; System.arraycopy(mpas, 0, mpasCopy, 0, mpas.length); return mpasCopy; } /* Is this one of the flavors that this service explicitly * generates postscript for, and so can control how it is rendered? */ private boolean isServiceFormattedFlavor(DocFlavor flavor) { return 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); } public boolean isAttributeValueSupported(Attribute attr, DocFlavor flavor, AttributeSet attributes) { if (attr == null) { throw new NullPointerException("null attribute"); } if (flavor != null) { if (!isDocFlavorSupported(flavor)) { throw new IllegalArgumentException(flavor + " is an unsupported flavor"); } else if (isAutoSense(flavor)) { return false; } } Class category = attr.getCategory(); if (!isAttributeCategorySupported(category)) { return false; } else if (attr.getCategory() == Chromaticity.class) { if (flavor == null || isServiceFormattedFlavor(flavor)) { return attr == Chromaticity.COLOR; } else { return false; } } else if (attr.getCategory() == Copies.class) { return (flavor == null || !(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) || flavor.equals(DocFlavor.URL.POSTSCRIPT) || flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) && isSupportedCopies((Copies)attr); } else if (attr.getCategory() == Destination.class) { URI uri = ((Destination)attr).getURI(); if ("file".equals(uri.getScheme()) && !uri.getSchemeSpecificPart().isEmpty()) { return true; } else { return false; } } else if (attr.getCategory() == Media.class) { if (attr instanceof MediaSizeName) { return isSupportedMedia((MediaSizeName)attr); } else { return false; } } else if (attr.getCategory() == OrientationRequested.class) { if (attr == OrientationRequested.REVERSE_PORTRAIT || (flavor != null) && !isServiceFormattedFlavor(flavor)) { return false; } } else if (attr.getCategory() == PageRanges.class) { if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { return false; } } else if (attr.getCategory() == SheetCollate.class) { if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { return false; } } else if (attr.getCategory() == Sides.class) { if (flavor != null && !(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) { return false; } } else if (attr.getCategory() == DialogOwner.class) { DialogOwner owner = (DialogOwner)attr; // ID not supported on any dialog type on Unix platforms. if (DialogOwnerAccessor.getID(owner) != 0) { return false; } // UnixPrintService is not used on Mac, so this is // always some Unix system that does not have CUPS/IPP // Which means we always use a Swing dialog and we need // only check if alwaysOnTop is supported by the toolkit. if (owner.getOwner() != null) { return true; } else { return Toolkit.getDefaultToolkit().isAlwaysOnTopSupported(); } } else if (attr.getCategory() == DialogTypeSelection.class) { DialogTypeSelection dts = (DialogTypeSelection)attr; return dts == DialogTypeSelection.COMMON; } 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 c) { return (c == sun.print.PSPrinterJob.class); } }