Path: blob/master/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java
41152 views
/*1* Copyright (c) 2000, 2021, 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.util.ArrayList;2829import javax.print.DocFlavor;30import javax.print.MultiDocPrintService;31import javax.print.PrintService;32import javax.print.PrintServiceLookup;33import javax.print.attribute.Attribute;34import javax.print.attribute.AttributeSet;35import javax.print.attribute.HashPrintRequestAttributeSet;36import javax.print.attribute.HashPrintServiceAttributeSet;37import javax.print.attribute.PrintRequestAttribute;38import javax.print.attribute.PrintRequestAttributeSet;39import javax.print.attribute.PrintServiceAttribute;40import javax.print.attribute.PrintServiceAttributeSet;41import javax.print.attribute.standard.PrinterName;4243@SuppressWarnings("removal")44public class PrintServiceLookupProvider extends PrintServiceLookup {4546private PrintService defaultPrintService;47private PrintService[] printServices; /* includes the default printer */4849static {50java.security.AccessController.doPrivileged(51new java.security.PrivilegedAction<Void>() {52public Void run() {53System.loadLibrary("awt");54return null;55}56});57}5859/* The singleton win32 print lookup service.60* Code that is aware of this field and wants to use it must first61* see if its null, and if so instantiate it by calling a method such as62* javax.print.PrintServiceLookup.defaultPrintService() so that the63* same instance is stored there.64*/65private static PrintServiceLookupProvider win32PrintLUS;6667/* Think carefully before calling this. Preferably don't call it. */68public static PrintServiceLookupProvider getWin32PrintLUS() {69if (win32PrintLUS == null) {70/* This call is internally synchronized.71* When it returns an instance of this class will have72* been instantiated - else there's a JDK internal error.73*/74PrintServiceLookup.lookupDefaultPrintService();75}76return win32PrintLUS;77}7879public PrintServiceLookupProvider() {8081if (win32PrintLUS == null) {82win32PrintLUS = this;8384// start the local printer listener thread85Thread thr = new Thread(null, new PrinterChangeListener(),86"PrinterListener", 0, false);87thr.setDaemon(true);88thr.start();8990// start the remote printer listener thread91Thread remThr = new Thread(null, new RemotePrinterChangeListener(),92"RemotePrinterListener", 0, false);93remThr.setDaemon(true);94remThr.start();95} /* else condition ought to never happen! */96}9798/* Want the PrintService which is default print service to have99* equality of reference with the equivalent in list of print services100* This isn't required by the API and there's a risk doing this will101* lead people to assume its guaranteed.102*/103public synchronized PrintService[] getPrintServices() {104SecurityManager security = System.getSecurityManager();105if (security != null) {106security.checkPrintJobAccess();107}108if (printServices == null) {109refreshServices();110}111return printServices;112}113114private synchronized void refreshServices() {115String[] printers = getAllPrinterNames();116if (printers == null) {117// In Windows it is safe to assume no default if printers == null so we118// don't get the default.119invalidateServices();120printServices = new PrintService[0];121return;122}123124PrintService[] newServices = new PrintService[printers.length];125PrintService defService = getDefaultPrintService();126for (int p = 0; p < printers.length; p++) {127if (defService != null &&128printers[p].equals(defService.getName())) {129newServices[p] = defService;130} else {131if (printServices == null) {132newServices[p] = new Win32PrintService(printers[p]);133} else {134int j;135for (j = 0; j < printServices.length; j++) {136if ((printServices[j]!= null) &&137(printers[p].equals(printServices[j].getName()))) {138newServices[p] = printServices[j];139printServices[j] = null;140break;141}142}143if (j == printServices.length) {144newServices[p] = new Win32PrintService(printers[p]);145}146}147}148}149150invalidateServices();151printServices = newServices;152}153154private void invalidateServices() {155// Look for deleted services and invalidate these156if (printServices != null) {157for (int j=0; j < printServices.length; j++) {158if ((printServices[j] instanceof Win32PrintService) &&159(!printServices[j].equals(defaultPrintService))) {160161((Win32PrintService)printServices[j]).invalidateService();162}163}164}165}166167168public synchronized PrintService getPrintServiceByName(String name) {169170if (name == null || name.isEmpty()) {171return null;172} else {173/* getPrintServices() is now very fast. */174PrintService[] printServices = getPrintServices();175for (int i=0; i<printServices.length; i++) {176if (printServices[i].getName().equals(name)) {177return printServices[i];178}179}180return null;181}182}183184@SuppressWarnings("unchecked") // Cast to Class<PrintServiceAttribute>185boolean matchingService(PrintService service,186PrintServiceAttributeSet serviceSet) {187if (serviceSet != null) {188Attribute [] attrs = serviceSet.toArray();189Attribute serviceAttr;190for (int i=0; i<attrs.length; i++) {191serviceAttr192= service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());193if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {194return false;195}196}197}198return true;199}200201public PrintService[] getPrintServices(DocFlavor flavor,202AttributeSet attributes) {203204SecurityManager security = System.getSecurityManager();205if (security != null) {206security.checkPrintJobAccess();207}208PrintRequestAttributeSet requestSet = null;209PrintServiceAttributeSet serviceSet = null;210211if (attributes != null && !attributes.isEmpty()) {212213requestSet = new HashPrintRequestAttributeSet();214serviceSet = new HashPrintServiceAttributeSet();215216Attribute[] attrs = attributes.toArray();217for (int i=0; i<attrs.length; i++) {218if (attrs[i] instanceof PrintRequestAttribute) {219requestSet.add(attrs[i]);220} else if (attrs[i] instanceof PrintServiceAttribute) {221serviceSet.add(attrs[i]);222}223}224}225226/*227* Special case: If client is asking for a particular printer228* (by name) then we can save time by getting just that service229* to check against the rest of the specified attributes.230*/231PrintService[] services = null;232if (serviceSet != null && serviceSet.get(PrinterName.class) != null) {233PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);234PrintService service = getPrintServiceByName(name.getValue());235if (service == null || !matchingService(service, serviceSet)) {236services = new PrintService[0];237} else {238services = new PrintService[1];239services[0] = service;240}241} else {242services = getPrintServices();243}244245if (services.length == 0) {246return services;247} else {248ArrayList<PrintService> matchingServices = new ArrayList<>();249for (int i=0; i<services.length; i++) {250try {251if (services[i].252getUnsupportedAttributes(flavor, requestSet) == null) {253matchingServices.add(services[i]);254}255} catch (IllegalArgumentException e) {256}257}258services = new PrintService[matchingServices.size()];259return matchingServices.toArray(services);260}261}262263/*264* return empty array as don't support multi docs265*/266public MultiDocPrintService[]267getMultiDocPrintServices(DocFlavor[] flavors,268AttributeSet attributes) {269SecurityManager security = System.getSecurityManager();270if (security != null) {271security.checkPrintJobAccess();272}273return new MultiDocPrintService[0];274}275276277public synchronized PrintService getDefaultPrintService() {278SecurityManager security = System.getSecurityManager();279if (security != null) {280security.checkPrintJobAccess();281}282283284// Windows does not have notification for a change in default285// so we always get the latest.286String defaultPrinter = getDefaultPrinterName();287if (defaultPrinter == null) {288return null;289}290291if ((defaultPrintService != null) &&292defaultPrintService.getName().equals(defaultPrinter)) {293294return defaultPrintService;295}296297// Not the same as default so proceed to get new PrintService.298299// clear defaultPrintService300defaultPrintService = null;301302if (printServices != null) {303for (int j=0; j<printServices.length; j++) {304if (defaultPrinter.equals(printServices[j].getName())) {305defaultPrintService = printServices[j];306break;307}308}309}310311if (defaultPrintService == null) {312defaultPrintService = new Win32PrintService(defaultPrinter);313}314return defaultPrintService;315}316317private final class PrinterChangeListener implements Runnable {318@Override319public void run() {320notifyLocalPrinterChange(); // busy loop in the native code321}322}323324private final class RemotePrinterChangeListener implements Runnable {325@Override326public void run() {327notifyRemotePrinterChange(); // busy loop in the native code328}329}330331private native String getDefaultPrinterName();332private native String[] getAllPrinterNames();333private native void notifyLocalPrinterChange();334private native void notifyRemotePrinterChange();335}336337338