| /* |
| * Copyright (c) 2000, 2015, 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 sun.misc.ManagedLocalsThread; |
| |
| import java.io.BufferedReader; |
| import java.io.FileInputStream; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.Vector; |
| import java.security.AccessController; |
| import java.security.PrivilegedActionException; |
| import java.security.PrivilegedExceptionAction; |
| import javax.print.DocFlavor; |
| import javax.print.MultiDocPrintService; |
| import javax.print.PrintService; |
| import javax.print.PrintServiceLookup; |
| import javax.print.attribute.Attribute; |
| import javax.print.attribute.AttributeSet; |
| import javax.print.attribute.HashPrintRequestAttributeSet; |
| import javax.print.attribute.HashPrintServiceAttributeSet; |
| import javax.print.attribute.PrintRequestAttribute; |
| import javax.print.attribute.PrintRequestAttributeSet; |
| import javax.print.attribute.PrintServiceAttribute; |
| import javax.print.attribute.PrintServiceAttributeSet; |
| import javax.print.attribute.standard.PrinterName; |
| import javax.print.attribute.standard.PrinterURI; |
| import java.io.File; |
| import java.io.FileReader; |
| import java.net.URL; |
| import java.nio.file.Files; |
| |
| /* |
| * Remind: This class uses solaris commands. We also need a linux |
| * version |
| */ |
| public class PrintServiceLookupProvider extends PrintServiceLookup |
| implements BackgroundServiceLookup, Runnable { |
| |
| /* Remind: the current implementation is static, as its assumed |
| * its preferable to minimize creation of PrintService instances. |
| * Later we should add logic to add/remove services on the fly which |
| * will take a hit of needing to regather the list of services. |
| */ |
| private String defaultPrinter; |
| private PrintService defaultPrintService; |
| private PrintService[] printServices; /* includes the default printer */ |
| private Vector<BackgroundLookupListener> lookupListeners = null; |
| private static String debugPrefix = "PrintServiceLookupProvider>> "; |
| private static boolean pollServices = true; |
| private static final int DEFAULT_MINREFRESH = 120; // 2 minutes |
| private static int minRefreshTime = DEFAULT_MINREFRESH; |
| |
| |
| static String osname; |
| |
| // List of commands used to deal with the printer queues on AIX |
| String[] lpNameComAix = { |
| "/usr/bin/lsallq", |
| "/usr/bin/lpstat -W -p|/usr/bin/expand|/usr/bin/cut -f1 -d' '", |
| "/usr/bin/lpstat -W -d|/usr/bin/expand|/usr/bin/cut -f1 -d' '", |
| "/usr/bin/lpstat -W -v" |
| }; |
| private static final int aix_lsallq = 0; |
| private static final int aix_lpstat_p = 1; |
| private static final int aix_lpstat_d = 2; |
| private static final int aix_lpstat_v = 3; |
| private static int aix_defaultPrinterEnumeration = aix_lsallq; |
| |
| static { |
| /* The system property "sun.java2d.print.polling" |
| * can be used to force the printing code to poll or not poll |
| * for PrintServices. |
| */ |
| String pollStr = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction("sun.java2d.print.polling")); |
| |
| if (pollStr != null) { |
| if (pollStr.equalsIgnoreCase("true")) { |
| pollServices = true; |
| } else if (pollStr.equalsIgnoreCase("false")) { |
| pollServices = false; |
| } |
| } |
| |
| /* The system property "sun.java2d.print.minRefreshTime" |
| * can be used to specify minimum refresh time (in seconds) |
| * for polling PrintServices. The default is 120. |
| */ |
| String refreshTimeStr = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction( |
| "sun.java2d.print.minRefreshTime")); |
| |
| if (refreshTimeStr != null) { |
| try { |
| minRefreshTime = (new Integer(refreshTimeStr)).intValue(); |
| } catch (NumberFormatException e) { |
| } |
| if (minRefreshTime < DEFAULT_MINREFRESH) { |
| minRefreshTime = DEFAULT_MINREFRESH; |
| } |
| } |
| |
| osname = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction("os.name")); |
| |
| /* The system property "sun.java2d.print.aix.lpstat" |
| * can be used to force the usage of 'lpstat -p' to enumerate all |
| * printer queues. By default we use 'lsallq', because 'lpstat -p' can |
| * take lots of time if thousands of printers are attached to a server. |
| */ |
| if (isAIX()) { |
| String aixPrinterEnumerator = java.security.AccessController.doPrivileged( |
| new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat")); |
| |
| if (aixPrinterEnumerator != null) { |
| if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) { |
| aix_defaultPrinterEnumeration = aix_lpstat_p; |
| } else if (aixPrinterEnumerator.equalsIgnoreCase("lsallq")) { |
| aix_defaultPrinterEnumeration = aix_lsallq; |
| } |
| } |
| } |
| } |
| |
| static boolean isMac() { |
| return osname.startsWith("Mac"); |
| } |
| |
| static boolean isSysV() { |
| return osname.equals("SunOS"); |
| } |
| |
| static boolean isLinux() { |
| return (osname.equals("Linux")); |
| } |
| |
| static boolean isBSD() { |
| return (osname.equals("Linux") || |
| osname.contains("OS X")); |
| } |
| |
| static boolean isAIX() { |
| return osname.equals("AIX"); |
| } |
| |
| static final int UNINITIALIZED = -1; |
| static final int BSD_LPD = 0; |
| static final int BSD_LPD_NG = 1; |
| |
| static int cmdIndex = UNINITIALIZED; |
| |
| String[] lpcFirstCom = { |
| "/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'", |
| "/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" |
| }; |
| |
| String[] lpcAllCom = { |
| "/usr/sbin/lpc status all | grep : | sed -e 's/://'", |
| "/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort" |
| }; |
| |
| String[] lpcNameCom = { |
| "| grep : | sed -ne 's/://p'", |
| "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" |
| }; |
| |
| |
| static int getBSDCommandIndex() { |
| String command = "/usr/sbin/lpc status all"; |
| String[] names = execCmd(command); |
| |
| if ((names == null) || (names.length == 0)) { |
| return BSD_LPD_NG; |
| } |
| |
| for (int i=0; i<names.length; i++) { |
| if (names[i].indexOf('@') != -1) { |
| return BSD_LPD_NG; |
| } |
| } |
| |
| return BSD_LPD; |
| } |
| |
| |
| public PrintServiceLookupProvider() { |
| // start the printer listener thread |
| if (pollServices) { |
| Thread thr = new ManagedLocalsThread(new PrinterChangeListener()); |
| thr.setDaemon(true); |
| thr.start(); |
| IPPPrintService.debug_println(debugPrefix+"polling turned on"); |
| } |
| } |
| |
| /* Want the PrintService which is default print service to have |
| * equality of reference with the equivalent in list of print services |
| * This isn't required by the API and there's a risk doing this will |
| * lead people to assume its guaranteed. |
| */ |
| public synchronized PrintService[] getPrintServices() { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPrintJobAccess(); |
| } |
| |
| if (printServices == null || !pollServices) { |
| refreshServices(); |
| } |
| if (printServices == null) { |
| return new PrintService[0]; |
| } else { |
| return printServices.clone(); |
| } |
| } |
| |
| private int addPrintServiceToList(ArrayList<PrintService> printerList, PrintService ps) { |
| int index = printerList.indexOf(ps); |
| // Check if PrintService with same name is already in the list. |
| if (CUPSPrinter.isCupsRunning() && index != -1) { |
| // Bug in Linux: Duplicate entry of a remote printer |
| // and treats it as local printer but it is returning wrong |
| // information when queried using IPP. Workaround is to remove it. |
| // Even CUPS ignores these entries as shown in lpstat or using |
| // their web configuration. |
| PrinterURI uri = ps.getAttribute(PrinterURI.class); |
| if (uri.getURI().getHost().equals("localhost")) { |
| IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps); |
| return index; // Do not add this. |
| } |
| PrintService oldPS = printerList.get(index); |
| uri = oldPS.getAttribute(PrinterURI.class); |
| if (uri.getURI().getHost().equals("localhost")) { |
| IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS); |
| printerList.remove(oldPS); |
| } else { |
| return index; |
| } |
| } |
| printerList.add(ps); |
| return (printerList.size() - 1); |
| } |
| |
| |
| // refreshes "printServices" |
| public synchronized void refreshServices() { |
| /* excludes the default printer */ |
| String[] printers = null; // array of printer names |
| String[] printerURIs = null; //array of printer URIs |
| |
| try { |
| getDefaultPrintService(); |
| } catch (Throwable t) { |
| IPPPrintService.debug_println(debugPrefix+ |
| "Exception getting default printer : " + t); |
| } |
| if (CUPSPrinter.isCupsRunning()) { |
| try { |
| printerURIs = CUPSPrinter.getAllPrinters(); |
| IPPPrintService.debug_println("CUPS URIs = " + printerURIs); |
| if (printerURIs != null) { |
| for (int p = 0; p < printerURIs.length; p++) { |
| IPPPrintService.debug_println("URI="+printerURIs[p]); |
| } |
| } |
| } catch (Throwable t) { |
| IPPPrintService.debug_println(debugPrefix+ |
| "Exception getting all CUPS printers : " + t); |
| } |
| if ((printerURIs != null) && (printerURIs.length > 0)) { |
| printers = new String[printerURIs.length]; |
| for (int i=0; i<printerURIs.length; i++) { |
| int lastIndex = printerURIs[i].lastIndexOf("/"); |
| printers[i] = printerURIs[i].substring(lastIndex+1); |
| } |
| } |
| } else { |
| if (isMac() || isSysV()) { |
| printers = getAllPrinterNamesSysV(); |
| } else if (isAIX()) { |
| printers = getAllPrinterNamesAIX(); |
| } else { //BSD |
| printers = getAllPrinterNamesBSD(); |
| } |
| } |
| |
| if (printers == null) { |
| if (defaultPrintService != null) { |
| printServices = new PrintService[1]; |
| printServices[0] = defaultPrintService; |
| } else { |
| printServices = null; |
| } |
| return; |
| } |
| |
| ArrayList<PrintService> printerList = new ArrayList<>(); |
| int defaultIndex = -1; |
| for (int p=0; p<printers.length; p++) { |
| if (printers[p] == null) { |
| continue; |
| } |
| if ((defaultPrintService != null) |
| && printers[p].equals(getPrinterDestName(defaultPrintService))) { |
| defaultIndex = addPrintServiceToList(printerList, defaultPrintService); |
| } else { |
| if (printServices == null) { |
| IPPPrintService.debug_println(debugPrefix+ |
| "total# of printers = "+printers.length); |
| |
| if (CUPSPrinter.isCupsRunning()) { |
| try { |
| addPrintServiceToList(printerList, |
| new IPPPrintService(printers[p], |
| printerURIs[p], |
| true)); |
| } catch (Exception e) { |
| IPPPrintService.debug_println(debugPrefix+ |
| " getAllPrinters Exception "+ |
| e); |
| |
| } |
| } else { |
| printerList.add(new UnixPrintService(printers[p])); |
| } |
| } else { |
| int j; |
| for (j=0; j<printServices.length; j++) { |
| if (printServices[j] != null) { |
| if (printers[p].equals(getPrinterDestName(printServices[j]))) { |
| printerList.add(printServices[j]); |
| printServices[j] = null; |
| break; |
| } |
| } |
| } |
| |
| if (j == printServices.length) { // not found? |
| if (CUPSPrinter.isCupsRunning()) { |
| try { |
| addPrintServiceToList(printerList, |
| new IPPPrintService(printers[p], |
| printerURIs[p], |
| true)); |
| } catch (Exception e) { |
| IPPPrintService.debug_println(debugPrefix+ |
| " getAllPrinters Exception "+ |
| e); |
| |
| } |
| } else { |
| printerList.add(new UnixPrintService(printers[p])); |
| } |
| } |
| } |
| } |
| } |
| |
| // Look for deleted services and invalidate these |
| if (printServices != null) { |
| for (int j=0; j < printServices.length; j++) { |
| if ((printServices[j] instanceof UnixPrintService) && |
| (!printServices[j].equals(defaultPrintService))) { |
| ((UnixPrintService)printServices[j]).invalidateService(); |
| } |
| } |
| } |
| |
| //if defaultService is not found in printerList |
| if (defaultIndex == -1 && defaultPrintService != null) { |
| defaultIndex = addPrintServiceToList(printerList, defaultPrintService); |
| } |
| |
| printServices = printerList.toArray(new PrintService[] {}); |
| |
| // swap default with the first in the list |
| if (defaultIndex > 0) { |
| PrintService saveService = printServices[0]; |
| printServices[0] = printServices[defaultIndex]; |
| printServices[defaultIndex] = saveService; |
| } |
| } |
| |
| private boolean matchesAttributes(PrintService service, |
| PrintServiceAttributeSet attributes) { |
| |
| Attribute [] attrs = attributes.toArray(); |
| for (int i=0; i<attrs.length; i++) { |
| @SuppressWarnings("unchecked") |
| Attribute serviceAttr |
| = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory()); |
| if (serviceAttr == null || !serviceAttr.equals(attrs[i])) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /* This checks for validity of the printer name before passing as |
| * parameter to a shell command. |
| */ |
| private boolean checkPrinterName(String s) { |
| char c; |
| |
| for (int i=0; i < s.length(); i++) { |
| c = s.charAt(i); |
| if (Character.isLetterOrDigit(c) || |
| c == '-' || c == '_' || c == '.' || c == '/') { |
| continue; |
| } else { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| /* |
| * Gets the printer name compatible with the list of printers returned by |
| * the system when we query default or all the available printers. |
| */ |
| private String getPrinterDestName(PrintService ps) { |
| if (isMac()) { |
| return ((IPPPrintService)ps).getDest(); |
| } |
| return ps.getName(); |
| } |
| |
| /* On a network with many (hundreds) of network printers, it |
| * can save several seconds if you know all you want is a particular |
| * printer, to ask for that printer rather than retrieving all printers. |
| */ |
| private PrintService getServiceByName(PrinterName nameAttr) { |
| String name = nameAttr.getValue(); |
| if (name == null || name.equals("") || !checkPrinterName(name)) { |
| return null; |
| } |
| /* check if all printers are already available */ |
| if (printServices != null) { |
| for (PrintService printService : printServices) { |
| PrinterName printerName = printService.getAttribute(PrinterName.class); |
| if (printerName.getValue().equals(name)) { |
| return printService; |
| } |
| } |
| } |
| /* take CUPS into account first */ |
| if (CUPSPrinter.isCupsRunning()) { |
| try { |
| return new IPPPrintService(name, |
| new URL("http://"+ |
| CUPSPrinter.getServer()+":"+ |
| CUPSPrinter.getPort()+"/"+ |
| name)); |
| } catch (Exception e) { |
| IPPPrintService.debug_println(debugPrefix+ |
| " getServiceByName Exception "+ |
| e); |
| } |
| } |
| /* fallback if nothing not having a printer at this point */ |
| PrintService printer = null; |
| if (isMac() || isSysV()) { |
| printer = getNamedPrinterNameSysV(name); |
| } else if (isAIX()) { |
| printer = getNamedPrinterNameAIX(name); |
| } else { |
| printer = getNamedPrinterNameBSD(name); |
| } |
| return printer; |
| } |
| |
| private PrintService[] |
| getPrintServices(PrintServiceAttributeSet serviceSet) { |
| |
| if (serviceSet == null || serviceSet.isEmpty()) { |
| return getPrintServices(); |
| } |
| |
| /* Typically expect that if a service attribute is specified that |
| * its a printer name and there ought to be only one match. |
| * Directly retrieve that service and confirm |
| * that it meets the other requirements. |
| * If printer name isn't mentioned then go a slow path checking |
| * all printers if they meet the reqiremements. |
| */ |
| PrintService[] services; |
| PrinterName name = (PrinterName)serviceSet.get(PrinterName.class); |
| PrintService defService; |
| if (name != null && (defService = getDefaultPrintService()) != null) { |
| /* To avoid execing a unix command see if the client is asking |
| * for the default printer by name, since we already have that |
| * initialised. |
| */ |
| |
| PrinterName defName = defService.getAttribute(PrinterName.class); |
| |
| if (defName != null && name.equals(defName)) { |
| if (matchesAttributes(defService, serviceSet)) { |
| services = new PrintService[1]; |
| services[0] = defService; |
| return services; |
| } else { |
| return new PrintService[0]; |
| } |
| } else { |
| /* Its not the default service */ |
| PrintService service = getServiceByName(name); |
| if (service != null && |
| matchesAttributes(service, serviceSet)) { |
| services = new PrintService[1]; |
| services[0] = service; |
| return services; |
| } else { |
| return new PrintService[0]; |
| } |
| } |
| } else { |
| /* specified service attributes don't include a name.*/ |
| Vector<PrintService> matchedServices = new Vector<>(); |
| services = getPrintServices(); |
| for (int i = 0; i< services.length; i++) { |
| if (matchesAttributes(services[i], serviceSet)) { |
| matchedServices.add(services[i]); |
| } |
| } |
| services = new PrintService[matchedServices.size()]; |
| for (int i = 0; i< services.length; i++) { |
| services[i] = matchedServices.elementAt(i); |
| } |
| return services; |
| } |
| } |
| |
| /* |
| * If service attributes are specified then there must be additional |
| * filtering. |
| */ |
| public PrintService[] getPrintServices(DocFlavor flavor, |
| AttributeSet attributes) { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPrintJobAccess(); |
| } |
| PrintRequestAttributeSet requestSet = null; |
| PrintServiceAttributeSet serviceSet = null; |
| |
| if (attributes != null && !attributes.isEmpty()) { |
| |
| requestSet = new HashPrintRequestAttributeSet(); |
| serviceSet = new HashPrintServiceAttributeSet(); |
| |
| Attribute[] attrs = attributes.toArray(); |
| for (int i=0; i<attrs.length; i++) { |
| if (attrs[i] instanceof PrintRequestAttribute) { |
| requestSet.add(attrs[i]); |
| } else if (attrs[i] instanceof PrintServiceAttribute) { |
| serviceSet.add(attrs[i]); |
| } |
| } |
| } |
| |
| PrintService[] services = getPrintServices(serviceSet); |
| if (services.length == 0) { |
| return services; |
| } |
| |
| if (CUPSPrinter.isCupsRunning()) { |
| ArrayList<PrintService> matchingServices = new ArrayList<>(); |
| for (int i=0; i<services.length; i++) { |
| try { |
| if (services[i]. |
| getUnsupportedAttributes(flavor, requestSet) == null) { |
| matchingServices.add(services[i]); |
| } |
| } catch (IllegalArgumentException e) { |
| } |
| } |
| services = new PrintService[matchingServices.size()]; |
| return matchingServices.toArray(services); |
| |
| } else { |
| // We only need to compare 1 PrintService because all |
| // UnixPrintServices are the same anyway. We will not use |
| // default PrintService because it might be null. |
| PrintService service = services[0]; |
| if ((flavor == null || |
| service.isDocFlavorSupported(flavor)) && |
| service.getUnsupportedAttributes(flavor, requestSet) == null) |
| { |
| return services; |
| } else { |
| return new PrintService[0]; |
| } |
| } |
| } |
| |
| /* |
| * return empty array as don't support multi docs |
| */ |
| public MultiDocPrintService[] |
| getMultiDocPrintServices(DocFlavor[] flavors, |
| AttributeSet attributes) { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPrintJobAccess(); |
| } |
| return new MultiDocPrintService[0]; |
| } |
| |
| |
| public synchronized PrintService getDefaultPrintService() { |
| SecurityManager security = System.getSecurityManager(); |
| if (security != null) { |
| security.checkPrintJobAccess(); |
| } |
| |
| // clear defaultPrintService |
| defaultPrintService = null; |
| String psuri = null; |
| |
| IPPPrintService.debug_println("isRunning ? "+ |
| (CUPSPrinter.isCupsRunning())); |
| if (CUPSPrinter.isCupsRunning()) { |
| String[] printerInfo = CUPSPrinter.getDefaultPrinter(); |
| if (printerInfo != null && printerInfo.length >= 2) { |
| defaultPrinter = printerInfo[0]; |
| psuri = printerInfo[1]; |
| } |
| } else { |
| if (isMac() || isSysV()) { |
| defaultPrinter = getDefaultPrinterNameSysV(); |
| } else if (isAIX()) { |
| defaultPrinter = getDefaultPrinterNameAIX(); |
| } else { |
| defaultPrinter = getDefaultPrinterNameBSD(); |
| } |
| } |
| if (defaultPrinter == null) { |
| return null; |
| } |
| defaultPrintService = null; |
| if (printServices != null) { |
| for (int j=0; j<printServices.length; j++) { |
| if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) { |
| defaultPrintService = printServices[j]; |
| break; |
| } |
| } |
| } |
| if (defaultPrintService == null) { |
| if (CUPSPrinter.isCupsRunning()) { |
| try { |
| PrintService defaultPS; |
| if ((psuri != null) && !psuri.startsWith("file")) { |
| defaultPS = new IPPPrintService(defaultPrinter, |
| psuri, true); |
| } else { |
| defaultPS = new IPPPrintService(defaultPrinter, |
| new URL("http://"+ |
| CUPSPrinter.getServer()+":"+ |
| CUPSPrinter.getPort()+"/"+ |
| defaultPrinter)); |
| } |
| defaultPrintService = defaultPS; |
| } catch (Exception e) { |
| } |
| } else { |
| defaultPrintService = new UnixPrintService(defaultPrinter); |
| } |
| } |
| |
| return defaultPrintService; |
| } |
| |
| public synchronized void |
| getServicesInbackground(BackgroundLookupListener listener) { |
| if (printServices != null) { |
| listener.notifyServices(printServices); |
| } else { |
| if (lookupListeners == null) { |
| lookupListeners = new Vector<>(); |
| lookupListeners.add(listener); |
| Thread lookupThread = new Thread(this); |
| lookupThread.start(); |
| } else { |
| lookupListeners.add(listener); |
| } |
| } |
| } |
| |
| /* This method isn't used in most cases because we rely on code in |
| * javax.print.PrintServiceLookup. This is needed just for the cases |
| * where those interfaces are by-passed. |
| */ |
| private PrintService[] copyOf(PrintService[] inArr) { |
| if (inArr == null || inArr.length == 0) { |
| return inArr; |
| } else { |
| PrintService []outArr = new PrintService[inArr.length]; |
| System.arraycopy(inArr, 0, outArr, 0, inArr.length); |
| return outArr; |
| } |
| } |
| |
| public void run() { |
| PrintService[] services = getPrintServices(); |
| synchronized (this) { |
| BackgroundLookupListener listener; |
| for (int i=0; i<lookupListeners.size(); i++) { |
| listener = lookupListeners.elementAt(i); |
| listener.notifyServices(copyOf(services)); |
| } |
| lookupListeners = null; |
| } |
| } |
| |
| private String getDefaultPrinterNameBSD() { |
| if (cmdIndex == UNINITIALIZED) { |
| cmdIndex = getBSDCommandIndex(); |
| } |
| String[] names = execCmd(lpcFirstCom[cmdIndex]); |
| if (names == null || names.length == 0) { |
| return null; |
| } |
| |
| if ((cmdIndex==BSD_LPD_NG) && |
| (names[0].startsWith("missingprinter"))) { |
| return null; |
| } |
| return names[0]; |
| } |
| |
| private PrintService getNamedPrinterNameBSD(String name) { |
| if (cmdIndex == UNINITIALIZED) { |
| cmdIndex = getBSDCommandIndex(); |
| } |
| String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex]; |
| String[] result = execCmd(command); |
| |
| if (result == null || !(result[0].equals(name))) { |
| return null; |
| } |
| return new UnixPrintService(name); |
| } |
| |
| private String[] getAllPrinterNamesBSD() { |
| if (cmdIndex == UNINITIALIZED) { |
| cmdIndex = getBSDCommandIndex(); |
| } |
| String[] names = execCmd(lpcAllCom[cmdIndex]); |
| if (names == null || names.length == 0) { |
| return null; |
| } |
| return names; |
| } |
| |
| static String getDefaultPrinterNameSysV() { |
| String defaultPrinter = "lp"; |
| String command = "/usr/bin/lpstat -d"; |
| |
| String [] names = execCmd(command); |
| if (names == null || names.length == 0) { |
| return defaultPrinter; |
| } else { |
| int index = names[0].indexOf(":"); |
| if (index == -1 || (names[0].length() <= index+1)) { |
| return null; |
| } else { |
| String name = names[0].substring(index+1).trim(); |
| if (name.length() == 0) { |
| return null; |
| } else { |
| return name; |
| } |
| } |
| } |
| } |
| |
| private PrintService getNamedPrinterNameSysV(String name) { |
| |
| String command = "/usr/bin/lpstat -v " + name; |
| String []result = execCmd(command); |
| |
| if (result == null || result[0].indexOf("unknown printer") > 0) { |
| return null; |
| } else { |
| return new UnixPrintService(name); |
| } |
| } |
| |
| private String[] getAllPrinterNamesSysV() { |
| String defaultPrinter = "lp"; |
| String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort"; |
| |
| String [] names = execCmd(command); |
| ArrayList<String> printerNames = new ArrayList<>(); |
| for (int i=0; i < names.length; i++) { |
| if (!names[i].equals("_default") && |
| !names[i].equals(defaultPrinter) && |
| !names[i].equals("")) { |
| printerNames.add(names[i]); |
| } |
| } |
| return printerNames.toArray(new String[printerNames.size()]); |
| } |
| |
| private String getDefaultPrinterNameAIX() { |
| String[] names = execCmd(lpNameComAix[aix_lpstat_d]); |
| // Remove headers and bogus entries added by remote printers. |
| names = UnixPrintService.filterPrinterNamesAIX(names); |
| if (names == null || names.length != 1) { |
| // No default printer found |
| return null; |
| } else { |
| return names[0]; |
| } |
| } |
| |
| private PrintService getNamedPrinterNameAIX(String name) { |
| // On AIX there should be no blank after '-v'. |
| String[] result = execCmd(lpNameComAix[aix_lpstat_v] + name); |
| // Remove headers and bogus entries added by remote printers. |
| result = UnixPrintService.filterPrinterNamesAIX(result); |
| if (result == null || result.length != 1) { |
| return null; |
| } else { |
| return new UnixPrintService(name); |
| } |
| } |
| |
| private String[] getAllPrinterNamesAIX() { |
| // Determine all printers of the system. |
| String [] names = execCmd(lpNameComAix[aix_defaultPrinterEnumeration]); |
| |
| // Remove headers and bogus entries added by remote printers. |
| names = UnixPrintService.filterPrinterNamesAIX(names); |
| |
| ArrayList<String> printerNames = new ArrayList<String>(); |
| for ( int i=0; i < names.length; i++) { |
| printerNames.add(names[i]); |
| } |
| return printerNames.toArray(new String[printerNames.size()]); |
| } |
| |
| static String[] execCmd(final String command) { |
| ArrayList<String> results = null; |
| try { |
| final String[] cmd = new String[3]; |
| if (isSysV() || isAIX()) { |
| cmd[0] = "/usr/bin/sh"; |
| cmd[1] = "-c"; |
| cmd[2] = "env LC_ALL=C " + command; |
| } else { |
| cmd[0] = "/bin/sh"; |
| cmd[1] = "-c"; |
| cmd[2] = "LC_ALL=C " + command; |
| } |
| |
| results = AccessController.doPrivileged( |
| new PrivilegedExceptionAction<ArrayList<String>>() { |
| public ArrayList<String> run() throws IOException { |
| |
| Process proc; |
| BufferedReader bufferedReader = null; |
| File f = Files.createTempFile("prn","xc").toFile(); |
| cmd[2] = cmd[2]+">"+f.getAbsolutePath(); |
| |
| proc = Runtime.getRuntime().exec(cmd); |
| try { |
| boolean done = false; // in case of interrupt. |
| while (!done) { |
| try { |
| proc.waitFor(); |
| done = true; |
| } catch (InterruptedException e) { |
| } |
| } |
| |
| if (proc.exitValue() == 0) { |
| FileReader reader = new FileReader(f); |
| bufferedReader = new BufferedReader(reader); |
| String line; |
| ArrayList<String> results = new ArrayList<>(); |
| while ((line = bufferedReader.readLine()) |
| != null) { |
| results.add(line); |
| } |
| return results; |
| } |
| } finally { |
| f.delete(); |
| // promptly close all streams. |
| if (bufferedReader != null) { |
| bufferedReader.close(); |
| } |
| proc.getInputStream().close(); |
| proc.getErrorStream().close(); |
| proc.getOutputStream().close(); |
| } |
| return null; |
| } |
| }); |
| } catch (PrivilegedActionException e) { |
| } |
| if (results == null) { |
| return new String[0]; |
| } else { |
| return results.toArray(new String[results.size()]); |
| } |
| } |
| |
| private class PrinterChangeListener implements Runnable { |
| |
| @Override |
| public void run() { |
| int refreshSecs; |
| while (true) { |
| try { |
| refreshServices(); |
| } catch (Exception se) { |
| IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread."); |
| break; |
| } |
| |
| if ((printServices != null) && |
| (printServices.length > minRefreshTime)) { |
| // compute new refresh time 1 printer = 1 sec |
| refreshSecs = printServices.length; |
| } else { |
| refreshSecs = minRefreshTime; |
| } |
| try { |
| Thread.sleep(refreshSecs * 1000); |
| } catch (InterruptedException e) { |
| break; |
| } |
| } |
| } |
| } |
| } |