386
387 /* Windows provides *PrinterChangeNotification* functions that provides
388 information about printer status changes of the local printers but not
389 network printers.
390 Alternatively, Windows provides a way thro' which one can get the
391 network printer status changes by using WMI, RegistryKeyChange combination,
392 which is a slightly complex mechanism.
393 The Windows WMI offers an async and sync method to read thro' registry
394 via the WQL query. The async method is considered dangerous as it leaves
395 open a channel until we close it. But the async method has the advantage of
396 being notified of a change in registry by calling callback without polling for it.
397 The sync method uses the polling mechanism to notify.
398 RegistryValueChange cannot be used in combination with WMI to get registry
399 value change notification because of an error that may be generated because the
400 scope of the query would be too big to handle(at times).
401 Hence an alternative mechanism is choosen via the EnumPrinters by polling for the
402 count of printer status changes(add\remove) and based on it update the printers
403 list.
404 */
405 class RemotePrinterChangeListener implements Runnable {
406 private String[] prevRemotePrinters;
407
408 RemotePrinterChangeListener() {
409 prevRemotePrinters = getRemotePrintersNames();
410 }
411
412 boolean doCompare(String[] str1, String[] str2) {
413 if (str1.length != str2.length) {
414 return true;
415 } else {
416 for (int i = 0;i < str1.length;i++) {
417 for (int j = 0;j < str2.length;j++) {
418 if (!str1[i].equals(str2[j])) {
419 return true;
420 }
421 }
422 }
423 }
424
425 return false;
426 }
427
428 @Override
429 public void run() {
430 while (true) {
431 String[] currentRemotePrinters = getRemotePrintersNames();
432 if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
433
434 // updated the printers data
435 // printers list now contains both local and network printer data
436 refreshServices();
437
438 // store the current data for next comparison
439 prevRemotePrinters = currentRemotePrinters;
440 }
441
442 try {
443 Thread.sleep(minRefreshTime * 1000);
444 } catch (InterruptedException e) {
445 break;
446 }
447 }
448 }
449 }
450
451 private native String getDefaultPrinterName();
452 private native String[] getAllPrinterNames();
453 private native long notifyFirstPrinterChange(String printer);
454 private native void notifyClosePrinterChange(long chgObj);
455 private native int notifyPrinterChange(long chgObj);
456 private native String[] getRemotePrintersNames();
457 }
|
386
387 /* Windows provides *PrinterChangeNotification* functions that provides
388 information about printer status changes of the local printers but not
389 network printers.
390 Alternatively, Windows provides a way thro' which one can get the
391 network printer status changes by using WMI, RegistryKeyChange combination,
392 which is a slightly complex mechanism.
393 The Windows WMI offers an async and sync method to read thro' registry
394 via the WQL query. The async method is considered dangerous as it leaves
395 open a channel until we close it. But the async method has the advantage of
396 being notified of a change in registry by calling callback without polling for it.
397 The sync method uses the polling mechanism to notify.
398 RegistryValueChange cannot be used in combination with WMI to get registry
399 value change notification because of an error that may be generated because the
400 scope of the query would be too big to handle(at times).
401 Hence an alternative mechanism is choosen via the EnumPrinters by polling for the
402 count of printer status changes(add\remove) and based on it update the printers
403 list.
404 */
405 class RemotePrinterChangeListener implements Runnable {
406 private String[] prevRemotePrinters = null;
407
408 RemotePrinterChangeListener() {
409 prevRemotePrinters = getRemotePrintersNames();
410 }
411
412 boolean doCompare(String[] str1, String[] str2) {
413 if (str1 == null && str2 == null) {
414 return false;
415 } else if (str1 == null || str2 == null) {
416 return true;
417 }
418
419 if (str1.length != str2.length) {
420 return true;
421 } else {
422 for (int i = 0;i < str1.length;i++) {
423 for (int j = 0;j < str2.length;j++) {
424 // skip if both are nulls
425 if (str1[i] == null && str2[j] == null) {
426 continue;
427 }
428
429 // return true if there is a 'difference' but
430 // no need to access the individual string
431 if (str1[i] == null || str2[j] == null) {
432 return true;
433 }
434
435 // do comparison only if they are non-nulls
436 if (!str1[i].equals(str2[j])) {
437 return true;
438 }
439 }
440 }
441 }
442
443 return false;
444 }
445
446 @Override
447 public void run() {
448 while (true) {
449 if (prevRemotePrinters != null && prevRemotePrinters.length > 0) {
450 String[] currentRemotePrinters = getRemotePrintersNames();
451 if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
452
453 // updated the printers data
454 // printers list now contains both local and network printer data
455 refreshServices();
456
457 // store the current data for next comparison
458 prevRemotePrinters = currentRemotePrinters;
459 }
460 } else {
461 prevRemotePrinters = getRemotePrintersNames();
462 }
463
464 try {
465 Thread.sleep(minRefreshTime * 1000);
466 } catch (InterruptedException e) {
467 break;
468 }
469 }
470 }
471 }
472
473 private native String getDefaultPrinterName();
474 private native String[] getAllPrinterNames();
475 private native long notifyFirstPrinterChange(String printer);
476 private native void notifyClosePrinterChange(long chgObj);
477 private native int notifyPrinterChange(long chgObj);
478 private native String[] getRemotePrintersNames();
479 }
|