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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,14 +25,8 @@
|
||||||
|
|
||||||
package sun.print;
|
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.AccessController;
|
||||||
import java.security.PrivilegedActionException;
|
import java.util.ArrayList;
|
||||||
import java.security.PrivilegedExceptionAction;
|
|
||||||
import javax.print.DocFlavor;
|
import javax.print.DocFlavor;
|
||||||
import javax.print.MultiDocPrintService;
|
import javax.print.MultiDocPrintService;
|
||||||
import javax.print.PrintService;
|
import javax.print.PrintService;
|
||||||
|
@ -81,8 +75,9 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
||||||
|
|
||||||
if (refreshTimeStr != null) {
|
if (refreshTimeStr != null) {
|
||||||
try {
|
try {
|
||||||
minRefreshTime = (Integer.valueOf(refreshTimeStr)).intValue();
|
minRefreshTime = Integer.parseInt(refreshTimeStr);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
if (minRefreshTime < DEFAULT_MINREFRESH) {
|
if (minRefreshTime < DEFAULT_MINREFRESH) {
|
||||||
minRefreshTime = DEFAULT_MINREFRESH;
|
minRefreshTime = DEFAULT_MINREFRESH;
|
||||||
|
@ -358,6 +353,7 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
||||||
}
|
}
|
||||||
return defaultPrintService;
|
return defaultPrintService;
|
||||||
}
|
}
|
||||||
|
|
||||||
class PrinterChangeListener implements Runnable {
|
class PrinterChangeListener implements Runnable {
|
||||||
long chgObj;
|
long chgObj;
|
||||||
PrinterChangeListener() {
|
PrinterChangeListener() {
|
||||||
|
@ -387,10 +383,10 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
||||||
/* Windows provides *PrinterChangeNotification* functions that provides
|
/* Windows provides *PrinterChangeNotification* functions that provides
|
||||||
information about printer status changes of the local printers but not
|
information about printer status changes of the local printers but not
|
||||||
network printers.
|
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,
|
network printer status changes by using WMI, RegistryKeyChange combination,
|
||||||
which is a slightly complex mechanism.
|
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
|
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
|
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.
|
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
|
RegistryValueChange cannot be used in combination with WMI to get registry
|
||||||
value change notification because of an error that may be generated because the
|
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).
|
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
|
count of printer status changes(add\remove) and based on it update the printers
|
||||||
list.
|
list.
|
||||||
*/
|
*/
|
||||||
class RemotePrinterChangeListener implements Runnable {
|
class RemotePrinterChangeListener implements Runnable {
|
||||||
private String[] prevRemotePrinters = null;
|
private String[] prevRemotePrinters;
|
||||||
|
|
||||||
RemotePrinterChangeListener() {
|
RemotePrinterChangeListener() {
|
||||||
prevRemotePrinters = getRemotePrintersNames();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean doCompare(String[] str1, String[] str2) {
|
private boolean doCompare(String[] str1, String[] str2) {
|
||||||
if (str1 == null && str2 == null) {
|
if (str1 == null && str2 == null) {
|
||||||
return false;
|
return false;
|
||||||
} else if (str1 == null || str2 == null) {
|
} else if (str1 == null || str2 == null) {
|
||||||
|
@ -445,27 +440,26 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (true) {
|
// Init the list of remote printers
|
||||||
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 {
|
|
||||||
prevRemotePrinters = getRemotePrintersNames();
|
prevRemotePrinters = getRemotePrintersNames();
|
||||||
}
|
|
||||||
|
|
||||||
|
while (true) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(minRefreshTime * 1000);
|
Thread.sleep(minRefreshTime * 1000);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
break;
|
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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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
|
static jobjectArray getPrinterNames(JNIEnv *env, DWORD flags) {
|
||||||
Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
|
|
||||||
jobject peer)
|
|
||||||
{
|
|
||||||
TRY;
|
TRY;
|
||||||
|
|
||||||
DWORD cbNeeded = 0;
|
DWORD cbNeeded = 0;
|
||||||
|
@ -136,10 +133,10 @@ Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
|
||||||
jobjectArray nameArray;
|
jobjectArray nameArray;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
|
::EnumPrinters(flags,
|
||||||
NULL, 4, NULL, 0, &cbNeeded, &cReturned);
|
NULL, 4, NULL, 0, &cbNeeded, &cReturned);
|
||||||
pPrinterEnum = new BYTE[cbNeeded];
|
pPrinterEnum = new BYTE[cbNeeded];
|
||||||
::EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS,
|
::EnumPrinters(flags,
|
||||||
NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded,
|
NULL, 4, pPrinterEnum, cbNeeded, &cbNeeded,
|
||||||
&cReturned);
|
&cReturned);
|
||||||
|
|
||||||
|
@ -174,6 +171,20 @@ Java_sun_print_PrintServiceLookupProvider_getAllPrinterNames(JNIEnv *env,
|
||||||
CATCH_BAD_ALLOC_RET(NULL);
|
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
|
JNIEXPORT jlong JNICALL
|
||||||
Java_sun_print_PrintServiceLookupProvider_notifyFirstPrinterChange(JNIEnv *env,
|
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
|
JNIEXPORT jfloatArray JNICALL
|
||||||
Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env,
|
Java_sun_print_Win32PrintService_getMediaPrintableArea(JNIEnv *env,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue