Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
2ef257ad
D
dragonwell8_jdk
项目概览
openanolis
/
dragonwell8_jdk
通知
4
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dragonwell8_jdk
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
2ef257ad
编写于
6月 25, 2018
作者:
S
sveerabhadra
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
8153732: Windows remote printer changes do not reflect in lookupPrintServices()
Reviewed-by: prr, psadhukhan
上级
242cf2e0
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
442 addition
and
2 deletion
+442
-2
src/windows/classes/sun/print/PrintServiceLookupProvider.java
...windows/classes/sun/print/PrintServiceLookupProvider.java
+108
-2
src/windows/native/sun/windows/WPrinterJob.cpp
src/windows/native/sun/windows/WPrinterJob.cpp
+70
-0
test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java
...emotePrinterStatusRefresh/RemotePrinterStatusRefresh.java
+264
-0
未找到文件。
src/windows/classes/sun/print/PrintServiceLookupProvider.java
浏览文件 @
2ef257ad
...
...
@@ -53,8 +53,42 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
private
PrintService
defaultPrintService
;
private
String
[]
printers
;
/* excludes the default printer */
private
PrintService
[]
printServices
;
/* includes the default printer */
private
static
boolean
pollServices
=
true
;
private
static
final
int
DEFAULT_MINREFRESH
=
240
;
// 4 minutes
private
static
int
minRefreshTime
=
DEFAULT_MINREFRESH
;
static
{
/* The system property "sun.java2d.print.polling"
* can be used to force the printing code to poll or not poll
* for PrintServices.
*/
String
pollStr
=
java
.
security
.
AccessController
.
doPrivileged
(
new
sun
.
security
.
action
.
GetPropertyAction
(
"sun.java2d.print.polling"
));
if
(
pollStr
!=
null
)
{
if
(
pollStr
.
equalsIgnoreCase
(
"false"
))
{
pollServices
=
false
;
}
}
/* The system property "sun.java2d.print.minRefreshTime"
* can be used to specify minimum refresh time (in seconds)
* for polling PrintServices. The default is 240.
*/
String
refreshTimeStr
=
java
.
security
.
AccessController
.
doPrivileged
(
new
sun
.
security
.
action
.
GetPropertyAction
(
"sun.java2d.print.minRefreshTime"
));
if
(
refreshTimeStr
!=
null
)
{
try
{
minRefreshTime
=
(
Integer
.
valueOf
(
refreshTimeStr
)).
intValue
();
}
catch
(
NumberFormatException
e
)
{
}
if
(
minRefreshTime
<
DEFAULT_MINREFRESH
)
{
minRefreshTime
=
DEFAULT_MINREFRESH
;
}
}
java
.
security
.
AccessController
.
doPrivileged
(
new
java
.
security
.
PrivilegedAction
<
Void
>()
{
public
Void
run
()
{
...
...
@@ -96,10 +130,17 @@ public class PrintServiceLookupProvider extends PrintServiceLookup {
if
(
osName
!=
null
&&
osName
.
startsWith
(
"Windows 98"
))
{
return
;
}
// start the printer listener thread
PrinterChangeListener
thr
=
new
PrinterChangeListener
();
// start the
local
printer listener thread
Thread
thr
=
new
PrinterChangeListener
();
thr
.
setDaemon
(
true
);
thr
.
start
();
if
(
pollServices
)
{
// start the remote printer listener thread
Thread
remThr
=
new
RemotePrinterChangeListener
();
remThr
.
setDaemon
(
true
);
remThr
.
start
();
}
}
/* else condition ought to never happen! */
}
...
...
@@ -340,9 +381,74 @@ 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
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
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.
The sync method uses the polling mechanism to notify.
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
count of printer status changes(add\remove) and based on it update the printers
list.
*/
class
RemotePrinterChangeListener
extends
Thread
{
private
String
[]
prevRemotePrinters
;
RemotePrinterChangeListener
()
{
prevRemotePrinters
=
getRemotePrintersNames
();
}
boolean
doCompare
(
String
[]
str1
,
String
[]
str2
)
{
if
(
str1
.
length
!=
str2
.
length
)
{
return
true
;
}
else
{
for
(
int
i
=
0
;
i
<
str1
.
length
;
i
++)
{
for
(
int
j
=
0
;
j
<
str2
.
length
;
j
++)
{
if
(!
str1
[
i
].
equals
(
str2
[
j
]))
{
return
true
;
}
}
}
}
return
false
;
}
@Override
public
void
run
()
{
while
(
true
)
{
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
;
}
try
{
Thread
.
sleep
(
minRefreshTime
*
1000
);
}
catch
(
InterruptedException
e
)
{
break
;
}
}
}
}
private
native
String
getDefaultPrinterName
();
private
native
String
[]
getAllPrinterNames
();
private
native
long
notifyFirstPrinterChange
(
String
printer
);
private
native
void
notifyClosePrinterChange
(
long
chgObj
);
private
native
int
notifyPrinterChange
(
long
chgObj
);
private
native
String
[]
getRemotePrintersNames
();
}
src/windows/native/sun/windows/WPrinterJob.cpp
浏览文件 @
2ef257ad
...
...
@@ -232,6 +232,76 @@ 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
;
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
;
}
}
// Allocate space only for the network type printers
nameArray
=
env
->
NewObjectArray
(
remotePrintersCount
,
clazz
,
NULL
);
if
(
nameArray
==
NULL
)
{
throw
std
::
bad_alloc
();
}
}
else
{
nameArray
=
NULL
;
}
// 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
;
return
nameArray
;
CATCH_BAD_ALLOC_RET
(
NULL
);
}
JNIEXPORT
jfloatArray
JNICALL
Java_sun_print_Win32PrintService_getMediaPrintableArea
(
JNIEnv
*
env
,
...
...
test/jdk/java/awt/print/RemotePrinterStatusRefresh/RemotePrinterStatusRefresh.java
0 → 100644
浏览文件 @
2ef257ad
/*
* Copyright (c) 2018, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8153732
* @requires (os.family == "Windows")
* @summary Windows remote printer changes do not reflect in lookupPrintServices()
* @ignore Requires a new network printer installation\removal
* @run main/manual RemotePrinterStatusRefresh
*/
import
java.awt.GridBagConstraints
;
import
java.awt.GridBagLayout
;
import
java.awt.event.ActionEvent
;
import
java.awt.print.PageFormat
;
import
java.awt.print.Paper
;
import
java.awt.print.PrinterException
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
import
javax.swing.BorderFactory
;
import
javax.swing.Box
;
import
javax.swing.JButton
;
import
javax.swing.JFrame
;
import
javax.swing.JLabel
;
import
javax.swing.JPanel
;
import
javax.swing.JTextArea
;
import
javax.swing.SwingUtilities
;
import
java.awt.print.PrinterJob
;
import
javax.print.PrintService
;
public
class
RemotePrinterStatusRefresh
{
private
static
TestUI
test
=
null
;
public
static
void
main
(
String
args
[])
throws
Exception
{
final
CountDownLatch
latch
=
new
CountDownLatch
(
1
);
// Test UI creation
test
=
new
TestUI
(
latch
);
SwingUtilities
.
invokeAndWait
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
test
.
createUI
();
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
}
});
// RemotePrinterStatusRefresh creation
RemotePrinterStatusRefresh
RemotePrinterStatusRefresh
=
new
RemotePrinterStatusRefresh
();
SwingUtilities
.
invokeAndWait
(()
->
{
collectPrintersList
(
test
.
resultsTextArea
,
true
);
});
// 8 min = 480000 msec
if
(
waitForFlag
(
480000
))
{
SwingUtilities
.
invokeAndWait
(()
->
{
collectPrintersList
(
test
.
resultsTextArea
,
false
);
});
}
else
{
dispose
();
throw
new
RuntimeException
(
"No new network printer got added/removed!! Test timed out!!"
);
}
boolean
status
=
latch
.
await
(
1
,
TimeUnit
.
MINUTES
);
if
(!
status
)
{
dispose
();
throw
new
RuntimeException
(
"Test timed out."
);
}
if
(
test
.
testResult
==
false
)
{
dispose
();
throw
new
RuntimeException
(
"Test Failed."
);
}
dispose
();
}
public
static
void
dispose
()
throws
Exception
{
SwingUtilities
.
invokeAndWait
(()
->
{
test
.
disposeUI
();
});
}
public
static
boolean
waitForFlag
(
long
maxTimeoutInMsec
)
throws
Exception
{
while
(!
test
.
isAdded
&&
maxTimeoutInMsec
>
0
)
{
maxTimeoutInMsec
-=
100
;
Thread
.
sleep
(
100
);
}
if
(
maxTimeoutInMsec
<=
0
)
{
return
false
;
}
else
{
return
true
;
}
}
private
static
void
collectPrintersList
(
JTextArea
textArea
,
boolean
before
)
{
if
(
before
)
{
System
.
out
.
println
(
"List of printers(before): "
);
textArea
.
setText
(
"List of printers(before): \n"
);
for
(
PrintService
printServiceBefore
:
PrinterJob
.
lookupPrintServices
())
{
System
.
out
.
println
(
printServiceBefore
);
textArea
.
append
(
printServiceBefore
.
toString
());
textArea
.
append
(
"\n"
);
}
}
else
{
textArea
.
append
(
"\n"
);
System
.
out
.
println
(
"List of printers(after): "
);
textArea
.
append
(
"List of printers(after): \n"
);
for
(
PrintService
printServiceAfter
:
PrinterJob
.
lookupPrintServices
())
{
System
.
out
.
println
(
printServiceAfter
);
textArea
.
append
(
printServiceAfter
.
toString
());
textArea
.
append
(
"\n"
);
}
}
}
}
class
TestUI
{
private
static
JFrame
mainFrame
;
private
static
JPanel
mainControlPanel
;
private
static
JTextArea
instructionTextArea
;
private
static
JPanel
resultButtonPanel
;
private
static
JButton
passButton
;
private
static
JButton
failButton
;
private
static
JButton
addedButton
;
private
static
JPanel
testPanel
;
private
static
JButton
testButton
;
private
static
JLabel
buttonPressCountLabel
;
private
static
GridBagLayout
layout
;
private
final
CountDownLatch
latch
;
public
boolean
testResult
=
false
;
public
volatile
Boolean
isAdded
=
false
;
public
static
JTextArea
resultsTextArea
;
public
TestUI
(
CountDownLatch
latch
)
throws
Exception
{
this
.
latch
=
latch
;
}
public
final
void
createUI
()
{
mainFrame
=
new
JFrame
(
"RemotePrinterStatusRefresh"
);
layout
=
new
GridBagLayout
();
mainControlPanel
=
new
JPanel
(
layout
);
resultButtonPanel
=
new
JPanel
(
layout
);
testPanel
=
new
JPanel
(
layout
);
GridBagConstraints
gbc
=
new
GridBagConstraints
();
// Create Test instructions
String
instructions
=
"This test displays the current list of printers(before) attached to \n"
+
"this computer in the results panel.\n\n"
+
"Please follow the below steps for this manual test\n"
+
"--------------------------------------------------------------------\n"
+
"Step 1: Add/Remove a new network printer and Wait for 4 minutes after adding/removing\n"
+
"Step 2: Then click on 'Printer Added/Removed' button\n"
+
"Step 2: Once the new network printer is added/removed, see if it is \n"
+
" the same as displayed/not displayed in the results panel.\n"
+
"Step 3: If displayed/not displayed, then click 'Pass' else click on 'Fail' button"
;
instructionTextArea
=
new
JTextArea
();
instructionTextArea
.
setText
(
instructions
);
instructionTextArea
.
setEditable
(
false
);
instructionTextArea
.
setBorder
(
BorderFactory
.
createTitledBorder
(
"Test Instructions"
));
gbc
.
gridx
=
0
;
gbc
.
gridy
=
0
;
gbc
.
fill
=
GridBagConstraints
.
HORIZONTAL
;
mainControlPanel
.
add
(
instructionTextArea
,
gbc
);
gbc
.
gridx
=
0
;
gbc
.
gridy
=
1
;
testPanel
.
add
(
Box
.
createVerticalStrut
(
50
));
mainControlPanel
.
add
(
testPanel
);
addedButton
=
new
JButton
(
"Printer Added/Removed"
);
addedButton
.
setActionCommand
(
"Added"
);
addedButton
.
addActionListener
((
ActionEvent
e
)
->
{
System
.
out
.
println
(
"Added Button pressed!"
);
isAdded
=
true
;
});
// Create resultButtonPanel with Pass, Fail buttons
passButton
=
new
JButton
(
"Pass"
);
passButton
.
setActionCommand
(
"Pass"
);
passButton
.
addActionListener
((
ActionEvent
e
)
->
{
System
.
out
.
println
(
"Pass Button pressed!"
);
testResult
=
true
;
latch
.
countDown
();
disposeUI
();
});
failButton
=
new
JButton
(
"Fail"
);
failButton
.
setActionCommand
(
"Fail"
);
failButton
.
addActionListener
((
ActionEvent
e
)
->
{
System
.
out
.
println
(
"Fail Button pressed!"
);
testResult
=
false
;
latch
.
countDown
();
disposeUI
();
});
gbc
.
gridx
=
0
;
gbc
.
gridy
=
0
;
resultButtonPanel
.
add
(
addedButton
,
gbc
);
gbc
.
gridx
=
1
;
gbc
.
gridy
=
0
;
resultButtonPanel
.
add
(
passButton
,
gbc
);
gbc
.
gridx
=
2
;
gbc
.
gridy
=
0
;
resultButtonPanel
.
add
(
failButton
,
gbc
);
resultsTextArea
=
new
JTextArea
();
resultsTextArea
.
setEditable
(
false
);
resultsTextArea
.
setBorder
(
BorderFactory
.
createTitledBorder
(
"Results"
));
gbc
.
gridx
=
0
;
gbc
.
gridy
=
1
;
gbc
.
fill
=
GridBagConstraints
.
HORIZONTAL
;
mainControlPanel
.
add
(
resultsTextArea
,
gbc
);
gbc
.
gridx
=
0
;
gbc
.
gridy
=
2
;
mainControlPanel
.
add
(
resultButtonPanel
,
gbc
);
mainFrame
.
add
(
mainControlPanel
);
mainFrame
.
pack
();
mainFrame
.
setVisible
(
true
);
}
public
void
disposeUI
()
{
mainFrame
.
dispose
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录