001: /*
002: * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.print;
027:
028: import java.io.BufferedReader;
029: import java.io.FileInputStream;
030: import java.io.InputStream;
031: import java.io.InputStreamReader;
032: import java.io.IOException;
033: import java.util.ArrayList;
034: import java.util.Vector;
035: import java.security.AccessController;
036: import java.security.PrivilegedActionException;
037: import java.security.PrivilegedExceptionAction;
038: import javax.print.DocFlavor;
039: import javax.print.MultiDocPrintService;
040: import javax.print.PrintService;
041: import javax.print.PrintServiceLookup;
042: import javax.print.attribute.Attribute;
043: import javax.print.attribute.AttributeSet;
044: import javax.print.attribute.HashPrintRequestAttributeSet;
045: import javax.print.attribute.HashPrintServiceAttributeSet;
046: import javax.print.attribute.PrintRequestAttribute;
047: import javax.print.attribute.PrintRequestAttributeSet;
048: import javax.print.attribute.PrintServiceAttribute;
049: import javax.print.attribute.PrintServiceAttributeSet;
050: import javax.print.attribute.standard.PrinterName;
051: import java.io.File;
052: import java.io.FileReader;
053: import java.net.URL;
054:
055: /*
056: * Remind: This class uses solaris commands. We also need a linux
057: * version
058: */
059: public class UnixPrintServiceLookup extends PrintServiceLookup
060: implements BackgroundServiceLookup, Runnable {
061:
062: /* Remind: the current implementation is static, as its assumed
063: * its preferable to minimise creation of PrintService instances.
064: * Later we should add logic to add/remove services on the fly which
065: * will take a hit of needing to regather the list of services.
066: */
067: private String defaultPrinter;
068: private PrintService defaultPrintService;
069: private PrintService[] printServices; /* includes the default printer */
070: private Vector lookupListeners = null;
071: private static String debugPrefix = "UnixPrintServiceLookup>> ";
072: private static boolean pollServices = true;
073: private static final int DEFAULT_MINREFRESH = 120; // 2 minutes
074: private static int minRefreshTime = DEFAULT_MINREFRESH;
075:
076: static String osname;
077:
078: static {
079: /* The system property "sun.java2d.print.polling"
080: * can be used to force the printing code to poll or not poll
081: * for PrintServices.
082: */
083: String pollStr = (String) java.security.AccessController
084: .doPrivileged(new sun.security.action.GetPropertyAction(
085: "sun.java2d.print.polling"));
086:
087: if (pollStr != null) {
088: if (pollStr.equalsIgnoreCase("true")) {
089: pollServices = true;
090: } else if (pollStr.equalsIgnoreCase("false")) {
091: pollServices = false;
092: }
093: }
094:
095: /* The system property "sun.java2d.print.minRefreshTime"
096: * can be used to specify minimum refresh time (in seconds)
097: * for polling PrintServices. The default is 120.
098: */
099: String refreshTimeStr = (String) java.security.AccessController
100: .doPrivileged(new sun.security.action.GetPropertyAction(
101: "sun.java2d.print.minRefreshTime"));
102:
103: if (refreshTimeStr != null) {
104: try {
105: minRefreshTime = (new Integer(refreshTimeStr))
106: .intValue();
107: } catch (NumberFormatException e) {
108: }
109: if (minRefreshTime < DEFAULT_MINREFRESH) {
110: minRefreshTime = DEFAULT_MINREFRESH;
111: }
112: }
113:
114: osname = (String) java.security.AccessController
115: .doPrivileged(new sun.security.action.GetPropertyAction(
116: "os.name"));
117: }
118:
119: static boolean isSysV() {
120: return osname.equals("SunOS");
121: }
122:
123: static boolean isBSD() {
124: return osname.equals("Linux");
125: }
126:
127: static final int UNINITIALIZED = -1;
128: static final int BSD_LPD = 0;
129: static final int BSD_LPD_NG = 1;
130:
131: static int cmdIndex = UNINITIALIZED;
132:
133: String[] lpcFirstCom = {
134: "/usr/sbin/lpc status | grep : | sed -ne '1,1 s/://p'",
135: "/usr/sbin/lpc status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" };
136:
137: String[] lpcAllCom = {
138: "/usr/sbin/lpc status | grep : | sed -e 's/://'",
139: "/usr/sbin/lpc -a status | grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}' | sort" };
140:
141: String[] lpcNameCom = { "| grep : | sed -ne 's/://p'",
142: "| grep -E '^[ 0-9a-zA-Z_-]*@' | awk -F'@' '{print $1}'" };
143:
144: static int getBSDCommandIndex() {
145: String command = "/usr/sbin/lpc status";
146: String[] names = execCmd(command);
147:
148: if ((names == null) || (names.length == 0)) {
149: return BSD_LPD_NG;
150: }
151:
152: for (int i = 0; i < names.length; i++) {
153: if (names[i].indexOf('@') != -1) {
154: return BSD_LPD_NG;
155: }
156: }
157:
158: return BSD_LPD;
159: }
160:
161: public UnixPrintServiceLookup() {
162: // start the printer listener thread
163: if (pollServices) {
164: PrinterChangeListener thr = new PrinterChangeListener();
165: thr.setDaemon(true);
166: thr.start();
167: IPPPrintService.debug_println(debugPrefix
168: + "polling turned on");
169: }
170: }
171:
172: /* Want the PrintService which is default print service to have
173: * equality of reference with the equivalent in list of print services
174: * This isn't required by the API and there's a risk doing this will
175: * lead people to assume its guaranteed.
176: */
177: public synchronized PrintService[] getPrintServices() {
178: SecurityManager security = System.getSecurityManager();
179: if (security != null) {
180: security.checkPrintJobAccess();
181: }
182:
183: if (printServices == null || !pollServices) {
184: refreshServices();
185: }
186: if (printServices == null) {
187: return new PrintService[0];
188: } else {
189: return printServices;
190: }
191: }
192:
193: // refreshes "printServices"
194: public synchronized void refreshServices() {
195: String[] printers; /* excludes the default printer */
196:
197: getDefaultPrintService();
198: if (CUPSPrinter.isCupsRunning()) {
199: printers = CUPSPrinter.getAllPrinters();
200: } else {
201: if (isSysV()) {
202: printers = getAllPrinterNamesSysV();
203: } else { //BSD
204: printers = getAllPrinterNamesBSD();
205: }
206: }
207:
208: if (printers == null) {
209: if (defaultPrintService != null) {
210: printServices = new PrintService[1];
211: printServices[0] = defaultPrintService;
212: } else {
213: printServices = null;
214: }
215: return;
216: }
217:
218: ArrayList printerList = new ArrayList();
219: int defaultIndex = -1;
220: for (int p = 0; p < printers.length; p++) {
221: if (printers[p] == null) {
222: continue;
223: }
224: if ((defaultPrintService != null)
225: && printers[p]
226: .equals(defaultPrintService.getName())) {
227: printerList.add(defaultPrintService);
228: defaultIndex = printerList.size() - 1;
229: } else {
230: if (printServices == null) {
231: IPPPrintService
232: .debug_println(debugPrefix
233: + "total# of printers = "
234: + printers.length);
235:
236: if (CUPSPrinter.isCupsRunning()) {
237: try {
238: URL serviceURL = new URL("http://"
239: + CUPSPrinter.getServer() + ":"
240: + CUPSPrinter.getPort() + "/"
241: + printers[p]);
242: printerList.add(new IPPPrintService(
243: printers[p], serviceURL));
244: } catch (Exception e) {
245: IPPPrintService.debug_println(debugPrefix
246: + " getAllPrinters Exception " + e);
247:
248: }
249: } else {
250: printerList.add(new UnixPrintService(
251: printers[p]));
252: }
253: } else {
254: int j;
255: for (j = 0; j < printServices.length; j++) {
256: if ((printServices[j] != null)
257: && (printers[p].equals(printServices[j]
258: .getName()))) {
259: printerList.add(printServices[j]);
260: printServices[j] = null;
261: break;
262: }
263: }
264:
265: if (j == printServices.length) { // not found?
266: if (CUPSPrinter.isCupsRunning()) {
267: try {
268: URL serviceURL = new URL("http://"
269: + CUPSPrinter.getServer() + ":"
270: + CUPSPrinter.getPort() + "/"
271: + printers[p]);
272: printerList.add(new IPPPrintService(
273: printers[p], serviceURL));
274: } catch (Exception e) {
275: IPPPrintService
276: .debug_println(debugPrefix
277: + " getAllPrinters Exception "
278: + e);
279:
280: }
281: } else {
282: printerList.add(new UnixPrintService(
283: printers[p]));
284: }
285: }
286: }
287: }
288: }
289:
290: // Look for deleted services and invalidate these
291: if (printServices != null) {
292: for (int j = 0; j < printServices.length; j++) {
293: if ((printServices[j] instanceof UnixPrintService)
294: && (!printServices[j]
295: .equals(defaultPrintService))) {
296: ((UnixPrintService) printServices[j])
297: .invalidateService();
298: }
299: }
300: }
301:
302: //if defaultService is not found in printerList
303: if (defaultIndex == -1 && defaultPrintService != null) {
304: //add default to the list
305: printerList.add(defaultPrintService);
306: defaultIndex = printerList.size() - 1;
307: }
308:
309: printServices = (PrintService[]) printerList
310: .toArray(new PrintService[] {});
311:
312: // swap default with the first in the list
313: if (defaultIndex > 0) {
314: PrintService saveService = printServices[0];
315: printServices[0] = printServices[defaultIndex];
316: printServices[defaultIndex] = saveService;
317: }
318: }
319:
320: private boolean matchesAttributes(PrintService service,
321: PrintServiceAttributeSet attributes) {
322:
323: Attribute[] attrs = attributes.toArray();
324: Attribute serviceAttr;
325: for (int i = 0; i < attrs.length; i++) {
326: serviceAttr = service
327: .getAttribute((Class<PrintServiceAttribute>) attrs[i]
328: .getCategory());
329: if (serviceAttr == null || !serviceAttr.equals(attrs[i])) {
330: return false;
331: }
332: }
333: return true;
334: }
335:
336: /* This checks for validity of the printer name before passing as
337: * parameter to a shell command.
338: */
339: private boolean checkPrinterName(String s) {
340: char c;
341:
342: for (int i = 0; i < s.length(); i++) {
343: c = s.charAt(i);
344: if (Character.isLetterOrDigit(c) || c == '-' || c == '_'
345: || c == '.' || c == '/') {
346: continue;
347: } else {
348: return false;
349: }
350: }
351: return true;
352: }
353:
354: /* On a network with many (hundreds) of network printers, it
355: * can save several seconds if you know all you want is a particular
356: * printer, to ask for that printer rather than retrieving all printers.
357: */
358: private PrintService getServiceByName(PrinterName nameAttr) {
359: String name = nameAttr.getValue();
360: PrintService printer = null;
361: if (name == null || name.equals("") || !checkPrinterName(name)) {
362: return null;
363: }
364: if (isSysV()) {
365: printer = getNamedPrinterNameSysV(name);
366: } else {
367: printer = getNamedPrinterNameBSD(name);
368: }
369: return printer;
370: }
371:
372: private PrintService[] getPrintServices(
373: PrintServiceAttributeSet serviceSet) {
374:
375: if (serviceSet == null || serviceSet.isEmpty()) {
376: return getPrintServices();
377: }
378:
379: /* Typically expect that if a service attribute is specified that
380: * its a printer name and there ought to be only one match.
381: * Directly retrieve that service and confirm
382: * that it meets the other requirements.
383: * If printer name isn't mentioned then go a slow path checking
384: * all printers if they meet the reqiremements.
385: */
386: PrintService[] services;
387: PrinterName name = (PrinterName) serviceSet
388: .get(PrinterName.class);
389: PrintService defService;
390: if (name != null
391: && (defService = getDefaultPrintService()) != null) {
392: /* To avoid execing a unix command see if the client is asking
393: * for the default printer by name, since we already have that
394: * initialised.
395: */
396:
397: PrinterName defName = (PrinterName) defService
398: .getAttribute(PrinterName.class);
399:
400: if (defName != null && name.equals(defName)) {
401: if (matchesAttributes(defService, serviceSet)) {
402: services = new PrintService[1];
403: services[0] = defService;
404: return services;
405: } else {
406: return new PrintService[0];
407: }
408: } else {
409: /* Its not the default service */
410: PrintService service = getServiceByName(name);
411: if (service != null
412: && matchesAttributes(service, serviceSet)) {
413: services = new PrintService[1];
414: services[0] = service;
415: return services;
416: } else {
417: return new PrintService[0];
418: }
419: }
420: } else {
421: /* specified service attributes don't include a name.*/
422: Vector matchedServices = new Vector();
423: services = getPrintServices();
424: for (int i = 0; i < services.length; i++) {
425: if (matchesAttributes(services[i], serviceSet)) {
426: matchedServices.add(services[i]);
427: }
428: }
429: services = new PrintService[matchedServices.size()];
430: for (int i = 0; i < services.length; i++) {
431: services[i] = (PrintService) matchedServices
432: .elementAt(i);
433: }
434: return services;
435: }
436: }
437:
438: /*
439: * If service attributes are specified then there must be additional
440: * filtering.
441: */
442: public PrintService[] getPrintServices(DocFlavor flavor,
443: AttributeSet attributes) {
444: SecurityManager security = System.getSecurityManager();
445: if (security != null) {
446: security.checkPrintJobAccess();
447: }
448: PrintRequestAttributeSet requestSet = null;
449: PrintServiceAttributeSet serviceSet = null;
450:
451: if (attributes != null && !attributes.isEmpty()) {
452:
453: requestSet = new HashPrintRequestAttributeSet();
454: serviceSet = new HashPrintServiceAttributeSet();
455:
456: Attribute[] attrs = attributes.toArray();
457: for (int i = 0; i < attrs.length; i++) {
458: if (attrs[i] instanceof PrintRequestAttribute) {
459: requestSet.add(attrs[i]);
460: } else if (attrs[i] instanceof PrintServiceAttribute) {
461: serviceSet.add(attrs[i]);
462: }
463: }
464: }
465:
466: PrintService[] services = getPrintServices(serviceSet);
467: if (services.length == 0) {
468: return services;
469: }
470:
471: if (CUPSPrinter.isCupsRunning()) {
472: ArrayList matchingServices = new ArrayList();
473: for (int i = 0; i < services.length; i++) {
474: try {
475: if (services[i].getUnsupportedAttributes(flavor,
476: requestSet) == null) {
477: matchingServices.add(services[i]);
478: }
479: } catch (IllegalArgumentException e) {
480: }
481: }
482: services = new PrintService[matchingServices.size()];
483: return (PrintService[]) matchingServices.toArray(services);
484:
485: } else {
486: // We only need to compare 1 PrintService because all
487: // UnixPrintServices are the same anyway. We will not use
488: // default PrintService because it might be null.
489: PrintService service = services[0];
490: if ((flavor == null || service.isDocFlavorSupported(flavor))
491: && service.getUnsupportedAttributes(flavor,
492: requestSet) == null) {
493: return services;
494: } else {
495: return new PrintService[0];
496: }
497: }
498: }
499:
500: /*
501: * return empty array as don't support multi docs
502: */
503: public MultiDocPrintService[] getMultiDocPrintServices(
504: DocFlavor[] flavors, AttributeSet attributes) {
505: SecurityManager security = System.getSecurityManager();
506: if (security != null) {
507: security.checkPrintJobAccess();
508: }
509: return new MultiDocPrintService[0];
510: }
511:
512: public synchronized PrintService getDefaultPrintService() {
513: SecurityManager security = System.getSecurityManager();
514: if (security != null) {
515: security.checkPrintJobAccess();
516: }
517:
518: // clear defaultPrintService
519: defaultPrintService = null;
520:
521: IPPPrintService.debug_println("isRunning ? "
522: + (CUPSPrinter.isCupsRunning()));
523: if (CUPSPrinter.isCupsRunning()) {
524: defaultPrinter = CUPSPrinter.getDefaultPrinter();
525: } else {
526: if (isSysV()) {
527: defaultPrinter = getDefaultPrinterNameSysV();
528: } else {
529: defaultPrinter = getDefaultPrinterNameBSD();
530: }
531: }
532: if (defaultPrinter == null) {
533: return null;
534: }
535: defaultPrintService = null;
536: if (printServices != null) {
537: for (int j = 0; j < printServices.length; j++) {
538: if (defaultPrinter.equals(printServices[j].getName())) {
539: defaultPrintService = printServices[j];
540: break;
541: }
542: }
543: }
544: if (defaultPrintService == null) {
545: if (CUPSPrinter.isCupsRunning()) {
546: try {
547: PrintService defaultPS = new IPPPrintService(
548: defaultPrinter, new URL("http://"
549: + CUPSPrinter.getServer() + ":"
550: + CUPSPrinter.getPort() + "/"
551: + defaultPrinter));
552: defaultPrintService = defaultPS;
553: } catch (Exception e) {
554: }
555: } else {
556: defaultPrintService = new UnixPrintService(
557: defaultPrinter);
558: }
559: }
560:
561: return defaultPrintService;
562: }
563:
564: public synchronized void getServicesInbackground(
565: BackgroundLookupListener listener) {
566: if (printServices != null) {
567: listener.notifyServices(printServices);
568: } else {
569: if (lookupListeners == null) {
570: lookupListeners = new Vector();
571: lookupListeners.add(listener);
572: Thread lookupThread = new Thread(this );
573: lookupThread.start();
574: } else {
575: lookupListeners.add(listener);
576: }
577: }
578: }
579:
580: /* This method isn't used in most cases because we rely on code in
581: * javax.print.PrintServiceLookup. This is needed just for the cases
582: * where those interfaces are by-passed.
583: */
584: private PrintService[] copyOf(PrintService[] inArr) {
585: if (inArr == null || inArr.length == 0) {
586: return inArr;
587: } else {
588: PrintService[] outArr = new PrintService[inArr.length];
589: System.arraycopy(inArr, 0, outArr, 0, inArr.length);
590: return outArr;
591: }
592: }
593:
594: public void run() {
595: PrintService[] services = getPrintServices();
596: synchronized (this ) {
597: BackgroundLookupListener listener;
598: for (int i = 0; i < lookupListeners.size(); i++) {
599: listener = (BackgroundLookupListener) lookupListeners
600: .elementAt(i);
601: listener.notifyServices(copyOf(services));
602: }
603: lookupListeners = null;
604: }
605: }
606:
607: private String getDefaultPrinterNameBSD() {
608: if (cmdIndex == UNINITIALIZED) {
609: cmdIndex = getBSDCommandIndex();
610: }
611: String[] names = execCmd(lpcFirstCom[cmdIndex]);
612: if (names == null || names.length == 0) {
613: return null;
614: }
615:
616: if ((cmdIndex == BSD_LPD_NG)
617: && (names[0].startsWith("missingprinter"))) {
618: return null;
619: }
620: return names[0];
621: }
622:
623: private PrintService getNamedPrinterNameBSD(String name) {
624: if (cmdIndex == UNINITIALIZED) {
625: cmdIndex = getBSDCommandIndex();
626: }
627: String command = "/usr/sbin/lpc status " + name
628: + lpcNameCom[cmdIndex];
629: String[] result = execCmd(command);
630:
631: if (result == null || !(result[0].equals(name))) {
632: return null;
633: }
634: return new UnixPrintService(name);
635: }
636:
637: private String[] getAllPrinterNamesBSD() {
638: if (cmdIndex == UNINITIALIZED) {
639: cmdIndex = getBSDCommandIndex();
640: }
641: String[] names = execCmd(lpcAllCom[cmdIndex]);
642: if (names == null || names.length == 0) {
643: return null;
644: }
645: return names;
646: }
647:
648: private String getDefaultPrinterNameSysV() {
649: String defaultPrinter = "lp";
650: String command = "/usr/bin/lpstat -d";
651:
652: String[] names = execCmd(command);
653: if (names == null || names.length == 0) {
654: return defaultPrinter;
655: } else {
656: int index = names[0].indexOf(":");
657: if (index == -1 || (names[0].length() <= index + 1)) {
658: return null;
659: } else {
660: String name = names[0].substring(index + 1).trim();
661: if (name.length() == 0) {
662: return null;
663: } else {
664: return name;
665: }
666: }
667: }
668: }
669:
670: private PrintService getNamedPrinterNameSysV(String name) {
671:
672: String command = "/usr/bin/lpstat -v " + name;
673: String[] result = execCmd(command);
674:
675: if (result == null || result[0].indexOf("unknown printer") > 0) {
676: return null;
677: } else {
678: return new UnixPrintService(name);
679: }
680: }
681:
682: private String[] getAllPrinterNamesSysV() {
683: String defaultPrinter = "lp";
684: String command = "/usr/bin/lpstat -v|/usr/bin/expand|/usr/bin/cut -f3 -d' ' |/usr/bin/cut -f1 -d':' | /usr/bin/sort";
685:
686: String[] names = execCmd(command);
687: ArrayList printerNames = new ArrayList();
688: for (int i = 0; i < names.length; i++) {
689: if (!names[i].equals("_default")
690: && !names[i].equals(defaultPrinter)
691: && !names[i].equals("")) {
692: printerNames.add(names[i]);
693: }
694: }
695: return (String[]) printerNames.toArray(new String[printerNames
696: .size()]);
697: }
698:
699: static String[] execCmd(final String command) {
700: ArrayList results = null;
701: try {
702: final String[] cmd = new String[3];
703: if (isSysV()) {
704: cmd[0] = "/usr/bin/sh";
705: cmd[1] = "-c";
706: cmd[2] = "env LC_ALL=C " + command;
707: } else {
708: cmd[0] = "/bin/sh";
709: cmd[1] = "-c";
710: cmd[2] = "LC_ALL=C " + command;
711: }
712:
713: results = (ArrayList) AccessController
714: .doPrivileged(new PrivilegedExceptionAction() {
715: public Object run() throws IOException {
716:
717: Process proc;
718: BufferedReader bufferedReader = null;
719: File f = File.createTempFile("prn", "xc");
720: cmd[2] = cmd[2] + ">" + f.getAbsolutePath();
721:
722: proc = Runtime.getRuntime().exec(cmd);
723: try {
724: boolean done = false; // in case of interrupt.
725: while (!done) {
726: try {
727: proc.waitFor();
728: done = true;
729: } catch (InterruptedException e) {
730: }
731: }
732:
733: if (proc.exitValue() == 0) {
734: FileReader reader = new FileReader(
735: f);
736: bufferedReader = new BufferedReader(
737: reader);
738: String line;
739: ArrayList results = new ArrayList();
740: while ((line = bufferedReader
741: .readLine()) != null) {
742: results.add(line);
743: }
744: return results;
745: }
746: } finally {
747: f.delete();
748: // promptly close all streams.
749: if (bufferedReader != null) {
750: bufferedReader.close();
751: }
752: proc.getInputStream().close();
753: proc.getErrorStream().close();
754: proc.getOutputStream().close();
755: }
756: return null;
757: }
758: });
759: } catch (PrivilegedActionException e) {
760: }
761: if (results == null) {
762: return new String[0];
763: } else {
764: return (String[]) results
765: .toArray(new String[results.size()]);
766: }
767: }
768:
769: private class PrinterChangeListener extends Thread {
770:
771: public void run() {
772: int refreshSecs;
773: while (true) {
774: try {
775: refreshServices();
776: } catch (Exception se) {
777: IPPPrintService.debug_println(debugPrefix
778: + "Exception in refresh thread.");
779: break;
780: }
781:
782: if ((printServices != null)
783: && (printServices.length > minRefreshTime)) {
784: // compute new refresh time 1 printer = 1 sec
785: refreshSecs = printServices.length;
786: } else {
787: refreshSecs = minRefreshTime;
788: }
789: try {
790: sleep(refreshSecs * 1000);
791: } catch (InterruptedException e) {
792: break;
793: }
794: }
795: }
796: }
797: }
|