提交 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.
*
* 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;
......@@ -384,10 +379,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.
......@@ -395,18 +390,18 @@ 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 extends Thread {
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) {
......@@ -416,8 +411,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;
......@@ -442,27 +437,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 {
prevRemotePrinters = getRemotePrintersNames();
}
// 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;
}
}
}
}
......
/*
* 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.
*
* 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,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册