提交 7d6192ab 编写于 作者: A aivanov

8221412: lookupPrintServices() does not always update the list of Windows remote printers

Reviewed-by: prr, serb
上级 f6182c3e
/* /*
* Copyright (c) 2000, 2012, 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 @@ ...@@ -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 { ...@@ -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;
...@@ -384,10 +379,10 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { ...@@ -384,10 +379,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.
...@@ -395,18 +390,18 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { ...@@ -395,18 +390,18 @@ 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 extends Thread { class RemotePrinterChangeListener extends Thread {
private String[] prevRemotePrinters = null; private String[] prevRemotePrinters;
RemotePrinterChangeListener() { RemotePrinterChangeListener() {
prevRemotePrinters = getRemotePrintersNames(); 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) {
...@@ -416,8 +411,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { ...@@ -416,8 +411,8 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
if (str1.length != str2.length) { if (str1.length != str2.length) {
return true; return true;
} else { } else {
for (int i = 0;i < str1.length;i++) { for (int i = 0; i < str1.length; i++) {
for (int j = 0;j < str2.length;j++) { for (int j = 0; j < str2.length; j++) {
// skip if both are nulls // skip if both are nulls
if (str1[i] == null && str2[j] == null) { if (str1[i] == null && str2[j] == null) {
continue; continue;
...@@ -442,27 +437,26 @@ public class PrintServiceLookupProvider extends PrintServiceLookup { ...@@ -442,27 +437,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) { prevRemotePrinters = getRemotePrintersNames();
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();
}
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;
}
} }
} }
} }
......
/* /*
* Copyright (c) 2000, 2014, 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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册