/*
* 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 getPrinterIsAcceptingJobsSysV() {
String command = "/usr/bin/lpstat -a " + printer;
String[] results= PrintServiceLookupProvider.execCmd(command);
if (results != null && results.length > 0) {
if (results[0].startsWith(printer + " accepting requests")) {
return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
}
else if (results[0].startsWith(printer)) {
/* As well as "myprinter accepting requests", look for
* "myprinter@somehost accepting requests".
*/
int index = printer.length();
String str = results[0];
if (str.length() > index &&
str.charAt(index) == '@' &&
str.indexOf(" accepting requests", index) > 0 &&
str.indexOf(" not accepting requests", index) == -1) {
return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
}
}
}
return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS ;
}
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<String> 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.isSysV()) {
return getPrinterIsAcceptingJobsSysV();
} else 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 getQueuedJobCountSysV() {
String command = "/usr/bin/lpstat -R " + printer;
String[] results= PrintServiceLookupProvider.execCmd(command);
int qlen = (results == null) ? 0 : results.length;
return new QueuedJobCount(qlen);
}
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.isSysV()) {
return getQueuedJobCountSysV();
} else if (PrintServiceLookupProvider.isBSD()) {
return getQueuedJobCountBSD();
} else if (PrintServiceLookupProvider.isAIX()) {
return getQueuedJobCountAIX();
} else {
return new QueuedJobCount(0);
}
}
private PrintServiceAttributeSet getSysVServiceAttributes() {
PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
attrs.add(getQueuedJobCountSysV());
attrs.add(getPrinterIsAcceptingJobsSysV());
return attrs;
}
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<mediaSizes.length; i++) {
if (msn.equals(mediaSizes[i])) {
return true;
}
}
return false;
}
public DocPrintJob createPrintJob() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPrintJobAccess();
}
return new UnixPrintJob(this);
}
private PrintServiceAttributeSet getDynamicAttributes() {
if (PrintServiceLookupProvider.isSysV()) {
return getSysVServiceAttributes();
} else if (PrintServiceLookupProvider.isAIX()) {
return getAIXServiceAttributes();
} else {
return getBSDServiceAttributes();
}
}
public PrintServiceAttributeSet getUpdatedAttributes() {
PrintServiceAttributeSet currSet = getDynamicAttributes();
if (lastSet == null) {
lastSet = currSet;
return AttributeSetUtilities.unmodifiableView(currSet);
} else {
PrintServiceAttributeSet updates =
new HashPrintServiceAttributeSet();
Attribute []attrs = currSet.toArray();
Attribute attr;
for (int i=0; i<attrs.length; i++) {
attr = attrs[i];
if (!lastSet.containsValue(attr)) {
updates.add(attr);
}
}
lastSet = currSet;
return AttributeSetUtilities.unmodifiableView(updates);
}
}
public void wakeNotifier() {
synchronized (this) {
if (notifier != null) {
notifier.wake();
}
}
}
public void addPrintServiceAttributeListener(
PrintServiceAttributeListener listener) {
synchronized (this) {
if (listener == null) {
return;
}
if (notifier == null) {
notifier = new ServiceNotifier(this);
}
notifier.addListener(listener);
}
}
public void removePrintServiceAttributeListener(
PrintServiceAttributeListener listener) {
synchronized (this) {
if (listener == null || notifier == null ) {
return;
}
notifier.removeListener(listener);
if (notifier.isEmpty()) {
notifier.stopNotifier();
notifier = null;
}
}
}
@SuppressWarnings("unchecked")
public <T extends PrintServiceAttribute>
T getAttribute(Class<T> 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<supportedDocFlavors.length; f++) {
if (flavor.equals(supportedDocFlavors[f])) {
return true;
}
}
return false;
}
public Class<?>[] getSupportedAttributeCategories() {
ArrayList<Class<?>> 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<? extends Attribute> 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<otherAttrCats.length;i++) {
if (category == otherAttrCats[i]) {
return true;
}
}
return false;
}
/* return defaults for all attributes for which there is a default
* value
*/
public Object
getDefaultAttributeValue(Class<? extends Attribute> 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<? extends Attribute> 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<? extends Attribute> 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) {
/**代码未完, 请加载全部代码(NowJava.com).**/