OpenJDK / jdk / jdk
changeset 54400:31c35004f300
8221412: lookupPrintServices() does not always update the list of Windows remote printers
Reviewed-by: prr, serb
author | aivanov |
---|---|
date | Thu, 28 Mar 2019 14:52:41 +0000 |
parents | b10e1f4f8b69 |
children | 3a217bbdd3a2 |
files | src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp |
diffstat | 2 files changed, 45 insertions(+), 116 deletions(-) [+] |
line wrap: on
line diff
--- a/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java Thu Mar 28 13:49:27 2019 +0530 +++ b/src/java.desktop/windows/classes/sun/print/PrintServiceLookupProvider.java Thu Mar 28 14:52:41 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,8 @@ package sun.print; -import java.io.BufferedReader; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.IOException; +import java.security.AccessController; import java.util.ArrayList; -import java.security.AccessController; -import java.security.PrivilegedActionException; -import java.security.PrivilegedExceptionAction; import javax.print.DocFlavor; import javax.print.MultiDocPrintService; import javax.print.PrintService; @@ -81,8 +75,9 @@ if (refreshTimeStr != null) { try { - minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue(); + minRefreshTime = Integer.parseInt(refreshTimeStr); } catch (NumberFormatException e) { + // ignore } if (minRefreshTime < DEFAULT_MINREFRESH) { minRefreshTime = DEFAULT_MINREFRESH; @@ -139,7 +134,7 @@ if (pollServices) { // start the remote printer listener thread Thread remThr = new Thread(null, new RemotePrinterChangeListener(), - "RemotePrinterListener", 0, false); + "RemotePrinterListener", 0, false); remThr.setDaemon(true); remThr.start(); } @@ -358,6 +353,7 @@ } return defaultPrintService; } + class PrinterChangeListener implements Runnable { long chgObj; PrinterChangeListener() { @@ -387,10 +383,10 @@ /* Windows provides *PrinterChangeNotification* functions that provides information about printer status changes of the local printers but not network printers. - Alternatively, Windows provides a way thro' which one can get the + Alternatively, Windows provides a way through which one can get the network printer status changes by using WMI, RegistryKeyChange combination, which is a slightly complex mechanism. - The Windows WMI offers an async and sync method to read thro' registry + The Windows WMI offers an async and sync method to read through registry via the WQL query. The async method is considered dangerous as it leaves open a channel until we close it. But the async method has the advantage of being notified of a change in registry by calling callback without polling for it. @@ -398,18 +394,17 @@ RegistryValueChange cannot be used in combination with WMI to get registry value change notification because of an error that may be generated because the scope of the query would be too big to handle(at times). - Hence an alternative mechanism is choosen via the EnumPrinters by polling for the + Hence an alternative mechanism is chosen via the EnumPrinters by polling for the count of printer status changes(add\remove) and based on it update the printers list. */ class RemotePrinterChangeListener implements Runnable { - private String[] prevRemotePrinters = null; + private String[] prevRemotePrinters; RemotePrinterChangeListener() { - prevRemotePrinters = getRemotePrintersNames(); } - boolean doCompare(String[] str1, String[] str2) { + private boolean doCompare(String[] str1, String[] str2) { if (str1 == null && str2 == null) { return false; } else if (str1 == null || str2 == null) { @@ -419,8 +414,8 @@ if (str1.length != str2.length) { return true; } else { - for (int i = 0;i < str1.length;i++) { - for (int j = 0;j < str2.length;j++) { + for (int i = 0; i < str1.length; i++) { + for (int j = 0; j < str2.length; j++) { // skip if both are nulls if (str1[i] == null && str2[j] == null) { continue; @@ -445,27 +440,26 @@ @Override public void run() { - while (true) { - if (prevRemotePrinters != null && prevRemotePrinters.length > 0) { - String[] currentRemotePrinters = getRemotePrintersNames(); - if (doCompare(prevRemotePrinters, currentRemotePrinters)) { + // Init the list of remote printers + prevRemotePrinters = getRemotePrintersNames(); - // updated the printers data - // printers list now contains both local and network printer data - refreshServices(); - - // store the current data for next comparison - prevRemotePrinters = currentRemotePrinters; - } - } else { - prevRemotePrinters = getRemotePrintersNames(); - } - + while (true) { try { Thread.sleep(minRefreshTime * 1000); } catch (InterruptedException e) { break; } + + String[] currentRemotePrinters = getRemotePrintersNames(); + if (doCompare(prevRemotePrinters, currentRemotePrinters)) { + // The list of remote printers got updated, + // so update the cached list printers which + // includes both local and network printers + refreshServices(); + + // store the current data for next comparison + prevRemotePrinters = currentRemotePrinters; + } } } }
--- a/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp Thu Mar 28 13:49:27 2019 +0530 +++ b/src/java.desktop/windows/native/libawt/windows/WPrinterJob.cpp Thu Mar 28 14:52:41 2019 +0000 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -118,10 +118,7 @@ } -JNIEXPORT jobjectArray JNICALL -Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env, - jobject peer) -{ +static jobjectArray getPrinterNames(JNIEnv *env, DWORD flags) { TRY; DWORD cbNeeded = 0; @@ -136,10 +133,10 @@ jobjectArray nameArray; try { - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + ::EnumPrinters(flags, NULL, 4, NULL, 0, &cbNeeded, &cReturned); pPrinterEnum = new BYTE[cbNeeded]; - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, + ::EnumPrinters(flags, NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded, &cReturned); @@ -174,6 +171,20 @@ CATCH_BAD_ALLOC_RET(NULL); } +JNIEXPORT jobjectArray JNICALL +Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env, + jobject peer) +{ + return getPrinterNames(env, PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS); +} + +JNIEXPORT jobjectArray JNICALL +Java_sun_print_PrintServiceLookupProvider_getRemotePrintersNames(JNIEnv *env, + jobject peer) +{ + return getPrinterNames(env, PRINTER_ENUM_CONNECTIONS); +} + JNIEXPORT jlong JNICALL Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv *env, @@ -232,82 +243,6 @@ } } -JNIEXPORT jobjectArray JNICALL -Java_sun_print_PrintServiceLookupProvider_getRemotePrintersNames(JNIEnv *env, - jobject peer) -{ - TRY; - - int remotePrintersCount = 0; - DWORD cbNeeded = 0; - DWORD cReturned = 0; - LPBYTE pPrinterEnum = NULL; - LPBYTE pNetworkPrinterLoc = NULL; - - jstring utf_str; - jclass clazz = env->FindClass("java/lang/String"); - if (clazz == NULL) { - return NULL; - } - jobjectArray nameArray = NULL; - - try { - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - NULL, 4, NULL, 0, &cbNeeded, &cReturned); - pPrinterEnum = new BYTE[cbNeeded]; - pNetworkPrinterLoc = new BYTE[cbNeeded/sizeof(PRINTER_INFO_4)]; - ::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, - NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded, - &cReturned); - - if (cReturned > 0) { - for (DWORD i = 0; i < cReturned; i++) { - PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) (pPrinterEnum + i * sizeof(PRINTER_INFO_4)); - - // Store the network printers indexes - if (info4->Attributes & PRINTER_ATTRIBUTE_NETWORK) { - pNetworkPrinterLoc[remotePrintersCount++] = i; - } - } - - // return remote printers only if the list contains it. - if (remotePrintersCount > 0) { - // Allocate space only for the network type printers - nameArray = env->NewObjectArray(remotePrintersCount, clazz, NULL); - if (nameArray == NULL) { - throw std::bad_alloc(); - } - } - } - - // Loop thro' network printers list only - for (int i = 0; i < remotePrintersCount; i++) { - PRINTER_INFO_4 *info4 = (PRINTER_INFO_4 *) - (pPrinterEnum + pNetworkPrinterLoc[i] * sizeof(PRINTER_INFO_4)); - utf_str = JNU_NewStringPlatform(env, info4->pPrinterName); - if (utf_str == NULL) { - throw std::bad_alloc(); - } - env->SetObjectArrayElement(nameArray, i, utf_str); - env->DeleteLocalRef(utf_str); - } - } catch (std::bad_alloc&) { - delete [] pPrinterEnum; - delete [] pNetworkPrinterLoc; - throw; - } - - delete [] pPrinterEnum; - delete [] pNetworkPrinterLoc; - - if (nameArray != NULL) { - return nameArray; - } else { - return env->NewObjectArray(0, clazz, NULL); - } - - CATCH_BAD_ALLOC_RET(NULL); -} JNIEXPORT jfloatArray JNICALL Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env,