0N/A/*
2362N/A * Copyright (c) 2000, 2007, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.print;
0N/A
0N/Aimport java.io.BufferedReader;
0N/Aimport java.io.InputStream;
0N/Aimport java.io.InputStreamReader;
0N/Aimport java.io.IOException;
0N/Aimport java.util.ArrayList;
0N/Aimport java.security.AccessController;
0N/Aimport java.security.PrivilegedActionException;
0N/Aimport java.security.PrivilegedExceptionAction;
0N/Aimport javax.print.DocFlavor;
0N/Aimport javax.print.MultiDocPrintService;
0N/Aimport javax.print.PrintService;
0N/Aimport javax.print.PrintServiceLookup;
0N/Aimport javax.print.attribute.Attribute;
0N/Aimport javax.print.attribute.AttributeSet;
0N/Aimport javax.print.attribute.HashPrintRequestAttributeSet;
0N/Aimport javax.print.attribute.HashPrintServiceAttributeSet;
0N/Aimport javax.print.attribute.PrintRequestAttribute;
0N/Aimport javax.print.attribute.PrintRequestAttributeSet;
0N/Aimport javax.print.attribute.PrintServiceAttribute;
0N/Aimport javax.print.attribute.PrintServiceAttributeSet;
0N/Aimport javax.print.attribute.standard.PrinterName;
0N/A
0N/Apublic class Win32PrintServiceLookup extends PrintServiceLookup {
0N/A
0N/A private String defaultPrinter;
0N/A private PrintService defaultPrintService;
0N/A private String[] printers; /* excludes the default printer */
0N/A private PrintService[] printServices; /* includes the default printer */
0N/A
0N/A static {
0N/A java.security.AccessController.doPrivileged(
0N/A new sun.security.action.LoadLibraryAction("awt"));
0N/A }
0N/A
0N/A /* The singleton win32 print lookup service.
0N/A * Code that is aware of this field and wants to use it must first
0N/A * see if its null, and if so instantiate it by calling a method such as
0N/A * javax.print.PrintServiceLookup.defaultPrintService() so that the
0N/A * same instance is stored there.
0N/A */
0N/A private static Win32PrintServiceLookup win32PrintLUS;
0N/A
0N/A /* Think carefully before calling this. Preferably don't call it. */
0N/A public static Win32PrintServiceLookup getWin32PrintLUS() {
0N/A if (win32PrintLUS == null) {
0N/A /* This call is internally synchronized.
0N/A * When it returns an instance of this class will have
0N/A * been instantiated - else there's a JDK internal error.
0N/A */
0N/A PrintServiceLookup.lookupDefaultPrintService();
0N/A }
0N/A return win32PrintLUS;
0N/A }
0N/A
0N/A public Win32PrintServiceLookup() {
0N/A
0N/A if (win32PrintLUS == null) {
0N/A win32PrintLUS = this;
0N/A
0N/A String osName = AccessController.doPrivileged(
0N/A new sun.security.action.GetPropertyAction("os.name"));
0N/A // There's no capability for Win98 to refresh printers.
0N/A // See "OpenPrinter" for more info.
0N/A if (osName != null && osName.startsWith("Windows 98")) {
0N/A return;
0N/A }
0N/A // start the printer listener thread
0N/A PrinterChangeListener thr = new PrinterChangeListener();
0N/A thr.setDaemon(true);
0N/A thr.start();
0N/A } /* else condition ought to never happen! */
0N/A }
0N/A
0N/A /* Want the PrintService which is default print service to have
0N/A * equality of reference with the equivalent in list of print services
0N/A * This isn't required by the API and there's a risk doing this will
0N/A * lead people to assume its guaranteed.
0N/A */
0N/A public synchronized PrintService[] getPrintServices() {
0N/A SecurityManager security = System.getSecurityManager();
0N/A if (security != null) {
0N/A security.checkPrintJobAccess();
0N/A }
0N/A if (printServices == null) {
0N/A refreshServices();
0N/A }
0N/A return printServices;
0N/A }
0N/A
0N/A private synchronized void refreshServices() {
0N/A printers = getAllPrinterNames();
0N/A if (printers == null) {
0N/A // In Windows it is safe to assume no default if printers == null so we
0N/A // don't get the default.
0N/A printServices = new PrintService[0];
0N/A return;
0N/A }
0N/A
0N/A PrintService[] newServices = new PrintService[printers.length];
0N/A PrintService defService = getDefaultPrintService();
0N/A for (int p = 0; p < printers.length; p++) {
0N/A if (defService != null &&
0N/A printers[p].equals(defService.getName())) {
0N/A newServices[p] = defService;
0N/A } else {
0N/A if (printServices == null) {
0N/A newServices[p] = new Win32PrintService(printers[p]);
0N/A } else {
0N/A int j;
0N/A for (j = 0; j < printServices.length; j++) {
0N/A if ((printServices[j]!= null) &&
0N/A (printers[p].equals(printServices[j].getName()))) {
0N/A newServices[p] = printServices[j];
0N/A printServices[j] = null;
0N/A break;
0N/A }
0N/A }
0N/A if (j == printServices.length) {
0N/A newServices[p] = new Win32PrintService(printers[p]);
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A // Look for deleted services and invalidate these
0N/A if (printServices != null) {
0N/A for (int j=0; j < printServices.length; j++) {
0N/A if ((printServices[j] instanceof Win32PrintService) &&
0N/A (!printServices[j].equals(defaultPrintService))) {
0N/A ((Win32PrintService)printServices[j]).invalidateService();
0N/A }
0N/A }
0N/A }
0N/A printServices = newServices;
0N/A }
0N/A
0N/A
0N/A public synchronized PrintService getPrintServiceByName(String name) {
0N/A
0N/A if (name == null || name.equals("")) {
0N/A return null;
0N/A } else {
0N/A /* getPrintServices() is now very fast. */
0N/A PrintService[] printServices = getPrintServices();
0N/A for (int i=0; i<printServices.length; i++) {
0N/A if (printServices[i].getName().equals(name)) {
0N/A return printServices[i];
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A }
0N/A
0N/A boolean matchingService(PrintService service,
0N/A PrintServiceAttributeSet serviceSet) {
0N/A if (serviceSet != null) {
0N/A Attribute [] attrs = serviceSet.toArray();
0N/A Attribute serviceAttr;
0N/A for (int i=0; i<attrs.length; i++) {
0N/A serviceAttr
0N/A = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());
0N/A if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {
0N/A return false;
0N/A }
0N/A }
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A public PrintService[] getPrintServices(DocFlavor flavor,
0N/A AttributeSet attributes) {
0N/A
0N/A SecurityManager security = System.getSecurityManager();
0N/A if (security != null) {
0N/A security.checkPrintJobAccess();
0N/A }
0N/A PrintRequestAttributeSet requestSet = null;
0N/A PrintServiceAttributeSet serviceSet = null;
0N/A
0N/A if (attributes != null && !attributes.isEmpty()) {
0N/A
0N/A requestSet = new HashPrintRequestAttributeSet();
0N/A serviceSet = new HashPrintServiceAttributeSet();
0N/A
0N/A Attribute[] attrs = attributes.toArray();
0N/A for (int i=0; i<attrs.length; i++) {
0N/A if (attrs[i] instanceof PrintRequestAttribute) {
0N/A requestSet.add(attrs[i]);
0N/A } else if (attrs[i] instanceof PrintServiceAttribute) {
0N/A serviceSet.add(attrs[i]);
0N/A }
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * Special case: If client is asking for a particular printer
0N/A * (by name) then we can save time by getting just that service
0N/A * to check against the rest of the specified attributes.
0N/A */
0N/A PrintService[] services = null;
0N/A if (serviceSet != null && serviceSet.get(PrinterName.class) != null) {
0N/A PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);
0N/A PrintService service = getPrintServiceByName(name.getValue());
0N/A if (service == null || !matchingService(service, serviceSet)) {
0N/A services = new PrintService[0];
0N/A } else {
0N/A services = new PrintService[1];
0N/A services[0] = service;
0N/A }
0N/A } else {
0N/A services = getPrintServices();
0N/A }
0N/A
0N/A if (services.length == 0) {
0N/A return services;
0N/A } else {
0N/A ArrayList matchingServices = new ArrayList();
0N/A for (int i=0; i<services.length; i++) {
0N/A try {
0N/A if (services[i].
0N/A getUnsupportedAttributes(flavor, requestSet) == null) {
0N/A matchingServices.add(services[i]);
0N/A }
0N/A } catch (IllegalArgumentException e) {
0N/A }
0N/A }
0N/A services = new PrintService[matchingServices.size()];
0N/A return (PrintService[])matchingServices.toArray(services);
0N/A }
0N/A }
0N/A
0N/A /*
0N/A * return empty array as don't support multi docs
0N/A */
0N/A public MultiDocPrintService[]
0N/A getMultiDocPrintServices(DocFlavor[] flavors,
0N/A AttributeSet attributes) {
0N/A SecurityManager security = System.getSecurityManager();
0N/A if (security != null) {
0N/A security.checkPrintJobAccess();
0N/A }
0N/A return new MultiDocPrintService[0];
0N/A }
0N/A
0N/A
0N/A public synchronized PrintService getDefaultPrintService() {
0N/A SecurityManager security = System.getSecurityManager();
0N/A if (security != null) {
0N/A security.checkPrintJobAccess();
0N/A }
0N/A
0N/A
0N/A // Windows does not have notification for a change in default
0N/A // so we always get the latest.
0N/A defaultPrinter = getDefaultPrinterName();
0N/A if (defaultPrinter == null) {
0N/A return null;
0N/A }
0N/A
0N/A if ((defaultPrintService != null) &&
0N/A defaultPrintService.getName().equals(defaultPrinter)) {
0N/A
0N/A return defaultPrintService;
0N/A }
0N/A
0N/A // Not the same as default so proceed to get new PrintService.
0N/A
0N/A // clear defaultPrintService
0N/A defaultPrintService = null;
0N/A
0N/A if (printServices != null) {
0N/A for (int j=0; j<printServices.length; j++) {
0N/A if (defaultPrinter.equals(printServices[j].getName())) {
0N/A defaultPrintService = printServices[j];
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A if (defaultPrintService == null) {
0N/A defaultPrintService = new Win32PrintService(defaultPrinter);
0N/A }
0N/A return defaultPrintService;
0N/A }
0N/A
0N/A class PrinterChangeListener extends Thread {
0N/A long chgObj;
0N/A PrinterChangeListener() {
0N/A chgObj = notifyFirstPrinterChange(null);
0N/A }
0N/A
0N/A public void run() {
0N/A if (chgObj != -1) {
0N/A while (true) {
0N/A // wait for configuration to change
0N/A if (notifyPrinterChange(chgObj) != 0) {
0N/A try {
0N/A refreshServices();
0N/A } catch (SecurityException se) {
0N/A break;
0N/A }
0N/A } else {
0N/A notifyClosePrinterChange(chgObj);
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A private native String getDefaultPrinterName();
0N/A private native String[] getAllPrinterNames();
0N/A private native long notifyFirstPrinterChange(String printer);
0N/A private native void notifyClosePrinterChange(long chgObj);
0N/A private native int notifyPrinterChange(long chgObj);
0N/A}