300 // Not the same as default so proceed to get new PrintService. 301 302 // clear defaultPrintService 303 defaultPrintService = null; 304 305 if (printServices != null) { 306 for (int j=0; j<printServices.length; j++) { 307 if (defaultPrinter.equals(printServices[j].getName())) { 308 defaultPrintService = printServices[j]; 309 break; 310 } 311 } 312 } 313 314 if (defaultPrintService == null) { 315 defaultPrintService = new Win32PrintService(defaultPrinter); 316 } 317 return defaultPrintService; 318 } 319 320 class PrinterChangeListener implements Runnable { 321 long chgObj; 322 PrinterChangeListener() { 323 chgObj = notifyFirstPrinterChange(null); 324 } 325 326 @Override 327 public void run() { 328 if (chgObj != -1) { 329 while (true) { 330 // wait for configuration to change 331 if (notifyPrinterChange(chgObj) != 0) { 332 try { 333 refreshServices(); 334 } catch (SecurityException se) { 335 break; 336 } 337 } else { 338 notifyClosePrinterChange(chgObj); 339 break; 340 } 341 } 342 } 343 } 344 } 345 346 private native String getDefaultPrinterName(); 347 private native String[] getAllPrinterNames(); 348 private native long notifyFirstPrinterChange(String printer); 349 private native void notifyClosePrinterChange(long chgObj); 350 private native int notifyPrinterChange(long chgObj); 351 } | 300 // Not the same as default so proceed to get new PrintService. 301 302 // clear defaultPrintService 303 defaultPrintService = null; 304 305 if (printServices != null) { 306 for (int j=0; j<printServices.length; j++) { 307 if (defaultPrinter.equals(printServices[j].getName())) { 308 defaultPrintService = printServices[j]; 309 break; 310 } 311 } 312 } 313 314 if (defaultPrintService == null) { 315 defaultPrintService = new Win32PrintService(defaultPrinter); 316 } 317 return defaultPrintService; 318 } 319 320 /* Windows provides *PrinterChangeNotification* functions that provides 321 information about printer status changes of the local printers but not 322 network printers. 323 Alternatively, Windows provides a way thro' which one can get the 324 network printer status changes by using WMI, RegistryKeyChange combination, 325 which is a slightly complex mechanism. 326 The Windows WMI offers an async and sync method to read thro' registry 327 via the WQL query. The async method is considered dangerous as it leaves 328 open a channel until we close it. But the async method has the advantage of 329 being notified of a change in registry by calling callback without polling for it. 330 The sync method uses the polling mechanism to notify. 331 RegistryValueChange cannot be used in combination with WMI to get registry 332 value change notification because of an error that may be generated because the 333 scope of the query would be too big to handle(at times). 334 Hence an alternative mechanism is choosen via the EnumPrinters by polling for the 335 count of printer status changes(add\remove) and based on it update the printers 336 list. 337 */ 338 class PrinterChangeListener implements Runnable { 339 long prevRemotePrintersCount = 0; 340 341 PrinterChangeListener() { 342 prevRemotePrintersCount = GetRemotePrintersCount(); 343 } 344 345 @Override 346 public void run() { 347 while(true) { 348 long currentRemotePrintersCount = GetRemotePrintersCount(); 349 if(prevRemotePrintersCount != currentRemotePrintersCount) { 350 351 // updated the printers data 352 // printers list now contains both local and network printer data 353 refreshServices(); 354 355 // store the current data for next comparison 356 prevRemotePrintersCount = currentRemotePrintersCount; 357 } 358 } 359 } 360 } 361 362 private native String getDefaultPrinterName(); 363 private native String[] getAllPrinterNames(); 364 private native long GetRemotePrintersCount(); 365 } |