1 /* 2 * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.print; 27 28 import java.io.BufferedReader; 29 import java.io.FileInputStream; 30 import java.io.InputStream; 31 import java.io.InputStreamReader; 32 import java.io.IOException; 33 import java.util.ArrayList; 34 import java.util.Vector; 35 import java.security.AccessController; 36 import java.security.PrivilegedActionException; 37 import java.security.PrivilegedExceptionAction; 38 import javax.print.DocFlavor; 39 import javax.print.MultiDocPrintService; 40 import javax.print.PrintService; 41 import javax.print.PrintServiceLookup; 42 import javax.print.attribute.Attribute; 43 import javax.print.attribute.AttributeSet; 44 import javax.print.attribute.HashPrintRequestAttributeSet; 45 import javax.print.attribute.HashPrintServiceAttributeSet; 46 import javax.print.attribute.PrintRequestAttribute; 47 import javax.print.attribute.PrintRequestAttributeSet; 48 import javax.print.attribute.PrintServiceAttribute; 49 import javax.print.attribute.PrintServiceAttributeSet; 50 import javax.print.attribute.standard.PrinterName; 51 import javax.print.attribute.standard.PrinterURI; 52 import java.io.File; 53 import java.io.FileReader; 54 import java.net.URL; 55 import java.nio.file.Files; 56 57 /* 58 * Remind: This class uses solaris commands. We also need a linux 59 * version 60 */ 61 public class UnixPrintServiceLookup extends PrintServiceLookup 62 implements BackgroundServiceLookup, Runnable { 63 64 /* Remind: the current implementation is static, as its assumed 65 * its preferable to minimize creation of PrintService instances. 66 * Later we should add logic to add/remove services on the fly which 67 * will take a hit of needing to regather the list of services. 68 */ 69 private String defaultPrinter; 70 private PrintService defaultPrintService; 71 private PrintService[] printServices; /* includes the default printer */ 72 private Vector lookupListeners = null; 73 private static String debugPrefix = "UnixPrintServiceLookup>> "; 74 private static boolean pollServices = true; 75 private static final int DEFAULT_MINREFRESH = 120; // 2 minutes 76 private static int minRefreshTime = DEFAULT_MINREFRESH; 77 78 79 static String osname; 80 81 static { 82 /* The system property "sun.java2d.print.polling" 83 * can be used to force the printing code to poll or not poll 84 * for PrintServices. 85 */ 86 String pollStr = java.security.AccessController.doPrivileged( 87 new sun.security.action.GetPropertyAction("sun.java2d.print.polling")); 88 89 if (pollStr != null) { 90 if (pollStr.equalsIgnoreCase("true")) { 91 pollServices = true; 92 } else if (pollStr.equalsIgnoreCase("false")) { 93 pollServices = false; 94 } 95 } 96 97 /* The system property "sun.java2d.print.minRefreshTime" 98 * can be used to specify minimum refresh time (in seconds) 99 * for polling PrintServices. The default is 120. 100 */ 101 String refreshTimeStr = java.security.AccessController.doPrivileged( 102 new sun.security.action.GetPropertyAction( 103 "sun.java2d.print.minRefreshTime")); 104 105 if (refreshTimeStr != null) { 106 try { 107 minRefreshTime = (new Integer(refreshTimeStr)).intValue(); 108 } catch (NumberFormatException e) { 109 } 110 if (minRefreshTime < DEFAULT_MINREFRESH) { 111 minRefreshTime = DEFAULT_MINREFRESH; 112 } 113 } 114 115 osname = java.security.AccessController.doPrivileged( 116 new sun.security.action.GetPropertyAction("os.name")); 117 } 118 119 static boolean isMac() { 120 return osname.startsWith("Mac"); 121 } 122 123 static boolean isSysV() { 124 return osname.equals("SunOS"); 125 } 126 127 static boolean isLinux() { 128 return (osname.equals("Linux")); 129 } 130 131 static boolean isBSD() { 132 return (osname.equals("Linux") || 133 osname.contains("OS X")); 134 } 135 136 static final int UNINITIALIZED = -1; 137 static final int BSD_LPD = 0; 138 static final int BSD_LPD_NG = 1; 139 140 static int cmdIndex = UNINITIALIZED; 141 142 String[] lpcFirstCom = { 143 "/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'", 144 "/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" 145 }; 146 147 String[] lpcAllCom = { 148 "/usr/sbin/lpc status all | grep : | sed -e 's/://'", 149 "/usr/sbin/lpc status all | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort" 150 }; 151 152 String[] lpcNameCom = { 153 "| grep : | sed -ne 's/://p'", 154 "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" 155 }; 156 157 158 static int getBSDCommandIndex() { 159 String command = "/usr/sbin/lpc status all"; 160 String[] names = execCmd(command); 161 162 if ((names == null) || (names.length == 0)) { 163 return BSD_LPD_NG; 164 } 165 166 for (int i=0; i<names.length; i++) { 167 if (names[i].indexOf('@') != -1) { 168 return BSD_LPD_NG; 169 } 170 } 171 172 return BSD_LPD; 173 } 174 175 176 public UnixPrintServiceLookup() { 177 // start the printer listener thread 178 if (pollServices) { 179 PrinterChangeListener thr = new PrinterChangeListener(); 180 thr.setDaemon(true); 181 thr.start(); 182 IPPPrintService.debug_println(debugPrefix+"polling turned on"); 183 } 184 } 185 186 /* Want the PrintService which is default print service to have 187 * equality of reference with the equivalent in list of print services 188 * This isn't required by the API and there's a risk doing this will 189 * lead people to assume its guaranteed. 190 */ 191 public synchronized PrintService[] getPrintServices() { 192 SecurityManager security = System.getSecurityManager(); 193 if (security != null) { 194 security.checkPrintJobAccess(); 195 } 196 197 if (printServices == null || !pollServices) { 198 refreshServices(); 199 } 200 if (printServices == null) { 201 return new PrintService[0]; 202 } else { 203 return (PrintService[])printServices.clone(); 204 } 205 } 206 207 private int addPrintServiceToList(ArrayList printerList, PrintService ps) { 208 int index = printerList.indexOf(ps); 209 // Check if PrintService with same name is already in the list. 210 if (CUPSPrinter.isCupsRunning() && index != -1) { 211 // Bug in Linux: Duplicate entry of a remote printer 212 // and treats it as local printer but it is returning wrong 213 // information when queried using IPP. Workaround is to remove it. 214 // Even CUPS ignores these entries as shown in lpstat or using 215 // their web configuration. 216 PrinterURI uri = (PrinterURI)ps.getAttribute(PrinterURI.class); 217 if (uri.getURI().getHost().equals("localhost")) { 218 IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, ignoring the new local printer: "+ps); 219 return index; // Do not add this. 220 } 221 PrintService oldPS = (PrintService)(printerList.get(index)); 222 uri = (PrinterURI)oldPS.getAttribute(PrinterURI.class); 223 if (uri.getURI().getHost().equals("localhost")) { 224 IPPPrintService.debug_println(debugPrefix+"duplicate PrintService, removing existing local printer: "+oldPS); 225 printerList.remove(oldPS); 226 } else { 227 return index; 228 } 229 } 230 printerList.add(ps); 231 return (printerList.size() - 1); 232 } 233 234 235 // refreshes "printServices" 236 public synchronized void refreshServices() { 237 /* excludes the default printer */ 238 String[] printers = null; // array of printer names 239 String[] printerURIs = null; //array of printer URIs 240 241 getDefaultPrintService(); 242 if (CUPSPrinter.isCupsRunning()) { 243 printerURIs = CUPSPrinter.getAllPrinters(); 244 if ((printerURIs != null) && (printerURIs.length > 0)) { 245 printers = new String[printerURIs.length]; 246 for (int i=0; i<printerURIs.length; i++) { 247 int lastIndex = printerURIs[i].lastIndexOf("/"); 248 printers[i] = printerURIs[i].substring(lastIndex+1); 249 } 250 } 251 } else { 252 if (isMac() || isSysV()) { 253 printers = getAllPrinterNamesSysV(); 254 } else { //BSD 255 printers = getAllPrinterNamesBSD(); 256 } 257 } 258 259 if (printers == null) { 260 if (defaultPrintService != null) { 261 printServices = new PrintService[1]; 262 printServices[0] = defaultPrintService; 263 } else { 264 printServices = null; 265 } 266 return; 267 } 268 269 ArrayList printerList = new ArrayList(); 270 int defaultIndex = -1; 271 for (int p=0; p<printers.length; p++) { 272 if (printers[p] == null) { 273 continue; 274 } 275 if ((defaultPrintService != null) 276 && printers[p].equals(getPrinterDestName(defaultPrintService))) { 277 defaultIndex = addPrintServiceToList(printerList, defaultPrintService); 278 } else { 279 if (printServices == null) { 280 IPPPrintService.debug_println(debugPrefix+ 281 "total# of printers = "+printers.length); 282 283 if (CUPSPrinter.isCupsRunning()) { 284 try { 285 addPrintServiceToList(printerList, 286 new IPPPrintService(printers[p], 287 printerURIs[p], 288 true)); 289 } catch (Exception e) { 290 IPPPrintService.debug_println(debugPrefix+ 291 " getAllPrinters Exception "+ 292 e); 293 294 } 295 } else { 296 printerList.add(new UnixPrintService(printers[p])); 297 } 298 } else { 299 int j; 300 for (j=0; j<printServices.length; j++) { 301 if (printServices[j] != null) { 302 if (printers[p].equals(getPrinterDestName(printServices[j]))) { 303 printerList.add(printServices[j]); 304 printServices[j] = null; 305 break; 306 } 307 } 308 } 309 310 if (j == printServices.length) { // not found? 311 if (CUPSPrinter.isCupsRunning()) { 312 try { 313 addPrintServiceToList(printerList, 314 new IPPPrintService(printers[p], 315 printerURIs[p], 316 true)); 317 } catch (Exception e) { 318 IPPPrintService.debug_println(debugPrefix+ 319 " getAllPrinters Exception "+ 320 e); 321 322 } 323 } else { 324 printerList.add(new UnixPrintService(printers[p])); 325 } 326 } 327 } 328 } 329 } 330 331 // Look for deleted services and invalidate these 332 if (printServices != null) { 333 for (int j=0; j < printServices.length; j++) { 334 if ((printServices[j] instanceof UnixPrintService) && 335 (!printServices[j].equals(defaultPrintService))) { 336 ((UnixPrintService)printServices[j]).invalidateService(); 337 } 338 } 339 } 340 341 //if defaultService is not found in printerList 342 if (defaultIndex == -1 && defaultPrintService != null) { 343 defaultIndex = addPrintServiceToList(printerList, defaultPrintService); 344 } 345 346 printServices = (PrintService[])printerList.toArray( 347 new PrintService[] {}); 348 349 // swap default with the first in the list 350 if (defaultIndex > 0) { 351 PrintService saveService = printServices[0]; 352 printServices[0] = printServices[defaultIndex]; 353 printServices[defaultIndex] = saveService; 354 } 355 } 356 357 private boolean matchesAttributes(PrintService service, 358 PrintServiceAttributeSet attributes) { 359 360 Attribute [] attrs = attributes.toArray(); 361 Attribute serviceAttr; 362 for (int i=0; i<attrs.length; i++) { 363 serviceAttr 364 = service.getAttribute((Class<PrintServiceAttribute>)attrs[i].getCategory()); 365 if (serviceAttr == null || !serviceAttr.equals(attrs[i])) { 366 return false; 367 } 368 } 369 return true; 370 } 371 372 /* This checks for validity of the printer name before passing as 373 * parameter to a shell command. 374 */ 375 private boolean checkPrinterName(String s) { 376 char c; 377 378 for (int i=0; i < s.length(); i++) { 379 c = s.charAt(i); 380 if (Character.isLetterOrDigit(c) || 381 c == '-' || c == '_' || c == '.' || c == '/') { 382 continue; 383 } else { 384 return false; 385 } 386 } 387 return true; 388 } 389 390 /* 391 * Gets the printer name compatible with the list of printers returned by 392 * the system when we query default or all the available printers. 393 */ 394 private String getPrinterDestName(PrintService ps) { 395 if (isMac()) { 396 return ((IPPPrintService)ps).getDest(); 397 } 398 return ps.getName(); 399 } 400 401 /* On a network with many (hundreds) of network printers, it 402 * can save several seconds if you know all you want is a particular 403 * printer, to ask for that printer rather than retrieving all printers. 404 */ 405 private PrintService getServiceByName(PrinterName nameAttr) { 406 String name = nameAttr.getValue(); 407 if (name == null || name.equals("") || !checkPrinterName(name)) { 408 return null; 409 } 410 /* check if all printers are already available */ 411 if (printServices != null) { 412 for (PrintService printService : printServices) { 413 PrinterName printerName = 414 (PrinterName)printService.getAttribute(PrinterName.class); 415 if (printerName.getValue().equals(name)) { 416 return printService; 417 } 418 } 419 } 420 /* take CUPS into account first */ 421 if (CUPSPrinter.isCupsRunning()) { 422 try { 423 return new IPPPrintService(name, 424 new URL("http://"+ 425 CUPSPrinter.getServer()+":"+ 426 CUPSPrinter.getPort()+"/"+ 427 name)); 428 } catch (Exception e) { 429 IPPPrintService.debug_println(debugPrefix+ 430 " getServiceByName Exception "+ 431 e); 432 } 433 } 434 /* fallback if nothing not having a printer at this point */ 435 PrintService printer = null; 436 if (isMac() || isSysV()) { 437 printer = getNamedPrinterNameSysV(name); 438 } else { 439 printer = getNamedPrinterNameBSD(name); 440 } 441 return printer; 442 } 443 444 private PrintService[] 445 getPrintServices(PrintServiceAttributeSet serviceSet) { 446 447 if (serviceSet == null || serviceSet.isEmpty()) { 448 return getPrintServices(); 449 } 450 451 /* Typically expect that if a service attribute is specified that 452 * its a printer name and there ought to be only one match. 453 * Directly retrieve that service and confirm 454 * that it meets the other requirements. 455 * If printer name isn't mentioned then go a slow path checking 456 * all printers if they meet the reqiremements. 457 */ 458 PrintService[] services; 459 PrinterName name = (PrinterName)serviceSet.get(PrinterName.class); 460 PrintService defService; 461 if (name != null && (defService = getDefaultPrintService()) != null) { 462 /* To avoid execing a unix command see if the client is asking 463 * for the default printer by name, since we already have that 464 * initialised. 465 */ 466 467 PrinterName defName = 468 (PrinterName)defService.getAttribute(PrinterName.class); 469 470 if (defName != null && name.equals(defName)) { 471 if (matchesAttributes(defService, serviceSet)) { 472 services = new PrintService[1]; 473 services[0] = defService; 474 return services; 475 } else { 476 return new PrintService[0]; 477 } 478 } else { 479 /* Its not the default service */ 480 PrintService service = getServiceByName(name); 481 if (service != null && 482 matchesAttributes(service, serviceSet)) { 483 services = new PrintService[1]; 484 services[0] = service; 485 return services; 486 } else { 487 return new PrintService[0]; 488 } 489 } 490 } else { 491 /* specified service attributes don't include a name.*/ 492 Vector matchedServices = new Vector(); 493 services = getPrintServices(); 494 for (int i = 0; i< services.length; i++) { 495 if (matchesAttributes(services[i], serviceSet)) { 496 matchedServices.add(services[i]); 497 } 498 } 499 services = new PrintService[matchedServices.size()]; 500 for (int i = 0; i< services.length; i++) { 501 services[i] = (PrintService)matchedServices.elementAt(i); 502 } 503 return services; 504 } 505 } 506 507 /* 508 * If service attributes are specified then there must be additional 509 * filtering. 510 */ 511 public PrintService[] getPrintServices(DocFlavor flavor, 512 AttributeSet attributes) { 513 SecurityManager security = System.getSecurityManager(); 514 if (security != null) { 515 security.checkPrintJobAccess(); 516 } 517 PrintRequestAttributeSet requestSet = null; 518 PrintServiceAttributeSet serviceSet = null; 519 520 if (attributes != null && !attributes.isEmpty()) { 521 522 requestSet = new HashPrintRequestAttributeSet(); 523 serviceSet = new HashPrintServiceAttributeSet(); 524 525 Attribute[] attrs = attributes.toArray(); 526 for (int i=0; i<attrs.length; i++) { 527 if (attrs[i] instanceof PrintRequestAttribute) { 528 requestSet.add(attrs[i]); 529 } else if (attrs[i] instanceof PrintServiceAttribute) { 530 serviceSet.add(attrs[i]); 531 } 532 } 533 } 534 535 PrintService[] services = getPrintServices(serviceSet); 536 if (services.length == 0) { 537 return services; 538 } 539 540 if (CUPSPrinter.isCupsRunning()) { 541 ArrayList matchingServices = new ArrayList(); 542 for (int i=0; i<services.length; i++) { 543 try { 544 if (services[i]. 545 getUnsupportedAttributes(flavor, requestSet) == null) { 546 matchingServices.add(services[i]); 547 } 548 } catch (IllegalArgumentException e) { 549 } 550 } 551 services = new PrintService[matchingServices.size()]; 552 return (PrintService[])matchingServices.toArray(services); 553 554 } else { 555 // We only need to compare 1 PrintService because all 556 // UnixPrintServices are the same anyway. We will not use 557 // default PrintService because it might be null. 558 PrintService service = services[0]; 559 if ((flavor == null || 560 service.isDocFlavorSupported(flavor)) && 561 service.getUnsupportedAttributes(flavor, requestSet) == null) 562 { 563 return services; 564 } else { 565 return new PrintService[0]; 566 } 567 } 568 } 569 570 /* 571 * return empty array as don't support multi docs 572 */ 573 public MultiDocPrintService[] 574 getMultiDocPrintServices(DocFlavor[] flavors, 575 AttributeSet attributes) { 576 SecurityManager security = System.getSecurityManager(); 577 if (security != null) { 578 security.checkPrintJobAccess(); 579 } 580 return new MultiDocPrintService[0]; 581 } 582 583 584 public synchronized PrintService getDefaultPrintService() { 585 SecurityManager security = System.getSecurityManager(); 586 if (security != null) { 587 security.checkPrintJobAccess(); 588 } 589 590 // clear defaultPrintService 591 defaultPrintService = null; 592 String psuri = null; 593 594 IPPPrintService.debug_println("isRunning ? "+ 595 (CUPSPrinter.isCupsRunning())); 596 if (CUPSPrinter.isCupsRunning()) { 597 String[] printerInfo = CUPSPrinter.getDefaultPrinter(); 598 defaultPrinter = printerInfo[0]; 599 psuri = printerInfo[1]; 600 } else { 601 if (isMac() || isSysV()) { 602 defaultPrinter = getDefaultPrinterNameSysV(); 603 } else { 604 defaultPrinter = getDefaultPrinterNameBSD(); 605 } 606 } 607 if (defaultPrinter == null) { 608 return null; 609 } 610 defaultPrintService = null; 611 if (printServices != null) { 612 for (int j=0; j<printServices.length; j++) { 613 if (defaultPrinter.equals(getPrinterDestName(printServices[j]))) { 614 defaultPrintService = printServices[j]; 615 break; 616 } 617 } 618 } 619 if (defaultPrintService == null) { 620 if (CUPSPrinter.isCupsRunning()) { 621 try { 622 PrintService defaultPS; 623 if ((psuri != null) && !psuri.startsWith("file")) { 624 defaultPS = new IPPPrintService(defaultPrinter, 625 psuri, true); 626 } else { 627 defaultPS = new IPPPrintService(defaultPrinter, 628 new URL("http://"+ 629 CUPSPrinter.getServer()+":"+ 630 CUPSPrinter.getPort()+"/"+ 631 defaultPrinter)); 632 } 633 defaultPrintService = defaultPS; 634 } catch (Exception e) { 635 } 636 } else { 637 defaultPrintService = new UnixPrintService(defaultPrinter); 638 } 639 } 640 641 return defaultPrintService; 642 } 643 644 public synchronized void 645 getServicesInbackground(BackgroundLookupListener listener) { 646 if (printServices != null) { 647 listener.notifyServices(printServices); 648 } else { 649 if (lookupListeners == null) { 650 lookupListeners = new Vector(); 651 lookupListeners.add(listener); 652 Thread lookupThread = new Thread(this); 653 lookupThread.start(); 654 } else { 655 lookupListeners.add(listener); 656 } 657 } 658 } 659 660 /* This method isn't used in most cases because we rely on code in 661 * javax.print.PrintServiceLookup. This is needed just for the cases 662 * where those interfaces are by-passed. 663 */ 664 private PrintService[] copyOf(PrintService[] inArr) { 665 if (inArr == null || inArr.length == 0) { 666 return inArr; 667 } else { 668 PrintService []outArr = new PrintService[inArr.length]; 669 System.arraycopy(inArr, 0, outArr, 0, inArr.length); 670 return outArr; 671 } 672 } 673 674 public void run() { 675 PrintService[] services = getPrintServices(); 676 synchronized (this) { 677 BackgroundLookupListener listener; 678 for (int i=0; i<lookupListeners.size(); i++) { 679 listener = 680 (BackgroundLookupListener)lookupListeners.elementAt(i); 681 listener.notifyServices(copyOf(services)); 682 } 683 lookupListeners = null; 684 } 685 } 686 687 private String getDefaultPrinterNameBSD() { 688 if (cmdIndex == UNINITIALIZED) { 689 cmdIndex = getBSDCommandIndex(); 690 } 691 String[] names = execCmd(lpcFirstCom[cmdIndex]); 692 if (names == null || names.length == 0) { 693 return null; 694 } 695 696 if ((cmdIndex==BSD_LPD_NG) && 697 (names[0].startsWith("missingprinter"))) { 698 return null; 699 } 700 return names[0]; 701 } 702 703 private PrintService getNamedPrinterNameBSD(String name) { 704 if (cmdIndex == UNINITIALIZED) { 705 cmdIndex = getBSDCommandIndex(); 706 } 707 String command = "/usr/sbin/lpc status " + name + lpcNameCom[cmdIndex]; 708 String[] result = execCmd(command); 709 710 if (result == null || !(result[0].equals(name))) { 711 return null; 712 } 713 return new UnixPrintService(name); 714 } 715 716 private String[] getAllPrinterNamesBSD() { 717 if (cmdIndex == UNINITIALIZED) { 718 cmdIndex = getBSDCommandIndex(); 719 } 720 String[] names = execCmd(lpcAllCom[cmdIndex]); 721 if (names == null || names.length == 0) { 722 return null; 723 } 724 return names; 725 } 726 727 static String getDefaultPrinterNameSysV() { 728 String defaultPrinter = "lp"; 729 String command = "/usr/bin/lpstat -d"; 730 731 String [] names = execCmd(command); 732 if (names == null || names.length == 0) { 733 return defaultPrinter; 734 } else { 735 int index = names[0].indexOf(":"); 736 if (index == -1 || (names[0].length() <= index+1)) { 737 return null; 738 } else { 739 String name = names[0].substring(index+1).trim(); 740 if (name.length() == 0) { 741 return null; 742 } else { 743 return name; 744 } 745 } 746 } 747 } 748 749 private PrintService getNamedPrinterNameSysV(String name) { 750 751 String command = "/usr/bin/lpstat -v " + name; 752 String []result = execCmd(command); 753 754 if (result == null || result[0].indexOf("unknown printer") > 0) { 755 return null; 756 } else { 757 return new UnixPrintService(name); 758 } 759 } 760 761 private String[] getAllPrinterNamesSysV() { 762 String defaultPrinter = "lp"; 763 String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort"; 764 765 String [] names = execCmd(command); 766 ArrayList printerNames = new ArrayList(); 767 for (int i=0; i < names.length; i++) { 768 if (!names[i].equals("_default") && 769 !names[i].equals(defaultPrinter) && 770 !names[i].equals("")) { 771 printerNames.add(names[i]); 772 } 773 } 774 return (String[])printerNames.toArray(new String[printerNames.size()]); 775 } 776 777 static String[] execCmd(final String command) { 778 ArrayList results = null; 779 try { 780 final String[] cmd = new String[3]; 781 if (isSysV()) { 782 cmd[0] = "/usr/bin/sh"; 783 cmd[1] = "-c"; 784 cmd[2] = "env LC_ALL=C " + command; 785 } else { 786 cmd[0] = "/bin/sh"; 787 cmd[1] = "-c"; 788 cmd[2] = "LC_ALL=C " + command; 789 } 790 791 results = (ArrayList)AccessController.doPrivileged( 792 new PrivilegedExceptionAction() { 793 public Object run() throws IOException { 794 795 Process proc; 796 BufferedReader bufferedReader = null; 797 File f = Files.createTempFile("prn","xc").toFile(); 798 cmd[2] = cmd[2]+">"+f.getAbsolutePath(); 799 800 proc = Runtime.getRuntime().exec(cmd); 801 try { 802 boolean done = false; // in case of interrupt. 803 while (!done) { 804 try { 805 proc.waitFor(); 806 done = true; 807 } catch (InterruptedException e) { 808 } 809 } 810 811 if (proc.exitValue() == 0) { 812 FileReader reader = new FileReader(f); 813 bufferedReader = new BufferedReader(reader); 814 String line; 815 ArrayList results = new ArrayList(); 816 while ((line = bufferedReader.readLine()) 817 != null) { 818 results.add(line); 819 } 820 return results; 821 } 822 } finally { 823 f.delete(); 824 // promptly close all streams. 825 if (bufferedReader != null) { 826 bufferedReader.close(); 827 } 828 proc.getInputStream().close(); 829 proc.getErrorStream().close(); 830 proc.getOutputStream().close(); 831 } 832 return null; 833 } 834 }); 835 } catch (PrivilegedActionException e) { 836 } 837 if (results == null) { 838 return new String[0]; 839 } else { 840 return (String[])results.toArray(new String[results.size()]); 841 } 842 } 843 844 private class PrinterChangeListener extends Thread { 845 846 public void run() { 847 int refreshSecs; 848 while (true) { 849 try { 850 refreshServices(); 851 } catch (Exception se) { 852 IPPPrintService.debug_println(debugPrefix+"Exception in refresh thread."); 853 break; 854 } 855 856 if ((printServices != null) && 857 (printServices.length > minRefreshTime)) { 858 // compute new refresh time 1 printer = 1 sec 859 refreshSecs = printServices.length; 860 } else { 861 refreshSecs = minRefreshTime; 862 } 863 try { 864 sleep(refreshSecs * 1000); 865 } catch (InterruptedException e) { 866 break; 867 } 868 } 869 } 870 } 871 }