Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/solaris/classes/sun/print/PrintServiceLookupProvider.java
32287 views
/*1* Copyright (c) 2000, 2013, 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.io.BufferedReader;28import java.io.FileInputStream;29import java.io.InputStream;30import java.io.InputStreamReader;31import java.io.IOException;32import java.util.ArrayList;33import java.util.Vector;34import java.security.AccessController;35import java.security.PrivilegedActionException;36import java.security.PrivilegedExceptionAction;37import javax.print.DocFlavor;38import javax.print.MultiDocPrintService;39import javax.print.PrintService;40import javax.print.PrintServiceLookup;41import javax.print.attribute.Attribute;42import javax.print.attribute.AttributeSet;43import javax.print.attribute.HashPrintRequestAttributeSet;44import javax.print.attribute.HashPrintServiceAttributeSet;45import javax.print.attribute.PrintRequestAttribute;46import javax.print.attribute.PrintRequestAttributeSet;47import javax.print.attribute.PrintServiceAttribute;48import javax.print.attribute.PrintServiceAttributeSet;49import javax.print.attribute.standard.PrinterName;50import javax.print.attribute.standard.PrinterURI;51import java.io.File;52import java.io.FileReader;53import java.net.URL;54import java.nio.file.Files;5556/*57* Remind: This class uses solaris commands. We also need a linux58* version59*/60public class PrintServiceLookupProvider extends PrintServiceLookup61implements BackgroundServiceLookup, Runnable {6263/* Remind: the current implementation is static, as its assumed64* its preferable to minimize creation of PrintService instances.65* Later we should add logic to add/remove services on the fly which66* will take a hit of needing to regather the list of services.67*/68private String defaultPrinter;69private PrintService defaultPrintService;70private PrintService[] printServices; /* includes the default printer */71private Vector lookupListeners = null;72private static String debugPrefix = "PrintServiceLookupProvider>> ";73private static boolean pollServices = true;74private static final int DEFAULT_MINREFRESH = 120; // 2 minutes75private static int minRefreshTime = DEFAULT_MINREFRESH;767778static String osname;7980// List of commands used to deal with the printer queues on AIX81String[] lpNameComAix = {82"/usr/bin/lsallq",83"/usr/bin/lpstat -W -p|/usr/bin/expand|/usr/bin/cut -f1 -d' '",84"/usr/bin/lpstat -W -d|/usr/bin/expand|/usr/bin/cut -f1 -d' '",85"/usr/bin/lpstat -W -v"86};87private static final int aix_lsallq = 0;88private static final int aix_lpstat_p = 1;89private static final int aix_lpstat_d = 2;90private static final int aix_lpstat_v = 3;91private static int aix_defaultPrinterEnumeration = aix_lsallq;9293static {94/* The system property "sun.java2d.print.polling"95* can be used to force the printing code to poll or not poll96* for PrintServices.97*/98String pollStr = java.security.AccessController.doPrivileged(99new sun.security.action.GetPropertyAction("sun.java2d.print.polling"));100101if (pollStr != null) {102if (pollStr.equalsIgnoreCase("true")) {103pollServices = true;104} else if (pollStr.equalsIgnoreCase("false")) {105pollServices = false;106}107}108109/* The system property "sun.java2d.print.minRefreshTime"110* can be used to specify minimum refresh time (in seconds)111* for polling PrintServices. The default is 120.112*/113String refreshTimeStr = java.security.AccessController.doPrivileged(114new sun.security.action.GetPropertyAction(115"sun.java2d.print.minRefreshTime"));116117if (refreshTimeStr != null) {118try {119minRefreshTime = (new Integer(refreshTimeStr)).intValue();120} catch (NumberFormatException e) {121}122if (minRefreshTime < DEFAULT_MINREFRESH) {123minRefreshTime = DEFAULT_MINREFRESH;124}125}126127osname = java.security.AccessController.doPrivileged(128new sun.security.action.GetPropertyAction("os.name"));129130/* The system property "sun.java2d.print.aix.lpstat"131* can be used to force the usage of 'lpstat -p' to enumerate all132* printer queues. By default we use 'lsallq', because 'lpstat -p' can133* take lots of time if thousands of printers are attached to a server.134*/135if (isAIX()) {136String aixPrinterEnumerator = java.security.AccessController.doPrivileged(137new sun.security.action.GetPropertyAction("sun.java2d.print.aix.lpstat"));138139if (aixPrinterEnumerator != null) {140if (aixPrinterEnumerator.equalsIgnoreCase("lpstat")) {141aix_defaultPrinterEnumeration = aix_lpstat_p;142} else if (aixPrinterEnumerator.equalsIgnoreCase("lsallq")) {143aix_defaultPrinterEnumeration = aix_lsallq;144}145}146}147}148149static boolean isMac() {150return osname.startsWith("Mac");151}152153static boolean isSysV() {154return osname.equals("SunOS");155}156157static boolean isLinux() {158return (osname.equals("Linux"));159}160161static boolean isBSD() {162return (osname.equals("Linux") ||163osname.contains("OS X"));164}165166static boolean isAIX() {167return osname.equals("AIX");168}169170static final int UNINITIALIZED = -1;171static final int BSD_LPD = 0;172static final int BSD_LPD_NG = 1;173174static int cmdIndex = UNINITIALIZED;175176String[] lpcFirstCom = {177"/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'",178"/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'"179};180181String[] lpcAllCom = {182"/usr/sbin/lpc status all | grep : | sed -e 's/://'",183"/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort"184};185186String[] lpcNameCom = {187"| grep : | sed -ne 's/://p'",188"| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'"189};190191192static int getBSDCommandIndex() {193String command = "/usr/sbin/lpc status all";194String[] names = execCmd(command);195196if ((names == null) || (names.length == 0)) {197return BSD_LPD_NG;198}199200for (int i=0; i<names.length; i++) {201if (names[i].indexOf('@') != -1) {202return BSD_LPD_NG;203}204}205206return BSD_LPD;207}208209210public PrintServiceLookupProvider() {211// start the printer listener thread212if (pollServices) {213PrinterChangeListener thr = new PrinterChangeListener();214thr.setDaemon(true);215thr.start();216IPPPrintService.debug_println(debugPrefix+"polling turned on");217}218}219220/* Want the PrintService which is default print service to have221* equality of reference with the equivalent in list of print services222* This isn't required by the API and there's a risk doing this will223* lead people to assume its guaranteed.224*/225public synchronized PrintService[] getPrintServices() {226SecurityManager security = System.getSecurityManager();227if (security != null) {228security.checkPrintJobAccess();229}230231if (printServices == null || !pollServices) {232refreshServices();233}234if (printServices == null) {235return new PrintService[0];236} else {237return (PrintService[])printServices.clone();238}239}240241private int addPrintServiceToList(ArrayList printerList, PrintService ps) {242int index = printerList.indexOf(ps);243// Check if PrintService with same name is already in the list.244if (CUPSPrinter.isCupsRunning() && index != -1) {245// Bug in Linux: Duplicate entry of a remote printer246// and treats it as local printer but it is returning wrong247// information when queried using IPP. Workaround is to remove it.248// Even CUPS ignores these entries as shown in lpstat or using249// their web configuration.250PrinterURI uri = (PrinterURI)ps.getAttribute(PrinterURI.class);251if (uri.getURI().getHost().equals("localhost")) {252IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps);253return index; // Do not add this.254}255PrintService oldPS = (PrintService)(printerList.get(index));256uri = (PrinterURI)oldPS.getAttribute(PrinterURI.class);257if (uri.getURI().getHost().equals("localhost")) {258IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS);259printerList.remove(oldPS);260} else {261return index;262}263}264printerList.add(ps);265return (printerList.size() - 1);266}267268269// refreshes "printServices"270public synchronized void refreshServices() {271/* excludes the default printer */272String[] printers = null; // array of printer names273String[] printerURIs = null; //array of printer URIs274275try {276getDefaultPrintService();277} catch (Throwable t) {278IPPPrintService.debug_println(debugPrefix+279"Exception getting default printer : " + t);280}281if (CUPSPrinter.isCupsRunning()) {282try {283printerURIs = CUPSPrinter.getAllPrinters();284IPPPrintService.debug_println("CUPS URIs = " + printerURIs);285if (printerURIs != null) {286for (int p = 0; p < printerURIs.length; p++) {287IPPPrintService.debug_println("URI="+printerURIs[p]);288}289}290} catch (Throwable t) {291IPPPrintService.debug_println(debugPrefix+292"Exception getting all CUPS printers : " + t);293}294if ((printerURIs != null) && (printerURIs.length > 0)) {295printers = new String[printerURIs.length];296for (int i=0; i<printerURIs.length; i++) {297int lastIndex = printerURIs[i].lastIndexOf("/");298printers[i] = printerURIs[i].substring(lastIndex+1);299}300}301} else {302if (isMac() || isSysV()) {303printers = getAllPrinterNamesSysV();304} else if (isAIX()) {305printers = getAllPrinterNamesAIX();306} else { //BSD307printers = getAllPrinterNamesBSD();308}309}310311if (printers == null) {312if (defaultPrintService != null) {313printServices = new PrintService[1];314printServices[0] = defaultPrintService;315} else {316printServices = null;317}318return;319}320321ArrayList printerList = new ArrayList();322int defaultIndex = -1;323for (int p=0; p<printers.length; p++) {324if (printers[p] == null) {325continue;326}327if ((defaultPrintService != null)328&& printers[p].equals(getPrinterDestName(defaultPrintService))) {329defaultIndex = addPrintServiceToList(printerList, defaultPrintService);330} else {331if (printServices == null) {332IPPPrintService.debug_println(debugPrefix+333"total# of printers = "+printers.length);334335if (CUPSPrinter.isCupsRunning()) {336try {337addPrintServiceToList(printerList,338new IPPPrintService(printers[p],339printerURIs[p],340true));341} catch (Exception e) {342IPPPrintService.debug_println(debugPrefix+343" getAllPrinters Exception "+344e);345346}347} else {348printerList.add(new UnixPrintService(printers[p]));349}350} else {351int j;352for (j=0; j<printServices.length; j++) {353if (printServices[j] != null) {354if (printers[p].equals(getPrinterDestName(printServices[j]))) {355printerList.add(printServices[j]);356printServices[j] = null;357break;358}359}360}361362if (j == printServices.length) { // not found?363if (CUPSPrinter.isCupsRunning()) {364try {365addPrintServiceToList(printerList,366new IPPPrintService(printers[p],367printerURIs[p],368true));369} catch (Exception e) {370IPPPrintService.debug_println(debugPrefix+371" getAllPrinters Exception "+372e);373374}375} else {376printerList.add(new UnixPrintService(printers[p]));377}378}379}380}381}382383// Look for deleted services and invalidate these384if (printServices != null) {385for (int j=0; j < printServices.length; j++) {386if ((printServices[j] instanceof UnixPrintService) &&387(!printServices[j].equals(defaultPrintService))) {388((UnixPrintService)printServices[j]).invalidateService();389}390}391}392393//if defaultService is not found in printerList394if (defaultIndex == -1 && defaultPrintService != null) {395defaultIndex = addPrintServiceToList(printerList, defaultPrintService);396}397398printServices = (PrintService[])printerList.toArray(399new PrintService[] {});400401// swap default with the first in the list402if (defaultIndex > 0) {403PrintService saveService = printServices[0];404printServices[0] = printServices[defaultIndex];405printServices[defaultIndex] = saveService;406}407}408409private boolean matchesAttributes(PrintService service,410PrintServiceAttributeSet attributes) {411412Attribute [] attrs = attributes.toArray();413Attribute serviceAttr;414for (int i=0; i<attrs.length; i++) {415serviceAttr416= service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory());417if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {418return false;419}420}421return true;422}423424/* This checks for validity of the printer name before passing as425* parameter to a shell command.426*/427private boolean checkPrinterName(String s) {428char c;429430for (int i=0; i < s.length(); i++) {431c = s.charAt(i);432if (Character.isLetterOrDigit(c) ||433c == '-' || c == '_' || c == '.' || c == '/') {434continue;435} else {436return false;437}438}439return true;440}441442/*443* Gets the printer name compatible with the list of printers returned by444* the system when we query default or all the available printers.445*/446private String getPrinterDestName(PrintService ps) {447if (isMac()) {448return ((IPPPrintService)ps).getDest();449}450return ps.getName();451}452453/* On a network with many (hundreds) of network printers, it454* can save several seconds if you know all you want is a particular455* printer, to ask for that printer rather than retrieving all printers.456*/457private PrintService getServiceByName(PrinterName nameAttr) {458String name = nameAttr.getValue();459if (name == null || name.equals("") || !checkPrinterName(name)) {460return null;461}462/* check if all printers are already available */463if (printServices != null) {464for (PrintService printService : printServices) {465PrinterName printerName =466(PrinterName)printService.getAttribute(PrinterName.class);467if (printerName.getValue().equals(name)) {468return printService;469}470}471}472/* take CUPS into account first */473if (CUPSPrinter.isCupsRunning()) {474try {475return new IPPPrintService(name,476new URL("http://"+477CUPSPrinter.getServer()+":"+478CUPSPrinter.getPort()+"/"+479name));480} catch (Exception e) {481IPPPrintService.debug_println(debugPrefix+482" getServiceByName Exception "+483e);484}485}486/* fallback if nothing not having a printer at this point */487PrintService printer = null;488if (isMac() || isSysV()) {489printer = getNamedPrinterNameSysV(name);490} else if (isAIX()) {491printer = getNamedPrinterNameAIX(name);492} else {493printer = getNamedPrinterNameBSD(name);494}495return printer;496}497498private PrintService[]499getPrintServices(PrintServiceAttributeSet serviceSet) {500501if (serviceSet == null || serviceSet.isEmpty()) {502return getPrintServices();503}504505/* Typically expect that if a service attribute is specified that506* its a printer name and there ought to be only one match.507* Directly retrieve that service and confirm508* that it meets the other requirements.509* If printer name isn't mentioned then go a slow path checking510* all printers if they meet the reqiremements.511*/512PrintService[] services;513PrinterName name = (PrinterName)serviceSet.get(PrinterName.class);514PrintService defService;515if (name != null && (defService = getDefaultPrintService()) != null) {516/* To avoid execing a unix command see if the client is asking517* for the default printer by name, since we already have that518* initialised.519*/520521PrinterName defName =522(PrinterName)defService.getAttribute(PrinterName.class);523524if (defName != null && name.equals(defName)) {525if (matchesAttributes(defService, serviceSet)) {526services = new PrintService[1];527services[0] = defService;528return services;529} else {530return new PrintService[0];531}532} else {533/* Its not the default service */534PrintService service = getServiceByName(name);535if (service != null &&536matchesAttributes(service, serviceSet)) {537services = new PrintService[1];538services[0] = service;539return services;540} else {541return new PrintService[0];542}543}544} else {545/* specified service attributes don't include a name.*/546Vector matchedServices = new Vector();547services = getPrintServices();548for (int i = 0; i< services.length; i++) {549if (matchesAttributes(services[i], serviceSet)) {550matchedServices.add(services[i]);551}552}553services = new PrintService[matchedServices.size()];554for (int i = 0; i< services.length; i++) {555services[i] = (PrintService)matchedServices.elementAt(i);556}557return services;558}559}560561/*562* If service attributes are specified then there must be additional563* filtering.564*/565public PrintService[] getPrintServices(DocFlavor flavor,566AttributeSet attributes) {567SecurityManager security = System.getSecurityManager();568if (security != null) {569security.checkPrintJobAccess();570}571PrintRequestAttributeSet requestSet = null;572PrintServiceAttributeSet serviceSet = null;573574if (attributes != null && !attributes.isEmpty()) {575576requestSet = new HashPrintRequestAttributeSet();577serviceSet = new HashPrintServiceAttributeSet();578579Attribute[] attrs = attributes.toArray();580for (int i=0; i<attrs.length; i++) {581if (attrs[i] instanceof PrintRequestAttribute) {582requestSet.add(attrs[i]);583} else if (attrs[i] instanceof PrintServiceAttribute) {584serviceSet.add(attrs[i]);585}586}587}588589PrintService[] services = getPrintServices(serviceSet);590if (services.length == 0) {591return services;592}593594if (CUPSPrinter.isCupsRunning()) {595ArrayList matchingServices = new ArrayList();596for (int i=0; i<services.length; i++) {597try {598if (services[i].599getUnsupportedAttributes(flavor, requestSet) == null) {600matchingServices.add(services[i]);601}602} catch (IllegalArgumentException e) {603}604}605services = new PrintService[matchingServices.size()];606return (PrintService[])matchingServices.toArray(services);607608} else {609// We only need to compare 1 PrintService because all610// UnixPrintServices are the same anyway. We will not use611// default PrintService because it might be null.612PrintService service = services[0];613if ((flavor == null ||614service.isDocFlavorSupported(flavor)) &&615service.getUnsupportedAttributes(flavor, requestSet) == null)616{617return services;618} else {619return new PrintService[0];620}621}622}623624/*625* return empty array as don't support multi docs626*/627public MultiDocPrintService[]628getMultiDocPrintServices(DocFlavor[] flavors,629AttributeSet attributes) {630SecurityManager security = System.getSecurityManager();631if (security != null) {632security.checkPrintJobAccess();633}634return new MultiDocPrintService[0];635}636637638public synchronized PrintService getDefaultPrintService() {639SecurityManager security = System.getSecurityManager();640if (security != null) {641security.checkPrintJobAccess();642}643644// clear defaultPrintService645defaultPrintService = null;646String psuri = null;647648IPPPrintService.debug_println("isRunning ? "+649(CUPSPrinter.isCupsRunning()));650if (CUPSPrinter.isCupsRunning()) {651String[] printerInfo = CUPSPrinter.getDefaultPrinter();652if (printerInfo != null && printerInfo.length >= 2) {653defaultPrinter = printerInfo[0];654psuri = printerInfo[1];655}656} else {657if (isMac() || isSysV()) {658defaultPrinter = getDefaultPrinterNameSysV();659} else if (isAIX()) {660defaultPrinter = getDefaultPrinterNameAIX();661} else {662defaultPrinter = getDefaultPrinterNameBSD();663}664}665if (defaultPrinter == null) {666return null;667}668defaultPrintService = null;669if (printServices != null) {670for (int j=0; j<printServices.length; j++) {671if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) {672defaultPrintService = printServices[j];673break;674}675}676}677if (defaultPrintService == null) {678if (CUPSPrinter.isCupsRunning()) {679try {680PrintService defaultPS;681if ((psuri != null) && !psuri.startsWith("file")) {682defaultPS = new IPPPrintService(defaultPrinter,683psuri, true);684} else {685defaultPS = new IPPPrintService(defaultPrinter,686new URL("http://"+687CUPSPrinter.getServer()+":"+688CUPSPrinter.getPort()+"/"+689defaultPrinter));690}691defaultPrintService = defaultPS;692} catch (Exception e) {693}694} else {695defaultPrintService = new UnixPrintService(defaultPrinter);696}697}698699return defaultPrintService;700}701702public synchronized void703getServicesInbackground(BackgroundLookupListener listener) {704if (printServices != null) {705listener.notifyServices(printServices);706} else {707if (lookupListeners == null) {708lookupListeners = new Vector();709lookupListeners.add(listener);710Thread lookupThread = new Thread(this);711lookupThread.start();712} else {713lookupListeners.add(listener);714}715}716}717718/* This method isn't used in most cases because we rely on code in719* javax.print.PrintServiceLookup. This is needed just for the cases720* where those interfaces are by-passed.721*/722private PrintService[] copyOf(PrintService[] inArr) {723if (inArr == null || inArr.length == 0) {724return inArr;725} else {726PrintService []outArr = new PrintService[inArr.length];727System.arraycopy(inArr, 0, outArr, 0, inArr.length);728return outArr;729}730}731732public void run() {733PrintService[] services = getPrintServices();734synchronized (this) {735BackgroundLookupListener listener;736for (int i=0; i<lookupListeners.size(); i++) {737listener =738(BackgroundLookupListener)lookupListeners.elementAt(i);739listener.notifyServices(copyOf(services));740}741lookupListeners = null;742}743}744745private String getDefaultPrinterNameBSD() {746if (cmdIndex == UNINITIALIZED) {747cmdIndex = getBSDCommandIndex();748}749String[] names = execCmd(lpcFirstCom[cmdIndex]);750if (names == null || names.length == 0) {751return null;752}753754if ((cmdIndex==BSD_LPD_NG) &&755(names[0].startsWith("missingprinter"))) {756return null;757}758return names[0];759}760761private PrintService getNamedPrinterNameBSD(String name) {762if (cmdIndex == UNINITIALIZED) {763cmdIndex = getBSDCommandIndex();764}765String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex];766String[] result = execCmd(command);767768if (result == null || !(result[0].equals(name))) {769return null;770}771return new UnixPrintService(name);772}773774private String[] getAllPrinterNamesBSD() {775if (cmdIndex == UNINITIALIZED) {776cmdIndex = getBSDCommandIndex();777}778String[] names = execCmd(lpcAllCom[cmdIndex]);779if (names == null || names.length == 0) {780return null;781}782return names;783}784785static String getDefaultPrinterNameSysV() {786String defaultPrinter = "lp";787String command = "/usr/bin/lpstat -d";788789String [] names = execCmd(command);790if (names == null || names.length == 0) {791return defaultPrinter;792} else {793int index = names[0].indexOf(":");794if (index == -1 || (names[0].length() <= index+1)) {795return null;796} else {797String name = names[0].substring(index+1).trim();798if (name.length() == 0) {799return null;800} else {801return name;802}803}804}805}806807private PrintService getNamedPrinterNameSysV(String name) {808809String command = "/usr/bin/lpstat -v " + name;810String []result = execCmd(command);811812if (result == null || result[0].indexOf("unknown printer") > 0) {813return null;814} else {815return new UnixPrintService(name);816}817}818819private String[] getAllPrinterNamesSysV() {820String defaultPrinter = "lp";821String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort";822823String [] names = execCmd(command);824ArrayList printerNames = new ArrayList();825for (int i=0; i < names.length; i++) {826if (!names[i].equals("_default") &&827!names[i].equals(defaultPrinter) &&828!names[i].equals("")) {829printerNames.add(names[i]);830}831}832return (String[])printerNames.toArray(new String[printerNames.size()]);833}834835private String getDefaultPrinterNameAIX() {836String[] names = execCmd(lpNameComAix[aix_lpstat_d]);837// Remove headers and bogus entries added by remote printers.838names = UnixPrintService.filterPrinterNamesAIX(names);839if (names == null || names.length != 1) {840// No default printer found841return null;842} else {843return names[0];844}845}846847private PrintService getNamedPrinterNameAIX(String name) {848// On AIX there should be no blank after '-v'.849String[] result = execCmd(lpNameComAix[aix_lpstat_v] + name);850// Remove headers and bogus entries added by remote printers.851result = UnixPrintService.filterPrinterNamesAIX(result);852if (result == null || result.length != 1) {853return null;854} else {855return new UnixPrintService(name);856}857}858859private String[] getAllPrinterNamesAIX() {860// Determine all printers of the system.861String [] names = execCmd(lpNameComAix[aix_defaultPrinterEnumeration]);862863// Remove headers and bogus entries added by remote printers.864names = UnixPrintService.filterPrinterNamesAIX(names);865866ArrayList<String> printerNames = new ArrayList<String>();867for ( int i=0; i < names.length; i++) {868printerNames.add(names[i]);869}870return (String[])printerNames.toArray(new String[printerNames.size()]);871}872873static String[] execCmd(final String command) {874ArrayList results = null;875try {876final String[] cmd = new String[3];877if (isSysV() || isAIX()) {878cmd[0] = "/usr/bin/sh";879cmd[1] = "-c";880cmd[2] = "env LC_ALL=C " + command;881} else {882cmd[0] = "/bin/sh";883cmd[1] = "-c";884cmd[2] = "LC_ALL=C " + command;885}886887results = (ArrayList)AccessController.doPrivileged(888new PrivilegedExceptionAction() {889public Object run() throws IOException {890891Process proc;892BufferedReader bufferedReader = null;893File f = Files.createTempFile("prn","xc").toFile();894cmd[2] = cmd[2]+">"+f.getAbsolutePath();895896proc = Runtime.getRuntime().exec(cmd);897try {898boolean done = false; // in case of interrupt.899while (!done) {900try {901proc.waitFor();902done = true;903} catch (InterruptedException e) {904}905}906907if (proc.exitValue() == 0) {908FileReader reader = new FileReader(f);909bufferedReader = new BufferedReader(reader);910String line;911ArrayList results = new ArrayList();912while ((line = bufferedReader.readLine())913!= null) {914results.add(line);915}916return results;917}918} finally {919f.delete();920// promptly close all streams.921if (bufferedReader != null) {922bufferedReader.close();923}924proc.getInputStream().close();925proc.getErrorStream().close();926proc.getOutputStream().close();927}928return null;929}930});931} catch (PrivilegedActionException e) {932}933if (results == null) {934return new String[0];935} else {936return (String[])results.toArray(new String[results.size()]);937}938}939940private class PrinterChangeListener extends Thread {941942public void run() {943int refreshSecs;944while (true) {945try {946refreshServices();947} catch (Exception se) {948IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread.");949break;950}951952if ((printServices != null) &&953(printServices.length > minRefreshTime)) {954// compute new refresh time 1 printer = 1 sec955refreshSecs = printServices.length;956} else {957refreshSecs = minRefreshTime;958}959try {960sleep(refreshSecs * 1000);961} catch (InterruptedException e) {962break;963}964}965}966}967}968969970