mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
8221412: lookupPrintServices() does not always update the list of Windows remote printers
Reviewed-by: prr, serb
This commit is contained in:
parent
21e9b4d59f
commit
f883ffee64
2 changed files with 45 additions and 116 deletions
|
@ -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.util.ArrayList;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import javax.print.DocFlavor;
|
||||
import javax.print.MultiDocPrintService;
|
||||
import javax.print.PrintService;
|
||||
|
@ -81,8 +75,9 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
|
||||
if (refreshTimeStr != null) {
|
||||
try {
|
||||
minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
|
||||
minRefreshTime = Integer.parseInt(refreshTimeStr);
|
||||
} catch (NumberFormatException e) {
|
||||
// ignore
|
||||
}
|
||||
if (minRefreshTime < DEFAULT_MINREFRESH) {
|
||||
minRefreshTime = DEFAULT_MINREFRESH;
|
||||
|
@ -358,6 +353,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
}
|
||||
return defaultPrintService;
|
||||
}
|
||||
|
||||
class PrinterChangeListener implements Runnable {
|
||||
long chgObj;
|
||||
PrinterChangeListener() {
|
||||
|
@ -387,10 +383,10 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
/* 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 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
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 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
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 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
if (prevRemotePrinters != null && prevRemotePrinters.length > 0) {
|
||||
String[] currentRemotePrinters = getRemotePrintersNames();
|
||||
if (doCompare(prevRemotePrinters, currentRemotePrinters)) {
|
||||
|
||||
// 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 {
|
||||
// Init the list of remote printers
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@ Java_sun_print_PrintServiceLookupProvider_getDefaultPrinterName(JNIEnv *env,
|
|||
}
|
||||
|
||||
|
||||
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 @@ Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
|
|||
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 @@ Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
|
|||
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 @@ Java_sun_print_PrintServiceLookupProvider_notifyPrinterChange(JNIEnv *env,
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue