Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/print/UnixPrintService.java
32287 views
/*1* Copyright (c) 2000, 2007, 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.io.File;28import java.net.URI;29import java.net.URISyntaxException;30import java.util.ArrayList;31import java.util.Locale;3233import javax.print.DocFlavor;34import javax.print.DocPrintJob;35import javax.print.PrintService;36import javax.print.ServiceUIFactory;37import javax.print.attribute.Attribute;38import javax.print.attribute.AttributeSet;39import javax.print.attribute.AttributeSetUtilities;40import javax.print.attribute.HashAttributeSet;41import javax.print.attribute.PrintServiceAttribute;42import javax.print.attribute.PrintServiceAttributeSet;43import javax.print.attribute.HashPrintServiceAttributeSet;44import javax.print.attribute.Size2DSyntax;45import javax.print.attribute.standard.PrinterName;46import javax.print.attribute.standard.PrinterIsAcceptingJobs;47import javax.print.attribute.standard.QueuedJobCount;48import javax.print.attribute.standard.JobName;49import javax.print.attribute.standard.JobSheets;50import javax.print.attribute.standard.RequestingUserName;51import javax.print.attribute.standard.Chromaticity;52import javax.print.attribute.standard.ColorSupported;53import javax.print.attribute.standard.Copies;54import javax.print.attribute.standard.CopiesSupported;55import javax.print.attribute.standard.Destination;56import javax.print.attribute.standard.Fidelity;57import javax.print.attribute.standard.Media;58import javax.print.attribute.standard.MediaPrintableArea;59import javax.print.attribute.standard.MediaSize;60import javax.print.attribute.standard.MediaSizeName;61import javax.print.attribute.standard.OrientationRequested;62import javax.print.attribute.standard.PageRanges;63import javax.print.attribute.standard.PrinterState;64import javax.print.attribute.standard.PrinterStateReason;65import javax.print.attribute.standard.PrinterStateReasons;66import javax.print.attribute.standard.Severity;67import javax.print.attribute.standard.SheetCollate;68import javax.print.attribute.standard.Sides;69import javax.print.event.PrintServiceAttributeListener;707172public class UnixPrintService implements PrintService, AttributeUpdater,73SunPrinterJobService {7475/* define doc flavors for text types in the default encoding of76* this platform since we can always read those.77*/78private static String encoding = "ISO8859_1";79private static DocFlavor textByteFlavor;8081private static DocFlavor[] supportedDocFlavors = null;82private static final DocFlavor[] supportedDocFlavorsInit = {83DocFlavor.BYTE_ARRAY.POSTSCRIPT,84DocFlavor.INPUT_STREAM.POSTSCRIPT,85DocFlavor.URL.POSTSCRIPT,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,9596DocFlavor.CHAR_ARRAY.TEXT_PLAIN,97DocFlavor.READER.TEXT_PLAIN,98DocFlavor.STRING.TEXT_PLAIN,99100DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8,101DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16,102DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE,103DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE,104DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII,105106107DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8,108DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16,109DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE,110DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE,111DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII,112113114DocFlavor.URL.TEXT_PLAIN_UTF_8,115DocFlavor.URL.TEXT_PLAIN_UTF_16,116DocFlavor.URL.TEXT_PLAIN_UTF_16BE,117DocFlavor.URL.TEXT_PLAIN_UTF_16LE,118DocFlavor.URL.TEXT_PLAIN_US_ASCII,119120DocFlavor.SERVICE_FORMATTED.PAGEABLE,121DocFlavor.SERVICE_FORMATTED.PRINTABLE,122123DocFlavor.BYTE_ARRAY.AUTOSENSE,124DocFlavor.URL.AUTOSENSE,125DocFlavor.INPUT_STREAM.AUTOSENSE126};127128private static final DocFlavor[] supportedHostDocFlavors = {129DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST,130DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,131DocFlavor.URL.TEXT_PLAIN_HOST132};133134String[] lpcStatusCom = {135"",136"| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $2, $3}'"137};138139String[] lpcQueueCom = {140"",141"| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $4}'"142};143144static {145encoding = java.security.AccessController.doPrivileged(146new sun.security.action.GetPropertyAction("file.encoding"));147}148149/* let's try to support a few of these */150private static final Class[] serviceAttrCats = {151PrinterName.class,152PrinterIsAcceptingJobs.class,153QueuedJobCount.class,154};155156/* it turns out to be inconvenient to store the other categories157* separately because many attributes are in multiple categories.158*/159private static final Class[] otherAttrCats = {160Chromaticity.class,161Copies.class,162Destination.class,163Fidelity.class,164JobName.class,165JobSheets.class,166Media.class, /* have to support this somehow ... */167MediaPrintableArea.class,168OrientationRequested.class,169PageRanges.class,170RequestingUserName.class,171SheetCollate.class,172Sides.class,173};174175private static int MAXCOPIES = 1000;176177private static final MediaSizeName mediaSizes[] = {178MediaSizeName.NA_LETTER,179MediaSizeName.TABLOID,180MediaSizeName.LEDGER,181MediaSizeName.NA_LEGAL,182MediaSizeName.EXECUTIVE,183MediaSizeName.ISO_A3,184MediaSizeName.ISO_A4,185MediaSizeName.ISO_A5,186MediaSizeName.ISO_B4,187MediaSizeName.ISO_B5,188};189190private String printer;191private PrinterName name;192private boolean isInvalid;193194transient private PrintServiceAttributeSet lastSet;195transient private ServiceNotifier notifier = null;196197UnixPrintService(String name) {198if (name == null) {199throw new IllegalArgumentException("null printer name");200}201printer = name;202isInvalid = false;203}204205public void invalidateService() {206isInvalid = true;207}208209public String getName() {210return printer;211}212213private PrinterName getPrinterName() {214if (name == null) {215name = new PrinterName(printer, null);216}217return name;218}219220private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {221String command = "/usr/bin/lpstat -a " + printer;222String results[]= PrintServiceLookupProvider.execCmd(command);223224if (results != null && results.length > 0) {225if (results[0].startsWith(printer + " accepting requests")) {226return PrinterIsAcceptingJobs.ACCEPTING_JOBS;227}228else if (results[0].startsWith(printer)) {229/* As well as "myprinter accepting requests", look for230* "myprinter@somehost accepting requests".231*/232int index = printer.length();233String str = results[0];234if (str.length() > index &&235str.charAt(index) == '@' &&236str.indexOf(" accepting requests", index) > 0 &&237str.indexOf(" not accepting requests", index) == -1) {238return PrinterIsAcceptingJobs.ACCEPTING_JOBS;239}240}241}242return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;243}244245private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {246if (PrintServiceLookupProvider.cmdIndex ==247PrintServiceLookupProvider.UNINITIALIZED) {248249PrintServiceLookupProvider.cmdIndex =250PrintServiceLookupProvider.getBSDCommandIndex();251}252253String command = "/usr/sbin/lpc status " + printer254+ lpcStatusCom[PrintServiceLookupProvider.cmdIndex];255String results[]= PrintServiceLookupProvider.execCmd(command);256257if (results != null && results.length > 0) {258if (PrintServiceLookupProvider.cmdIndex ==259PrintServiceLookupProvider.BSD_LPD_NG) {260if (results[0].startsWith("enabled enabled")) {261return PrinterIsAcceptingJobs.ACCEPTING_JOBS ;262}263} else {264if ((results[1].trim().startsWith("queuing is enabled") &&265results[2].trim().startsWith("printing is enabled")) ||266(results.length >= 4 &&267results[2].trim().startsWith("queuing is enabled") &&268results[3].trim().startsWith("printing is enabled"))) {269return PrinterIsAcceptingJobs.ACCEPTING_JOBS ;270}271}272}273return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;274}275276// Filter the list of possible AIX Printers and remove header lines277// and extra lines which have been added for remote printers.278// 'protected' because this method is also used from PrintServiceLookupProvider.279protected static String[] filterPrinterNamesAIX(String[] posPrinters) {280ArrayList printers = new ArrayList();281String [] splitPart;282283for(int i = 0; i < posPrinters.length; i++) {284// Remove the header lines285if (posPrinters[i].startsWith("---") ||286posPrinters[i].startsWith("Queue") ||287posPrinters[i].equals("")) continue;288289// Check if there is a ":" in the end of the first colomn.290// This means that it is not a valid printer definition.291splitPart = posPrinters[i].split(" ");292if(splitPart.length >= 1 && !splitPart[0].trim().endsWith(":")) {293printers.add(posPrinters[i]);294}295}296297return (String[])printers.toArray(new String[printers.size()]);298}299300private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsAIX() {301// On AIX there should not be a blank after '-a'.302String command = "/usr/bin/lpstat -a" + printer;303String results[]= PrintServiceLookupProvider.execCmd(command);304305// Remove headers and bogus entries added by remote printers.306results = filterPrinterNamesAIX(results);307308if (results != null && results.length > 0) {309for (int i = 0; i < results.length; i++) {310if (results[i].contains("READY") ||311results[i].contains("RUNNING")) {312return PrinterIsAcceptingJobs.ACCEPTING_JOBS;313}314}315}316317return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;318319}320321private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {322if (PrintServiceLookupProvider.isSysV()) {323return getPrinterIsAcceptingJobsSysV();324} else if (PrintServiceLookupProvider.isBSD()) {325return getPrinterIsAcceptingJobsBSD();326} else if (PrintServiceLookupProvider.isAIX()) {327return getPrinterIsAcceptingJobsAIX();328} else {329return PrinterIsAcceptingJobs.ACCEPTING_JOBS;330}331}332333private PrinterState getPrinterState() {334if (isInvalid) {335return PrinterState.STOPPED;336} else {337return null;338}339}340341private PrinterStateReasons getPrinterStateReasons() {342if (isInvalid) {343PrinterStateReasons psr = new PrinterStateReasons();344psr.put(PrinterStateReason.SHUTDOWN, Severity.ERROR);345return psr;346} else {347return null;348}349}350351private QueuedJobCount getQueuedJobCountSysV() {352String command = "/usr/bin/lpstat -R " + printer;353String results[]= PrintServiceLookupProvider.execCmd(command);354int qlen = (results == null) ? 0 : results.length;355356return new QueuedJobCount(qlen);357}358359private QueuedJobCount getQueuedJobCountBSD() {360if (PrintServiceLookupProvider.cmdIndex ==361PrintServiceLookupProvider.UNINITIALIZED) {362363PrintServiceLookupProvider.cmdIndex =364PrintServiceLookupProvider.getBSDCommandIndex();365}366367int qlen = 0;368String command = "/usr/sbin/lpc status " + printer369+ lpcQueueCom[PrintServiceLookupProvider.cmdIndex];370String results[] = PrintServiceLookupProvider.execCmd(command);371372if (results != null && results.length > 0) {373String queued;374if (PrintServiceLookupProvider.cmdIndex ==375PrintServiceLookupProvider.BSD_LPD_NG) {376queued = results[0];377} else {378queued = results[3].trim();379if (queued.startsWith("no")) {380return new QueuedJobCount(0);381} else {382queued = queued.substring(0, queued.indexOf(' '));383}384}385386try {387qlen = Integer.parseInt(queued);388} catch (NumberFormatException e) {389}390}391392return new QueuedJobCount(qlen);393}394395private QueuedJobCount getQueuedJobCountAIX() {396// On AIX there should not be a blank after '-a'.397String command = "/usr/bin/lpstat -a" + printer;398String results[]= PrintServiceLookupProvider.execCmd(command);399400// Remove headers and bogus entries added by remote printers.401results = filterPrinterNamesAIX(results);402403int qlen = 0;404if (results != null && results.length > 0){405for (int i = 0; i < results.length; i++) {406if (results[i].contains("QUEUED")){407qlen ++;408}409}410}411return new QueuedJobCount(qlen);412}413414private QueuedJobCount getQueuedJobCount() {415if (PrintServiceLookupProvider.isSysV()) {416return getQueuedJobCountSysV();417} else if (PrintServiceLookupProvider.isBSD()) {418return getQueuedJobCountBSD();419} else if (PrintServiceLookupProvider.isAIX()) {420return getQueuedJobCountAIX();421} else {422return new QueuedJobCount(0);423}424}425426private PrintServiceAttributeSet getSysVServiceAttributes() {427PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();428attrs.add(getQueuedJobCountSysV());429attrs.add(getPrinterIsAcceptingJobsSysV());430return attrs;431}432433private PrintServiceAttributeSet getBSDServiceAttributes() {434PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();435attrs.add(getQueuedJobCountBSD());436attrs.add(getPrinterIsAcceptingJobsBSD());437return attrs;438}439440private PrintServiceAttributeSet getAIXServiceAttributes() {441PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();442attrs.add(getQueuedJobCountAIX());443attrs.add(getPrinterIsAcceptingJobsAIX());444return attrs;445}446447private boolean isSupportedCopies(Copies copies) {448int numCopies = copies.getValue();449return (numCopies > 0 && numCopies < MAXCOPIES);450}451452private boolean isSupportedMedia(MediaSizeName msn) {453for (int i=0; i<mediaSizes.length; i++) {454if (msn.equals(mediaSizes[i])) {455return true;456}457}458return false;459}460461public DocPrintJob createPrintJob() {462SecurityManager security = System.getSecurityManager();463if (security != null) {464security.checkPrintJobAccess();465}466return new UnixPrintJob(this);467}468469private PrintServiceAttributeSet getDynamicAttributes() {470if (PrintServiceLookupProvider.isSysV()) {471return getSysVServiceAttributes();472} else if (PrintServiceLookupProvider.isAIX()) {473return getAIXServiceAttributes();474} else {475return getBSDServiceAttributes();476}477}478479public PrintServiceAttributeSet getUpdatedAttributes() {480PrintServiceAttributeSet currSet = getDynamicAttributes();481if (lastSet == null) {482lastSet = currSet;483return AttributeSetUtilities.unmodifiableView(currSet);484} else {485PrintServiceAttributeSet updates =486new HashPrintServiceAttributeSet();487Attribute []attrs = currSet.toArray();488Attribute attr;489for (int i=0; i<attrs.length; i++) {490attr = attrs[i];491if (!lastSet.containsValue(attr)) {492updates.add(attr);493}494}495lastSet = currSet;496return AttributeSetUtilities.unmodifiableView(updates);497}498}499500public void wakeNotifier() {501synchronized (this) {502if (notifier != null) {503notifier.wake();504}505}506}507508public void addPrintServiceAttributeListener(509PrintServiceAttributeListener listener) {510synchronized (this) {511if (listener == null) {512return;513}514if (notifier == null) {515notifier = new ServiceNotifier(this);516}517notifier.addListener(listener);518}519}520521public void removePrintServiceAttributeListener(522PrintServiceAttributeListener listener) {523synchronized (this) {524if (listener == null || notifier == null ) {525return;526}527notifier.removeListener(listener);528if (notifier.isEmpty()) {529notifier.stopNotifier();530notifier = null;531}532}533}534535public <T extends PrintServiceAttribute>536T getAttribute(Class<T> category)537{538if (category == null) {539throw new NullPointerException("category");540}541if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {542throw new IllegalArgumentException("Not a PrintServiceAttribute");543}544545if (category == PrinterName.class) {546return (T)getPrinterName();547} else if (category == PrinterState.class) {548return (T)getPrinterState();549} else if (category == PrinterStateReasons.class) {550return (T)getPrinterStateReasons();551} else if (category == QueuedJobCount.class) {552return (T)getQueuedJobCount();553} else if (category == PrinterIsAcceptingJobs.class) {554return (T)getPrinterIsAcceptingJobs();555} else {556return null;557}558}559560public PrintServiceAttributeSet getAttributes() {561PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();562attrs.add(getPrinterName());563attrs.add(getPrinterIsAcceptingJobs());564PrinterState prnState = getPrinterState();565if (prnState != null) {566attrs.add(prnState);567}568PrinterStateReasons prnStateReasons = getPrinterStateReasons();569if (prnStateReasons != null) {570attrs.add(prnStateReasons);571}572attrs.add(getQueuedJobCount());573return AttributeSetUtilities.unmodifiableView(attrs);574}575576private void initSupportedDocFlavors() {577String hostEnc = DocFlavor.hostEncoding.toLowerCase(Locale.ENGLISH);578if (!hostEnc.equals("utf-8") && !hostEnc.equals("utf-16") &&579!hostEnc.equals("utf-16be") && !hostEnc.equals("utf-16le") &&580!hostEnc.equals("us-ascii")) {581582int len = supportedDocFlavorsInit.length;583DocFlavor[] flavors =584new DocFlavor[len + supportedHostDocFlavors.length];585// copy host encoding flavors586System.arraycopy(supportedHostDocFlavors, 0, flavors,587len, supportedHostDocFlavors.length);588System.arraycopy(supportedDocFlavorsInit, 0, flavors, 0, len);589590supportedDocFlavors = flavors;591} else {592supportedDocFlavors = supportedDocFlavorsInit;593}594}595596public DocFlavor[] getSupportedDocFlavors() {597if (supportedDocFlavors == null) {598initSupportedDocFlavors();599}600int len = supportedDocFlavors.length;601DocFlavor[] flavors = new DocFlavor[len];602System.arraycopy(supportedDocFlavors, 0, flavors, 0, len);603604return flavors;605}606607public boolean isDocFlavorSupported(DocFlavor flavor) {608if (supportedDocFlavors == null) {609initSupportedDocFlavors();610}611for (int f=0; f<supportedDocFlavors.length; f++) {612if (flavor.equals(supportedDocFlavors[f])) {613return true;614}615}616return false;617}618619public Class[] getSupportedAttributeCategories() {620int totalCats = otherAttrCats.length;621Class [] cats = new Class[totalCats];622System.arraycopy(otherAttrCats, 0, cats, 0, otherAttrCats.length);623return cats;624}625626public boolean627isAttributeCategorySupported(Class<? extends Attribute> category)628{629if (category == null) {630throw new NullPointerException("null category");631}632if (!(Attribute.class.isAssignableFrom(category))) {633throw new IllegalArgumentException(category +634" is not an Attribute");635}636637for (int i=0;i<otherAttrCats.length;i++) {638if (category == otherAttrCats[i]) {639return true;640}641}642return false;643}644645/* return defaults for all attributes for which there is a default646* value647*/648public Object649getDefaultAttributeValue(Class<? extends Attribute> category)650{651if (category == null) {652throw new NullPointerException("null category");653}654if (!Attribute.class.isAssignableFrom(category)) {655throw new IllegalArgumentException(category +656" is not an Attribute");657}658659if (!isAttributeCategorySupported(category)) {660return null;661}662663if (category == Copies.class) {664return new Copies(1);665} else if (category == Chromaticity.class) {666return Chromaticity.COLOR;667} else if (category == Destination.class) {668try {669return new Destination((new File("out.ps")).toURI());670} catch (SecurityException se) {671try {672return new Destination(new URI("file:out.ps"));673} catch (URISyntaxException e) {674return null;675}676}677} else if (category == Fidelity.class) {678return Fidelity.FIDELITY_FALSE;679} else if (category == JobName.class) {680return new JobName("Java Printing", null);681} else if (category == JobSheets.class) {682return JobSheets.STANDARD;683} else if (category == Media.class) {684String defaultCountry = Locale.getDefault().getCountry();685if (defaultCountry != null &&686(defaultCountry.equals("") ||687defaultCountry.equals(Locale.US.getCountry()) ||688defaultCountry.equals(Locale.CANADA.getCountry()))) {689return MediaSizeName.NA_LETTER;690} else {691return MediaSizeName.ISO_A4;692}693} else if (category == MediaPrintableArea.class) {694String defaultCountry = Locale.getDefault().getCountry();695float iw, ih;696if (defaultCountry != null &&697(defaultCountry.equals("") ||698defaultCountry.equals(Locale.US.getCountry()) ||699defaultCountry.equals(Locale.CANADA.getCountry()))) {700iw = MediaSize.NA.LETTER.getX(Size2DSyntax.INCH) - 0.5f;701ih = MediaSize.NA.LETTER.getY(Size2DSyntax.INCH) - 0.5f;702} else {703iw = MediaSize.ISO.A4.getX(Size2DSyntax.INCH) - 0.5f;704ih = MediaSize.ISO.A4.getY(Size2DSyntax.INCH) - 0.5f;705}706return new MediaPrintableArea(0.25f, 0.25f, iw, ih,707MediaPrintableArea.INCH);708} else if (category == OrientationRequested.class) {709return OrientationRequested.PORTRAIT;710} else if (category == PageRanges.class) {711return new PageRanges(1, Integer.MAX_VALUE);712} else if (category == RequestingUserName.class) {713String userName = "";714try {715userName = System.getProperty("user.name", "");716} catch (SecurityException se) {717}718return new RequestingUserName(userName, null);719} else if (category == SheetCollate.class) {720return SheetCollate.UNCOLLATED;721} else if (category == Sides.class) {722return Sides.ONE_SIDED;723} else724return null;725}726727728private boolean isAutoSense(DocFlavor flavor) {729if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE) ||730flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE) ||731flavor.equals(DocFlavor.URL.AUTOSENSE)) {732return true;733}734else {735return false;736}737}738739public Object740getSupportedAttributeValues(Class<? extends Attribute> category,741DocFlavor flavor,742AttributeSet attributes)743{744745if (category == null) {746throw new NullPointerException("null category");747}748if (!Attribute.class.isAssignableFrom(category)) {749throw new IllegalArgumentException(category +750" does not implement Attribute");751}752if (flavor != null) {753if (!isDocFlavorSupported(flavor)) {754throw new IllegalArgumentException(flavor +755" is an unsupported flavor");756} else if (isAutoSense(flavor)) {757return null;758}759}760761if (!isAttributeCategorySupported(category)) {762return null;763}764765if (category == Chromaticity.class) {766if (flavor == null || isServiceFormattedFlavor(flavor)) {767Chromaticity[]arr = new Chromaticity[1];768arr[0] = Chromaticity.COLOR;769return (arr);770} else {771return null;772}773} else if (category == Destination.class) {774try {775return new Destination((new File("out.ps")).toURI());776} catch (SecurityException se) {777try {778return new Destination(new URI("file:out.ps"));779} catch (URISyntaxException e) {780return null;781}782}783} else if (category == JobName.class) {784return new JobName("Java Printing", null);785} else if (category == JobSheets.class) {786JobSheets arr[] = new JobSheets[2];787arr[0] = JobSheets.NONE;788arr[1] = JobSheets.STANDARD;789return arr;790} else if (category == RequestingUserName.class) {791String userName = "";792try {793userName = System.getProperty("user.name", "");794} catch (SecurityException se) {795}796return new RequestingUserName(userName, null);797} else if (category == OrientationRequested.class) {798if (flavor == null || isServiceFormattedFlavor(flavor)) {799OrientationRequested []arr = new OrientationRequested[3];800arr[0] = OrientationRequested.PORTRAIT;801arr[1] = OrientationRequested.LANDSCAPE;802arr[2] = OrientationRequested.REVERSE_LANDSCAPE;803return arr;804} else {805return null;806}807} else if ((category == Copies.class) ||808(category == CopiesSupported.class)) {809if (flavor == null ||810!(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||811flavor.equals(DocFlavor.URL.POSTSCRIPT) ||812flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) {813return new CopiesSupported(1, MAXCOPIES);814} else {815return null;816}817} else if (category == Media.class) {818Media []arr = new Media[mediaSizes.length];819System.arraycopy(mediaSizes, 0, arr, 0, mediaSizes.length);820return arr;821} else if (category == Fidelity.class) {822Fidelity []arr = new Fidelity[2];823arr[0] = Fidelity.FIDELITY_FALSE;824arr[1] = Fidelity.FIDELITY_TRUE;825return arr;826} else if (category == MediaPrintableArea.class) {827/* The code below implements the behaviour that if no Media or828* MediaSize attribute is specified, return an array of829* MediaPrintableArea, one for each supported Media.830* If a MediaSize is specified, return a MPA consistent for that,831* and if a Media is specified locate its MediaSize and return832* its MPA, and if none is found, return an MPA for the default833* Media for this service.834*/835if (attributes == null) {836return getAllPrintableAreas();837}838MediaSize mediaSize = (MediaSize)attributes.get(MediaSize.class);839Media media = (Media)attributes.get(Media.class);840MediaPrintableArea []arr = new MediaPrintableArea[1];841if (mediaSize == null) {842if (media instanceof MediaSizeName) {843MediaSizeName msn = (MediaSizeName)media;844mediaSize = MediaSize.getMediaSizeForName(msn);845if (mediaSize == null) {846/* try to get a size from the default media */847media = (Media)getDefaultAttributeValue(Media.class);848if (media instanceof MediaSizeName) {849msn = (MediaSizeName)media;850mediaSize = MediaSize.getMediaSizeForName(msn);851}852if (mediaSize == null) {853/* shouldn't happen, return a default */854arr[0] = new MediaPrintableArea(0.25f, 0.25f,8558f, 10.5f,856MediaSize.INCH);857return arr;858}859}860} else {861return getAllPrintableAreas();862}863}864/* If reach here MediaSize is non-null */865assert mediaSize != null;866arr[0] = new MediaPrintableArea(0.25f, 0.25f,867mediaSize.getX(MediaSize.INCH)-0.5f,868mediaSize.getY(MediaSize.INCH)-0.5f,869MediaSize.INCH);870return arr;871} else if (category == PageRanges.class) {872if (flavor == null ||873flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||874flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {875PageRanges []arr = new PageRanges[1];876arr[0] = new PageRanges(1, Integer.MAX_VALUE);877return arr;878} else {879return null;880}881} else if (category == SheetCollate.class) {882if (flavor == null ||883flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||884flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {885SheetCollate []arr = new SheetCollate[2];886arr[0] = SheetCollate.UNCOLLATED;887arr[1] = SheetCollate.COLLATED;888return arr;889} else {890return null;891}892} else if (category == Sides.class) {893if (flavor == null ||894flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||895flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {896Sides []arr = new Sides[3];897arr[0] = Sides.ONE_SIDED;898arr[1] = Sides.TWO_SIDED_LONG_EDGE;899arr[2] = Sides.TWO_SIDED_SHORT_EDGE;900return arr;901} else {902return null;903}904} else {905return null;906}907}908909private static MediaPrintableArea[] mpas = null;910private MediaPrintableArea[] getAllPrintableAreas() {911912if (mpas == null) {913Media[] media = (Media[])getSupportedAttributeValues(Media.class,914null, null);915mpas = new MediaPrintableArea[media.length];916for (int i=0; i< mpas.length; i++) {917if (media[i] instanceof MediaSizeName) {918MediaSizeName msn = (MediaSizeName)media[i];919MediaSize mediaSize = MediaSize.getMediaSizeForName(msn);920if (mediaSize == null) {921mpas[i] = (MediaPrintableArea)922getDefaultAttributeValue(MediaPrintableArea.class);923} else {924mpas[i] = new MediaPrintableArea(0.25f, 0.25f,925mediaSize.getX(MediaSize.INCH)-0.5f,926mediaSize.getY(MediaSize.INCH)-0.5f,927MediaSize.INCH);928}929}930}931}932MediaPrintableArea[] mpasCopy = new MediaPrintableArea[mpas.length];933System.arraycopy(mpas, 0, mpasCopy, 0, mpas.length);934return mpasCopy;935}936937/* Is this one of the flavors that this service explicitly938* generates postscript for, and so can control how it is rendered?939*/940private boolean isServiceFormattedFlavor(DocFlavor flavor) {941return942flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||943flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE) ||944flavor.equals(DocFlavor.BYTE_ARRAY.GIF) ||945flavor.equals(DocFlavor.INPUT_STREAM.GIF) ||946flavor.equals(DocFlavor.URL.GIF) ||947flavor.equals(DocFlavor.BYTE_ARRAY.JPEG) ||948flavor.equals(DocFlavor.INPUT_STREAM.JPEG) ||949flavor.equals(DocFlavor.URL.JPEG) ||950flavor.equals(DocFlavor.BYTE_ARRAY.PNG) ||951flavor.equals(DocFlavor.INPUT_STREAM.PNG) ||952flavor.equals(DocFlavor.URL.PNG);953}954955public boolean isAttributeValueSupported(Attribute attr,956DocFlavor flavor,957AttributeSet attributes) {958if (attr == null) {959throw new NullPointerException("null attribute");960}961if (flavor != null) {962if (!isDocFlavorSupported(flavor)) {963throw new IllegalArgumentException(flavor +964" is an unsupported flavor");965} else if (isAutoSense(flavor)) {966return false;967}968}969Class category = attr.getCategory();970if (!isAttributeCategorySupported(category)) {971return false;972}973else if (attr.getCategory() == Chromaticity.class) {974if (flavor == null || isServiceFormattedFlavor(flavor)) {975return attr == Chromaticity.COLOR;976} else {977return false;978}979}980else if (attr.getCategory() == Copies.class) {981return (flavor == null ||982!(flavor.equals(DocFlavor.INPUT_STREAM.POSTSCRIPT) ||983flavor.equals(DocFlavor.URL.POSTSCRIPT) ||984flavor.equals(DocFlavor.BYTE_ARRAY.POSTSCRIPT))) &&985isSupportedCopies((Copies)attr);986} else if (attr.getCategory() == Destination.class) {987URI uri = ((Destination)attr).getURI();988if ("file".equals(uri.getScheme()) &&989!(uri.getSchemeSpecificPart().equals(""))) {990return true;991} else {992return false;993}994} else if (attr.getCategory() == Media.class) {995if (attr instanceof MediaSizeName) {996return isSupportedMedia((MediaSizeName)attr);997} else {998return false;999}1000} else if (attr.getCategory() == OrientationRequested.class) {1001if (attr == OrientationRequested.REVERSE_PORTRAIT ||1002(flavor != null) &&1003!isServiceFormattedFlavor(flavor)) {1004return false;1005}1006} else if (attr.getCategory() == PageRanges.class) {1007if (flavor != null &&1008!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1009flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {1010return false;1011}1012} else if (attr.getCategory() == SheetCollate.class) {1013if (flavor != null &&1014!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1015flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {1016return false;1017}1018} else if (attr.getCategory() == Sides.class) {1019if (flavor != null &&1020!(flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) ||1021flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {1022return false;1023}1024}1025return true;1026}10271028public AttributeSet getUnsupportedAttributes(DocFlavor flavor,1029AttributeSet attributes) {10301031if (flavor != null && !isDocFlavorSupported(flavor)) {1032throw new IllegalArgumentException("flavor " + flavor +1033"is not supported");1034}10351036if (attributes == null) {1037return null;1038}10391040Attribute attr;1041AttributeSet unsupp = new HashAttributeSet();1042Attribute []attrs = attributes.toArray();1043for (int i=0; i<attrs.length; i++) {1044try {1045attr = attrs[i];1046if (!isAttributeCategorySupported(attr.getCategory())) {1047unsupp.add(attr);1048} else if (!isAttributeValueSupported(attr, flavor,1049attributes)) {1050unsupp.add(attr);1051}1052} catch (ClassCastException e) {1053}1054}1055if (unsupp.isEmpty()) {1056return null;1057} else {1058return unsupp;1059}1060}10611062public ServiceUIFactory getServiceUIFactory() {1063return null;1064}10651066public String toString() {1067return "Unix Printer : " + getName();1068}10691070public boolean equals(Object obj) {1071return (obj == this ||1072(obj instanceof UnixPrintService &&1073((UnixPrintService)obj).getName().equals(getName())));1074}10751076public int hashCode() {1077return this.getClass().hashCode()+getName().hashCode();1078}10791080public boolean usesClass(Class c) {1081return (c == sun.print.PSPrinterJob.class);1082}10831084}108510861087