001: /*
002: * Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.print;
027:
028: import java.io.File;
029: import java.net.URI;
030: import java.net.URISyntaxException;
031: import java.util.Locale;
032:
033: import javax.print.DocFlavor;
034: import javax.print.DocPrintJob;
035: import javax.print.PrintService;
036: import javax.print.ServiceUIFactory;
037: import javax.print.attribute.Attribute;
038: import javax.print.attribute.AttributeSet;
039: import javax.print.attribute.AttributeSetUtilities;
040: import javax.print.attribute.HashAttributeSet;
041: import javax.print.attribute.PrintServiceAttribute;
042: import javax.print.attribute.PrintServiceAttributeSet;
043: import javax.print.attribute.HashPrintServiceAttributeSet;
044: import javax.print.attribute.Size2DSyntax;
045: import javax.print.attribute.standard.PrinterName;
046: import javax.print.attribute.standard.PrinterIsAcceptingJobs;
047: import javax.print.attribute.standard.QueuedJobCount;
048: import javax.print.attribute.standard.JobName;
049: import javax.print.attribute.standard.JobSheets;
050: import javax.print.attribute.standard.RequestingUserName;
051: import javax.print.attribute.standard.Chromaticity;
052: import javax.print.attribute.standard.ColorSupported;
053: import javax.print.attribute.standard.Copies;
054: import javax.print.attribute.standard.CopiesSupported;
055: import javax.print.attribute.standard.Destination;
056: import javax.print.attribute.standard.Fidelity;
057: import javax.print.attribute.standard.Media;
058: import javax.print.attribute.standard.MediaPrintableArea;
059: import javax.print.attribute.standard.MediaSize;
060: import javax.print.attribute.standard.MediaSizeName;
061: import javax.print.attribute.standard.OrientationRequested;
062: import javax.print.attribute.standard.PageRanges;
063: import javax.print.attribute.standard.PrinterState;
064: import javax.print.attribute.standard.PrinterStateReason;
065: import javax.print.attribute.standard.PrinterStateReasons;
066: import javax.print.attribute.standard.Severity;
067: import javax.print.attribute.standard.SheetCollate;
068: import javax.print.attribute.standard.Sides;
069: import javax.print.event.PrintServiceAttributeListener;
070:
071: public class UnixPrintService implements PrintService,
072: AttributeUpdater, SunPrinterJobService {
073:
074: /* define doc flavors for text types in the default encoding of
075: * this platform since we can always read those.
076: */
077: private static String encoding = "ISO8859_1";
078: private static DocFlavor textByteFlavor;
079:
080: private static DocFlavor[] supportedDocFlavors = null;
081: private static final DocFlavor[] supportedDocFlavorsInit = {
082: DocFlavor.BYTE_ARRAY.POSTSCRIPT,
083: DocFlavor.INPUT_STREAM.POSTSCRIPT,
084: DocFlavor.URL.POSTSCRIPT, DocFlavor.BYTE_ARRAY.GIF,
085: DocFlavor.INPUT_STREAM.GIF, DocFlavor.URL.GIF,
086: DocFlavor.BYTE_ARRAY.JPEG, DocFlavor.INPUT_STREAM.JPEG,
087: DocFlavor.URL.JPEG, DocFlavor.BYTE_ARRAY.PNG,
088: DocFlavor.INPUT_STREAM.PNG, DocFlavor.URL.PNG,
089:
090: DocFlavor.CHAR_ARRAY.TEXT_PLAIN,
091: DocFlavor.READER.TEXT_PLAIN, DocFlavor.STRING.TEXT_PLAIN,
092:
093: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8,
094: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16,
095: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16BE,
096: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_16LE,
097: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_US_ASCII,
098:
099: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_8,
100: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16,
101: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16BE,
102: DocFlavor.INPUT_STREAM.TEXT_PLAIN_UTF_16LE,
103: DocFlavor.INPUT_STREAM.TEXT_PLAIN_US_ASCII,
104:
105: DocFlavor.URL.TEXT_PLAIN_UTF_8,
106: DocFlavor.URL.TEXT_PLAIN_UTF_16,
107: DocFlavor.URL.TEXT_PLAIN_UTF_16BE,
108: DocFlavor.URL.TEXT_PLAIN_UTF_16LE,
109: DocFlavor.URL.TEXT_PLAIN_US_ASCII,
110:
111: DocFlavor.SERVICE_FORMATTED.PAGEABLE,
112: DocFlavor.SERVICE_FORMATTED.PRINTABLE,
113:
114: DocFlavor.BYTE_ARRAY.AUTOSENSE, DocFlavor.URL.AUTOSENSE,
115: DocFlavor.INPUT_STREAM.AUTOSENSE };
116:
117: private static final DocFlavor[] supportedHostDocFlavors = {
118: DocFlavor.BYTE_ARRAY.TEXT_PLAIN_HOST,
119: DocFlavor.INPUT_STREAM.TEXT_PLAIN_HOST,
120: DocFlavor.URL.TEXT_PLAIN_HOST };
121:
122: String[] lpcStatusCom = { "",
123: "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $2, $3}'" };
124:
125: String[] lpcQueueCom = { "",
126: "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk '{print $4}'" };
127:
128: static {
129: encoding = (String) java.security.AccessController
130: .doPrivileged(new sun.security.action.GetPropertyAction(
131: "file.encoding"));
132: }
133:
134: /* let's try to support a few of these */
135: private static final Class[] serviceAttrCats = { PrinterName.class,
136: PrinterIsAcceptingJobs.class, QueuedJobCount.class, };
137:
138: /* it turns out to be inconvenient to store the other categories
139: * separately because many attributes are in multiple categories.
140: */
141: private static final Class[] otherAttrCats = { Chromaticity.class,
142: Copies.class, Destination.class, Fidelity.class,
143: JobName.class, JobSheets.class, Media.class, /* have to support this somehow ... */
144: MediaPrintableArea.class, OrientationRequested.class,
145: PageRanges.class, RequestingUserName.class,
146: SheetCollate.class, Sides.class, };
147:
148: private static int MAXCOPIES = 1000;
149:
150: private static final MediaSizeName mediaSizes[] = {
151: MediaSizeName.NA_LETTER, MediaSizeName.TABLOID,
152: MediaSizeName.LEDGER, MediaSizeName.NA_LEGAL,
153: MediaSizeName.EXECUTIVE, MediaSizeName.ISO_A3,
154: MediaSizeName.ISO_A4, MediaSizeName.ISO_A5,
155: MediaSizeName.ISO_B4, MediaSizeName.ISO_B5, };
156:
157: private String printer;
158: private PrinterName name;
159: private boolean isInvalid;
160:
161: transient private PrintServiceAttributeSet lastSet;
162: transient private ServiceNotifier notifier = null;
163:
164: UnixPrintService(String name) {
165: if (name == null) {
166: throw new IllegalArgumentException("null printer name");
167: }
168: printer = name;
169: isInvalid = false;
170: }
171:
172: public void invalidateService() {
173: isInvalid = true;
174: }
175:
176: public String getName() {
177: return printer;
178: }
179:
180: private PrinterName getPrinterName() {
181: if (name == null) {
182: name = new PrinterName(printer, null);
183: }
184: return name;
185: }
186:
187: private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsSysV() {
188: String command = "/usr/bin/lpstat -a " + printer;
189: String results[] = UnixPrintServiceLookup.execCmd(command);
190:
191: if (results != null && results.length > 0) {
192: if (results[0].startsWith(printer + " accepting requests")) {
193: return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
194: } else if (results[0].startsWith(printer)) {
195: /* As well as "myprinter accepting requests", look for
196: * "myprinter@somehost accepting requests".
197: */
198: int index = printer.length();
199: String str = results[0];
200: if (str.length() > index
201: && str.charAt(index) == '@'
202: && str.indexOf(" accepting requests", index) > 0
203: && str
204: .indexOf(" not accepting requests",
205: index) == -1) {
206: return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
207: }
208: }
209: }
210: return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
211: }
212:
213: private PrinterIsAcceptingJobs getPrinterIsAcceptingJobsBSD() {
214: if (UnixPrintServiceLookup.cmdIndex == UnixPrintServiceLookup.UNINITIALIZED) {
215:
216: UnixPrintServiceLookup.cmdIndex = UnixPrintServiceLookup
217: .getBSDCommandIndex();
218: }
219:
220: String command = "/usr/sbin/lpc status " + printer
221: + lpcStatusCom[UnixPrintServiceLookup.cmdIndex];
222: String results[] = UnixPrintServiceLookup.execCmd(command);
223:
224: if (results != null && results.length > 0) {
225: if (UnixPrintServiceLookup.cmdIndex == UnixPrintServiceLookup.BSD_LPD_NG) {
226: if (results[0].startsWith("enabled enabled")) {
227: return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
228: }
229: } else {
230: if ((results[1].trim().startsWith("queuing is enabled") && results[2]
231: .trim().startsWith("printing is enabled"))
232: || (results.length >= 4
233: && results[2].trim().startsWith(
234: "queuing is enabled") && results[3]
235: .trim().startsWith(
236: "printing is enabled"))) {
237: return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
238: }
239: }
240: }
241: return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS;
242: }
243:
244: private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() {
245: if (UnixPrintServiceLookup.isSysV()) {
246: return getPrinterIsAcceptingJobsSysV();
247: } else if (UnixPrintServiceLookup.isBSD()) {
248: return getPrinterIsAcceptingJobsBSD();
249: } else {
250: return PrinterIsAcceptingJobs.ACCEPTING_JOBS;
251: }
252: }
253:
254: private PrinterState getPrinterState() {
255: if (isInvalid) {
256: return PrinterState.STOPPED;
257: } else {
258: return null;
259: }
260: }
261:
262: private PrinterStateReasons getPrinterStateReasons() {
263: if (isInvalid) {
264: PrinterStateReasons psr = new PrinterStateReasons();
265: psr.put(PrinterStateReason.SHUTDOWN, Severity.ERROR);
266: return psr;
267: } else {
268: return null;
269: }
270: }
271:
272: private QueuedJobCount getQueuedJobCountSysV() {
273: String command = "/usr/bin/lpstat -R " + printer;
274: String results[] = UnixPrintServiceLookup.execCmd(command);
275: int qlen = (results == null) ? 0 : results.length;
276:
277: return new QueuedJobCount(qlen);
278: }
279:
280: private QueuedJobCount getQueuedJobCountBSD() {
281: if (UnixPrintServiceLookup.cmdIndex == UnixPrintServiceLookup.UNINITIALIZED) {
282:
283: UnixPrintServiceLookup.cmdIndex = UnixPrintServiceLookup
284: .getBSDCommandIndex();
285: }
286:
287: int qlen = 0;
288: String command = "/usr/sbin/lpc status " + printer
289: + lpcQueueCom[UnixPrintServiceLookup.cmdIndex];
290: String results[] = UnixPrintServiceLookup.execCmd(command);
291:
292: if (results != null && results.length > 0) {
293: String queued;
294: if (UnixPrintServiceLookup.cmdIndex == UnixPrintServiceLookup.BSD_LPD_NG) {
295: queued = results[0];
296: } else {
297: queued = results[3].trim();
298: if (queued.startsWith("no")) {
299: return new QueuedJobCount(0);
300: } else {
301: queued = queued.substring(0, queued.indexOf(' '));
302: }
303: }
304:
305: try {
306: qlen = Integer.parseInt(queued);
307: } catch (NumberFormatException e) {
308: }
309: }
310:
311: return new QueuedJobCount(qlen);
312: }
313:
314: private QueuedJobCount getQueuedJobCount() {
315: if (UnixPrintServiceLookup.isSysV()) {
316: return getQueuedJobCountSysV();
317: } else if (UnixPrintServiceLookup.isBSD()) {
318: return getQueuedJobCountBSD();
319: } else {
320: return new QueuedJobCount(0);
321: }
322: }
323:
324: private PrintServiceAttributeSet getSysVServiceAttributes() {
325: PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
326: attrs.add(getQueuedJobCountSysV());
327: attrs.add(getPrinterIsAcceptingJobsSysV());
328: return attrs;
329: }
330:
331: private PrintServiceAttributeSet getBSDServiceAttributes() {
332: PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
333: attrs.add(getQueuedJobCountBSD());
334: attrs.add(getPrinterIsAcceptingJobsBSD());
335: return attrs;
336: }
337:
338: private boolean isSupportedCopies(Copies copies) {
339: int numCopies = copies.getValue();
340: return (numCopies > 0 && numCopies < MAXCOPIES);
341: }
342:
343: private boolean isSupportedMedia(MediaSizeName msn) {
344: for (int i = 0; i < mediaSizes.length; i++) {
345: if (msn.equals(mediaSizes[i])) {
346: return true;
347: }
348: }
349: return false;
350: }
351:
352: public DocPrintJob createPrintJob() {
353: SecurityManager security = System.getSecurityManager();
354: if (security != null) {
355: security.checkPrintJobAccess();
356: }
357: return new UnixPrintJob(this );
358: }
359:
360: private PrintServiceAttributeSet getDynamicAttributes() {
361: if (UnixPrintServiceLookup.isSysV()) {
362: return getSysVServiceAttributes();
363: } else {
364: return getBSDServiceAttributes();
365: }
366: }
367:
368: public PrintServiceAttributeSet getUpdatedAttributes() {
369: PrintServiceAttributeSet currSet = getDynamicAttributes();
370: if (lastSet == null) {
371: lastSet = currSet;
372: return AttributeSetUtilities.unmodifiableView(currSet);
373: } else {
374: PrintServiceAttributeSet updates = new HashPrintServiceAttributeSet();
375: Attribute[] attrs = currSet.toArray();
376: Attribute attr;
377: for (int i = 0; i < attrs.length; i++) {
378: attr = attrs[i];
379: if (!lastSet.containsValue(attr)) {
380: updates.add(attr);
381: }
382: }
383: lastSet = currSet;
384: return AttributeSetUtilities.unmodifiableView(updates);
385: }
386: }
387:
388: public void wakeNotifier() {
389: synchronized (this ) {
390: if (notifier != null) {
391: notifier.wake();
392: }
393: }
394: }
395:
396: public void addPrintServiceAttributeListener(
397: PrintServiceAttributeListener listener) {
398: synchronized (this ) {
399: if (listener == null) {
400: return;
401: }
402: if (notifier == null) {
403: notifier = new ServiceNotifier(this );
404: }
405: notifier.addListener(listener);
406: }
407: }
408:
409: public void removePrintServiceAttributeListener(
410: PrintServiceAttributeListener listener) {
411: synchronized (this ) {
412: if (listener == null || notifier == null) {
413: return;
414: }
415: notifier.removeListener(listener);
416: if (notifier.isEmpty()) {
417: notifier.stopNotifier();
418: notifier = null;
419: }
420: }
421: }
422:
423: public <T extends PrintServiceAttribute> T getAttribute(
424: Class<T> category) {
425: if (category == null) {
426: throw new NullPointerException("category");
427: }
428: if (!(PrintServiceAttribute.class.isAssignableFrom(category))) {
429: throw new IllegalArgumentException(
430: "Not a PrintServiceAttribute");
431: }
432:
433: if (category == PrinterName.class) {
434: return (T) getPrinterName();
435: } else if (category == PrinterState.class) {
436: return (T) getPrinterState();
437: } else if (category == PrinterStateReasons.class) {
438: return (T) getPrinterStateReasons();
439: } else if (category == QueuedJobCount.class) {
440: return (T) getQueuedJobCount();
441: } else if (category == PrinterIsAcceptingJobs.class) {
442: return (T) getPrinterIsAcceptingJobs();
443: } else {
444: return null;
445: }
446: }
447:
448: public PrintServiceAttributeSet getAttributes() {
449: PrintServiceAttributeSet attrs = new HashPrintServiceAttributeSet();
450: attrs.add(getPrinterName());
451: attrs.add(getPrinterIsAcceptingJobs());
452: PrinterState prnState = getPrinterState();
453: if (prnState != null) {
454: attrs.add(prnState);
455: }
456: PrinterStateReasons prnStateReasons = getPrinterStateReasons();
457: if (prnStateReasons != null) {
458: attrs.add(prnStateReasons);
459: }
460: attrs.add(getQueuedJobCount());
461: return AttributeSetUtilities.unmodifiableView(attrs);
462: }
463:
464: private void initSupportedDocFlavors() {
465: String hostEnc = DocFlavor.hostEncoding
466: .toLowerCase(Locale.ENGLISH);
467: if (!hostEnc.equals("utf-8") && !hostEnc.equals("utf-16")
468: && !hostEnc.equals("utf-16be")
469: && !hostEnc.equals("utf-16le")
470: && !hostEnc.equals("us-ascii")) {
471:
472: int len = supportedDocFlavorsInit.length;
473: DocFlavor[] flavors = new DocFlavor[len
474: + supportedHostDocFlavors.length];
475: // copy host encoding flavors
476: System.arraycopy(supportedHostDocFlavors, 0, flavors, len,
477: supportedHostDocFlavors.length);
478: System.arraycopy(supportedDocFlavorsInit, 0, flavors, 0,
479: len);
480:
481: supportedDocFlavors = flavors;
482: } else {
483: supportedDocFlavors = supportedDocFlavorsInit;
484: }
485: }
486:
487: public DocFlavor[] getSupportedDocFlavors() {
488: if (supportedDocFlavors == null) {
489: initSupportedDocFlavors();
490: }
491: int len = supportedDocFlavors.length;
492: DocFlavor[] flavors = new DocFlavor[len];
493: System.arraycopy(supportedDocFlavors, 0, flavors, 0, len);
494:
495: return flavors;
496: }
497:
498: public boolean isDocFlavorSupported(DocFlavor flavor) {
499: if (supportedDocFlavors == null) {
500: initSupportedDocFlavors();
501: }
502: for (int f = 0; f < supportedDocFlavors.length; f++) {
503: if (flavor.equals(supportedDocFlavors[f])) {
504: return true;
505: }
506: }
507: return false;
508: }
509:
510: public Class[] getSupportedAttributeCategories() {
511: int totalCats = otherAttrCats.length;
512: Class[] cats = new Class[totalCats];
513: System.arraycopy(otherAttrCats, 0, cats, 0,
514: otherAttrCats.length);
515: return cats;
516: }
517:
518: public boolean isAttributeCategorySupported(
519: Class<? extends Attribute> category) {
520: if (category == null) {
521: throw new NullPointerException("null category");
522: }
523: if (!(Attribute.class.isAssignableFrom(category))) {
524: throw new IllegalArgumentException(category
525: + " is not an Attribute");
526: }
527:
528: for (int i = 0; i < otherAttrCats.length; i++) {
529: if (category == otherAttrCats[i]) {
530: return true;
531: }
532: }
533: return false;
534: }
535:
536: /* return defaults for all attributes for which there is a default
537: * value
538: */
539: public Object getDefaultAttributeValue(
540: Class<? extends Attribute> category) {
541: if (category == null) {
542: throw new NullPointerException("null category");
543: }
544: if (!Attribute.class.isAssignableFrom(category)) {
545: throw new IllegalArgumentException(category
546: + " is not an Attribute");
547: }
548:
549: if (!isAttributeCategorySupported(category)) {
550: return null;
551: }
552:
553: if (category == Copies.class) {
554: return new Copies(1);
555: } else if (category == Chromaticity.class) {
556: return Chromaticity.COLOR;
557: } else if (category == Destination.class) {
558: try {
559: return new Destination((new File("out.ps")).toURI());
560: } catch (SecurityException se) {
561: try {
562: return new Destination(new URI("file:out.ps"));
563: } catch (URISyntaxException e) {
564: return null;
565: }
566: }
567: } else if (category == Fidelity.class) {
568: return Fidelity.FIDELITY_FALSE;
569: } else if (category == JobName.class) {
570: return new JobName("Java Printing", null);
571: } else if (category == JobSheets.class) {
572: return JobSheets.STANDARD;
573: } else if (category == Media.class) {
574: String defaultCountry = Locale.getDefault().getCountry();
575: if (defaultCountry != null
576: && (defaultCountry.equals("")
577: || defaultCountry.equals(Locale.US
578: .getCountry()) || defaultCountry
579: .equals(Locale.CANADA.getCountry()))) {
580: return MediaSizeName.NA_LETTER;
581: } else {
582: return MediaSizeName.ISO_A4;
583: }
584: } else if (category == MediaPrintableArea.class) {
585: String defaultCountry = Locale.getDefault().getCountry();
586: float iw, ih;
587: if (defaultCountry != null
588: && (defaultCountry.equals("")
589: || defaultCountry.equals(Locale.US
590: .getCountry()) || defaultCountry
591: .equals(Locale.CANADA.getCountry()))) {
592: iw = MediaSize.NA.LETTER.getX(Size2DSyntax.INCH) - 0.5f;
593: ih = MediaSize.NA.LETTER.getY(Size2DSyntax.INCH) - 0.5f;
594: } else {
595: iw = MediaSize.ISO.A4.getX(Size2DSyntax.INCH) - 0.5f;
596: ih = MediaSize.ISO.A4.getY(Size2DSyntax.INCH) - 0.5f;
597: }
598: return new MediaPrintableArea(0.25f, 0.25f, iw, ih,
599: MediaPrintableArea.INCH);
600: } else if (category == OrientationRequested.class) {
601: return OrientationRequested.PORTRAIT;
602: } else if (category == PageRanges.class) {
603: return new PageRanges(1, Integer.MAX_VALUE);
604: } else if (category == RequestingUserName.class) {
605: String userName = "";
606: try {
607: userName = System.getProperty("user.name", "");
608: } catch (SecurityException se) {
609: }
610: return new RequestingUserName(userName, null);
611: } else if (category == SheetCollate.class) {
612: return SheetCollate.UNCOLLATED;
613: } else if (category == Sides.class) {
614: return Sides.ONE_SIDED;
615: } else
616: return null;
617: }
618:
619: private boolean isAutoSense(DocFlavor flavor) {
620: if (flavor.equals(DocFlavor.BYTE_ARRAY.AUTOSENSE)
621: || flavor.equals(DocFlavor.INPUT_STREAM.AUTOSENSE)
622: || flavor.equals(DocFlavor.URL.AUTOSENSE)) {
623: return true;
624: } else {
625: return false;
626: }
627: }
628:
629: public Object getSupportedAttributeValues(
630: Class<? extends Attribute> category, DocFlavor flavor,
631: AttributeSet attributes) {
632:
633: if (category == null) {
634: throw new NullPointerException("null category");
635: }
636: if (!Attribute.class.isAssignableFrom(category)) {
637: throw new IllegalArgumentException(category
638: + " does not implement Attribute");
639: }
640: if (flavor != null) {
641: if (!isDocFlavorSupported(flavor)) {
642: throw new IllegalArgumentException(flavor
643: + " is an unsupported flavor");
644: } else if (isAutoSense(flavor)) {
645: return null;
646: }
647: }
648:
649: if (!isAttributeCategorySupported(category)) {
650: return null;
651: }
652:
653: if (category == Chromaticity.class) {
654: if (flavor == null
655: || flavor
656: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
657: || flavor
658: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)
659: || flavor.equals(DocFlavor.BYTE_ARRAY.GIF)
660: || flavor.equals(DocFlavor.INPUT_STREAM.GIF)
661: || flavor.equals(DocFlavor.URL.GIF)
662: || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG)
663: || flavor.equals(DocFlavor.INPUT_STREAM.JPEG)
664: || flavor.equals(DocFlavor.URL.JPEG)
665: || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)
666: || flavor.equals(DocFlavor.INPUT_STREAM.PNG)
667: || flavor.equals(DocFlavor.URL.PNG)) {
668:
669: Chromaticity[] arr = new Chromaticity[1];
670: arr[0] = Chromaticity.COLOR;
671: return (arr);
672: } else {
673: return null;
674: }
675: } else if (category == Destination.class) {
676: try {
677: return new Destination((new File("out.ps")).toURI());
678: } catch (SecurityException se) {
679: try {
680: return new Destination(new URI("file:out.ps"));
681: } catch (URISyntaxException e) {
682: return null;
683: }
684: }
685: } else if (category == JobName.class) {
686: return new JobName("Java Printing", null);
687: } else if (category == JobSheets.class) {
688: JobSheets arr[] = new JobSheets[2];
689: arr[0] = JobSheets.NONE;
690: arr[1] = JobSheets.STANDARD;
691: return arr;
692: } else if (category == RequestingUserName.class) {
693: String userName = "";
694: try {
695: userName = System.getProperty("user.name", "");
696: } catch (SecurityException se) {
697: }
698: return new RequestingUserName(userName, null);
699: } else if (category == OrientationRequested.class) {
700: if (flavor == null
701: || flavor
702: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
703: || flavor
704: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)
705: || flavor.equals(DocFlavor.INPUT_STREAM.GIF)
706: || flavor.equals(DocFlavor.INPUT_STREAM.JPEG)
707: || flavor.equals(DocFlavor.INPUT_STREAM.PNG)
708: || flavor.equals(DocFlavor.BYTE_ARRAY.GIF)
709: || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG)
710: || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)
711: || flavor.equals(DocFlavor.URL.GIF)
712: || flavor.equals(DocFlavor.URL.JPEG)
713: || flavor.equals(DocFlavor.URL.PNG)) {
714: OrientationRequested[] arr = new OrientationRequested[3];
715: arr[0] = OrientationRequested.PORTRAIT;
716: arr[1] = OrientationRequested.LANDSCAPE;
717: arr[2] = OrientationRequested.REVERSE_LANDSCAPE;
718: return arr;
719: } else {
720: return null;
721: }
722: } else if ((category == Copies.class)
723: || (category == CopiesSupported.class)) {
724: return new CopiesSupported(1, MAXCOPIES);
725: } else if (category == Media.class) {
726: Media[] arr = new Media[mediaSizes.length];
727: System.arraycopy(mediaSizes, 0, arr, 0, mediaSizes.length);
728: return arr;
729: } else if (category == Fidelity.class) {
730: Fidelity[] arr = new Fidelity[2];
731: arr[0] = Fidelity.FIDELITY_FALSE;
732: arr[1] = Fidelity.FIDELITY_TRUE;
733: return arr;
734: } else if (category == MediaPrintableArea.class) {
735: /* The code below implements the behaviour that if no Media or
736: * MediaSize attribute is specified, return an array of
737: * MediaPrintableArea, one for each supported Media.
738: * If a MediaSize is specified, return a MPA consistent for that,
739: * and if a Media is specified locate its MediaSize and return
740: * its MPA, and if none is found, return an MPA for the default
741: * Media for this service.
742: */
743: if (attributes == null) {
744: return getAllPrintableAreas();
745: }
746: MediaSize mediaSize = (MediaSize) attributes
747: .get(MediaSize.class);
748: Media media = (Media) attributes.get(Media.class);
749: MediaPrintableArea[] arr = new MediaPrintableArea[1];
750: if (mediaSize == null) {
751: if (media instanceof MediaSizeName) {
752: MediaSizeName msn = (MediaSizeName) media;
753: mediaSize = MediaSize.getMediaSizeForName(msn);
754: if (mediaSize == null) {
755: /* try to get a size from the default media */
756: media = (Media) getDefaultAttributeValue(Media.class);
757: if (media instanceof MediaSizeName) {
758: msn = (MediaSizeName) media;
759: mediaSize = MediaSize
760: .getMediaSizeForName(msn);
761: }
762: if (mediaSize == null) {
763: /* shouldn't happen, return a default */
764: arr[0] = new MediaPrintableArea(0.25f,
765: 0.25f, 8f, 10.5f, MediaSize.INCH);
766: return arr;
767: }
768: }
769: } else {
770: return getAllPrintableAreas();
771: }
772: }
773: /* If reach here MediaSize is non-null */
774: assert mediaSize != null;
775: arr[0] = new MediaPrintableArea(0.25f, 0.25f, mediaSize
776: .getX(MediaSize.INCH) - 0.5f, mediaSize
777: .getY(MediaSize.INCH) - 0.5f, MediaSize.INCH);
778: return arr;
779: } else if (category == PageRanges.class) {
780: if (flavor == null
781: || flavor
782: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
783: || flavor
784: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
785: PageRanges[] arr = new PageRanges[1];
786: arr[0] = new PageRanges(1, Integer.MAX_VALUE);
787: return arr;
788: } else {
789: return null;
790: }
791: } else if (category == SheetCollate.class) {
792: if (flavor == null
793: || flavor
794: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
795: || flavor
796: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
797: SheetCollate[] arr = new SheetCollate[2];
798: arr[0] = SheetCollate.UNCOLLATED;
799: arr[1] = SheetCollate.COLLATED;
800: return arr;
801: } else {
802: return null;
803: }
804: } else if (category == Sides.class) {
805: if (flavor == null
806: || flavor
807: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
808: || flavor
809: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)) {
810: Sides[] arr = new Sides[3];
811: arr[0] = Sides.ONE_SIDED;
812: arr[1] = Sides.TWO_SIDED_LONG_EDGE;
813: arr[2] = Sides.TWO_SIDED_SHORT_EDGE;
814: return arr;
815: } else {
816: return null;
817: }
818: } else {
819: return null;
820: }
821: }
822:
823: private static MediaPrintableArea[] mpas = null;
824:
825: private MediaPrintableArea[] getAllPrintableAreas() {
826:
827: if (mpas == null) {
828: Media[] media = (Media[]) getSupportedAttributeValues(
829: Media.class, null, null);
830: mpas = new MediaPrintableArea[media.length];
831: for (int i = 0; i < mpas.length; i++) {
832: if (media[i] instanceof MediaSizeName) {
833: MediaSizeName msn = (MediaSizeName) media[i];
834: MediaSize mediaSize = MediaSize
835: .getMediaSizeForName(msn);
836: if (mediaSize == null) {
837: mpas[i] = (MediaPrintableArea) getDefaultAttributeValue(MediaPrintableArea.class);
838: } else {
839: mpas[i] = new MediaPrintableArea(0.25f, 0.25f,
840: mediaSize.getX(MediaSize.INCH) - 0.5f,
841: mediaSize.getY(MediaSize.INCH) - 0.5f,
842: MediaSize.INCH);
843: }
844: }
845: }
846: }
847: MediaPrintableArea[] mpasCopy = new MediaPrintableArea[mpas.length];
848: System.arraycopy(mpas, 0, mpasCopy, 0, mpas.length);
849: return mpasCopy;
850: }
851:
852: /* Is this one of the flavors that this service explicitly
853: * generates postscript for, and so can control how it is rendered?
854: */
855: private boolean isServiceFormattedFlavor(DocFlavor flavor) {
856: return flavor.equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE)
857: || flavor.equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE)
858: || flavor.equals(DocFlavor.BYTE_ARRAY.GIF)
859: || flavor.equals(DocFlavor.INPUT_STREAM.GIF)
860: || flavor.equals(DocFlavor.URL.GIF)
861: || flavor.equals(DocFlavor.BYTE_ARRAY.JPEG)
862: || flavor.equals(DocFlavor.INPUT_STREAM.JPEG)
863: || flavor.equals(DocFlavor.URL.JPEG)
864: || flavor.equals(DocFlavor.BYTE_ARRAY.PNG)
865: || flavor.equals(DocFlavor.INPUT_STREAM.PNG)
866: || flavor.equals(DocFlavor.URL.PNG);
867: }
868:
869: public boolean isAttributeValueSupported(Attribute attr,
870: DocFlavor flavor, AttributeSet attributes) {
871: if (attr == null) {
872: throw new NullPointerException("null attribute");
873: }
874: if (flavor != null) {
875: if (!isDocFlavorSupported(flavor)) {
876: throw new IllegalArgumentException(flavor
877: + " is an unsupported flavor");
878: } else if (isAutoSense(flavor)) {
879: return false;
880: }
881: }
882: Class category = attr.getCategory();
883: if (!isAttributeCategorySupported(category)) {
884: return false;
885: } else if (attr.getCategory() == Chromaticity.class) {
886: if (flavor == null || isServiceFormattedFlavor(flavor)) {
887: return attr == Chromaticity.COLOR;
888: } else {
889: return false;
890: }
891: } else if (attr.getCategory() == Copies.class) {
892: return (flavor == null || isServiceFormattedFlavor(flavor))
893: && isSupportedCopies((Copies) attr);
894: } else if (attr.getCategory() == Destination.class) {
895: URI uri = ((Destination) attr).getURI();
896: if ("file".equals(uri.getScheme())
897: && !(uri.getSchemeSpecificPart().equals(""))) {
898: return true;
899: } else {
900: return false;
901: }
902: } else if (attr.getCategory() == Media.class) {
903: if (attr instanceof MediaSizeName) {
904: return isSupportedMedia((MediaSizeName) attr);
905: } else {
906: return false;
907: }
908: } else if (attr.getCategory() == OrientationRequested.class) {
909: if (attr == OrientationRequested.REVERSE_PORTRAIT
910: || (flavor != null)
911: && !isServiceFormattedFlavor(flavor)) {
912: return false;
913: }
914: } else if (attr.getCategory() == PageRanges.class) {
915: if (flavor != null
916: && !(flavor
917: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor
918: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
919: return false;
920: }
921: } else if (attr.getCategory() == SheetCollate.class) {
922: if (flavor != null
923: && !(flavor
924: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor
925: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
926: return false;
927: }
928: } else if (attr.getCategory() == Sides.class) {
929: if (flavor != null
930: && !(flavor
931: .equals(DocFlavor.SERVICE_FORMATTED.PAGEABLE) || flavor
932: .equals(DocFlavor.SERVICE_FORMATTED.PRINTABLE))) {
933: return false;
934: }
935: }
936: return true;
937: }
938:
939: public AttributeSet getUnsupportedAttributes(DocFlavor flavor,
940: AttributeSet attributes) {
941:
942: if (flavor != null && !isDocFlavorSupported(flavor)) {
943: throw new IllegalArgumentException("flavor " + flavor
944: + "is not supported");
945: }
946:
947: if (attributes == null) {
948: return null;
949: }
950:
951: Attribute attr;
952: AttributeSet unsupp = new HashAttributeSet();
953: Attribute[] attrs = attributes.toArray();
954: for (int i = 0; i < attrs.length; i++) {
955: try {
956: attr = attrs[i];
957: if (!isAttributeCategorySupported(attr.getCategory())) {
958: unsupp.add(attr);
959: } else if (!isAttributeValueSupported(attr, flavor,
960: attributes)) {
961: unsupp.add(attr);
962: }
963: } catch (ClassCastException e) {
964: }
965: }
966: if (unsupp.isEmpty()) {
967: return null;
968: } else {
969: return unsupp;
970: }
971: }
972:
973: public ServiceUIFactory getServiceUIFactory() {
974: return null;
975: }
976:
977: public String toString() {
978: return "Unix Printer : " + getName();
979: }
980:
981: public boolean equals(Object obj) {
982: return (obj == this || (obj instanceof UnixPrintService && ((UnixPrintService) obj)
983: .getName().equals(getName())));
984: }
985:
986: public int hashCode() {
987: return this .getClass().hashCode() + getName().hashCode();
988: }
989:
990: public boolean usesClass(Class c) {
991: return (c == sun.print.PSPrinterJob.class);
992: }
993:
994: }
|