Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openanolis
dragonwell8_jdk
提交
6b491fa1
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看板
提交
6b491fa1
编写于
11月 13, 2008
作者:
T
tbell
浏览文件
操作
浏览文件
下载
差异文件
Merge
上级
3f95510b
a2b5b0ea
变更
84
显示空白变更内容
内联
并排
Showing
84 changed file
with
6755 addition
and
1981 deletion
+6755
-1981
src/share/classes/com/sun/jmx/defaults/ServiceName.java
src/share/classes/com/sun/jmx/defaults/ServiceName.java
+2
-2
src/share/classes/com/sun/jmx/event/EventParams.java
src/share/classes/com/sun/jmx/event/EventParams.java
+1
-1
src/share/classes/com/sun/jmx/event/LeaseManager.java
src/share/classes/com/sun/jmx/event/LeaseManager.java
+4
-2
src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java
...classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java
+39
-13
src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java
...share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java
+2
-2
src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
...hare/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
+0
-354
src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java
...share/classes/com/sun/jmx/namespace/ObjectNameRouter.java
+0
-7
src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java
...classes/com/sun/jmx/namespace/RoutingConnectionProxy.java
+8
-25
src/share/classes/com/sun/jmx/namespace/RoutingProxy.java
src/share/classes/com/sun/jmx/namespace/RoutingProxy.java
+28
-44
src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java
...are/classes/com/sun/jmx/namespace/RoutingServerProxy.java
+8
-22
src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java
...lasses/com/sun/jmx/remote/util/EventClientConnection.java
+1
-3
src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
...nternal/www/protocol/https/HttpsURLConnectionOldImpl.java
+4
-0
src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
...classes/com/sun/security/auth/module/Krb5LoginModule.java
+69
-47
src/share/classes/java/net/HttpURLConnection.java
src/share/classes/java/net/HttpURLConnection.java
+63
-1
src/share/classes/java/security/cert/CertPathValidatorException.java
...lasses/java/security/cert/CertPathValidatorException.java
+1
-1
src/share/classes/javax/management/AttributeList.java
src/share/classes/javax/management/AttributeList.java
+120
-86
src/share/classes/javax/management/ClientContext.java
src/share/classes/javax/management/ClientContext.java
+1091
-0
src/share/classes/javax/management/Descriptor.java
src/share/classes/javax/management/Descriptor.java
+21
-11
src/share/classes/javax/management/JMX.java
src/share/classes/javax/management/JMX.java
+103
-5
src/share/classes/javax/management/MBeanInfo.java
src/share/classes/javax/management/MBeanInfo.java
+384
-0
src/share/classes/javax/management/MBeanServerConnection.java
...share/classes/javax/management/MBeanServerConnection.java
+89
-7
src/share/classes/javax/management/MBeanServerNotification.java
...are/classes/javax/management/MBeanServerNotification.java
+60
-5
src/share/classes/javax/management/Notification.java
src/share/classes/javax/management/Notification.java
+39
-5
src/share/classes/javax/management/QueryNotificationFilter.java
...are/classes/javax/management/QueryNotificationFilter.java
+5
-1
src/share/classes/javax/management/event/EventClient.java
src/share/classes/javax/management/event/EventClient.java
+28
-28
src/share/classes/javax/management/event/EventClientDelegate.java
...e/classes/javax/management/event/EventClientDelegate.java
+49
-9
src/share/classes/javax/management/event/EventClientDelegateMBean.java
...sses/javax/management/event/EventClientDelegateMBean.java
+3
-4
src/share/classes/javax/management/event/EventRelay.java
src/share/classes/javax/management/event/EventRelay.java
+0
-1
src/share/classes/javax/management/event/package-info.java
src/share/classes/javax/management/event/package-info.java
+2
-2
src/share/classes/javax/management/namespace/JMXNamespaces.java
...are/classes/javax/management/namespace/JMXNamespaces.java
+13
-27
src/share/classes/javax/management/namespace/JMXRemoteNamespace.java
...lasses/javax/management/namespace/JMXRemoteNamespace.java
+156
-81
src/share/classes/javax/management/openmbean/CompositeDataSupport.java
...sses/javax/management/openmbean/CompositeDataSupport.java
+181
-133
src/share/classes/javax/management/package.html
src/share/classes/javax/management/package.html
+156
-70
src/share/classes/javax/management/remote/JMXConnectorFactory.java
.../classes/javax/management/remote/JMXConnectorFactory.java
+11
-8
src/share/classes/javax/management/remote/JMXConnectorServer.java
...e/classes/javax/management/remote/JMXConnectorServer.java
+234
-154
src/share/classes/javax/management/remote/JMXConnectorServerMBean.java
...sses/javax/management/remote/JMXConnectorServerMBean.java
+2
-2
src/share/classes/javax/management/remote/rmi/RMIConnector.java
...are/classes/javax/management/remote/rmi/RMIConnector.java
+462
-462
src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
...asses/javax/management/remote/rmi/RMIConnectorServer.java
+5
-27
src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
.../classes/sun/net/www/protocol/http/HttpURLConnection.java
+28
-15
src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
...es/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
+4
-0
src/share/classes/sun/security/jgss/GSSContextImpl.java
src/share/classes/sun/security/jgss/GSSContextImpl.java
+3
-2
src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
...share/classes/sun/security/jgss/spnego/SpNegoContext.java
+8
-11
src/share/classes/sun/security/provider/certpath/OCSPResponse.java
.../classes/sun/security/provider/certpath/OCSPResponse.java
+9
-3
src/share/native/java/util/zip/zip_util.c
src/share/native/java/util/zip/zip_util.c
+7
-8
test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java
test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java
+2
-26
test/java/security/cert/CertPathValidatorException/GetMessage.java
.../security/cert/CertPathValidatorException/GetMessage.java
+63
-0
test/java/util/zip/TestEmptyZip.java
test/java/util/zip/TestEmptyZip.java
+34
-22
test/javax/management/Introspector/AnnotationTest.java
test/javax/management/Introspector/AnnotationTest.java
+156
-165
test/javax/management/MBeanServer/AttributeListMapTest.java
test/javax/management/MBeanServer/AttributeListMapTest.java
+115
-0
test/javax/management/MBeanServer/AttributeListTypeSafeTest.java
...vax/management/MBeanServer/AttributeListTypeSafeTest.java
+109
-0
test/javax/management/context/ContextForwarderTest.java
test/javax/management/context/ContextForwarderTest.java
+103
-0
test/javax/management/context/ContextTest.java
test/javax/management/context/ContextTest.java
+534
-0
test/javax/management/context/LocaleAwareBroadcasterTest.java
.../javax/management/context/LocaleAwareBroadcasterTest.java
+328
-0
test/javax/management/context/LocaleTest.java
test/javax/management/context/LocaleTest.java
+140
-0
test/javax/management/context/LocalizableTest.java
test/javax/management/context/LocalizableTest.java
+192
-0
test/javax/management/context/RemoteContextTest.java
test/javax/management/context/RemoteContextTest.java
+496
-0
test/javax/management/context/localizable/MBeanDescriptions.properties
...nagement/context/localizable/MBeanDescriptions.properties
+9
-0
test/javax/management/context/localizable/MBeanDescriptions_fr.java
.../management/context/localizable/MBeanDescriptions_fr.java
+42
-0
test/javax/management/context/localizable/Whatsit.java
test/javax/management/context/localizable/Whatsit.java
+59
-0
test/javax/management/context/localizable/WhatsitMBean.java
test/javax/management/context/localizable/WhatsitMBean.java
+53
-0
test/javax/management/eventService/CustomForwarderTest.java
test/javax/management/eventService/CustomForwarderTest.java
+1
-2
test/javax/management/eventService/EventClientExecutorTest.java
...avax/management/eventService/EventClientExecutorTest.java
+1
-2
test/javax/management/eventService/EventManagerTest.java
test/javax/management/eventService/EventManagerTest.java
+1
-1
test/javax/management/eventService/ListenerTest.java
test/javax/management/eventService/ListenerTest.java
+1
-1
test/javax/management/eventService/NotSerializableNotifTest.java
...vax/management/eventService/NotSerializableNotifTest.java
+1
-1
test/javax/management/eventService/UsingEventService.java
test/javax/management/eventService/UsingEventService.java
+23
-0
test/javax/management/namespace/EventWithNamespaceControlTest.java
...x/management/namespace/EventWithNamespaceControlTest.java
+1
-0
test/javax/management/namespace/JMXNamespaceSecurityTest.java
.../javax/management/namespace/JMXNamespaceSecurityTest.java
+1
-0
test/javax/management/namespace/JMXNamespaceViewTest.java
test/javax/management/namespace/JMXNamespaceViewTest.java
+1
-5
test/javax/management/namespace/JMXRemoteTargetNamespace.java
.../javax/management/namespace/JMXRemoteTargetNamespace.java
+8
-14
test/javax/management/namespace/NamespaceNotificationsTest.java
...avax/management/namespace/NamespaceNotificationsTest.java
+4
-12
test/javax/management/namespace/NullDomainObjectNameTest.java
.../javax/management/namespace/NullDomainObjectNameTest.java
+1
-1
test/javax/management/namespace/NullObjectNameTest.java
test/javax/management/namespace/NullObjectNameTest.java
+1
-1
test/javax/management/openmbean/CompositeDataStringTest.java
test/javax/management/openmbean/CompositeDataStringTest.java
+4
-4
test/javax/management/openmbean/CompositeDataToMapTest.java
test/javax/management/openmbean/CompositeDataToMapTest.java
+116
-0
test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java
.../remote/mandatory/connectorServer/ForwarderChainTest.java
+18
-13
test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java
...ote/mandatory/connectorServer/StandardForwardersTest.java
+22
-6
test/javax/management/remote/mandatory/provider/ProviderTest.java
...ax/management/remote/mandatory/provider/ProviderTest.java
+10
-2
test/javax/management/remote/mandatory/subjectDelegation/SimpleStandard.java
...nt/remote/mandatory/subjectDelegation/SimpleStandard.java
+7
-7
test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java
...nagement/remote/mandatory/version/JMXSpecVersionTest.java
+308
-0
test/sun/security/krb5/auto/Context.java
test/sun/security/krb5/auto/Context.java
+21
-4
test/sun/security/krb5/auto/KDC.java
test/sun/security/krb5/auto/KDC.java
+24
-1
test/sun/security/krb5/auto/LoginModuleOptions.java
test/sun/security/krb5/auto/LoginModuleOptions.java
+184
-0
test/sun/security/krb5/auto/NonMutualSpnego.java
test/sun/security/krb5/auto/NonMutualSpnego.java
+58
-0
未找到文件。
src/share/classes/com/sun/jmx/defaults/ServiceName.java
浏览文件 @
6b491fa1
...
@@ -69,9 +69,9 @@ public class ServiceName {
...
@@ -69,9 +69,9 @@ public class ServiceName {
/**
/**
* The version of the JMX specification implemented by this product.
* The version of the JMX specification implemented by this product.
* <BR>
* <BR>
* The value is <CODE>
1.4
</CODE>.
* The value is <CODE>
2.0
</CODE>.
*/
*/
public
static
final
String
JMX_SPEC_VERSION
=
"
1.4
"
;
public
static
final
String
JMX_SPEC_VERSION
=
"
2.0
"
;
/**
/**
* The vendor of the JMX specification implemented by this product.
* The vendor of the JMX specification implemented by this product.
...
...
src/share/classes/com/sun/jmx/event/EventParams.java
浏览文件 @
6b491fa1
...
@@ -41,7 +41,7 @@ public class EventParams {
...
@@ -41,7 +41,7 @@ public class EventParams {
@SuppressWarnings
(
"cast"
)
// cast for jdk 1.5
@SuppressWarnings
(
"cast"
)
// cast for jdk 1.5
public
static
long
getLeaseTimeout
()
{
public
static
long
getLeaseTimeout
()
{
long
timeout
=
EventClient
.
DEFAULT_
LEASE_TIMEOUT
;
long
timeout
=
EventClient
.
DEFAULT_
REQUESTED_LEASE_TIME
;
try
{
try
{
final
GetPropertyAction
act
=
final
GetPropertyAction
act
=
new
GetPropertyAction
(
DEFAULT_LEASE_TIMEOUT
);
new
GetPropertyAction
(
DEFAULT_LEASE_TIMEOUT
);
...
...
src/share/classes/com/sun/jmx/event/LeaseManager.java
浏览文件 @
6b491fa1
...
@@ -29,6 +29,7 @@ import com.sun.jmx.remote.util.ClassLogger;
...
@@ -29,6 +29,7 @@ import com.sun.jmx.remote.util.ClassLogger;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.ScheduledFuture
;
import
java.util.concurrent.ScheduledFuture
;
import
java.util.concurrent.ThreadFactory
;
import
java.util.concurrent.TimeUnit
;
import
java.util.concurrent.TimeUnit
;
/**
/**
...
@@ -143,9 +144,10 @@ public class LeaseManager {
...
@@ -143,9 +144,10 @@ public class LeaseManager {
private
final
Runnable
callback
;
private
final
Runnable
callback
;
private
ScheduledFuture
<?>
scheduled
;
// If null, the lease has expired.
private
ScheduledFuture
<?>
scheduled
;
// If null, the lease has expired.
private
static
final
ThreadFactory
threadFactory
=
new
DaemonThreadFactory
(
"JMX LeaseManager %d"
);
private
final
ScheduledExecutorService
executor
private
final
ScheduledExecutorService
executor
=
Executors
.
newScheduledThreadPool
(
1
,
=
Executors
.
newScheduledThreadPool
(
1
,
threadFactory
);
new
DaemonThreadFactory
(
"JMX LeaseManager %d"
));
private
static
final
ClassLogger
logger
=
private
static
final
ClassLogger
logger
=
new
ClassLogger
(
"javax.management.event"
,
"LeaseManager"
);
new
ClassLogger
(
"javax.management.event"
,
"LeaseManager"
);
...
...
src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java
浏览文件 @
6b491fa1
...
@@ -55,9 +55,19 @@ import javax.management.namespace.JMXNamespaces;
...
@@ -55,9 +55,19 @@ import javax.management.namespace.JMXNamespaces;
import
javax.management.namespace.MBeanServerSupport
;
import
javax.management.namespace.MBeanServerSupport
;
import
javax.management.remote.IdentityMBeanServerForwarder
;
import
javax.management.remote.IdentityMBeanServerForwarder
;
/**
* <p>An {@link MBeanServerForwarder} that simulates the existence of a
* given MBean. Requests for that MBean, call it X, are intercepted by the
* forwarder, and requests for any other MBean are forwarded to the next
* forwarder in the chain. Requests such as queryNames which can span both the
* X and other MBeans are handled by merging the results for X with the results
* from the next forwarder, unless the "visible" parameter is false, in which
* case X is invisible to such requests.</p>
*/
public
class
SingleMBeanForwarder
extends
IdentityMBeanServerForwarder
{
public
class
SingleMBeanForwarder
extends
IdentityMBeanServerForwarder
{
private
final
ObjectName
mbeanName
;
private
final
ObjectName
mbeanName
;
private
final
boolean
visible
;
private
DynamicMBean
mbean
;
private
DynamicMBean
mbean
;
private
MBeanServer
mbeanMBS
=
new
MBeanServerSupport
()
{
private
MBeanServer
mbeanMBS
=
new
MBeanServerSupport
()
{
...
@@ -85,10 +95,20 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
...
@@ -85,10 +95,20 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
return
null
;
return
null
;
}
}
// This will only be called if mbeanName has an empty domain.
// In that case a getAttribute (e.g.) of that name will have the
// domain replaced by MBeanServerSupport with the default domain,
// so we must be sure that the default domain is empty too.
@Override
public
String
getDefaultDomain
()
{
return
mbeanName
.
getDomain
();
}
};
};
public
SingleMBeanForwarder
(
ObjectName
mbeanName
,
DynamicMBean
mbean
)
{
public
SingleMBeanForwarder
(
ObjectName
mbeanName
,
DynamicMBean
mbean
,
boolean
visible
)
{
this
.
mbeanName
=
mbeanName
;
this
.
mbeanName
=
mbeanName
;
this
.
visible
=
visible
;
setSingleMBean
(
mbean
);
setSingleMBean
(
mbean
);
}
}
...
@@ -213,8 +233,10 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
...
@@ -213,8 +233,10 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
@Override
public
String
[]
getDomains
()
{
public
String
[]
getDomains
()
{
TreeSet
<
String
>
domainSet
=
String
[]
domains
=
super
.
getDomains
();
new
TreeSet
<
String
>(
Arrays
.
asList
(
super
.
getDomains
()));
if
(!
visible
)
return
domains
;
TreeSet
<
String
>
domainSet
=
new
TreeSet
<
String
>(
Arrays
.
asList
(
domains
));
domainSet
.
add
(
mbeanName
.
getDomain
());
domainSet
.
add
(
mbeanName
.
getDomain
());
return
domainSet
.
toArray
(
new
String
[
domainSet
.
size
()]);
return
domainSet
.
toArray
(
new
String
[
domainSet
.
size
()]);
}
}
...
@@ -222,7 +244,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
...
@@ -222,7 +244,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
@Override
public
Integer
getMBeanCount
()
{
public
Integer
getMBeanCount
()
{
Integer
count
=
super
.
getMBeanCount
();
Integer
count
=
super
.
getMBeanCount
();
if
(!
super
.
isRegistered
(
mbeanName
))
if
(
visible
&&
!
super
.
isRegistered
(
mbeanName
))
count
++;
count
++;
return
count
;
return
count
;
}
}
...
@@ -284,7 +306,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
...
@@ -284,7 +306,7 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
*/
*/
private
boolean
applies
(
ObjectName
pattern
)
{
private
boolean
applies
(
ObjectName
pattern
)
{
// we know pattern is not null.
// we know pattern is not null.
if
(!
pattern
.
apply
(
mbeanName
))
if
(!
visible
||
!
pattern
.
apply
(
mbeanName
))
return
false
;
return
false
;
final
String
dompat
=
pattern
.
getDomain
();
final
String
dompat
=
pattern
.
getDomain
();
...
@@ -306,22 +328,26 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
...
@@ -306,22 +328,26 @@ public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
@Override
@Override
public
Set
<
ObjectInstance
>
queryMBeans
(
ObjectName
name
,
QueryExp
query
)
{
public
Set
<
ObjectInstance
>
queryMBeans
(
ObjectName
name
,
QueryExp
query
)
{
Set
<
ObjectInstance
>
names
=
super
.
queryMBeans
(
name
,
query
);
Set
<
ObjectInstance
>
names
=
super
.
queryMBeans
(
name
,
query
);
if
(
visible
)
{
if
(
name
==
null
||
applies
(
name
)
)
{
if
(
name
==
null
||
applies
(
name
)
)
{
// Don't assume mbs.queryNames returns a writable set.
// Don't assume mbs.queryNames returns a writable set.
names
=
Util
.
cloneSet
(
names
);
names
=
Util
.
cloneSet
(
names
);
names
.
addAll
(
mbeanMBS
.
queryMBeans
(
name
,
query
));
names
.
addAll
(
mbeanMBS
.
queryMBeans
(
name
,
query
));
}
}
}
return
names
;
return
names
;
}
}
@Override
@Override
public
Set
<
ObjectName
>
queryNames
(
ObjectName
name
,
QueryExp
query
)
{
public
Set
<
ObjectName
>
queryNames
(
ObjectName
name
,
QueryExp
query
)
{
Set
<
ObjectName
>
names
=
super
.
queryNames
(
name
,
query
);
Set
<
ObjectName
>
names
=
super
.
queryNames
(
name
,
query
);
if
(
visible
)
{
if
(
name
==
null
||
applies
(
name
))
{
if
(
name
==
null
||
applies
(
name
))
{
// Don't assume mbs.queryNames returns a writable set.
// Don't assume mbs.queryNames returns a writable set.
names
=
Util
.
cloneSet
(
names
);
names
=
Util
.
cloneSet
(
names
);
names
.
addAll
(
mbeanMBS
.
queryNames
(
name
,
query
));
names
.
addAll
(
mbeanMBS
.
queryNames
(
name
,
query
));
}
}
}
return
names
;
return
names
;
}
}
...
...
src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java
浏览文件 @
6b491fa1
...
@@ -122,7 +122,7 @@ public final class JmxMBeanServer
...
@@ -122,7 +122,7 @@ public final class JmxMBeanServer
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
* instead.
* instead.
* <p>
* <p>
* By default,
{@link MBeanServerInterceptor}
are disabled. Use
* By default,
interceptors
are disabled. Use
* {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
* {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
* </ul>
* </ul>
* @param domain The default domain name used by this MBeanServer.
* @param domain The default domain name used by this MBeanServer.
...
@@ -239,7 +239,7 @@ public final class JmxMBeanServer
...
@@ -239,7 +239,7 @@ public final class JmxMBeanServer
this
.
mBeanServerDelegateObject
=
delegate
;
this
.
mBeanServerDelegateObject
=
delegate
;
this
.
outerShell
=
outer
;
this
.
outerShell
=
outer
;
final
Repository
repository
=
new
Repository
(
domain
,
fairLock
);
final
Repository
repository
=
new
Repository
(
domain
);
this
.
mbsInterceptor
=
this
.
mbsInterceptor
=
new
NamespaceDispatchInterceptor
(
outer
,
delegate
,
instantiator
,
new
NamespaceDispatchInterceptor
(
outer
,
delegate
,
instantiator
,
repository
);
repository
);
...
...
src/share/classes/com/sun/jmx/namespace/JMXNamespaceUtils.java
已删除
100644 → 0
浏览文件 @
3f95510b
/*
* Copyright 2008 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
com.sun.jmx.namespace
;
import
com.sun.jmx.defaults.JmxProperties
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.Map
;
import
java.util.WeakHashMap
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanServerConnection
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.event.EventClient
;
import
javax.management.event.EventClientDelegateMBean
;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.remote.JMXAddressable
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.JMXServiceURL
;
import
javax.security.auth.Subject
;
/**
* A collection of methods that provide JMXConnector wrappers for
* JMXRemoteNamepaces underlying connectors.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public
final
class
JMXNamespaceUtils
{
/**
* A logger for this class.
**/
private
static
final
Logger
LOG
=
JmxProperties
.
NAMESPACE_LOGGER
;
private
static
<
K
,
V
>
Map
<
K
,
V
>
newWeakHashMap
()
{
return
new
WeakHashMap
<
K
,
V
>();
}
/** There are no instances of this class */
private
JMXNamespaceUtils
()
{
}
// returns un unmodifiable view of a map.
public
static
<
K
,
V
>
Map
<
K
,
V
>
unmodifiableMap
(
Map
<
K
,
V
>
aMap
)
{
if
(
aMap
==
null
||
aMap
.
isEmpty
())
return
Collections
.
emptyMap
();
return
Collections
.
unmodifiableMap
(
aMap
);
}
/**
* A base class that helps writing JMXConnectors that return
* MBeanServerConnection wrappers.
* This base class wraps an inner JMXConnector (the source), and preserve
* its caching policy. If a connection is cached in the source, its wrapper
* will be cached in this connector too.
* Author's note: rewriting this with java.lang.reflect.Proxy could be
* envisaged. It would avoid the combinatory sub-classing introduced by
* JMXAddressable.
* <p>
* Note: all the standard JMXConnector implementations are serializable.
* This implementation here is not. Should it be?
* I believe it must not be serializable unless it becomes
* part of a public API (either standard or officially exposed
* and supported in a documented com.sun package)
**/
static
class
JMXCachingConnector
implements
JMXConnector
{
// private static final long serialVersionUID = -2279076110599707875L;
final
JMXConnector
source
;
// if this object is made serializable, then the variable below
// needs to become volatile transient and be lazyly-created...
private
final
Map
<
MBeanServerConnection
,
MBeanServerConnection
>
connectionMap
;
public
JMXCachingConnector
(
JMXConnector
source
)
{
this
.
source
=
checkNonNull
(
source
,
"source"
);
connectionMap
=
newWeakHashMap
();
}
private
MBeanServerConnection
getCached
(
MBeanServerConnection
inner
)
{
return
connectionMap
.
get
(
inner
);
}
private
MBeanServerConnection
putCached
(
final
MBeanServerConnection
inner
,
final
MBeanServerConnection
wrapper
)
{
if
(
inner
==
wrapper
)
return
wrapper
;
synchronized
(
this
)
{
final
MBeanServerConnection
concurrent
=
connectionMap
.
get
(
inner
);
if
(
concurrent
!=
null
)
return
concurrent
;
connectionMap
.
put
(
inner
,
wrapper
);
}
return
wrapper
;
}
public
void
addConnectionNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
{
source
.
addConnectionNotificationListener
(
listener
,
filter
,
handback
);
}
public
void
close
()
throws
IOException
{
source
.
close
();
}
public
void
connect
()
throws
IOException
{
source
.
connect
();
}
public
void
connect
(
Map
<
String
,?>
env
)
throws
IOException
{
source
.
connect
(
env
);
}
public
String
getConnectionId
()
throws
IOException
{
return
source
.
getConnectionId
();
}
/**
* Preserve caching policy of the underlying connector.
**/
public
MBeanServerConnection
getMBeanServerConnection
()
throws
IOException
{
final
MBeanServerConnection
inner
=
source
.
getMBeanServerConnection
();
final
MBeanServerConnection
cached
=
getCached
(
inner
);
if
(
cached
!=
null
)
return
cached
;
final
MBeanServerConnection
wrapper
=
wrap
(
inner
);
return
putCached
(
inner
,
wrapper
);
}
public
MBeanServerConnection
getMBeanServerConnection
(
Subject
delegationSubject
)
throws
IOException
{
final
MBeanServerConnection
wrapped
=
source
.
getMBeanServerConnection
(
delegationSubject
);
synchronized
(
this
)
{
final
MBeanServerConnection
cached
=
getCached
(
wrapped
);
if
(
cached
!=
null
)
return
cached
;
final
MBeanServerConnection
wrapper
=
wrapWithSubject
(
wrapped
,
delegationSubject
);
return
putCached
(
wrapped
,
wrapper
);
}
}
public
void
removeConnectionNotificationListener
(
NotificationListener
listener
)
throws
ListenerNotFoundException
{
source
.
removeConnectionNotificationListener
(
listener
);
}
public
void
removeConnectionNotificationListener
(
NotificationListener
l
,
NotificationFilter
f
,
Object
handback
)
throws
ListenerNotFoundException
{
source
.
removeConnectionNotificationListener
(
l
,
f
,
handback
);
}
/**
* This is the method that subclass will redefine. This method
* is called by {@code this.getMBeanServerConnection()}.
* {@code inner} is the connection returned by
* {@code source.getMBeanServerConnection()}.
**/
protected
MBeanServerConnection
wrap
(
MBeanServerConnection
inner
)
throws
IOException
{
return
inner
;
}
/**
* Subclass may also want to redefine this method.
* By default it calls wrap(inner). This method
* is called by {@code this.getMBeanServerConnection(Subject)}.
* {@code inner} is the connection returned by
* {@code source.getMBeanServerConnection(Subject)}.
**/
protected
MBeanServerConnection
wrapWithSubject
(
MBeanServerConnection
inner
,
Subject
delegationSubject
)
throws
IOException
{
return
wrap
(
inner
);
}
@Override
public
String
toString
()
{
if
(
source
instanceof
JMXAddressable
)
{
final
JMXServiceURL
address
=
((
JMXAddressable
)
source
).
getAddress
();
if
(
address
!=
null
)
return
address
.
toString
();
}
return
source
.
toString
();
}
}
/**
* The name space connector can do 'cd'
**/
static
class
JMXNamespaceConnector
extends
JMXCachingConnector
{
// private static final long serialVersionUID = -4813611540843020867L;
private
final
String
toDir
;
private
final
boolean
closeable
;
public
JMXNamespaceConnector
(
JMXConnector
source
,
String
toDir
,
boolean
closeable
)
{
super
(
source
);
this
.
toDir
=
toDir
;
this
.
closeable
=
closeable
;
}
@Override
public
void
close
()
throws
IOException
{
if
(!
closeable
)
throw
new
UnsupportedOperationException
(
"close"
);
else
super
.
close
();
}
@Override
protected
MBeanServerConnection
wrap
(
MBeanServerConnection
wrapped
)
throws
IOException
{
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
"Creating name space proxy connection for source: "
+
"namespace="
+
toDir
);
return
JMXNamespaces
.
narrowToNamespace
(
wrapped
,
toDir
);
}
@Override
public
String
toString
()
{
return
"JMXNamespaces.narrowToNamespace("
+
super
.
toString
()+
", \""
+
toDir
+
"\")"
;
}
}
static
class
JMXEventConnector
extends
JMXCachingConnector
{
// private static final long serialVersionUID = 4742659236340242785L;
JMXEventConnector
(
JMXConnector
wrapped
)
{
super
(
wrapped
);
}
@Override
protected
MBeanServerConnection
wrap
(
MBeanServerConnection
inner
)
throws
IOException
{
return
EventClient
.
getEventClientConnection
(
inner
);
}
@Override
public
String
toString
()
{
return
"EventClient.withEventClient("
+
super
.
toString
()+
")"
;
}
}
static
class
JMXAddressableEventConnector
extends
JMXEventConnector
implements
JMXAddressable
{
// private static final long serialVersionUID = -9128520234812124712L;
JMXAddressableEventConnector
(
JMXConnector
wrapped
)
{
super
(
wrapped
);
}
public
JMXServiceURL
getAddress
()
{
return
((
JMXAddressable
)
source
).
getAddress
();
}
}
/**
* Creates a connector whose MBeamServerConnection will point to the
* given sub name space inside the source connector.
* @see JMXNamespace
**/
public
static
JMXConnector
cd
(
final
JMXConnector
source
,
final
String
toNamespace
,
final
boolean
closeable
)
throws
IOException
{
checkNonNull
(
source
,
"JMXConnector"
);
if
(
toNamespace
==
null
||
toNamespace
.
equals
(
""
))
return
source
;
return
new
JMXNamespaceConnector
(
source
,
toNamespace
,
closeable
);
}
/**
* Returns a JMX Connector that will use an {@link EventClient}
* to subscribe for notifications. If the server doesn't have
* an {@link EventClientDelegateMBean}, then the connector will
* use the legacy notification mechanism instead.
*
* @param source The underlying JMX Connector wrapped by the returned
* connector.
* @return A JMX Connector that will uses an {@link EventClient}, if
* available.
* @see EventClient#getEventClientConnection(MBeanServerConnection)
*/
public
static
JMXConnector
withEventClient
(
final
JMXConnector
source
)
{
checkNonNull
(
source
,
"JMXConnector"
);
if
(
source
instanceof
JMXAddressable
)
return
new
JMXAddressableEventConnector
(
source
);
else
return
new
JMXEventConnector
(
source
);
}
public
static
<
T
>
T
checkNonNull
(
T
parameter
,
String
name
)
{
if
(
parameter
==
null
)
throw
new
IllegalArgumentException
(
name
+
" must not be null"
);
return
parameter
;
}
}
src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java
浏览文件 @
6b491fa1
...
@@ -49,11 +49,6 @@ public class ObjectNameRouter {
...
@@ -49,11 +49,6 @@ public class ObjectNameRouter {
final
int
tlen
;
final
int
tlen
;
final
boolean
identity
;
final
boolean
identity
;
public
ObjectNameRouter
(
String
targetDirName
)
{
this
(
targetDirName
,
null
);
}
/** Creates a new instance of ObjectNameRouter */
/** Creates a new instance of ObjectNameRouter */
public
ObjectNameRouter
(
final
String
remove
,
final
String
add
)
{
public
ObjectNameRouter
(
final
String
remove
,
final
String
add
)
{
this
.
targetPrefix
=
(
remove
==
null
?
""
:
remove
);
this
.
targetPrefix
=
(
remove
==
null
?
""
:
remove
);
...
@@ -186,6 +181,4 @@ public class ObjectNameRouter {
...
@@ -186,6 +181,4 @@ public class ObjectNameRouter {
b
.
append
(
NAMESPACE_SEPARATOR
);
b
.
append
(
NAMESPACE_SEPARATOR
);
return
b
.
toString
();
return
b
.
toString
();
}
}
}
}
src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java
浏览文件 @
6b491fa1
...
@@ -31,7 +31,6 @@ import java.util.logging.Level;
...
@@ -31,7 +31,6 @@ import java.util.logging.Level;
import
java.util.logging.Logger
;
import
java.util.logging.Logger
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerConnection
;
import
javax.management.namespace.JMXNamespaces
;
/**
/**
...
@@ -57,22 +56,14 @@ public class RoutingConnectionProxy
...
@@ -57,22 +56,14 @@ public class RoutingConnectionProxy
private
static
final
Logger
LOG
=
JmxProperties
.
NAMESPACE_LOGGER
;
private
static
final
Logger
LOG
=
JmxProperties
.
NAMESPACE_LOGGER
;
/**
* Creates a new instance of RoutingConnectionProxy
*/
public
RoutingConnectionProxy
(
MBeanServerConnection
source
,
String
sourceDir
)
{
this
(
source
,
sourceDir
,
""
,
false
);
}
/**
/**
* Creates a new instance of RoutingConnectionProxy
* Creates a new instance of RoutingConnectionProxy
*/
*/
public
RoutingConnectionProxy
(
MBeanServerConnection
source
,
public
RoutingConnectionProxy
(
MBeanServerConnection
source
,
String
sourceDir
,
String
sourceDir
,
String
targetDir
,
String
targetDir
,
boolean
forwardsContext
)
{
boolean
probe
)
{
super
(
source
,
sourceDir
,
targetDir
,
forwardsContext
);
super
(
source
,
sourceDir
,
targetDir
,
probe
);
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
"RoutingConnectionProxy for "
+
getSourceNamespace
()
+
LOG
.
finer
(
"RoutingConnectionProxy for "
+
getSourceNamespace
()
+
...
@@ -85,15 +76,13 @@ public class RoutingConnectionProxy
...
@@ -85,15 +76,13 @@ public class RoutingConnectionProxy
final
String
sourceNs
=
getSourceNamespace
();
final
String
sourceNs
=
getSourceNamespace
();
String
wrapped
=
String
.
valueOf
(
source
());
String
wrapped
=
String
.
valueOf
(
source
());
if
(
""
.
equals
(
targetNs
))
{
if
(
""
.
equals
(
targetNs
))
{
if
(
forwardsContext
)
wrapped
=
"ClientContext.withDynamicContext("
+
wrapped
+
")"
;
return
"JMXNamespaces.narrowToNamespace("
+
return
"JMXNamespaces.narrowToNamespace("
+
wrapped
+
", \""
+
wrapped
+
", \""
+
sourceNs
+
"\")"
;
sourceNs
+
"\")"
;
}
}
return
this
.
getClass
().
getSimpleName
()+
"("
+
wrapped
+
", \""
+
return
this
.
getClass
().
getSimpleName
()+
"("
+
wrapped
+
", \""
+
sourceNs
+
"\", \""
+
sourceNs
+
"\", \""
+
targetNs
+
"\"
, "
+
forwardsContext
+
"
)"
;
targetNs
+
"\")"
;
}
}
static
final
RoutingProxyFactory
static
final
RoutingProxyFactory
...
@@ -102,22 +91,16 @@ public class RoutingConnectionProxy
...
@@ -102,22 +91,16 @@ public class RoutingConnectionProxy
<
MBeanServerConnection
,
RoutingConnectionProxy
>()
{
<
MBeanServerConnection
,
RoutingConnectionProxy
>()
{
public
RoutingConnectionProxy
newInstance
(
MBeanServerConnection
source
,
public
RoutingConnectionProxy
newInstance
(
MBeanServerConnection
source
,
String
sourcePath
,
String
targetPath
,
String
sourcePath
,
String
targetPath
,
boolean
probe
)
{
boolean
forwardsContext
)
{
return
new
RoutingConnectionProxy
(
source
,
sourcePath
,
return
new
RoutingConnectionProxy
(
source
,
sourcePath
,
targetPath
,
forwardsContext
);
targetPath
,
probe
);
}
public
RoutingConnectionProxy
newInstance
(
MBeanServerConnection
source
,
String
sourcePath
)
{
return
new
RoutingConnectionProxy
(
source
,
sourcePath
);
}
}
};
};
public
static
MBeanServerConnection
cd
(
MBeanServerConnection
source
,
public
static
MBeanServerConnection
cd
(
String
sourcePath
)
{
MBeanServerConnection
source
,
String
sourcePath
,
boolean
probe
)
{
return
RoutingProxy
.
cd
(
RoutingConnectionProxy
.
class
,
FACTORY
,
return
RoutingProxy
.
cd
(
RoutingConnectionProxy
.
class
,
FACTORY
,
source
,
sourcePath
);
source
,
sourcePath
,
probe
);
}
}
}
}
src/share/classes/com/sun/jmx/namespace/RoutingProxy.java
浏览文件 @
6b491fa1
...
@@ -30,6 +30,7 @@ import java.io.IOException;
...
@@ -30,6 +30,7 @@ import java.io.IOException;
import
java.util.logging.Level
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
java.util.logging.Logger
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.MBeanException
;
import
javax.management.MBeanException
;
import
javax.management.MBeanRegistrationException
;
import
javax.management.MBeanRegistrationException
;
...
@@ -90,17 +91,9 @@ import javax.management.namespace.JMXNamespaces;
...
@@ -90,17 +91,9 @@ import javax.management.namespace.JMXNamespaces;
// targetNs=<encoded-context> // context must be removed from object name
// targetNs=<encoded-context> // context must be removed from object name
// sourceNs="" // nothing to add...
// sourceNs="" // nothing to add...
//
//
// RoutingProxies can also be used on the client side to implement
// "withClientContext" operations. In that case, the boolean parameter
// 'forwards context' is set to true, targetNs is "", and sourceNS may
// also be "". When forwardsContext is true, the RoutingProxy dynamically
// creates an ObjectNameRouter for each operation - in order to dynamically add
// the context attached to the thread to the routing ObjectName. This is
// performed in the getObjectNameRouter() method.
//
// Finally, in order to avoid too many layers of wrapping,
// Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a
// RoutingConnectionProxy and RoutingServerProxy can be created through a
// factory method that can concatenate namespace path
e
s in order to
// factory method that can concatenate namespace paths in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
// RoutingServerProxy.cd
...
@@ -146,16 +139,18 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -146,16 +139,18 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
private
final
T
source
;
private
final
T
source
;
// The name space we're narrowing to (usually some name space in
// The name space we're narrowing to (usually some name space in
// the source MBeanServerConnection
// the source MBeanServerConnection), e.g. "a" for the namespace
// "a//". This is empty in the case of ClientContext described above.
private
final
String
sourceNs
;
private
final
String
sourceNs
;
// The name space we pretend to be mounted in (usually "")
// The name space we pretend to be mounted in. This is empty except
// in the case of ClientContext described above (where it will be
// something like "jmx.context//foo=bar".
private
final
String
targetNs
;
private
final
String
targetNs
;
// The name of the JMXNamespace that handles the source name space
// The name of the JMXNamespace that handles the source name space
private
final
ObjectName
handlerName
;
private
final
ObjectName
handlerName
;
private
final
ObjectNameRouter
router
;
private
final
ObjectNameRouter
router
;
final
boolean
forwardsContext
;
private
volatile
String
defaultDomain
=
null
;
private
volatile
String
defaultDomain
=
null
;
/**
/**
...
@@ -164,7 +159,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -164,7 +159,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
protected
RoutingProxy
(
T
source
,
protected
RoutingProxy
(
T
source
,
String
sourceNs
,
String
sourceNs
,
String
targetNs
,
String
targetNs
,
boolean
forwardsContext
)
{
boolean
probe
)
{
if
(
source
==
null
)
throw
new
IllegalArgumentException
(
"null"
);
if
(
source
==
null
)
throw
new
IllegalArgumentException
(
"null"
);
this
.
sourceNs
=
JMXNamespaces
.
normalizeNamespaceName
(
sourceNs
);
this
.
sourceNs
=
JMXNamespaces
.
normalizeNamespaceName
(
sourceNs
);
...
@@ -177,21 +172,24 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -177,21 +172,24 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// System.err.println("sourceNs: "+sourceNs);
// System.err.println("sourceNs: "+sourceNs);
this
.
handlerName
=
this
.
handlerName
=
JMXNamespaces
.
getNamespaceObjectName
(
this
.
sourceNs
);
JMXNamespaces
.
getNamespaceObjectName
(
this
.
sourceNs
);
if
(
probe
)
{
try
{
try
{
// System.err.println("handlerName: "+handlerName);
if
(!
source
.
isRegistered
(
handlerName
))
{
if
(!
source
.
isRegistered
(
handlerName
))
InstanceNotFoundException
infe
=
new
InstanceNotFoundException
(
handlerName
);
throw
new
IllegalArgumentException
(
sourceNs
+
throw
new
IllegalArgumentException
(
sourceNs
+
": no such name space"
);
": no such name space"
,
infe
);
}
}
catch
(
IOException
x
)
{
}
catch
(
IOException
x
)
{
throw
new
IllegalArgumentException
(
"source stale: "
+
x
,
x
);
throw
new
IllegalArgumentException
(
"source stale: "
+
x
,
x
);
}
}
}
}
}
this
.
source
=
source
;
this
.
source
=
source
;
this
.
targetNs
=
(
targetNs
==
null
?
""
:
this
.
targetNs
=
(
targetNs
==
null
?
""
:
JMXNamespaces
.
normalizeNamespaceName
(
targetNs
));
JMXNamespaces
.
normalizeNamespaceName
(
targetNs
));
this
.
router
=
this
.
router
=
new
ObjectNameRouter
(
this
.
targetNs
,
this
.
sourceNs
);
new
ObjectNameRouter
(
this
.
targetNs
,
this
.
sourceNs
);
this
.
forwardsContext
=
forwardsContext
;
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
"RoutingProxy for "
+
this
.
sourceNs
+
" created"
);
LOG
.
finer
(
"RoutingProxy for "
+
this
.
sourceNs
+
" created"
);
...
@@ -200,14 +198,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -200,14 +198,6 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
@Override
@Override
public
T
source
()
{
return
source
;
}
public
T
source
()
{
return
source
;
}
ObjectNameRouter
getObjectNameRouter
()
{
// TODO: uncomment this when contexts are added
// if (forwardsContext)
// return ObjectNameRouter.wrapWithContext(router);
// else
return
router
;
}
@Override
@Override
public
ObjectName
toSource
(
ObjectName
targetName
)
public
ObjectName
toSource
(
ObjectName
targetName
)
throws
MalformedObjectNameException
{
throws
MalformedObjectNameException
{
...
@@ -222,8 +212,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -222,8 +212,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
if
(
defaultDomain
!=
null
)
if
(
defaultDomain
!=
null
)
targetName
=
targetName
.
withDomain
(
defaultDomain
);
targetName
=
targetName
.
withDomain
(
defaultDomain
);
}
}
final
ObjectNameRouter
r
=
getObjectNameRouter
();
return
router
.
toSourceContext
(
targetName
,
true
);
return
r
.
toSourceContext
(
targetName
,
true
);
}
}
@Override
@Override
...
@@ -243,8 +232,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -243,8 +232,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
public
ObjectName
toTarget
(
ObjectName
sourceName
)
public
ObjectName
toTarget
(
ObjectName
sourceName
)
throws
MalformedObjectNameException
{
throws
MalformedObjectNameException
{
if
(
sourceName
==
null
)
return
null
;
if
(
sourceName
==
null
)
return
null
;
final
ObjectNameRouter
r
=
getObjectNameRouter
();
return
router
.
toTargetContext
(
sourceName
,
false
);
return
r
.
toTargetContext
(
sourceName
,
false
);
}
}
private
Object
getAttributeFromHandler
(
String
attributeName
)
private
Object
getAttributeFromHandler
(
String
attributeName
)
...
@@ -357,11 +345,8 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -357,11 +345,8 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
// instance.
// instance.
static
interface
RoutingProxyFactory
<
T
extends
MBeanServerConnection
,
static
interface
RoutingProxyFactory
<
T
extends
MBeanServerConnection
,
R
extends
RoutingProxy
<
T
>>
{
R
extends
RoutingProxy
<
T
>>
{
R
newInstance
(
T
source
,
public
R
newInstance
(
String
sourcePath
,
String
targetPath
,
T
source
,
String
sourcePath
,
String
targetPath
,
boolean
probe
);
boolean
forwardsContext
);
R
newInstance
(
T
source
,
String
sourcePath
);
}
}
// Performs a narrowDownToNamespace operation.
// Performs a narrowDownToNamespace operation.
...
@@ -377,7 +362,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -377,7 +362,7 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
static
<
T
extends
MBeanServerConnection
,
R
extends
RoutingProxy
<
T
>>
static
<
T
extends
MBeanServerConnection
,
R
extends
RoutingProxy
<
T
>>
R
cd
(
Class
<
R
>
routingProxyClass
,
R
cd
(
Class
<
R
>
routingProxyClass
,
RoutingProxyFactory
<
T
,
R
>
factory
,
RoutingProxyFactory
<
T
,
R
>
factory
,
T
source
,
String
sourcePath
)
{
T
source
,
String
sourcePath
,
boolean
probe
)
{
if
(
source
==
null
)
throw
new
IllegalArgumentException
(
"null"
);
if
(
source
==
null
)
throw
new
IllegalArgumentException
(
"null"
);
if
(
source
.
getClass
().
equals
(
routingProxyClass
))
{
if
(
source
.
getClass
().
equals
(
routingProxyClass
))
{
// cast is OK here, but findbugs complains unless we use class.cast
// cast is OK here, but findbugs complains unless we use class.cast
...
@@ -400,14 +385,13 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
...
@@ -400,14 +385,13 @@ public abstract class RoutingProxy<T extends MBeanServerConnection>
final
String
path
=
final
String
path
=
JMXNamespaces
.
concat
(
other
.
getSourceNamespace
(),
JMXNamespaces
.
concat
(
other
.
getSourceNamespace
(),
sourcePath
);
sourcePath
);
return
factory
.
newInstance
(
other
.
source
(),
path
,
""
,
return
factory
.
newInstance
(
other
.
source
(),
path
,
""
,
probe
);
other
.
forwardsContext
);
}
}
// Note: we could do possibly something here - but it would involve
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// removing part of targetDir, and possibly adding
// something to sourcePath.
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
// Too complex to bother! => simply default to stacking...
}
}
return
factory
.
newInstance
(
source
,
sourcePath
);
return
factory
.
newInstance
(
source
,
sourcePath
,
""
,
probe
);
}
}
}
}
src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java
浏览文件 @
6b491fa1
...
@@ -54,7 +54,6 @@ import javax.management.OperationsException;
...
@@ -54,7 +54,6 @@ import javax.management.OperationsException;
import
javax.management.QueryExp
;
import
javax.management.QueryExp
;
import
javax.management.ReflectionException
;
import
javax.management.ReflectionException
;
import
javax.management.loading.ClassLoaderRepository
;
import
javax.management.loading.ClassLoaderRepository
;
import
javax.management.namespace.JMXNamespaces
;
/**
/**
* A RoutingServerProxy is an MBeanServer proxy that proxies a
* A RoutingServerProxy is an MBeanServer proxy that proxies a
...
@@ -76,19 +75,11 @@ public class RoutingServerProxy
...
@@ -76,19 +75,11 @@ public class RoutingServerProxy
extends
RoutingProxy
<
MBeanServer
>
extends
RoutingProxy
<
MBeanServer
>
implements
MBeanServer
{
implements
MBeanServer
{
/**
* Creates a new instance of RoutingServerProxy
*/
public
RoutingServerProxy
(
MBeanServer
source
,
String
sourceNs
)
{
this
(
source
,
sourceNs
,
""
,
false
);
}
public
RoutingServerProxy
(
MBeanServer
source
,
public
RoutingServerProxy
(
MBeanServer
source
,
String
sourceNs
,
String
sourceNs
,
String
targetNs
,
String
targetNs
,
boolean
forwardsContext
)
{
boolean
probe
)
{
super
(
source
,
sourceNs
,
targetNs
,
forwardsContext
);
super
(
source
,
sourceNs
,
targetNs
,
probe
);
}
}
/**
/**
...
@@ -571,20 +562,15 @@ public class RoutingServerProxy
...
@@ -571,20 +562,15 @@ public class RoutingServerProxy
FACTORY
=
new
RoutingProxyFactory
<
MBeanServer
,
RoutingServerProxy
>()
{
FACTORY
=
new
RoutingProxyFactory
<
MBeanServer
,
RoutingServerProxy
>()
{
public
RoutingServerProxy
newInstance
(
MBeanServer
source
,
public
RoutingServerProxy
newInstance
(
MBeanServer
source
,
String
sourcePath
,
String
targetPath
,
String
sourcePath
,
String
targetPath
,
boolean
probe
)
{
boolean
forwardsContext
)
{
return
new
RoutingServerProxy
(
return
new
RoutingServerProxy
(
source
,
sourcePath
,
source
,
sourcePath
,
targetPath
,
probe
);
targetPath
,
forwardsContext
);
}
public
RoutingServerProxy
newInstance
(
MBeanServer
source
,
String
sourcePath
)
{
return
new
RoutingServerProxy
(
source
,
sourcePath
);
}
}
};
};
public
static
MBeanServer
cd
(
MBeanServer
source
,
String
sourcePath
)
{
public
static
MBeanServer
cd
(
MBeanServer
source
,
String
sourcePath
,
boolean
probe
)
{
return
RoutingProxy
.
cd
(
RoutingServerProxy
.
class
,
FACTORY
,
return
RoutingProxy
.
cd
(
RoutingServerProxy
.
class
,
FACTORY
,
source
,
sourcePath
);
source
,
sourcePath
,
probe
);
}
}
}
}
src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java
浏览文件 @
6b491fa1
...
@@ -430,13 +430,11 @@ public class EventClientConnection implements InvocationHandler,
...
@@ -430,13 +430,11 @@ public class EventClientConnection implements InvocationHandler,
* The {@code EventClient} is created lazily, when it is needed
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
* (see {@link #createEventClient}).
* @return the
* @return the
MBeanServerConnection.
**/
**/
public
static
MBeanServerConnection
getEventConnectionFor
(
public
static
MBeanServerConnection
getEventConnectionFor
(
MBeanServerConnection
connection
,
MBeanServerConnection
connection
,
Callable
<
EventClient
>
eventClientFactory
)
{
Callable
<
EventClient
>
eventClientFactory
)
{
// if c already uses an EventClient no need to create a new one.
//
if
(
connection
instanceof
EventClientFactory
if
(
connection
instanceof
EventClientFactory
&&
eventClientFactory
!=
null
)
&&
eventClientFactory
!=
null
)
throw
new
IllegalArgumentException
(
"connection already uses EventClient"
);
throw
new
IllegalArgumentException
(
"connection already uses EventClient"
);
...
...
src/share/classes/com/sun/net/ssl/internal/www/protocol/https/HttpsURLConnectionOldImpl.java
浏览文件 @
6b491fa1
...
@@ -497,6 +497,10 @@ public class HttpsURLConnectionOldImpl
...
@@ -497,6 +497,10 @@ public class HttpsURLConnectionOldImpl
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
}
}
public
void
setFixedLengthStreamingMode
(
long
contentLength
)
{
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
}
public
void
setChunkedStreamingMode
(
int
chunklen
)
{
public
void
setChunkedStreamingMode
(
int
chunklen
)
{
delegate
.
setChunkedStreamingMode
(
chunklen
);
delegate
.
setChunkedStreamingMode
(
chunklen
);
}
}
...
...
src/share/classes/com/sun/security/auth/module/Krb5LoginModule.java
浏览文件 @
6b491fa1
...
@@ -86,6 +86,8 @@ import sun.misc.HexDumpEncoder;
...
@@ -86,6 +86,8 @@ import sun.misc.HexDumpEncoder;
* the principal name from the configuration is used. In the
* the principal name from the configuration is used. In the
* case where the principal property is not set and the principal
* case where the principal property is not set and the principal
* entry also does not exist, the user is prompted for the name.
* entry also does not exist, the user is prompted for the name.
* When this property of entry is set, and <code>useTicketCache</code>
* is set to true, only TGT belonging to this principal is used.
*
*
* <p> The following is a list of configuration options supported
* <p> The following is a list of configuration options supported
* for <code>Krb5LoginModule</code>:
* for <code>Krb5LoginModule</code>:
...
@@ -101,18 +103,19 @@ import sun.misc.HexDumpEncoder;
...
@@ -101,18 +103,19 @@ import sun.misc.HexDumpEncoder;
* to false if you do not want this module to use the ticket cache.
* to false if you do not want this module to use the ticket cache.
* (Default is False).
* (Default is False).
* This module will
* This module will
* search for the ticke
c
t
* search for the ticket
* cache in the following locations:
* cache in the following locations:
* For Windows 2000, it will use Local Security Authority (LSA) API
* On Solaris and Linux
* to get the TGT. On Solaris and Linux
* it will look for the ticket cache in /tmp/krb5cc_<code>uid</code>
* it will look for the ticket cache in /tmp/krb5cc_<code>uid</code>
* where the uid is numeric user
* where the uid is numeric user
* identifier. If the ticket cache is
* identifier. If the ticket cache is
* not available in
either of the above locations
, or if we are on a
* not available in
the above location
, or if we are on a
*
different Windows platform,
it will look for the cache as
*
Windows platform,
it will look for the cache as
* {user.home}{file.separator}krb5cc_{user.name}.
* {user.home}{file.separator}krb5cc_{user.name}.
* You can override the ticket cache location by using
* You can override the ticket cache location by using
* <code>ticketCache</code>
* <code>ticketCache</code>.
* For Windows, if a ticket cannot be retrieved from the file ticket cache,
* it will use Local Security Authority (LSA) API to get the TGT.
* <P>
* <P>
* <dt><b><code>ticketCache</code></b>:</dt>
* <dt><b><code>ticketCache</code></b>:</dt>
* <dd>Set this to the name of the ticket
* <dd>Set this to the name of the ticket
...
@@ -129,20 +132,20 @@ import sun.misc.HexDumpEncoder;
...
@@ -129,20 +132,20 @@ import sun.misc.HexDumpEncoder;
* <dt><b><code>doNotPrompt</code></b>:</dt>
* <dt><b><code>doNotPrompt</code></b>:</dt>
* <dd>Set this to true if you do not want to be
* <dd>Set this to true if you do not want to be
* prompted for the password
* prompted for the password
* if credentials can
* if credentials can
not be obtained from the cache, the keytab,
*
not be obtained from the cache or keytab
.(Default is false)
*
or through shared state
.(Default is false)
* If set to true
authentication will fail if credentials can
* If set to true
, credential must be obtained through cache, keytab,
*
not be obtained from the cache or keytab
.</dd>
*
or shared state. Otherwise, authentication will fail
.</dd>
* <P>
* <P>
* <dt><b><code>useKeyTab</code></b>:</dt>
* <dt><b><code>useKeyTab</code></b>:</dt>
* <dd>Set this to true if you
* <dd>Set this to true if you
* want the module to get the principal's key from the
* want the module to get the principal's key from the
* the keytab.(default value is False)
* the keytab.(default value is False)
* If <code>key
at
b</code>
* If <code>key
ta
b</code>
* is not set then
* is not set then
* the module will locate the keytab from the
* the module will locate the keytab from the
* Kerberos configuration file.
</dd>
* Kerberos configuration file.
* If it is not specifed in the Kerberos configuration file
* If it is not specif
i
ed in the Kerberos configuration file
* then it will look for the file
* then it will look for the file
* <code>{user.home}{file.separator}</code>krb5.keytab.</dd>
* <code>{user.home}{file.separator}</code>krb5.keytab.</dd>
* <P>
* <P>
...
@@ -210,20 +213,34 @@ import sun.misc.HexDumpEncoder;
...
@@ -210,20 +213,34 @@ import sun.misc.HexDumpEncoder;
* exist for the username and password in the shared
* exist for the username and password in the shared
* state, or if authentication fails.
* state, or if authentication fails.
*
*
* clearPass
if, true, this <code>LoginModule</code>
clears the
* clearPass
if, true, this LoginModule
clears the
* username and password stored in the module's shared
* username and password stored in the module's shared
* state after both phases of authentication
* state after both phases of authentication
* (login and commit) have completed.
* (login and commit) have completed.
* </pre>
* </pre>
* <p>If the principal system property or key is already provided, the value of
* "javax.security.auth.login.name" in the shared state is ignored.
* <p>When multiple mechanisms to retrieve a ticket or key is provided, the
* preference order looks like this:
* <ol>
* <li>ticket cache
* <li>keytab
* <li>shared state
* <li>user prompt
* </ol>
* <p>Note that if any step fails, it will fallback to the next step.
* There's only one exception, it the shared state step fails and
* <code>useFirstPass</code>=true, no user prompt is made.
* <p>Examples of some configuration values for Krb5LoginModule in
* <p>Examples of some configuration values for Krb5LoginModule in
* JAAS config file and the results are:
* JAAS config file and the results are:
* <ul>
* <ul>
* <p> <code>doNotPrompt</code>=true;
* <p> <code>doNotPrompt</code>=true;
* </ul>
* </ul>
* <p> This is an illegal combination since <code>useTicketCache</code>
* <p> This is an illegal combination since none of <code>useTicketCache</code>,
* is not set and the user can not be prompted for the password.
* <code>useKeyTab</code>, <code>useFirstPass</code> and <code>tryFirstPass</code>
* is set and the user can not be prompted for the password.
*<ul>
*<ul>
* <p> <code>ticketCache</code> =
< filename >
;
* <p> <code>ticketCache</code> =
<filename>
;
*</ul>
*</ul>
* <p> This is an illegal combination since <code>useTicketCache</code>
* <p> This is an illegal combination since <code>useTicketCache</code>
* is not set to true and the ticketCache is set. A configuration error
* is not set to true and the ticketCache is set. A configuration error
...
@@ -240,9 +257,9 @@ import sun.misc.HexDumpEncoder;
...
@@ -240,9 +257,9 @@ import sun.misc.HexDumpEncoder;
*</ul>
*</ul>
* <p> This is an illegal combination since <code>storeKey</code> is set to
* <p> This is an illegal combination since <code>storeKey</code> is set to
* true but the key can not be obtained either by prompting the user or from
* true but the key can not be obtained either by prompting the user or from
* the keytab
.
A configuration error will occur.
* the keytab
, or from the shared state.
A configuration error will occur.
* <ul>
* <ul>
* <p> <code>keyTab</code> =
< filename >
<code>doNotPrompt</code>=true ;
* <p> <code>keyTab</code> =
<filename>
<code>doNotPrompt</code>=true ;
* </ul>
* </ul>
* <p>This is an illegal combination since useKeyTab is not set to true and
* <p>This is an illegal combination since useKeyTab is not set to true and
* the keyTab is set. A configuration error will occur.
* the keyTab is set. A configuration error will occur.
...
@@ -260,7 +277,7 @@ import sun.misc.HexDumpEncoder;
...
@@ -260,7 +277,7 @@ import sun.misc.HexDumpEncoder;
* with the principal and TGT. If the TGT is not available,
* with the principal and TGT. If the TGT is not available,
* do not prompt the user, instead fail the authentication.
* do not prompt the user, instead fail the authentication.
* <ul>
* <ul>
* <p><code>principal</code>=
< name >
<code>useTicketCache</code> = true
* <p><code>principal</code>=
<name>
<code>useTicketCache</code> = true
* <code>doNotPrompt</code>=true;
* <code>doNotPrompt</code>=true;
*</ul>
*</ul>
* <p> Get the TGT from the default cache for the principal and populate the
* <p> Get the TGT from the default cache for the principal and populate the
...
@@ -269,9 +286,9 @@ import sun.misc.HexDumpEncoder;
...
@@ -269,9 +286,9 @@ import sun.misc.HexDumpEncoder;
* authentication will fail.
* authentication will fail.
* <ul>
* <ul>
* <p> <code>useTicketCache</code> = true
* <p> <code>useTicketCache</code> = true
* <code>ticketCache</code>=
< file name >
<code>useKeyTab</code> = true
* <code>ticketCache</code>=
<file name>
<code>useKeyTab</code> = true
* <code> keyTab</code>=
< keytab filename >
* <code> keyTab</code>=
<keytab filename>
* <code>principal</code> =
< principal name >
* <code>principal</code> =
<principal name>
* <code>doNotPrompt</code>=true;
* <code>doNotPrompt</code>=true;
*</ul>
*</ul>
* <p> Search the cache for the principal's TGT. If it is not available
* <p> Search the cache for the principal's TGT. If it is not available
...
@@ -281,7 +298,7 @@ import sun.misc.HexDumpEncoder;
...
@@ -281,7 +298,7 @@ import sun.misc.HexDumpEncoder;
* If the key is not available or valid then authentication will fail.
* If the key is not available or valid then authentication will fail.
* <ul>
* <ul>
* <p><code>useTicketCache</code> = true
* <p><code>useTicketCache</code> = true
* <code>ticketCache</code>=
< file name >
* <code>ticketCache</code>=
<file name>
*</ul>
*</ul>
* <p> The TGT will be obtained from the cache specified.
* <p> The TGT will be obtained from the cache specified.
* The Kerberos principal name used will be the principal name in
* The Kerberos principal name used will be the principal name in
...
@@ -292,8 +309,8 @@ import sun.misc.HexDumpEncoder;
...
@@ -292,8 +309,8 @@ import sun.misc.HexDumpEncoder;
* The Subject will be populated with the TGT.
* The Subject will be populated with the TGT.
*<ul>
*<ul>
* <p> <code>useKeyTab</code> = true
* <p> <code>useKeyTab</code> = true
* <code>keyTab</code>=
< keytab filename >
* <code>keyTab</code>=
<keytab filename>
* <code>principal</code>=
< principal name >
* <code>principal</code>=
<principal name>
* <code>storeKey</code>=true;
* <code>storeKey</code>=true;
*</ul>
*</ul>
* <p> The key for the principal will be retrieved from the keytab.
* <p> The key for the principal will be retrieved from the keytab.
...
@@ -303,7 +320,7 @@ import sun.misc.HexDumpEncoder;
...
@@ -303,7 +320,7 @@ import sun.misc.HexDumpEncoder;
* password entered.
* password entered.
* <ul>
* <ul>
* <p> <code>useKeyTab</code> = true
* <p> <code>useKeyTab</code> = true
* <code>keyTab</code>=
< keytabname >
* <code>keyTab</code>=
<keytabname>
* <code>storeKey</code>=true
* <code>storeKey</code>=true
* <code>doNotPrompt</code>=true;
* <code>doNotPrompt</code>=true;
*</ul>
*</ul>
...
@@ -316,21 +333,23 @@ import sun.misc.HexDumpEncoder;
...
@@ -316,21 +333,23 @@ import sun.misc.HexDumpEncoder;
* Subject's private credentials set. Otherwise the authentication will
* Subject's private credentials set. Otherwise the authentication will
* fail.
* fail.
*<ul>
*<ul>
* <p><code>useKeyTab</code> = true
* <p>
* <code>keyTab</code>=< file name > <code>storeKey</code>=true
* <code>principal</code>= < principal name >
* <code>useTicketCache</code>=true
* <code>useTicketCache</code>=true
* <code>ticketCache</code>=< file name >;
* <code>ticketCache</code>=<file name>;
* <code>useKeyTab</code> = true
* <code>keyTab</code>=<file name> <code>storeKey</code>=true
* <code>principal</code>= <principal name>
*</ul>
*</ul>
* <p>The principal's key will be retrieved from the keytab and added
* <p>
* to the <code>Subject</code>'s private credentials. If the key
* The client's TGT will be retrieved from the ticket cache and added to the
* is not available, the
* user will be prompted for the password; the key derived from the password
* will be added to the Subject's private credentials set. The
* client's TGT will be retrieved from the ticket cache and added to the
* <code>Subject</code>'s private credentials. If the TGT is not available
* <code>Subject</code>'s private credentials. If the TGT is not available
* in the ticket cache, it will be obtained using the authentication
* in the ticket cache, or the TGT's client name does not match the principal
* name, Java will use a secret key to obtain the TGT using the authentication
* exchange and added to the Subject's private credentials.
* exchange and added to the Subject's private credentials.
* This secret key will be first retrieved from the keytab. If the key
* is not available, the user will be prompted for the password. In either
* case, the key derived from the password will be added to the
* Subject's private credentials set.
* <ul>
* <ul>
* <p><code>isInitiator</code> = false
* <p><code>isInitiator</code> = false
*</ul>
*</ul>
...
@@ -856,11 +875,13 @@ public class Krb5LoginModule implements LoginModule {
...
@@ -856,11 +875,13 @@ public class Krb5LoginModule implements LoginModule {
}
}
private
void
validateConfiguration
()
throws
LoginException
{
private
void
validateConfiguration
()
throws
LoginException
{
if
(
doNotPrompt
&&
!
useTicketCache
&&
!
useKeyTab
)
if
(
doNotPrompt
&&
!
useTicketCache
&&
!
useKeyTab
&&
!
tryFirstPass
&&
!
useFirstPass
)
throw
new
LoginException
throw
new
LoginException
(
"Configuration Error"
(
"Configuration Error"
+
" - either doNotPrompt should be "
+
" - either doNotPrompt should be "
+
" false or useTicketCache/useKeyTab "
+
" false or at least one of useTicketCache, "
+
" useKeyTab, tryFirstPass and useFirstPass"
+
" should be true"
);
+
" should be true"
);
if
(
ticketCacheName
!=
null
&&
!
useTicketCache
)
if
(
ticketCacheName
!=
null
&&
!
useTicketCache
)
throw
new
LoginException
throw
new
LoginException
...
@@ -872,11 +893,12 @@ public class Krb5LoginModule implements LoginModule {
...
@@ -872,11 +893,12 @@ public class Krb5LoginModule implements LoginModule {
throw
new
LoginException
throw
new
LoginException
(
"Configuration Error - useKeyTab should be set to true "
(
"Configuration Error - useKeyTab should be set to true "
+
"to use the keytab"
+
keyTabName
);
+
"to use the keytab"
+
keyTabName
);
if
(
storeKey
&&
doNotPrompt
&&
!
useKeyTab
)
if
(
storeKey
&&
doNotPrompt
&&
!
useKeyTab
&&
!
tryFirstPass
&&
!
useFirstPass
)
throw
new
LoginException
throw
new
LoginException
(
"Configuration Error - either doNotPrompt "
(
"Configuration Error - either doNotPrompt
should be set to
"
+
"
should be set to false or
"
+
"
false or at least one of tryFirstPass, useFirstPass
"
+
"useKeyTab must be set to true for storeKey option"
);
+
"
or
useKeyTab must be set to true for storeKey option"
);
if
(
renewTGT
&&
!
useTicketCache
)
if
(
renewTGT
&&
!
useTicketCache
)
throw
new
LoginException
throw
new
LoginException
(
"Configuration Error"
(
"Configuration Error"
...
...
src/share/classes/java/net/HttpURLConnection.java
浏览文件 @
6b491fa1
...
@@ -73,10 +73,23 @@ abstract public class HttpURLConnection extends URLConnection {
...
@@ -73,10 +73,23 @@ abstract public class HttpURLConnection extends URLConnection {
* The fixed content-length when using fixed-length streaming mode.
* The fixed content-length when using fixed-length streaming mode.
* A value of <code>-1</code> means fixed-length streaming mode is disabled
* A value of <code>-1</code> means fixed-length streaming mode is disabled
* for output.
* for output.
*
* <P> <B>NOTE:</B> {@link #fixedContentLengthLong} is recommended instead
* of this field, as it allows larger content lengths to be set.
*
* @since 1.5
* @since 1.5
*/
*/
protected
int
fixedContentLength
=
-
1
;
protected
int
fixedContentLength
=
-
1
;
/**
* The fixed content-length when using fixed-length streaming mode.
* A value of {@code -1} means fixed-length streaming mode is disabled
* for output.
*
* @since 1.7
*/
protected
long
fixedContentLengthLong
=
-
1
;
/**
/**
* Returns the key for the <code>n</code><sup>th</sup> header field.
* Returns the key for the <code>n</code><sup>th</sup> header field.
* Some implementations may treat the <code>0</code><sup>th</sup>
* Some implementations may treat the <code>0</code><sup>th</sup>
...
@@ -109,6 +122,9 @@ abstract public class HttpURLConnection extends URLConnection {
...
@@ -109,6 +122,9 @@ abstract public class HttpURLConnection extends URLConnection {
* This exception can be queried for the details of the error.
* This exception can be queried for the details of the error.
* <p>
* <p>
* This method must be called before the URLConnection is connected.
* This method must be called before the URLConnection is connected.
* <p>
* <B>NOTE:</B> {@link #setFixedLengthStreamingMode(long)} is recommended
* instead of this method as it allows larger content lengths to be set.
*
*
* @param contentLength The number of bytes which will be written
* @param contentLength The number of bytes which will be written
* to the OutputStream.
* to the OutputStream.
...
@@ -135,6 +151,52 @@ abstract public class HttpURLConnection extends URLConnection {
...
@@ -135,6 +151,52 @@ abstract public class HttpURLConnection extends URLConnection {
fixedContentLength
=
contentLength
;
fixedContentLength
=
contentLength
;
}
}
/**
* This method is used to enable streaming of a HTTP request body
* without internal buffering, when the content length is known in
* advance.
*
* <P> An exception will be thrown if the application attempts to write
* more data than the indicated content-length, or if the application
* closes the OutputStream before writing the indicated amount.
*
* <P> When output streaming is enabled, authentication and redirection
* cannot be handled automatically. A {@linkplain HttpRetryException} will
* be thrown when reading the response if authentication or redirection
* are required. This exception can be queried for the details of the
* error.
*
* <P> This method must be called before the URLConnection is connected.
*
* <P> The content length set by invoking this method takes precedence
* over any value set by {@link #setFixedLengthStreamingMode(int)}.
*
* @param contentLength
* The number of bytes which will be written to the OutputStream.
*
* @throws IllegalStateException
* if URLConnection is already connected or if a different
* streaming mode is already enabled.
*
* @throws IllegalArgumentException
* if a content length less than zero is specified.
*
* @since 1.7
*/
public
void
setFixedLengthStreamingMode
(
long
contentLength
)
{
if
(
connected
)
{
throw
new
IllegalStateException
(
"Already connected"
);
}
if
(
chunkLength
!=
-
1
)
{
throw
new
IllegalStateException
(
"Chunked encoding streaming mode set"
);
}
if
(
contentLength
<
0
)
{
throw
new
IllegalArgumentException
(
"invalid content length"
);
}
fixedContentLengthLong
=
contentLength
;
}
/* Default chunk size (including chunk header) if not specified;
/* Default chunk size (including chunk header) if not specified;
* we want to keep this in sync with the one defined in
* we want to keep this in sync with the one defined in
* sun.net.www.http.ChunkedOutputStream
* sun.net.www.http.ChunkedOutputStream
...
@@ -170,7 +232,7 @@ abstract public class HttpURLConnection extends URLConnection {
...
@@ -170,7 +232,7 @@ abstract public class HttpURLConnection extends URLConnection {
if
(
connected
)
{
if
(
connected
)
{
throw
new
IllegalStateException
(
"Can't set streaming mode: already connected"
);
throw
new
IllegalStateException
(
"Can't set streaming mode: already connected"
);
}
}
if
(
fixedContentLength
!=
-
1
)
{
if
(
fixedContentLength
!=
-
1
||
fixedContentLengthLong
!=
-
1
)
{
throw
new
IllegalStateException
(
"Fixed length streaming mode set"
);
throw
new
IllegalStateException
(
"Fixed length streaming mode set"
);
}
}
chunkLength
=
chunklen
<=
0
?
DEFAULT_CHUNK_SIZE
:
chunklen
;
chunkLength
=
chunklen
<=
0
?
DEFAULT_CHUNK_SIZE
:
chunklen
;
...
...
src/share/classes/java/security/cert/CertPathValidatorException.java
浏览文件 @
6b491fa1
...
@@ -113,7 +113,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
...
@@ -113,7 +113,7 @@ public class CertPathValidatorException extends GeneralSecurityException {
* permitted, and indicates that the cause is nonexistent or unknown.)
* permitted, and indicates that the cause is nonexistent or unknown.)
*/
*/
public
CertPathValidatorException
(
Throwable
cause
)
{
public
CertPathValidatorException
(
Throwable
cause
)
{
this
(
null
,
cause
);
this
(
(
cause
==
null
?
null
:
cause
.
toString
())
,
cause
);
}
}
/**
/**
...
...
src/share/classes/javax/management/AttributeList.java
浏览文件 @
6b491fa1
/*
/*
* Copyright 1999-200
5
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-200
8
Sun Microsystems, Inc. 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
...
@@ -27,17 +27,23 @@ package javax.management;
...
@@ -27,17 +27,23 @@ package javax.management;
import
java.util.ArrayList
;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.LinkedHashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
/**
/**
* Represents a list of values for attributes of an MBean. The methods
* <p>Represents a list of values for attributes of an MBean. See the
* used for the insertion of {@link javax.management.Attribute
* {@link MBeanServerConnection#getAttributes getAttributes} and
* Attribute} objects in the <CODE>AttributeList</CODE> overrides the
* {@link MBeanServerConnection#setAttributes setAttributes} methods of
* corresponding methods in the superclass
* {@link MBeanServer} and {@link MBeanServerConnection}.</p>
* <CODE>ArrayList</CODE>. This is needed in order to insure that the
*
* objects contained in the <CODE>AttributeList</CODE> are only
* <p id="type-safe">For compatibility reasons, it is possible, though
* <CODE>Attribute</CODE> objects. This avoids getting an exception
* highly discouraged, to add objects to an {@code AttributeList} that are
* when retrieving elements from the <CODE>AttributeList</CODE>.
* not instances of {@code Attribute}. However, an {@code AttributeList}
* can be made <em>type-safe</em>, which means that an attempt to add
* an object that is not an {@code Attribute} will produce an {@code
* IllegalArgumentException}. An {@code AttributeList} becomes type-safe
* when the method {@link #asList()} is called on it.</p>
*
*
* @since 1.5
* @since 1.5
*/
*/
...
@@ -58,8 +64,8 @@ import java.util.List;
...
@@ -58,8 +64,8 @@ import java.util.List;
*/
*/
public
class
AttributeList
extends
ArrayList
<
Object
>
{
public
class
AttributeList
extends
ArrayList
<
Object
>
{
private
transient
boolean
typeSafe
;
private
transient
volatile
boolean
typeSafe
;
private
transient
boolean
tainted
;
private
transient
volatile
boolean
tainted
;
/* Serial version */
/* Serial version */
private
static
final
long
serialVersionUID
=
-
4077085769279709076L
;
private
static
final
long
serialVersionUID
=
-
4077085769279709076L
;
...
@@ -124,13 +130,63 @@ public class AttributeList extends ArrayList<Object> {
...
@@ -124,13 +130,63 @@ public class AttributeList extends ArrayList<Object> {
// Check for non-Attribute objects
// Check for non-Attribute objects
//
//
checkTypeSafe
(
list
);
adding
(
list
);
// Build the List<Attribute>
// Build the List<Attribute>
//
//
super
.
addAll
(
list
);
super
.
addAll
(
list
);
}
}
/**
* <p>Constructs an {@code AttributeList} containing the elements of
* the {@code Map} specified, in the order in which they appear in the
* {@code Map}'s {@link Map#entrySet entrySet}. For each <em>{@code
* key}</em> and <em>{@code value}</em> in the {@code Map}, the constructed
* {@code AttributeList} will contain {@link Attribute#Attribute
* Attribute(<em>key</em>, <em>value</em>)}.</p>
*
* @param map the {@code Map} defining the elements of the new
* {@code AttributeList}.
*/
public
AttributeList
(
Map
<
String
,
?>
map
)
{
for
(
Map
.
Entry
<
String
,
?>
entry
:
map
.
entrySet
())
add
(
new
Attribute
(
entry
.
getKey
(),
entry
.
getValue
()));
typeSafe
=
true
;
}
/**
* <p>Return a {@code Map} that is a snapshot of the values in this
* {@code AttributeList}. Each key in the {@code Map} is the {@linkplain
* Attribute#getName() name} of an {@code Attribute} in the list, and each
* value is the corresponding {@linkplain Attribute#getValue() value} of
* that {@code Attribute}. The {@code AttributeList} and the {@code Map}
* are unrelated after the call, that is, changes to one do not affect the
* other.</p>
*
* <p>If the {@code AttributeList} contains more than one {@code Attribute}
* with the same name, then the {@code Map} will contain an entry
* for that name where the value is that of the last of those {@code
* Attribute}s.</p>
*
* @return the new {@code Map}.
*
* @throws IllegalArgumentException if this {@code AttributeList} contains
* an element that is not an {@code Attribute}.
*/
public
Map
<
String
,
Object
>
toMap
()
{
Map
<
String
,
Object
>
map
=
new
LinkedHashMap
<
String
,
Object
>();
// We can't call adding(this) because we're not necessarily typeSafe
if
(
tainted
)
throw
new
IllegalArgumentException
(
"AttributeList contains non-Attribute"
);
for
(
Object
x
:
this
)
{
Attribute
a
=
(
Attribute
)
x
;
map
.
put
(
a
.
getName
(),
a
.
getValue
());
}
return
map
;
}
/**
/**
* Return a view of this list as a {@code List<Attribute>}.
* Return a view of this list as a {@code List<Attribute>}.
* Changes to the returned value are reflected by changes
* Changes to the returned value are reflected by changes
...
@@ -154,11 +210,9 @@ public class AttributeList extends ArrayList<Object> {
...
@@ -154,11 +210,9 @@ public class AttributeList extends ArrayList<Object> {
*/
*/
@SuppressWarnings
(
"unchecked"
)
@SuppressWarnings
(
"unchecked"
)
public
List
<
Attribute
>
asList
()
{
public
List
<
Attribute
>
asList
()
{
if
(!
typeSafe
)
{
if
(
tainted
)
checkTypeSafe
(
this
);
typeSafe
=
true
;
typeSafe
=
true
;
}
if
(
tainted
)
adding
((
Collection
<?>)
this
);
// will throw IllegalArgumentException
return
(
List
<
Attribute
>)
(
List
<?>)
this
;
return
(
List
<
Attribute
>)
(
List
<?>)
this
;
}
}
...
@@ -175,7 +229,7 @@ public class AttributeList extends ArrayList<Object> {
...
@@ -175,7 +229,7 @@ public class AttributeList extends ArrayList<Object> {
* Inserts the attribute specified as an element at the position specified.
* Inserts the attribute specified as an element at the position specified.
* Elements with an index greater than or equal to the current position are
* Elements with an index greater than or equal to the current position are
* shifted up. If the index is out of range (index < 0 || index >
* shifted up. If the index is out of range (index < 0 || index >
* size() a RuntimeOperationsException should be raised, wrapping the
* size()
)
a RuntimeOperationsException should be raised, wrapping the
* java.lang.IndexOutOfBoundsException thrown.
* java.lang.IndexOutOfBoundsException thrown.
*
*
* @param object The <CODE>Attribute</CODE> object to be inserted.
* @param object The <CODE>Attribute</CODE> object to be inserted.
...
@@ -245,8 +299,7 @@ public class AttributeList extends ArrayList<Object> {
...
@@ -245,8 +299,7 @@ public class AttributeList extends ArrayList<Object> {
public
boolean
addAll
(
int
index
,
AttributeList
list
)
{
public
boolean
addAll
(
int
index
,
AttributeList
list
)
{
try
{
try
{
return
super
.
addAll
(
index
,
list
);
return
super
.
addAll
(
index
,
list
);
}
}
catch
(
IndexOutOfBoundsException
e
)
{
catch
(
IndexOutOfBoundsException
e
)
{
throw
new
RuntimeOperationsException
(
e
,
throw
new
RuntimeOperationsException
(
e
,
"The specified index is out of range"
);
"The specified index is out of range"
);
}
}
...
@@ -258,96 +311,77 @@ public class AttributeList extends ArrayList<Object> {
...
@@ -258,96 +311,77 @@ public class AttributeList extends ArrayList<Object> {
* been called on this instance.
* been called on this instance.
*/
*/
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
@Override
public
boolean
add
(
Object
o
)
{
public
boolean
add
(
Object
element
)
{
if
(!
tainted
)
adding
(
element
);
tainted
=
isTainted
(
o
);
return
super
.
add
(
element
);
if
(
typeSafe
)
checkTypeSafe
(
o
);
return
super
.
add
(
o
);
}
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
@Override
public
void
add
(
int
index
,
Object
element
)
{
public
void
add
(
int
index
,
Object
element
)
{
if
(!
tainted
)
adding
(
element
);
tainted
=
isTainted
(
element
);
if
(
typeSafe
)
checkTypeSafe
(
element
);
super
.
add
(
index
,
element
);
super
.
add
(
index
,
element
);
}
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code c} contains an
* element that is not an {@code Attribute}.
*/
@Override
@Override
public
boolean
addAll
(
Collection
<?>
c
)
{
public
boolean
addAll
(
Collection
<?>
c
)
{
if
(!
tainted
)
adding
(
c
);
tainted
=
isTainted
(
c
);
if
(
typeSafe
)
checkTypeSafe
(
c
);
return
super
.
addAll
(
c
);
return
super
.
addAll
(
c
);
}
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code c} contains an
* element that is not an {@code Attribute}.
*/
@Override
@Override
public
boolean
addAll
(
int
index
,
Collection
<?>
c
)
{
public
boolean
addAll
(
int
index
,
Collection
<?>
c
)
{
if
(!
tainted
)
adding
(
c
);
tainted
=
isTainted
(
c
);
if
(
typeSafe
)
checkTypeSafe
(
c
);
return
super
.
addAll
(
index
,
c
);
return
super
.
addAll
(
index
,
c
);
}
}
/**
* {@inheritDoc}
* @throws IllegalArgumentException if this {@code AttributeList} is
* <a href="#type-safe">type-safe</a> and {@code element} is not an
* {@code Attribute}.
*/
@Override
@Override
public
Object
set
(
int
index
,
Object
element
)
{
public
Object
set
(
int
index
,
Object
element
)
{
if
(!
tainted
)
adding
(
element
);
tainted
=
isTainted
(
element
);
if
(
typeSafe
)
checkTypeSafe
(
element
);
return
super
.
set
(
index
,
element
);
return
super
.
set
(
index
,
element
);
}
}
/**
private
void
adding
(
Object
x
)
{
* IllegalArgumentException if o is a non-Attribute object.
if
(
x
==
null
||
x
instanceof
Attribute
)
*/
return
;
private
static
void
checkTypeSafe
(
Object
o
)
{
if
(
typeSafe
)
try
{
throw
new
IllegalArgumentException
(
"Not an Attribute: "
+
x
);
o
=
(
Attribute
)
o
;
else
}
catch
(
ClassCastException
e
)
{
tainted
=
true
;
throw
new
IllegalArgumentException
(
e
);
}
}
/**
* IllegalArgumentException if c contains any non-Attribute objects.
*/
private
static
void
checkTypeSafe
(
Collection
<?>
c
)
{
try
{
Attribute
a
;
for
(
Object
o
:
c
)
a
=
(
Attribute
)
o
;
}
catch
(
ClassCastException
e
)
{
throw
new
IllegalArgumentException
(
e
);
}
}
/**
* Returns true if o is a non-Attribute object.
*/
private
static
boolean
isTainted
(
Object
o
)
{
try
{
checkTypeSafe
(
o
);
}
catch
(
IllegalArgumentException
e
)
{
return
true
;
}
return
false
;
}
}
/**
private
void
adding
(
Collection
<?>
c
)
{
* Returns true if c contains any non-Attribute objects.
for
(
Object
x
:
c
)
*/
adding
(
x
);
private
static
boolean
isTainted
(
Collection
<?>
c
)
{
try
{
checkTypeSafe
(
c
);
}
catch
(
IllegalArgumentException
e
)
{
return
true
;
}
return
false
;
}
}
}
}
src/share/classes/javax/management/ClientContext.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
javax.management
;
import
com.sun.jmx.interceptor.SingleMBeanForwarder
;
import
com.sun.jmx.namespace.RoutingConnectionProxy
;
import
com.sun.jmx.namespace.RoutingProxy
;
import
com.sun.jmx.namespace.RoutingServerProxy
;
import
java.io.UnsupportedEncodingException
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.net.URLDecoder
;
import
java.net.URLEncoder
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.StringTokenizer
;
import
java.util.TreeMap
;
import
java.util.concurrent.Callable
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
static
javax
.
management
.
namespace
.
JMXNamespaces
.
NAMESPACE_SEPARATOR
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.namespace.JMXNamespaceMBean
;
import
javax.management.namespace.MBeanServerSupport
;
import
javax.management.remote.IdentityMBeanServerForwarder
;
import
javax.management.remote.MBeanServerForwarder
;
/**
* <p>Methods to communicate a client context to MBeans. A context is
* a {@literal Map<String, String>} that is provided by the client and
* that an MBean can consult using the {@link #getContext()} method.
* The context is set on a per-thread basis and can be consulted by any
* code that the target MBean calls within the thread.</p>
*
* <p>One common usage of client context is to communicate the client's
* {@link Locale} to MBeans. For example, if an MBean has a String attribute
* {@code LastProblemDescription}, the value of that attribute could be
* a description of the last problem encountered by the MBean, translated
* into the client's locale. Different clients accessing this attribute
* from different locales would each see the appropriate version for their
* locale.</p>
*
* <p>The locale case is sufficiently important that it has a special
* shorthand, the {@link #getLocale()} method. This method calls
* <code>{@link #getContext()}.get({@link #LOCALE_KEY})</code> and converts the
* resultant String into a Locale object.</p>
*
* <p>Here is what an MBean with a localized {@code LastProblemDescription}
* attribute might look like:</p>
*
* <pre>
* public class LocaleSensitive implements LocaleSensitiveMBean {
* ...
* public String getLastProblemDescription() {
* Locale loc = {@link #getLocale() ClientContext.getLocale()};
* ResourceBundle rb = ResourceBundle.getBundle("MyResources", loc);
* String resourceKey = getLastProblemResourceKey();
* return rb.getString(resourceKey);
* }
* ...
* }
* </pre>
*
* <p>Here is how a client can communicate its locale to the target
* MBean:</p>
*
* <pre>
* JMXConnector connector = JMXConnectorFactory.connect(url);
* MBeanServerConnection connection = connector.getMBeanServerConnection();
* <b>MBeanServerConnection localizedConnection =
* {@link #withLocale(MBeanServerConnection, Locale)
* ClientContext.withLocale}(connection, Locale.getDefault());</b>
* String problem = localizedConnection.getAttribute(
* objectName, "LastProblemDescription");
* </pre>
*
* <p>In the more general case where the client wants to communicate context
* other than the locale, it can use {@link #withContext(MBeanServerConnection,
* String, String) withContext} instead of {@code withLocale}, and the target
* MBean can retrieve the context using {@link #getContext()}.</p>
*
*
* <h3 id="remote-use">Remote use of contexts</h3>
*
* <p>The various {@code with*} methods, for example {@link
* #withLocale(javax.management.MBeanServer, java.util.Locale) withLocale},
* transmit the context of each request by encoding it in the ObjectName of
* the request. For example, if a client creates a connection in the
* French locale like this...</p>
*
* <pre>
* MBeanServerConnection mbsc = ...;
* Locale french = new Locale("fr");
* MBeanServerConnection localizedConnection = ClientContext.withLocale(mbsc, french);
* </pre>
*
* <p>...or, equivalently, like this...</p>
*
* <pre>
* MBeanServerConnection localizedConnection =
* ClientContext.withContext(mbsc, {@link #LOCALE_KEY "jmx.locale"}, "fr");
* </pre>
*
* <p>...then the context associates {@code "jmx.locale"} with {@code "fr"}
* and a request such as<br>
* {@code localizedConnection.getAttribute("java.lang:type=Runtime", "Name")}<br>
* is translated into<br>
* {@code mbsc.getAttribute("jmx.context//jmx.locale=fr//java.lang:Runtime", "Name")}.<br>
* A special {@linkplain javax.management.namespace namespace} {@code jmx.context//}
* extracts the context from the string {@code jmx.locale=fr} and establishes
* it in the thread that will do<br>
* {@code getAttribute("java.lang:Runtime", "Name")}.</p>
*
* <p>The details of how contexts are encoded into ObjectNames are explained
* in the {@link #encode encode} method.</p>
*
* <p>The namespace {@code jmx.context//} just mentioned is only needed by
* remote clients, since local clients can set the context directly using
* {@link #doWithContext doWithContext}. Accordingly, this namespace is not
* present by default in the {@code MBeanServer}. Instead, it is
* <em>simulated</em> by the standard RMI connector using a special
* {@link MBeanServerForwarder}. If you are using this connector, you do not
* need to do anything special. Other connectors may or may not simulate this
* namespace in the same way. If the connector server returns true from the
* method {@link
* javax.management.remote.JMXConnectorServer#supportsSystemMBeanServerForwarder()
* supportsSystemMBeanServerForwarder} then it does simulate the namespace.
* If you are using another connector, or if you want to be able to use the
* {@code with*} methods locally, then you can install the {@code
* MBeanServerForwarder} yourself as described in the method {@link
* #newContextForwarder newContextForwarder}.</p>
*/
public
class
ClientContext
{
/**
* <p>The context key for the client locale. The string associated with
* this key is an encoded locale such as {@code en_US} which could be
* returned by {@link Locale#toString()}.</p>
*/
public
static
final
String
LOCALE_KEY
=
"jmx.locale"
;
private
static
final
Logger
LOG
=
Logger
.
getLogger
(
"javax.management.context"
);
/**
* <p>The namespace that implements contexts, {@value}.</p>
*/
public
static
final
String
NAMESPACE
=
"jmx.context"
;
private
static
final
String
NAMESPACE_PLUS_SEP
=
NAMESPACE
+
NAMESPACE_SEPARATOR
;
static
final
ObjectName
CLIENT_CONTEXT_NAMESPACE_HANDLER
=
ObjectName
.
valueOf
(
NAMESPACE_PLUS_SEP
+
":"
+
JMXNamespace
.
TYPE_ASSIGNMENT
);
private
static
final
ObjectName
NAMESPACE_HANDLER_WITHOUT_NAMESPACE
=
ObjectName
.
valueOf
(
":"
+
JMXNamespace
.
TYPE_ASSIGNMENT
);
private
static
final
ThreadLocal
<
Map
<
String
,
String
>>
contextThreadLocal
=
new
InheritableThreadLocal
<
Map
<
String
,
String
>>()
{
@Override
protected
Map
<
String
,
String
>
initialValue
()
{
return
Collections
.
emptyMap
();
}
};
/** There are no instances of this class. */
private
ClientContext
()
{
}
/**
* <p>Get the client context associated with the current thread.
*
* @return the client context associated with the current thread.
* This may be an empty Map, but it cannot be null. The returned
* Map cannot be modified.
*/
public
static
Map
<
String
,
String
>
getContext
()
{
return
Collections
.
unmodifiableMap
(
contextThreadLocal
.
get
());
}
/**
* <p>Get the client locale associated with the current thread.
* If the client context includes the {@value #LOCALE_KEY} key
* then the returned value is the Locale encoded in that key.
* Otherwise the returned value is the {@linkplain Locale#getDefault()
* default locale}.
*
* @return the client locale.
*/
public
static
Locale
getLocale
()
{
String
localeS
=
getContext
().
get
(
LOCALE_KEY
);
if
(
localeS
==
null
)
return
Locale
.
getDefault
();
// Parse the locale string. Why isn't there a method in Locale for this?
String
language
,
country
,
variant
;
int
ui
=
localeS
.
indexOf
(
'_'
);
if
(
ui
<
0
)
{
language
=
localeS
;
country
=
variant
=
""
;
}
else
{
language
=
localeS
.
substring
(
0
,
ui
);
localeS
=
localeS
.
substring
(
ui
+
1
);
ui
=
localeS
.
indexOf
(
'_'
);
if
(
ui
<
0
)
{
country
=
localeS
;
variant
=
""
;
}
else
{
country
=
localeS
.
substring
(
0
,
ui
);
variant
=
localeS
.
substring
(
ui
+
1
);
}
}
return
new
Locale
(
language
,
country
,
variant
);
}
/**
* <p>Execute the given {@code task} with the client context set to
* the given Map. This Map will be the result of {@link #getContext()}
* within the {@code task}.</p>
*
* <p>The {@code task} may include nested calls to {@code doWithContext}.
* The value returned by {@link #getContext} at any point is the Map
* provided to the most recent {@code doWithContext} (in the current thread)
* that has not yet returned.</p>
*
* <p>The {@link #getContext()} method returns the same value immediately
* after a call to this method as immediately before. In other words,
* {@code doWithContext} only affects the context during the execution of
* the {@code task}.</p>
*
* <p>As an example, suppose you want to get an attribute with whatever
* context has already been set, plus the locale set to "fr". You could
* write this:</p>
*
* <pre>
* {@code Map<String, String>} context =
* new {@code HashMap<String, String>}(ClientContext.getContext());
* context.put(ClientContext.LOCALE_KEY, "fr");
* String lastProblemDescription =
* ClientContext.doWithContext(context, new {@code Callable<String>}() {
* public String call() {
* return (String) mbeanServer.getAttribute(mbean, "LastProblemDescription");
* }
* });
* </pre>
*
* @param <T> the type of value that the task will return. This type
* parameter is usually inferred from the type of the {@code task}
* parameter. For example, if {@code task} is a {@code Callable<String>}
* then {@code T} is {@code String}. If the task does not return a value,
* use a {@code Callable<Void>} and return null from its
* {@link Callable#call call} method.
* @param context the context to use while executing {@code task}.
* @param task the task to run with the {@code key}={@code value}
* binding.
* @return the result of {@link Callable#call() task.call()}.
* @throws IllegalArgumentException if either parameter is null, or
* if any key in {@code context} is null or empty, or if any value
* in {@code context} is null.
* @throws Exception If {@link Callable#call() task.call()} throws an
* exception, {@code doWithContext} throws the same exception.
*/
public
static
<
T
>
T
doWithContext
(
Map
<
String
,
String
>
context
,
Callable
<
T
>
task
)
throws
Exception
{
if
(
context
==
null
||
task
==
null
)
throw
new
IllegalArgumentException
(
"Null parameter"
);
Map
<
String
,
String
>
contextCopy
=
new
TreeMap
<
String
,
String
>(
context
);
validateContext
(
contextCopy
);
Map
<
String
,
String
>
oldContextMap
=
contextThreadLocal
.
get
();
try
{
contextThreadLocal
.
set
(
contextCopy
);
return
task
.
call
();
}
finally
{
contextThreadLocal
.
set
(
oldContextMap
);
}
}
private
static
void
validateContext
(
Map
<
String
,
String
>
context
)
{
for
(
Map
.
Entry
<
String
,
String
>
entry
:
context
.
entrySet
())
{
// If the user passes a raw Map rather than a Map<String, String>,
// entries could contain objects other than Strings. If so,
// we'll get a ClassCastException here.
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
if
(
key
==
null
||
value
==
null
)
throw
new
IllegalArgumentException
(
"Null key or value in context"
);
if
(
key
.
equals
(
""
))
throw
new
IllegalArgumentException
(
"Empty key in context"
);
}
}
/**
* <p>Return an MBeanServer object that is equivalent to the given
* MBeanServer object except that operations on MBeans run with
* the given Locale in their {@linkplain #getContext() thread context}.
* Note that this will only work if the given MBeanServer supports
* contexts, as described <a href="#remote-use">above</a>.</p>
*
* <p>This method is equivalent to {@link #withContext(MBeanServer,
* String, String) withContext}<code>(mbs, {@value LOCALE_KEY},
* locale.toString())</code>.</p>
*
* @throws IllegalArgumentException if either parameter is null, or if
* {@code mbs} does not support contexts. In the second case only,
* the cause of the {@code IllegalArgumentException} will be an {@link
* InstanceNotFoundException}.
*/
public
static
MBeanServer
withLocale
(
MBeanServer
mbs
,
Locale
locale
)
{
return
withLocale
(
mbs
,
MBeanServer
.
class
,
locale
);
}
/**
* <p>Return an MBeanServerConnection object that is equivalent to the given
* MBeanServerConnection object except that operations on MBeans run with
* the given Locale in their {@linkplain #getContext() thread context}.
* Note that this will only work if the given MBeanServerConnection supports
* contexts, as described <a href="#remote-use">above</a>.</p>
*
* <p>This method is equivalent to {@link #withContext(MBeanServerConnection,
* String, String) withContext}<code>(mbs, {@value LOCALE_KEY},
* locale.toString())</code>.</p>
*
* @throws IllegalArgumentException if either parameter is null, or if
* the communication with {@code mbsc} fails, or if {@code mbsc} does not
* support contexts. If the communication with {@code mbsc} fails, the
* {@linkplain Throwable#getCause() cause} of this exception will be an
* {@code IOException}. If {@code mbsc} does not support contexts, the
* cause will be an {@link InstanceNotFoundException}.
*/
public
static
MBeanServerConnection
withLocale
(
MBeanServerConnection
mbsc
,
Locale
locale
)
{
return
withLocale
(
mbsc
,
MBeanServerConnection
.
class
,
locale
);
}
private
static
<
T
extends
MBeanServerConnection
>
T
withLocale
(
T
mbsc
,
Class
<
T
>
mbscClass
,
Locale
locale
)
{
if
(
locale
==
null
)
throw
new
IllegalArgumentException
(
"Null locale"
);
return
withContext
(
mbsc
,
mbscClass
,
LOCALE_KEY
,
locale
.
toString
());
}
/**
* <p>Return an MBeanServer object that is equivalent to the given
* MBeanServer object except that operations on MBeans run with
* the given key bound to the given value in their {@linkplain
* #getContext() thread context}.
* Note that this will only work if the given MBeanServer supports
* contexts, as described <a href="#remote-use">above</a>.</p>
*
* @param mbs the original MBeanServer.
* @param key the key to bind in the context of MBean operations
* in the returned MBeanServer object.
* @param value the value to bind to the key in the context of MBean
* operations in the returned MBeanServer object.
* @throws IllegalArgumentException if any parameter is null, or
* if {@code key} is the empty string, or if {@code mbs} does not support
* contexts. In the last case only, the cause of the {@code
* IllegalArgumentException} will be an {@link InstanceNotFoundException}.
*/
public
static
MBeanServer
withContext
(
MBeanServer
mbs
,
String
key
,
String
value
)
{
return
withContext
(
mbs
,
MBeanServer
.
class
,
key
,
value
);
}
/**
* <p>Return an MBeanServerConnection object that is equivalent to the given
* MBeanServerConnection object except that operations on MBeans run with
* the given key bound to the given value in their {@linkplain
* #getContext() thread context}.
* Note that this will only work if the given MBeanServerConnection supports
* contexts, as described <a href="#remote-use">above</a>.</p>
*
* @param mbsc the original MBeanServerConnection.
* @param key the key to bind in the context of MBean operations
* in the returned MBeanServerConnection object.
* @param value the value to bind to the key in the context of MBean
* operations in the returned MBeanServerConnection object.
* @throws IllegalArgumentException if any parameter is null, or
* if {@code key} is the empty string, or if the communication with {@code
* mbsc} fails, or if {@code mbsc} does not support contexts. If
* the communication with {@code mbsc} fails, the {@linkplain
* Throwable#getCause() cause} of this exception will be an {@code
* IOException}. If {@code mbsc} does not support contexts, the cause will
* be an {@link InstanceNotFoundException}.
*/
public
static
MBeanServerConnection
withContext
(
MBeanServerConnection
mbsc
,
String
key
,
String
value
)
{
return
withContext
(
mbsc
,
MBeanServerConnection
.
class
,
key
,
value
);
}
/**
* <p>Returns an MBeanServerConnection object that is equivalent to the
* given MBeanServerConnection object except that remote operations on
* MBeans run with the context that has been established by the client
* using {@link #doWithContext doWithContext}. Note that this will
* only work if the remote system supports contexts, as described <a
* href="#remote-use">above</a>.</p>
*
* <p>For example, suppose the remote system does support contexts, and you
* have created a {@code JMXConnector} like this:</p>
*
* <pre>
* JMXServiceURL url = ...;
* JMXConnector client = JMXConnectorFactory.connect(url);
* MBeanServerConnection mbsc = client.getMBeanServerConnection();
* <b>mbsc = ClientContext.withDynamicContext(mbsc);</b>
* </pre>
*
* <p>Then if you do this...</p>
*
* <pre>
* MBeanInfo mbi = ClientContext.doWithContext(
* Collections.singletonMap(ClientContext.LOCALE_KEY, "fr"),
* new {@code Callable<MBeanInfo>}() {
* public MBeanInfo call() {
* return mbsc.getMBeanInfo(objectName);
* }
* });
* </pre>
*
* <p>...then the context with the locale set to "fr" will be in place
* when the {@code getMBeanInfo} is executed on the remote MBean Server.</p>
*
* @param mbsc the original MBeanServerConnection.
*
* @throws IllegalArgumentException if the {@code mbsc} parameter is null,
* or if the communication with {@code mbsc} fails, or if {@code mbsc}
* does not support contexts. If the communication with {@code mbsc}
* fails, the {@linkplain Throwable#getCause() cause} of this exception
* will be an {@code IOException}. If {@code mbsc} does not support
* contexts, the cause will be an {@link InstanceNotFoundException}.
*/
public
static
MBeanServerConnection
withDynamicContext
(
MBeanServerConnection
mbsc
)
{
// Probe mbsc to get the right exception if it's incommunicado or
// doesn't support namespaces.
JMXNamespaces
.
narrowToNamespace
(
mbsc
,
NAMESPACE
);
return
(
MBeanServerConnection
)
Proxy
.
newProxyInstance
(
MBeanServerConnection
.
class
.
getClassLoader
(),
new
Class
<?>[]
{
MBeanServerConnection
.
class
},
new
DynamicContextIH
(
mbsc
));
}
private
static
class
DynamicContextIH
implements
InvocationHandler
{
private
final
MBeanServerConnection
mbsc
;
public
DynamicContextIH
(
MBeanServerConnection
mbsc
)
{
this
.
mbsc
=
mbsc
;
}
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
MBeanServerConnection
dynMBSC
=
withContext
(
mbsc
,
MBeanServerConnection
.
class
,
getContext
(),
false
);
try
{
return
method
.
invoke
(
dynMBSC
,
args
);
}
catch
(
InvocationTargetException
e
)
{
throw
e
.
getCause
();
}
}
}
private
static
<
T
extends
MBeanServerConnection
>
T
withContext
(
T
mbsc
,
Class
<
T
>
mbscClass
,
String
key
,
String
value
)
{
return
withContext
(
mbsc
,
mbscClass
,
Collections
.
singletonMap
(
key
,
value
),
true
);
}
private
static
<
T
extends
MBeanServerConnection
>
T
withContext
(
T
mbsc
,
Class
<
T
>
mbscClass
,
Map
<
String
,
String
>
context
,
boolean
probe
)
{
if
(
mbsc
==
null
||
context
==
null
)
throw
new
IllegalArgumentException
(
"Null parameter"
);
if
(
context
.
isEmpty
())
return
mbsc
;
validateContext
(
context
);
Map
<
String
,
String
>
contextMap
=
null
;
if
(
mbsc
.
getClass
()
==
RoutingServerProxy
.
class
||
mbsc
.
getClass
()
==
RoutingProxy
.
class
)
{
RoutingProxy
<?>
nsp
=
(
RoutingProxy
<?>)
mbsc
;
String
where
=
nsp
.
getSourceNamespace
();
if
(
where
.
startsWith
(
NAMESPACE_PLUS_SEP
))
{
/* Try to merge the existing context namespace with the
* new one. If it doesn't work, we fall back to just
* prefixing jmx.context//key=value, which
* might lead to a name like jmx.c//k1=v1//jmx.c//k2=v2//d:k=v.
*/
String
encodedContext
=
where
.
substring
(
NAMESPACE_PLUS_SEP
.
length
());
if
(
encodedContext
.
indexOf
(
NAMESPACE_SEPARATOR
)
<
0
)
{
contextMap
=
stringToMapOrNull
(
encodedContext
);
if
(
contextMap
!=
null
)
{
contextMap
.
putAll
(
context
);
mbsc
=
mbscClass
.
cast
(
nsp
.
source
());
}
}
}
}
if
(
contextMap
==
null
)
contextMap
=
context
;
String
contextDir
=
NAMESPACE_PLUS_SEP
+
mapToString
(
contextMap
);
if
(
mbscClass
==
MBeanServer
.
class
)
{
return
mbscClass
.
cast
(
RoutingServerProxy
.
cd
(
(
MBeanServer
)
mbsc
,
contextDir
,
probe
));
}
else
if
(
mbscClass
==
MBeanServerConnection
.
class
)
{
return
mbscClass
.
cast
(
RoutingConnectionProxy
.
cd
(
mbsc
,
contextDir
,
probe
));
}
else
throw
new
AssertionError
(
"Bad MBSC: "
+
mbscClass
);
}
/**
* <p>Returns an encoded context prefix for ObjectNames.
* If the given context is empty, {@code ""} is returned.
* Otherwise, this method returns a string of the form
* {@code "jmx.context//key=value;key=value;..."}.
* For example, if the context has keys {@code "jmx.locale"}
* and {@code "xid"} with respective values {@code "fr"}
* and {@code "1234"}, this method will return
* {@code "jmx.context//jmx.locale=fr;xid=1234"} or
* {@code "jmx.context//xid=1234;jmx.locale=fr"}.</p>
*
* <p>Each key and each value in the encoded string is subject to
* encoding as if by the method {@link URLEncoder#encode(String, String)}
* with a character encoding of {@code "UTF-8"}, but with the additional
* encoding of any {@code *} character as {@code "%2A"}. This ensures
* that keys and values can contain any character. Without encoding,
* characters such as {@code =} and {@code :} would pose problems.</p>
*
* @param context the context to encode.
*
* @return the context in encoded form.
*
* @throws IllegalArgumentException if the {@code context} parameter
* is null or if it contains a null key or value.
**/
public
static
String
encode
(
Map
<
String
,
String
>
context
)
{
if
(
context
==
null
)
throw
new
IllegalArgumentException
(
"Null context"
);
if
(
context
.
isEmpty
())
return
""
;
StringBuilder
sb
=
new
StringBuilder
();
for
(
Map
.
Entry
<
String
,
String
>
entry
:
context
.
entrySet
())
{
String
key
=
entry
.
getKey
();
String
value
=
entry
.
getValue
();
if
(
key
==
null
||
value
==
null
)
throw
new
IllegalArgumentException
(
"Null key or value"
);
if
(
sb
.
length
()
>
0
)
sb
.
append
(
";"
);
sb
.
append
(
encode
(
key
)).
append
(
"="
).
append
(
encode
(
value
));
}
sb
.
insert
(
0
,
NAMESPACE_PLUS_SEP
);
return
sb
.
toString
();
}
/**
* <p>Create a new {@link MBeanServerForwarder} that applies the context
* received from a client to the current thread. A client using
* one of the various {@code with*} methods (for example {@link
* #withContext(MBeanServerConnection, String, String) withContext}) will
* encode that context into the {@code ObjectName} of each
* {@code MBeanServer} request. The object returned by this method
* decodes the context from that {@code ObjectName} and applies it
* as described for {@link #doWithContext doWithContext} while performing
* the {@code MBeanServer} request using the {@code ObjectName} without
* the encoded context.</p>
*
* <p>This forwarder can be used in a number of ways:</p>
*
* <ul>
* <li>
* <p>To add context decoding to a local {@code MBeanServer}, you can
* write:</p>
* <pre>
* MBeanServer mbs = {@link
* java.lang.management.ManagementFactory#getPlatformMBeanServer()
* ManagementFactory.getPlatformMBeanServer()}; // for example
* mbs = ClientContext.newContextForwarder(mbs, null);
* </pre>
*
* <li>
* <p>To add context decoding to a {@linkplain
* javax.management.remote.JMXConnectorServer connector server}:</p>
* <pre>
* JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
* MBeanServer nextMBS = cs.getMBeanServer();
* MBeanServerForwarder mbsf = ClientContext.newContextForwarder(nextMBS, null);
* cs.{@link
* javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
* setMBeanServerForwarder}(mbsf);
* </pre>
*
* <li>
* <p>For connectors, such as the standard RMI connector, that support
* a {@linkplain
* javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
* system chain} of {@code MBeanServerForwarder}s, this forwarder will
* be installed in that chain by default. See
* {@link javax.management.remote.JMXConnectorServer#CONTEXT_FORWARDER
* JMXConnectorServer.CONTEXT_FORWARDER}.
* </p>
*
* </ul>
*
* @param nextMBS the next {@code MBeanServer} in the chain of
* forwarders, which might be another {@code MBeanServerForwarder} or
* a plain {@code MBeanServer}. This is the object to which {@code
* MBeanServer} requests that do not include a context are sent. It
* will be the value of {@link MBeanServerForwarder#getMBeanServer()
* getMBeanServer()} on the returned object, and can be changed with {@link
* MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
* must be set to a non-null value before any {@code MBeanServer} requests
* arrive.
*
* @param loopMBS the {@code MBeanServer} to which requests that contain
* an encoded context should be sent once the context has been decoded.
* For example, if the request is {@link MBeanServer#getAttribute
* getAttribute}{@code ("jmx.context//jmx.locale=fr//java.lang:type=Runtime",
* "Name")}, then the {@linkplain #getContext() context} of the thread
* executing that request will have {@code "jmx.locale"} set to {@code "fr"}
* while executing {@code loopMBS.getAttribute("java.lang:type=Runtime",
* "Name")}. If this parameter is null, then these requests will be
* sent to the newly-created {@code MBeanServerForwarder}. Usually
* the parameter will either be null or will be the result of {@link
* javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
* getSystemMBeanServerForwarder()} for the connector server in which
* this forwarder will be installed.
*
* @return a new {@code MBeanServerForwarder} that decodes client context
* from {@code ObjectName}s.
*/
/*
* What we're building here is confusing enough to need a diagram.
* The MBSF that we return is actually the composition of two forwarders:
* the first one simulates the existence of the MBean
* jmx.context//:type=JMXNamespace, and the second one simulates the
* existence of the namespace jmx.context//. Furthermore, that namespace
* loops back to the composed forwarder, so that something like
* jmx.context//foo=bar//jmxcontext//baz=buh will work. And the loopback
* goes through yet another forwarder, which simulates the existence of
* (e.g.) jmx.context//foo=bar//:type=JMXNamespace, which is needed
* notably so that narrowToNamespace will work.
*
* | +--------------------------------------------------+
* v v |
* +----------------+ |
* | Handler MBSF |->accesses to jmx.context//:type=JMXNamespace |
* +----------------+ (handled completely here) +-------------------+
* | | 2nd Handler MBSF |
* v +-------------------+
* +----------------+ ^
* | Namespace MBSF |->accesses to jmx.context//**-------------------+
* +----------------+ (after attaching context to thread)
* |
* v accesses to anything else
*
* And finally, we need to ensure that from the outside the composed object
* looks like a single forwarder, so that its get/setMBeanServer methods
* will do the expected thing. That's what the anonymous subclass is for.
*/
public
static
MBeanServerForwarder
newContextForwarder
(
MBeanServer
nextMBS
,
MBeanServer
loopMBS
)
{
final
MBeanServerForwarder
mbsWrapper
=
new
IdentityMBeanServerForwarder
(
nextMBS
);
DynamicMBean
handlerMBean
=
new
StandardMBean
(
new
JMXNamespace
(
mbsWrapper
),
JMXNamespaceMBean
.
class
,
false
);
SingleMBeanForwarder
handlerForwarder
=
new
SingleMBeanForwarder
(
CLIENT_CONTEXT_NAMESPACE_HANDLER
,
handlerMBean
,
true
)
{
@Override
public
MBeanServer
getMBeanServer
()
{
return
((
MBeanServerForwarder
)
super
.
getMBeanServer
()).
getMBeanServer
();
}
@Override
public
void
setMBeanServer
(
MBeanServer
mbs1
)
{
MBeanServerForwarder
mbsf1
=
(
MBeanServerForwarder
)
super
.
getMBeanServer
();
if
(
mbsf1
!=
null
)
mbsf1
.
setMBeanServer
(
mbs1
);
else
super
.
setMBeanServer
(
mbs1
);
mbsWrapper
.
setMBeanServer
(
mbs1
);
}
};
if
(
loopMBS
==
null
)
loopMBS
=
handlerForwarder
;
ContextInvocationHandler
contextIH
=
new
ContextInvocationHandler
(
nextMBS
,
loopMBS
);
MBeanServerForwarder
contextForwarder
=
newForwarderProxy
(
contextIH
);
handlerForwarder
.
setMBeanServer
(
contextForwarder
);
return
handlerForwarder
;
}
/**
* <p>Create a new {@link MBeanServerForwarder} that localizes
* descriptions in {@code MBeanInfo} instances returned by
* {@link MBeanServer#getMBeanInfo getMBeanInfo}. The {@code
* MBeanServerForwarder} returned by this method passes all {@code
* MBeanServer} methods through unchanged to the supplied object, {@code
* mbs}, with the exception of {@code getMBeanInfo}. To handle {@code
* getMBeanInfo(objectName)}, it calls {@code mbs.getMBeanInfo(objectName)}
* to get an {@code MBeanInfo}, {@code mbi}; it calls {@link
* MBeanServer#getClassLoaderFor mbs.getClassLoaderFor(objectName)} to
* get a {@code ClassLoader}, {@code cl}; and it calls {@link
* #getLocale} to get a {@code Locale}, {@code locale}. The order
* of these three calls is not specified. Then the result is {@code
* mbi.localizeDescriptions(locale, loader)}.</p>
*
* <p>This forwarder can be used in a number of ways:</p>
*
* <ul>
* <li>
* <p>To add description localization to a local {@code MBeanServer}, you
* can write:</p>
*
* <pre>
* MBeanServer mbs = {@link
* java.lang.management.ManagementFactory#getPlatformMBeanServer()
* ManagementFactory.getPlatformMBeanServer()}; // for example
* mbs = ClientContext.newLocalizeMBeanInfoForwarder(mbs);
* </pre>
*
* <li>
* <p>To add description localization to a {@linkplain
* javax.management.remote.JMXConnectorServer connector server}, you will
* need to add both a {@linkplain #newContextForwarder context forwarder}
* and a localization forwarder, for example like this:</p>
*
* <pre>
* JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
* MBeanServer nextMBS = cs.getMBeanServer();
* MBeanServerForwarder localizeMBSF =
* ClientContext.newLocalizeMBeanInfoForwarder(nextMBS);
* MBeanServerForwarder contextMBSF =
* ClientContext.newContextForwarder(localizeMBSF, null);
* cs.{@link
* javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
* setMBeanServerForwarder}(contextMBSF);
* </pre>
*
* <p>Notice that the context forwarder must run before the localization
* forwarder, so that the locale is correctly established when the latter
* runs. So the {@code nextMBS} parameter of the context forwarder must
* be the localization forwarder, and not vice versa.</p>
*
* <li>
* <p>For connectors, such as the standard RMI connector, that support
* a {@linkplain
* javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
* system chain} of {@code MBeanServerForwarder}s, the context forwarder and
* the localization forwarder will be installed in that chain, in the right
* order, if you include
* {@link
* javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
* LOCALIZE_MBEAN_INFO_FORWARDER} in the environment {@code Map} with
* the value {@code "true"}, for example like this:</p>
* </p>
* <pre>
* MBeanServer mbs = ...;
* JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://...");
* {@code Map<String, Object>} env = new {@code HashMap<String, Object>}();
* env.put(JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER, "true");
* JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
* url, env, mbs);
* </pre>
*
* </ul>
*
* @param mbs the next {@code MBeanServer} in the chain of
* forwarders, which might be another {@code MBeanServerForwarder}
* or a plain {@code MBeanServer}. It will be the value of
* {@link MBeanServerForwarder#getMBeanServer() getMBeanServer()}
* on the returned object, and can be changed with {@link
* MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
* must be set to a non-null value before any {@code MBeanServer} requests
* arrive.
*
* @return a new {@code MBeanServerForwarder} that localizes descriptions
* in the result of {@code getMBeanInfo}.
*/
public
static
MBeanServerForwarder
newLocalizeMBeanInfoForwarder
(
MBeanServer
mbs
)
{
return
new
IdentityMBeanServerForwarder
(
mbs
)
{
@Override
public
MBeanInfo
getMBeanInfo
(
ObjectName
name
)
throws
InstanceNotFoundException
,
IntrospectionException
,
ReflectionException
{
MBeanInfo
mbi
=
super
.
getMBeanInfo
(
name
);
Locale
locale
=
getLocale
();
ClassLoader
loader
=
getClassLoaderFor
(
name
);
return
mbi
.
localizeDescriptions
(
locale
,
loader
);
}
};
}
private
static
MBeanServerForwarder
newForwarderProxy
(
InvocationHandler
ih
)
{
return
(
MBeanServerForwarder
)
Proxy
.
newProxyInstance
(
MBeanServerForwarder
.
class
.
getClassLoader
(),
new
Class
<?>[]
{
MBeanServerForwarder
.
class
},
ih
);
}
// A proxy connection that will strip the 'contextDir' at input (routing),
// and put it back at output (createMBean / registerMBean / query* /
// getObjectInstance). Usually RoutingProxy / RoutingServerProxy are used
// the other way round (they are used for 'cd' - where they need to add
// something at input and remove it at output).
// For 'cd' operations we create RoutingProxys with a non empty sourceDir,
// and a possibly non-empty targetDir. This is the only case where we use
// RoutingProxies with an empty sourceDir (sourceDir is what we add at input
// and remove at output, targetDir is what we remove at input and add at
// output.
//
// Note that using a transient ContextRoutingConnection
// is possible only because RoutingProxys don't rewrite
// notifications sources - otherwise we would have to
// keep the ContextRoutingConnection - just to preserve
// the 'wrapping listeners'
//
private
static
final
class
ContextRoutingConnection
extends
RoutingServerProxy
{
public
ContextRoutingConnection
(
MBeanServer
source
,
String
contextDir
)
{
super
(
source
,
""
,
contextDir
,
false
);
}
// Not really needed - but this is safer and more optimized.
// See RoutingProxy for more details.
//
@Override
public
Integer
getMBeanCount
()
{
return
source
().
getMBeanCount
();
}
// Not really needed - but this is safer and more optimized.
// See RoutingProxy for more details.
//
@Override
public
String
[]
getDomains
()
{
return
source
().
getDomains
();
}
// Not really needed - but this is safer and more optimized.
// See RoutingProxy for more details.
//
@Override
public
String
getDefaultDomain
()
{
return
source
().
getDefaultDomain
();
}
}
private
static
class
ContextInvocationHandler
implements
InvocationHandler
{
/*
* MBeanServer requests that don't include jmx.context//foo=bar//
* are forwarded to forwardMBS, which is the unadorned MBeanServer
* that knows nothing about the context namespace.
* MBeanServer requests that do include this prefix will
* usually (depending on the value of the loopMBS parameter to
* newContextForwarder) loop back to the combined MBeanServerForwarder
* that first implements
* jmx.context//:type=JMXNamespace and then implements
* jmx.context//foo=bar//. The reason is that it is valid
* to have jmx.context//foo=bar//jmx.context//baz=buh//, although
* usually that will be combined into jmx.context//foo=bar;baz=buh//.
*
* Before forwarding to loopMBS, we must check for :type=JMXNamespace
* so that jmx.context//foo=bar//:type=JMXNamespace will exist. Its
* existence is partial because it must remain "invisible": it should
* not show up in queryNames or getMBeanCount even though it does
* accept getAttribute and isRegistered and all other methods that
* reference a single MBean.
*/
private
MBeanServer
forwardMBS
;
private
final
MBeanServer
loopMBS
;
private
static
final
MBeanServer
emptyMBS
=
new
MBeanServerSupport
()
{
@Override
public
DynamicMBean
getDynamicMBeanFor
(
ObjectName
name
)
throws
InstanceNotFoundException
{
throw
new
InstanceNotFoundException
(
name
.
toString
());
}
@Override
protected
Set
<
ObjectName
>
getNames
()
{
return
Collections
.
emptySet
();
}
};
ContextInvocationHandler
(
MBeanServer
forwardMBS
,
MBeanServer
loopMBS
)
{
this
.
forwardMBS
=
forwardMBS
;
DynamicMBean
handlerMBean
=
new
StandardMBean
(
new
JMXNamespace
(
loopMBS
),
JMXNamespaceMBean
.
class
,
false
);
MBeanServerForwarder
handlerMBS
=
new
SingleMBeanForwarder
(
NAMESPACE_HANDLER_WITHOUT_NAMESPACE
,
handlerMBean
,
false
);
handlerMBS
.
setMBeanServer
(
loopMBS
);
this
.
loopMBS
=
handlerMBS
;
}
public
Object
invoke
(
Object
proxy
,
final
Method
method
,
final
Object
[]
args
)
throws
Throwable
{
String
methodName
=
method
.
getName
();
Class
<?>[]
paramTypes
=
method
.
getParameterTypes
();
// If this is a method from MBeanServerForwarder, handle it here.
// There are only two such methods: getMBeanServer() and
// setMBeanServer(mbs).
if
(
methodName
.
equals
(
"getMBeanServer"
))
return
forwardMBS
;
else
if
(
methodName
.
equals
(
"setMBeanServer"
))
{
this
.
forwardMBS
=
(
MBeanServer
)
args
[
0
];
return
null
;
}
// It is a method from MBeanServer.
// Find the first parameter whose declared type is ObjectName,
// and see if it is in the context namespace. If so we need to
// trigger the logic for that namespace. If not, we simply
// forward to the next MBeanServer in the chain. This logic
// depends on the fact that if a method in the MBeanServer interface
// has a "routing" ObjectName parameter, it is always the first
// parameter of that type. Conversely, if a method has an
// ObjectName parameter, then it makes sense to "route" that
// method. Except for deserialize and instantiate, but if we
// recognize a context namespace in those methods' ObjectName
// parameters it is pretty harmless.
int
objectNameI
=
-
1
;
for
(
int
i
=
0
;
i
<
paramTypes
.
length
;
i
++)
{
if
(
paramTypes
[
i
]
==
ObjectName
.
class
)
{
objectNameI
=
i
;
break
;
}
}
if
(
objectNameI
<
0
)
return
invoke
(
method
,
forwardMBS
,
args
);
ObjectName
target
=
(
ObjectName
)
args
[
objectNameI
];
if
(
target
==
null
||
!
target
.
getDomain
().
startsWith
(
NAMESPACE_PLUS_SEP
))
return
invoke
(
method
,
forwardMBS
,
args
);
String
domain
=
target
.
getDomain
().
substring
(
NAMESPACE_PLUS_SEP
.
length
());
// The method routes through the (simulated) context namespace.
// Decode the context after it, e.g. jmx.context//jmx.locale=fr//...
// If there is no context part, we can throw an exception,
// because a forwarder has already handled the unique MBean
// jmx.context//:type=JMXNamespace.
int
sep
=
domain
.
indexOf
(
NAMESPACE_SEPARATOR
);
if
(
sep
<
0
)
return
invoke
(
method
,
emptyMBS
,
args
);
// throw exception
final
String
encodedContext
=
domain
.
substring
(
0
,
sep
);
if
(
method
.
getName
().
startsWith
(
"query"
)
&&
(
encodedContext
.
contains
(
"*"
)
||
encodedContext
.
contains
(
"?"
)))
{
// Queries like jmx.context//*//d:k=v return
// an empty set, consistent with "real" namespaces.
return
Collections
.
EMPTY_SET
;
}
Map
<
String
,
String
>
ctx
=
new
TreeMap
<
String
,
String
>(
getContext
());
ctx
.
putAll
(
stringToMap
(
encodedContext
));
return
doWithContext
(
ctx
,
new
Callable
<
Object
>()
{
public
Object
call
()
throws
Exception
{
// Create a proxy connection that will strip
// "jmx.context//" + encodedContext + "//" on input,
// and put it back on output.
//
// Note that using a transient ContextRoutingConnection
// is possible only because it doesn't rewrite
// notification sources - otherwise we would have to
// keep the ContextRoutingConnection - just to preserve
// the 'wrapping listeners'
//
String
namespace
=
NAMESPACE_PLUS_SEP
+
encodedContext
;
final
ContextRoutingConnection
route
=
new
ContextRoutingConnection
(
loopMBS
,
namespace
);
if
(
LOG
.
isLoggable
(
Level
.
FINE
))
LOG
.
fine
(
"context="
+
encodedContext
);
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
method
.
getName
()+
""
+
((
args
==
null
)?
"()"
:(
""
+
Arrays
.
asList
(
args
))));
return
invoke
(
method
,
route
,
args
);
}
});
}
private
static
Object
invoke
(
Method
method
,
Object
target
,
Object
[]
args
)
throws
Exception
{
try
{
return
method
.
invoke
(
target
,
args
);
}
catch
(
InvocationTargetException
e
)
{
Throwable
cause
=
e
.
getCause
();
if
(
cause
instanceof
Error
)
throw
(
Error
)
cause
;
throw
(
Exception
)
cause
;
}
}
}
private
static
String
mapToString
(
Map
<
String
,
String
>
map
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
Map
.
Entry
<
String
,
String
>
entry
:
map
.
entrySet
())
{
String
key
=
encode
(
entry
.
getKey
());
String
value
=
encode
(
entry
.
getValue
());
if
(
sb
.
length
()
>
0
)
sb
.
append
(
";"
);
sb
.
append
(
key
).
append
(
"="
).
append
(
value
);
}
return
sb
.
toString
();
}
private
static
Map
<
String
,
String
>
stringToMap
(
String
encodedContext
)
{
Map
<
String
,
String
>
map
=
stringToMapOrNull
(
encodedContext
);
if
(
map
==
null
)
{
throw
new
IllegalArgumentException
(
"Invalid encoded context: "
+
encodedContext
);
}
return
map
;
}
private
static
Map
<
String
,
String
>
stringToMapOrNull
(
String
encodedContext
)
{
Map
<
String
,
String
>
map
=
new
LinkedHashMap
<
String
,
String
>();
StringTokenizer
stok
=
new
StringTokenizer
(
encodedContext
,
";"
);
while
(
stok
.
hasMoreTokens
())
{
String
tok
=
stok
.
nextToken
();
int
eq
=
tok
.
indexOf
(
'='
);
if
(
eq
<
0
)
return
null
;
String
key
=
decode
(
tok
.
substring
(
0
,
eq
));
if
(
key
.
equals
(
""
))
return
null
;
String
value
=
decode
(
tok
.
substring
(
eq
+
1
));
map
.
put
(
key
,
value
);
}
return
map
;
}
private
static
String
encode
(
String
s
)
{
try
{
s
=
URLEncoder
.
encode
(
s
,
"UTF-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
RuntimeException
(
e
);
// Should not happen
}
return
s
.
replace
(
"*"
,
"%2A"
);
// The * character is left intact in URL encodings, but for us it
// is special (an ObjectName wildcard) so we must map it.
// We are assuming that URLDecoder will decode it the same way as any
// other hex escape.
}
private
static
String
decode
(
String
s
)
{
try
{
return
URLDecoder
.
decode
(
s
,
"UTF-8"
);
}
catch
(
UnsupportedEncodingException
e
)
{
throw
new
RuntimeException
(
e
);
}
}
}
src/share/classes/javax/management/Descriptor.java
浏览文件 @
6b491fa1
...
@@ -35,8 +35,8 @@ import java.io.Serializable;
...
@@ -35,8 +35,8 @@ import java.io.Serializable;
// Javadoc imports:
// Javadoc imports:
import
java.lang.management.MemoryUsage
;
import
java.lang.management.MemoryUsage
;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Locale
;
import
java.util.ResourceBundle
;
import
java.util.ResourceBundle
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
javax.management.openmbean.OpenMBeanAttributeInfoSupport
;
import
javax.management.openmbean.OpenMBeanAttributeInfoSupport
;
...
@@ -118,19 +118,22 @@ import javax.management.openmbean.OpenType;
...
@@ -118,19 +118,22 @@ import javax.management.openmbean.OpenType;
* deprecation, for example {@code "1.3 Replaced by the Capacity
* deprecation, for example {@code "1.3 Replaced by the Capacity
* attribute"}.</td>
* attribute"}.</td>
*
*
* <tr
id="descriptionResourceBundleBaseName"
>
* <tr
><td id="descriptionResourceBundleBaseName"><i>descriptionResource<br
>
*
<td>descriptionResource<br>BundleBaseName
</td><td>String</td><td>Any</td>
*
BundleBaseName</i>
</td><td>String</td><td>Any</td>
*
*
* <td>The base name for the {@link ResourceBundle} in which the key given in
* <td>The base name for the {@link ResourceBundle} in which the key given in
* the {@code descriptionResourceKey} field can be found, for example
* the {@code descriptionResourceKey} field can be found, for example
* {@code "com.example.myapp.MBeanResources"}.</td>
* {@code "com.example.myapp.MBeanResources"}. See
* {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.</td>
*
*
* <tr
id="descriptionResourceKey"
>
* <tr
><td id="descriptionResourceKey"><i>descriptionResourceKey</i></td
>
* <td>
descriptionResourceKey</td><td>
String</td><td>Any</td>
* <td>String</td><td>Any</td>
*
*
* <td>A resource key for the description of this element. In
* <td>A resource key for the description of this element. In
* conjunction with the {@code descriptionResourceBundleBaseName},
* conjunction with the {@code descriptionResourceBundleBaseName},
* this can be used to find a localized version of the description.</td>
* this can be used to find a localized version of the description.
* See {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.
* </td>
*
*
* <tr><td>enabled</td><td>String</td>
* <tr><td>enabled</td><td>String</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
* <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
...
@@ -157,11 +160,11 @@ import javax.management.openmbean.OpenType;
...
@@ -157,11 +160,11 @@ import javax.management.openmbean.OpenType;
* href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a>
* href="MBeanInfo.html#info-changed">{@code "jmx.mbean.info.changed"}</a>
* notification.</td>
* notification.</td>
*
*
* <tr><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
* <tr
id="infoTimeout"
><td>infoTimeout</td><td>String<br>Long</td><td>MBeanInfo</td>
*
*
* <td
id="infoTimeout">The time in milli-seconds that the MBeanInfo can
* <td
>The time in milli-seconds that the MBeanInfo can reasonably be
*
reasonably be expected to be unchanged. The value can be a {@code Long}
*
expected to be unchanged. The value can be a {@code Long} or a
*
or a
decimal string. This provides a hint from a DynamicMBean or any
* decimal string. This provides a hint from a DynamicMBean or any
* MBean that does not define {@code immutableInfo} as {@code true}
* MBean that does not define {@code immutableInfo} as {@code true}
* that the MBeanInfo is not likely to change within this period and
* that the MBeanInfo is not likely to change within this period and
* therefore can be cached. When this field is missing or has the
* therefore can be cached. When this field is missing or has the
...
@@ -185,6 +188,13 @@ import javax.management.openmbean.OpenType;
...
@@ -185,6 +188,13 @@ import javax.management.openmbean.OpenType;
* <td>Legal values for an attribute or parameter. See
* <td>Legal values for an attribute or parameter. See
* {@link javax.management.openmbean}.</td>
* {@link javax.management.openmbean}.</td>
*
*
* <tr id="locale"><td><i>locale</i></td>
* <td>String</td><td>Any</td>
*
* <td>The {@linkplain Locale locale} of the description in this
* {@code MBeanInfo}, {@code MBeanAttributeInfo}, etc, as returned
* by {@link Locale#toString()}.</td>
*
* <tr id="maxValue"><td><i>maxValue</i><td>Object</td>
* <tr id="maxValue"><td><i>maxValue</i><td>Object</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
* <td>MBeanAttributeInfo<br>MBeanParameterInfo</td>
*
*
...
...
src/share/classes/javax/management/JMX.java
浏览文件 @
6b491fa1
...
@@ -30,6 +30,7 @@ import com.sun.jmx.mbeanserver.MBeanInjector;
...
@@ -30,6 +30,7 @@ import com.sun.jmx.mbeanserver.MBeanInjector;
import
com.sun.jmx.remote.util.ClassLogger
;
import
com.sun.jmx.remote.util.ClassLogger
;
import
java.beans.BeanInfo
;
import
java.beans.BeanInfo
;
import
java.beans.PropertyDescriptor
;
import
java.beans.PropertyDescriptor
;
import
java.io.IOException
;
import
java.io.Serializable
;
import
java.io.Serializable
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.InvocationTargetException
;
...
@@ -37,6 +38,7 @@ import java.lang.reflect.Method;
...
@@ -37,6 +38,7 @@ import java.lang.reflect.Method;
import
java.lang.reflect.Proxy
;
import
java.lang.reflect.Proxy
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.openmbean.MXBeanMappingFactory
;
import
javax.management.openmbean.MXBeanMappingFactory
;
/**
/**
...
@@ -60,6 +62,21 @@ public class JMX {
...
@@ -60,6 +62,21 @@ public class JMX {
*/
*/
public
static
final
String
DEFAULT_VALUE_FIELD
=
"defaultValue"
;
public
static
final
String
DEFAULT_VALUE_FIELD
=
"defaultValue"
;
/**
* The name of the <a
* href="Descriptor.html#descriptionResourceBundleBaseName">{@code
* descriptionResourceBundleBaseName}</a> field.
*/
public
static
final
String
DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
=
"descriptionResourceBundleBaseName"
;
/**
* The name of the <a href="Descriptor.html#descriptionResourceKey">{@code
* descriptionResourceKey}</a> field.
*/
public
static
final
String
DESCRIPTION_RESOURCE_KEY_FIELD
=
"descriptionResourceKey"
;
/**
/**
* The name of the <a href="Descriptor.html#immutableInfo">{@code
* The name of the <a href="Descriptor.html#immutableInfo">{@code
* immutableInfo}</a> field.
* immutableInfo}</a> field.
...
@@ -78,6 +95,12 @@ public class JMX {
...
@@ -78,6 +95,12 @@ public class JMX {
*/
*/
public
static
final
String
LEGAL_VALUES_FIELD
=
"legalValues"
;
public
static
final
String
LEGAL_VALUES_FIELD
=
"legalValues"
;
/**
* The name of the <a href="Descriptor.html#locale">{@code locale}</a>
* field.
*/
public
static
final
String
LOCALE_FIELD
=
"locale"
;
/**
/**
* The name of the <a href="Descriptor.html#maxValue">{@code
* The name of the <a href="Descriptor.html#maxValue">{@code
* maxValue}</a> field.
* maxValue}</a> field.
...
@@ -120,13 +143,12 @@ public class JMX {
...
@@ -120,13 +143,12 @@ public class JMX {
* <p>Options to apply to an MBean proxy or to an instance of {@link
* <p>Options to apply to an MBean proxy or to an instance of {@link
* StandardMBean}.</p>
* StandardMBean}.</p>
*
*
* <p>For example, to specify
a custom {@link MXBeanMappingFactory}
* <p>For example, to specify
the "wrapped object visible" option for a
*
for a
{@code StandardMBean}, you might write this:</p>
* {@code StandardMBean}, you might write this:</p>
*
*
* <pre>
* <pre>
* MXBeanMappingFactory factory = new MyMXBeanMappingFactory();
* StandardMBean.Options opts = new StandardMBean.Options();
* JMX.MBeanOptions opts = new JMX.MBeanOptions();
* opts.setWrappedObjectVisible(true);
* opts.setMXBeanMappingFactory(factory);
* StandardMBean mbean = new StandardMBean(impl, intf, opts);
* StandardMBean mbean = new StandardMBean(impl, intf, opts);
* </pre>
* </pre>
*
*
...
@@ -808,4 +830,80 @@ public class JMX {
...
@@ -808,4 +830,80 @@ public class JMX {
((
DynamicWrapperMBean
)
mbean
).
getWrappedObject
()
:
mbean
;
((
DynamicWrapperMBean
)
mbean
).
getWrappedObject
()
:
mbean
;
return
(
MBeanInjector
.
injectsSendNotification
(
resource
));
return
(
MBeanInjector
.
injectsSendNotification
(
resource
));
}
}
/**
* <p>Return the version of the JMX specification that a (possibly remote)
* MBean Server is using. The JMX specification described in this
* documentation is version 2.0. The earlier versions that might be
* reported by this method are 1.0, 1.1, 1.2, and 1.4. (There is no 1.3.)
* All of these versions and all future versions can be compared using
* {@link String#compareTo(String)}. So, for example, to tell if
* {@code mbsc} is running at least version 2.0 you can write:</p>
*
* <pre>
* String version = JMX.getSpecificationVersion(mbsc, null);
* boolean atLeast2dot0 = (version.compareTo("2.0") >= 0);
* </pre>
*
* <p>A remote MBean Server might be running an earlier version of the
* JMX API, and in that case <a href="package-summary.html#interop">certain
* features</a> might not be available in it.</p>
*
* <p>The version of the MBean Server {@code mbsc} is not necessarily
* the version of all namespaces within that MBean Server, for example
* if some of them use {@link javax.management.namespace.JMXRemoteNamespace
* JMXRemoteNamespace}. To determine the version of the namespace
* that a particular MBean is in, give its name as the {@code mbeanName}
* parameter.</p>
*
* @param mbsc a connection to an MBean Server.
*
* @param mbeanName the name of an MBean within that MBean Server, or null.
* If non-null, the namespace of this name, as determined by
* {@link JMXNamespaces#getContainingNamespace
* JMXNamespaces.getContainingNamespace}, is the one whose specification
* version will be returned.
*
* @return the JMX specification version reported by that MBean Server.
*
* @throws IllegalArgumentException if {@code mbsc} is null, or if
* {@code mbeanName} includes a wildcard character ({@code *} or {@code ?})
* in its namespace.
*
* @throws IOException if the version cannot be obtained, either because
* there is a communication problem or because the remote MBean Server
* does not have the appropriate {@linkplain
* MBeanServerDelegateMBean#getSpecificationVersion() attribute}.
*
* @see <a href="package-summary.html#interop">Interoperability between
* versions of the JMX specification</a>
* @see MBeanServerDelegateMBean#getSpecificationVersion
*/
public
static
String
getSpecificationVersion
(
MBeanServerConnection
mbsc
,
ObjectName
mbeanName
)
throws
IOException
{
if
(
mbsc
==
null
)
throw
new
IllegalArgumentException
(
"Null MBeanServerConnection"
);
String
namespace
;
if
(
mbeanName
==
null
)
namespace
=
""
;
else
namespace
=
JMXNamespaces
.
getContainingNamespace
(
mbeanName
);
if
(
namespace
.
contains
(
"*"
)
||
namespace
.
contains
(
"?"
))
{
throw
new
IllegalArgumentException
(
"ObjectName contains namespace wildcard: "
+
mbeanName
);
}
try
{
if
(
namespace
.
length
()
>
0
)
mbsc
=
JMXNamespaces
.
narrowToNamespace
(
mbsc
,
namespace
);
return
(
String
)
mbsc
.
getAttribute
(
MBeanServerDelegate
.
DELEGATE_NAME
,
"SpecificationVersion"
);
}
catch
(
IOException
e
)
{
throw
e
;
}
catch
(
Exception
e
)
{
throw
new
IOException
(
e
);
}
}
}
}
src/share/classes/javax/management/MBeanInfo.java
浏览文件 @
6b491fa1
...
@@ -25,6 +25,7 @@
...
@@ -25,6 +25,7 @@
package
javax.management
;
package
javax.management
;
import
com.sun.jmx.mbeanserver.Util
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.io.StreamCorruptedException
;
import
java.io.StreamCorruptedException
;
import
java.io.Serializable
;
import
java.io.Serializable
;
...
@@ -37,6 +38,12 @@ import java.util.WeakHashMap;
...
@@ -37,6 +38,12 @@ import java.util.WeakHashMap;
import
java.security.AccessController
;
import
java.security.AccessController
;
import
java.security.PrivilegedAction
;
import
java.security.PrivilegedAction
;
import
java.util.HashMap
;
import
java.util.Locale
;
import
java.util.MissingResourceException
;
import
java.util.ResourceBundle
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
static
javax
.
management
.
ImmutableDescriptor
.
nonNullDescriptor
;
import
static
javax
.
management
.
ImmutableDescriptor
.
nonNullDescriptor
;
/**
/**
...
@@ -290,6 +297,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
...
@@ -290,6 +297,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
* <p>Since this class is immutable, the clone method is chiefly of
* <p>Since this class is immutable, the clone method is chiefly of
* interest to subclasses.</p>
* interest to subclasses.</p>
*/
*/
@Override
public
Object
clone
()
{
public
Object
clone
()
{
try
{
try
{
return
super
.
clone
()
;
return
super
.
clone
()
;
...
@@ -474,6 +482,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
...
@@ -474,6 +482,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
return
(
Descriptor
)
nonNullDescriptor
(
descriptor
).
clone
();
return
(
Descriptor
)
nonNullDescriptor
(
descriptor
).
clone
();
}
}
@Override
public
String
toString
()
{
public
String
toString
()
{
return
return
getClass
().
getName
()
+
"["
+
getClass
().
getName
()
+
"["
+
...
@@ -505,6 +514,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
...
@@ -505,6 +514,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
* @return true if and only if <code>o</code> is an MBeanInfo that is equal
* @return true if and only if <code>o</code> is an MBeanInfo that is equal
* to this one according to the rules above.
* to this one according to the rules above.
*/
*/
@Override
public
boolean
equals
(
Object
o
)
{
public
boolean
equals
(
Object
o
)
{
if
(
o
==
this
)
if
(
o
==
this
)
return
true
;
return
true
;
...
@@ -524,6 +534,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
...
@@ -524,6 +534,7 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
Arrays
.
equals
(
p
.
fastGetNotifications
(),
fastGetNotifications
()));
Arrays
.
equals
(
p
.
fastGetNotifications
(),
fastGetNotifications
()));
}
}
@Override
public
int
hashCode
()
{
public
int
hashCode
()
{
/* Since computing the hashCode is quite expensive, we cache it.
/* Since computing the hashCode is quite expensive, we cache it.
If by some terrible misfortune the computed value is 0, the
If by some terrible misfortune the computed value is 0, the
...
@@ -747,4 +758,377 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
...
@@ -747,4 +758,377 @@ public class MBeanInfo implements Cloneable, Serializable, DescriptorRead {
throw
new
StreamCorruptedException
(
"Got unexpected byte."
);
throw
new
StreamCorruptedException
(
"Got unexpected byte."
);
}
}
}
}
/**
* <p>Return an {@code MBeanInfo} object that is the same as this one
* except that its descriptions are localized in the given locale.
* This means the text returned by {@link MBeanInfo#getDescription}
* (the description of the MBean itself), and the text returned by the
* {@link MBeanFeatureInfo#getDescription getDescription()} method
* for every {@linkplain MBeanAttributeInfo attribute}, {@linkplain
* MBeanOperationInfo operation}, {@linkplain MBeanConstructorInfo
* constructor}, and {@linkplain MBeanNotificationInfo notification}
* contained in the {@code MBeanInfo}.</p>
*
* <p>Here is how the description {@code this.getDescription()} is
* localized.</p>
*
* <p>First, if the {@linkplain #getDescriptor() descriptor}
* of this {@code MBeanInfo} contains a field <code><a
* href="Descriptor.html#locale">"locale"</a></code>, and the value of
* the field is the same as {@code locale.toString()}, then this {@code
* MBeanInfo} is returned. Otherwise, localization proceeds as follows,
* and the {@code "locale"} field in the returned {@code MBeanInfo} will
* be {@code locale.toString()}.
*
* <p>A <em>{@code className}</em> is determined. If this
* {@code MBeanInfo} contains a descriptor with the field
* <a href="Descriptor.html#interfaceClassName">{@code
* "interfaceClassName"}</a>, then the value of that field is the
* {@code className}. Otherwise, it is {@link #getClassName()}.
* Everything before the last period (.) in the {@code className} is
* the <em>{@code package}</em>, and everything after is the <em>{@code
* simpleClassName}</em>. (If there is no period, then the {@code package}
* is empty and the {@code simpleClassName} is the same as the {@code
* className}.)</p>
*
* <p>A <em>{@code resourceKey}</em> is determined. If this {@code
* MBeanInfo} contains a {@linkplain MBeanInfo#getDescriptor() descriptor}
* with a field {@link JMX#DESCRIPTION_RESOURCE_KEY_FIELD
* "descriptionResourceKey"}, the value of the field is
* the {@code resourceKey}. Otherwise, the {@code resourceKey} is {@code
* simpleClassName + ".mbean"}.</p>
*
* <p>A <em>{@code resourceBundleBaseName}</em> is determined. If
* this {@code MBeanInfo} contains a descriptor with a field {@link
* JMX#DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
* "descriptionResourceBundleBaseName"}, the value of the field
* is the {@code resourceBundleBaseName}. Otherwise, the {@code
* resourceBundleBaseName} is {@code package + ".MBeanDescriptions"}.
*
* <p>Then, a {@link java.util.ResourceBundle ResourceBundle} is
* determined, using<br> {@link java.util.ResourceBundle#getBundle(String,
* Locale, ClassLoader) ResourceBundle.getBundle(resourceBundleBaseName,
* locale, loader)}. If this succeeds, and if {@link
* java.util.ResourceBundle#getString(String) getString(resourceKey)}
* returns a string, then that string is the localized description.
* Otherwise, the original description is unchanged.</p>
*
* <p>A localized description for an {@code MBeanAttributeInfo} is
* obtained similarly. The default {@code resourceBundleBaseName}
* is the same as above. The default description and the
* descriptor fields {@code "descriptionResourceKey"} and {@code
* "descriptionResourceBundleBaseName"} come from the {@code
* MBeanAttributeInfo} rather than the {@code MBeanInfo}. If the
* attribute's {@linkplain MBeanFeatureInfo#getName() name} is {@code
* Foo} then its default {@code resourceKey} is {@code simpleClassName +
* ".attribute.Foo"}.</p>
*
* <p>Similar rules apply for operations, constructors, and notifications.
* If the name of the operation, constructor, or notification is {@code
* Foo} then the default {@code resourceKey} is respectively {@code
* simpleClassName + ".operation.Foo"}, {@code simpleClassName +
* ".constructor.Foo"}, or {@code simpleClassName + ".notification.Foo"}.
* If two operations or constructors have the same name (overloading) then
* they have the same default {@code resourceKey}; if different localized
* descriptions are needed then a non-default key must be supplied using
* {@code "descriptionResourceKey"}.</p>
*
* <p>Similar rules also apply for descriptions of parameters ({@link
* MBeanParameterInfo}). The default {@code resourceKey} for a parameter
* whose {@linkplain MBeanFeatureInfo#getName() name} is {@code
* Bar} in an operation or constructor called {@code Foo} is {@code
* simpleClassName + ".operation.Foo.Bar"} or {@code simpleClassName +
* ".constructor.Foo.Bar"} respectively.</p>
*
* <h4>Example</h4>
*
* <p>Suppose you have an MBean defined by these two Java source files:</p>
*
* <pre>
* // ConfigurationMBean.java
* package com.example;
* public interface ConfigurationMBean {
* public String getName();
* public void save(String fileName);
* }
*
* // Configuration.java
* package com.example;
* public class Configuration implements ConfigurationMBean {
* public Configuration(String defaultName) {
* ...
* }
* ...
* }
* </pre>
*
* <p>Then you could define the default descriptions for the MBean, by
* including a resource bundle called {@code com/example/MBeanDescriptions}
* with the compiled classes. Most often this is done by creating a file
* {@code MBeanDescriptions.properties} in the same directory as {@code
* ConfigurationMBean.java}. Make sure that this file is copied into the
* same place as the compiled classes; in typical build environments that
* will be true by default.</p>
*
* <p>The file {@code com/example/MBeanDescriptions.properties} might
* look like this:</p>
*
* <pre>
* # Description of the MBean
* ConfigurationMBean.mbean = Configuration manager
*
* # Description of the Name attribute
* ConfigurationMBean.attribute.Name = The name of the configuration
*
* # Description of the save operation
* ConfigurationMBean.operation.save = Save the configuration to a file
*
* # Description of the parameter to the save operation.
* # Parameter names from the original Java source are not available,
* # so the default names are p1, p2, etc. If the names were available,
* # this would be ConfigurationMBean.operation.save.fileName
* ConfigurationMBean.operation.save.p1 = The name of the file
*
* # Description of the constructor. The default name of a constructor is
* # its fully-qualified class name.
* ConfigurationMBean.constructor.com.example.Configuration = <!--
* -->Constructor with name of default file
* # Description of the constructor parameter.
* ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
* -->Name of the default file
* </pre>
*
* <p>Starting with this file, you could create descriptions for the French
* locale by creating {@code com/example/MBeanDescriptions_fr.properties}.
* The keys in this file are the same as before but the text has been
* translated:
*
* <pre>
* ConfigurationMBean.mbean = Gestionnaire de configuration
*
* ConfigurationMBean.attribute.Name = Le nom de la configuration
*
* ConfigurationMBean.operation.save = Sauvegarder la configuration <!--
* -->dans un fichier
*
* ConfigurationMBean.operation.save.p1 = Le nom du fichier
*
* ConfigurationMBean.constructor.com.example.Configuration = <!--
* -->Constructeur avec nom du fichier par défaut
* ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
* -->Nom du fichier par défaut
* </pre>
*
* <p>The descriptions in {@code MBeanDescriptions.properties} and
* {@code MBeanDescriptions_fr.properties} will only be consulted if
* {@code localizeDescriptions} is called, perhaps because the
* MBean Server has been wrapped by {@link
* ClientContext#newLocalizeMBeanInfoForwarder} or because the
* connector server has been created with the {@link
* javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
* LOCALIZE_MBEAN_INFO_FORWARDER} option. If you want descriptions
* even when there is no localization step, then you should consider
* using {@link Description @Description} annotations. Annotations
* provide descriptions by default but are overridden if {@code
* localizeDescriptions} is called.</p>
*
* @param locale the target locale for descriptions. Cannot be null.
*
* @param loader the {@code ClassLoader} to use for looking up resource
* bundles.
*
* @return an {@code MBeanInfo} with descriptions appropriately localized.
*
* @throws NullPointerException if {@code locale} is null.
*/
public
MBeanInfo
localizeDescriptions
(
Locale
locale
,
ClassLoader
loader
)
{
if
(
locale
==
null
)
throw
new
NullPointerException
(
"locale"
);
Descriptor
d
=
getDescriptor
();
String
mbiLocaleString
=
(
String
)
d
.
getFieldValue
(
JMX
.
LOCALE_FIELD
);
if
(
locale
.
toString
().
equals
(
mbiLocaleString
))
return
this
;
return
new
Rewriter
(
this
,
locale
,
loader
).
getMBeanInfo
();
}
private
static
class
Rewriter
{
private
final
MBeanInfo
mbi
;
private
final
ClassLoader
loader
;
private
final
Locale
locale
;
private
final
String
packageName
;
private
final
String
simpleClassNamePlusDot
;
private
ResourceBundle
defaultBundle
;
private
boolean
defaultBundleLoaded
;
// ResourceBundle.getBundle throws NullPointerException
// if the loader is null, even though that is perfectly
// valid and means the bootstrap loader. So we work
// around with a ClassLoader that is equivalent to the
// bootstrap loader but is not null.
private
static
final
ClassLoader
bootstrapLoader
=
new
ClassLoader
(
null
)
{};
Rewriter
(
MBeanInfo
mbi
,
Locale
locale
,
ClassLoader
loader
)
{
this
.
mbi
=
mbi
;
this
.
locale
=
locale
;
if
(
loader
==
null
)
loader
=
bootstrapLoader
;
this
.
loader
=
loader
;
String
intfName
=
(
String
)
mbi
.
getDescriptor
().
getFieldValue
(
"interfaceClassName"
);
if
(
intfName
==
null
)
intfName
=
mbi
.
getClassName
();
int
lastDot
=
intfName
.
lastIndexOf
(
'.'
);
this
.
packageName
=
intfName
.
substring
(
0
,
lastDot
+
1
);
this
.
simpleClassNamePlusDot
=
intfName
.
substring
(
lastDot
+
1
)
+
"."
;
// Inner classes show up as Outer$Inner so won't match the dot.
// When there is no dot, lastDot is -1,
// packageName is empty, and simpleClassNamePlusDot is intfName.
}
MBeanInfo
getMBeanInfo
()
{
MBeanAttributeInfo
[]
mbais
=
rewrite
(
mbi
.
getAttributes
(),
"attribute."
);
MBeanOperationInfo
[]
mbois
=
rewrite
(
mbi
.
getOperations
(),
"operation."
);
MBeanConstructorInfo
[]
mbcis
=
rewrite
(
mbi
.
getConstructors
(),
"constructor."
);
MBeanNotificationInfo
[]
mbnis
=
rewrite
(
mbi
.
getNotifications
(),
"notification."
);
Descriptor
d
=
mbi
.
getDescriptor
();
d
=
changeLocale
(
d
);
String
description
=
getDescription
(
d
,
"mbean"
,
""
);
if
(
description
==
null
)
description
=
mbi
.
getDescription
();
return
new
MBeanInfo
(
mbi
.
getClassName
(),
description
,
mbais
,
mbcis
,
mbois
,
mbnis
,
d
);
}
private
Descriptor
changeLocale
(
Descriptor
d
)
{
if
(
d
.
getFieldValue
(
JMX
.
LOCALE_FIELD
)
!=
null
)
{
Map
<
String
,
Object
>
map
=
new
HashMap
<
String
,
Object
>();
for
(
String
field
:
d
.
getFieldNames
())
map
.
put
(
field
,
d
.
getFieldValue
(
field
));
map
.
remove
(
JMX
.
LOCALE_FIELD
);
d
=
new
ImmutableDescriptor
(
map
);
}
return
ImmutableDescriptor
.
union
(
d
,
new
ImmutableDescriptor
(
JMX
.
LOCALE_FIELD
+
"="
+
locale
));
}
private
String
getDescription
(
Descriptor
d
,
String
defaultPrefix
,
String
defaultSuffix
)
{
ResourceBundle
bundle
=
bundleFromDescriptor
(
d
);
if
(
bundle
==
null
)
return
null
;
String
key
=
(
String
)
d
.
getFieldValue
(
JMX
.
DESCRIPTION_RESOURCE_KEY_FIELD
);
if
(
key
==
null
)
key
=
simpleClassNamePlusDot
+
defaultPrefix
+
defaultSuffix
;
return
descriptionFromResource
(
bundle
,
key
);
}
private
<
T
extends
MBeanFeatureInfo
>
T
[]
rewrite
(
T
[]
features
,
String
resourcePrefix
)
{
for
(
int
i
=
0
;
i
<
features
.
length
;
i
++)
{
T
feature
=
features
[
i
];
Descriptor
d
=
feature
.
getDescriptor
();
String
description
=
getDescription
(
d
,
resourcePrefix
,
feature
.
getName
());
if
(
description
!=
null
&&
!
description
.
equals
(
feature
.
getDescription
()))
{
features
[
i
]
=
setDescription
(
feature
,
description
);
}
}
return
features
;
}
private
<
T
extends
MBeanFeatureInfo
>
T
setDescription
(
T
feature
,
String
description
)
{
Object
newf
;
String
name
=
feature
.
getName
();
Descriptor
d
=
feature
.
getDescriptor
();
if
(
feature
instanceof
MBeanAttributeInfo
)
{
MBeanAttributeInfo
mbai
=
(
MBeanAttributeInfo
)
feature
;
newf
=
new
MBeanAttributeInfo
(
name
,
mbai
.
getType
(),
description
,
mbai
.
isReadable
(),
mbai
.
isWritable
(),
mbai
.
isIs
(),
d
);
}
else
if
(
feature
instanceof
MBeanOperationInfo
)
{
MBeanOperationInfo
mboi
=
(
MBeanOperationInfo
)
feature
;
MBeanParameterInfo
[]
sig
=
rewrite
(
mboi
.
getSignature
(),
"operation."
+
name
+
"."
);
newf
=
new
MBeanOperationInfo
(
name
,
description
,
sig
,
mboi
.
getReturnType
(),
mboi
.
getImpact
(),
d
);
}
else
if
(
feature
instanceof
MBeanConstructorInfo
)
{
MBeanConstructorInfo
mbci
=
(
MBeanConstructorInfo
)
feature
;
MBeanParameterInfo
[]
sig
=
rewrite
(
mbci
.
getSignature
(),
"constructor."
+
name
+
"."
);
newf
=
new
MBeanConstructorInfo
(
name
,
description
,
sig
,
d
);
}
else
if
(
feature
instanceof
MBeanNotificationInfo
)
{
MBeanNotificationInfo
mbni
=
(
MBeanNotificationInfo
)
feature
;
newf
=
new
MBeanNotificationInfo
(
mbni
.
getNotifTypes
(),
name
,
description
,
d
);
}
else
if
(
feature
instanceof
MBeanParameterInfo
)
{
MBeanParameterInfo
mbpi
=
(
MBeanParameterInfo
)
feature
;
newf
=
new
MBeanParameterInfo
(
name
,
mbpi
.
getType
(),
description
,
d
);
}
else
{
logger
().
log
(
Level
.
FINE
,
"Unknown feature type: "
+
feature
.
getClass
());
newf
=
feature
;
}
return
Util
.<
T
>
cast
(
newf
);
}
private
ResourceBundle
bundleFromDescriptor
(
Descriptor
d
)
{
String
bundleName
=
(
String
)
d
.
getFieldValue
(
JMX
.
DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
);
if
(
bundleName
!=
null
)
return
getBundle
(
bundleName
);
if
(
defaultBundleLoaded
)
return
defaultBundle
;
bundleName
=
packageName
+
"MBeanDescriptions"
;
defaultBundle
=
getBundle
(
bundleName
);
defaultBundleLoaded
=
true
;
return
defaultBundle
;
}
private
String
descriptionFromResource
(
ResourceBundle
bundle
,
String
key
)
{
try
{
return
bundle
.
getString
(
key
);
}
catch
(
MissingResourceException
e
)
{
logger
().
log
(
Level
.
FINEST
,
"No resource for "
+
key
,
e
);
}
catch
(
Exception
e
)
{
logger
().
log
(
Level
.
FINE
,
"Bad resource for "
+
key
,
e
);
}
return
null
;
}
private
ResourceBundle
getBundle
(
String
name
)
{
try
{
return
ResourceBundle
.
getBundle
(
name
,
locale
,
loader
);
}
catch
(
Exception
e
)
{
logger
().
log
(
Level
.
FINE
,
"Could not load ResourceBundle "
+
name
,
e
);
return
null
;
}
}
private
Logger
logger
()
{
return
Logger
.
getLogger
(
"javax.management.locale"
);
}
}
}
}
src/share/classes/javax/management/MBeanServerConnection.java
浏览文件 @
6b491fa1
...
@@ -532,8 +532,30 @@ public interface MBeanServerConnection extends NotificationManager {
...
@@ -532,8 +532,30 @@ public interface MBeanServerConnection extends NotificationManager {
/**
/**
* Enables the values of several attributes of a named MBean. The MBean
* <p>Retrieves the values of several attributes of a named MBean. The MBean
* is identified by its object name.
* is identified by its object name.</p>
*
* <p>If one or more attributes cannot be retrieved for some reason, they
* will be omitted from the returned {@code AttributeList}. The caller
* should check that the list is the same size as the {@code attributes}
* array. To discover what problem prevented a given attribute from being
* retrieved, call {@link #getAttribute getAttribute} for that attribute.</p>
*
* <p>Here is an example of calling this method and checking that it
* succeeded in retrieving all the requested attributes:</p>
*
* <pre>
* String[] attrNames = ...;
* AttributeList list = mbeanServerConnection.getAttributes(objectName, attrNames);
* if (list.size() == attrNames.length)
* System.out.println("All attributes were retrieved successfully");
* else {
* {@code List<String>} missing = new {@code ArrayList<String>}(<!--
* -->{@link java.util.Arrays#asList Arrays.asList}(attrNames));
* missing.removeAll(list.toMap().keySet());
* System.out.println("Did not retrieve: " + missing);
* }
* </pre>
*
*
* @param name The object name of the MBean from which the
* @param name The object name of the MBean from which the
* attributes are retrieved.
* attributes are retrieved.
...
@@ -557,6 +579,7 @@ public interface MBeanServerConnection extends NotificationManager {
...
@@ -557,6 +579,7 @@ public interface MBeanServerConnection extends NotificationManager {
throws
InstanceNotFoundException
,
ReflectionException
,
throws
InstanceNotFoundException
,
ReflectionException
,
IOException
;
IOException
;
/**
/**
* Sets the value of a specific attribute of a named MBean. The MBean
* Sets the value of a specific attribute of a named MBean. The MBean
* is identified by its object name.
* is identified by its object name.
...
@@ -592,10 +615,36 @@ public interface MBeanServerConnection extends NotificationManager {
...
@@ -592,10 +615,36 @@ public interface MBeanServerConnection extends NotificationManager {
ReflectionException
,
IOException
;
ReflectionException
,
IOException
;
/**
/**
* Sets the values of several attributes of a named MBean. The MBean is
* <p>Sets the values of several attributes of a named MBean. The MBean is
* identified by its object name.
* identified by its object name.</p>
*
* <p>If one or more attributes cannot be set for some reason, they will be
* omitted from the returned {@code AttributeList}. The caller should check
* that the input {@code AttributeList} is the same size as the output one.
* To discover what problem prevented a given attribute from being retrieved,
* it will usually be possible to call {@link #setAttribute setAttribute}
* for that attribute, although this is not guaranteed to work. (For
* example, the values of two attributes may have been rejected because
* they were inconsistent with each other. Setting one of them alone might
* be allowed.)<p>
*
* <p>Here is an example of calling this method and checking that it
* succeeded in setting all the requested attributes:</p>
*
* <pre>
* AttributeList inputAttrs = ...;
* AttributeList outputAttrs = mbeanServerConnection.setAttributes(<!--
* -->objectName, inputAttrs);
* if (inputAttrs.size() == outputAttrs.size())
* System.out.println("All attributes were set successfully");
* else {
* {@code List<String>} missing = new {@code ArrayList<String>}(<!--
* -->inputAttrs.toMap().keySet());
* missing.removeAll(outputAttrs.toMap().keySet());
* System.out.println("Did not set: " + missing);
* }
* </pre>
*
*
* @param name The object name of the MBean within which the
* @param name The object name of the MBean within which the
* attributes are to be set.
* attributes are to be set.
...
@@ -622,7 +671,39 @@ public interface MBeanServerConnection extends NotificationManager {
...
@@ -622,7 +671,39 @@ public interface MBeanServerConnection extends NotificationManager {
throws
InstanceNotFoundException
,
ReflectionException
,
IOException
;
throws
InstanceNotFoundException
,
ReflectionException
,
IOException
;
/**
/**
* Invokes an operation on an MBean.
* <p>Invokes an operation on an MBean.</p>
*
* <p>Because of the need for a {@code signature} to differentiate
* possibly-overloaded operations, it is much simpler to invoke operations
* through an {@linkplain JMX#newMBeanProxy(MBeanServerConnection, ObjectName,
* Class) MBean proxy} where possible. For example, suppose you have a
* Standard MBean interface like this:</p>
*
* <pre>
* public interface FooMBean {
* public int countMatches(String[] patterns, boolean ignoreCase);
* }
* </pre>
*
* <p>The {@code countMatches} operation can be invoked as follows:</p>
*
* <pre>
* String[] myPatterns = ...;
* int count = (Integer) mbeanServerConnection.invoke(
* objectName,
* "countMatches",
* new Object[] {myPatterns, true},
* new String[] {String[].class.getName(), boolean.class.getName()});
* </pre>
*
* <p>Alternatively, it can be invoked through a proxy as follows:</p>
*
* <pre>
* String[] myPatterns = ...;
* FooMBean fooProxy = JMX.newMBeanProxy(
* mbeanServerConnection, objectName, FooMBean.class);
* int count = fooProxy.countMatches(myPatterns, true);
* </pre>
*
*
* @param name The object name of the MBean on which the method is
* @param name The object name of the MBean on which the method is
* to be invoked.
* to be invoked.
...
@@ -630,7 +711,8 @@ public interface MBeanServerConnection extends NotificationManager {
...
@@ -630,7 +711,8 @@ public interface MBeanServerConnection extends NotificationManager {
* @param params An array containing the parameters to be set when
* @param params An array containing the parameters to be set when
* the operation is invoked
* the operation is invoked
* @param signature An array containing the signature of the
* @param signature An array containing the signature of the
* operation. The class objects will be loaded using the same
* operation, an array of class names in the format returned by
* {@link Class#getName()}. The class objects will be loaded using the same
* class loader as the one used for loading the MBean on which the
* class loader as the one used for loading the MBean on which the
* operation was invoked.
* operation was invoked.
*
*
...
...
src/share/classes/javax/management/MBeanServerNotification.java
浏览文件 @
6b491fa1
...
@@ -27,15 +27,70 @@ package javax.management;
...
@@ -27,15 +27,70 @@ package javax.management;
/**
/**
* Represents a notification emitted by the MBean
s
erver through the MBeanServerDelegate MBean.
* Represents a notification emitted by the MBean
S
erver through the MBeanServerDelegate MBean.
* The MBean Server emits the following types of notifications: MBean registration, MBean
* The MBean Server emits the following types of notifications: MBean registration, MBean
*
de-
registration.
*
un
registration.
* <P>
* <P>
* To receive to MBeanServerNotifications, you need to be declared as listener to
* To receive MBeanServerNotifications, you need to register a listener with
* the {@link javax.management.MBeanServerDelegate javax.management.MBeanServerDelegate} MBean
* the {@link MBeanServerDelegate MBeanServerDelegate} MBean
* that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is:
* that represents the MBeanServer. The ObjectName of the MBeanServerDelegate is
* {@link MBeanServerDelegate#DELEGATE_NAME}, which is
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
* <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
*
*
* <p>The following code prints a message every time an MBean is registered
* or unregistered in the MBean Server {@code mbeanServer}:</p>
*
* <pre>
* private static final NotificationListener printListener = new NotificationListener() {
* public void handleNotification(Notification n, Object handback) {
* if (!(n instanceof MBeanServerNotification)) {
* System.out.println("Ignored notification of class " + n.getClass().getName());
* return;
* }
* MBeanServerNotification mbsn = (MBeanServerNotification) n;
* String what;
* if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
* what = "MBean registered";
* else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
* what = "MBean unregistered";
* else
* what = "Unknown type " + n.getType();
* System.out.println("Received MBean Server notification: " + what + ": " +
* mbsn.getMBeanName());
* };
*
* ...
* mbeanServer.addNotificationListener(
* MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
* </pre>
*
* <p>The following code prints a message every time an MBean is registered
* or unregistered in the MBean Server {@code mbeanServer}:</p>
*
* <pre>
* private static final NotificationListener printListener = new NotificationListener() {
* public void handleNotification(Notification n, Object handback) {
* if (!(n instanceof MBeanServerNotification)) {
* System.out.println("Ignored notification of class " + n.getClass().getName());
* return;
* }
* MBeanServerNotification mbsn = (MBeanServerNotification) n;
* String what;
* if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION))
* what = "MBean registered";
* else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
* what = "MBean unregistered";
* else
* what = "Unknown type " + n.getType();
* System.out.println("Received MBean Server notification: " + what + ": " +
* mbsn.getMBeanName());
* };
*
* ...
* mbeanServer.addNotificationListener(
* MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
* </pre>
*
* @since 1.5
* @since 1.5
*/
*/
public
class
MBeanServerNotification
extends
Notification
{
public
class
MBeanServerNotification
extends
Notification
{
...
...
src/share/classes/javax/management/Notification.java
浏览文件 @
6b491fa1
...
@@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetPropertyAction;
...
@@ -54,7 +54,7 @@ import com.sun.jmx.mbeanserver.GetPropertyAction;
* @since 1.5
* @since 1.5
*/
*/
@SuppressWarnings
(
"serial"
)
// serialVersionUID is not constant
@SuppressWarnings
(
"serial"
)
// serialVersionUID is not constant
public
class
Notification
extends
EventObject
{
public
class
Notification
extends
EventObject
implements
Cloneable
{
// Serialization compatibility stuff:
// Serialization compatibility stuff:
// Two serial forms are supported in this class. The selected form depends
// Two serial forms are supported in this class. The selected form depends
...
@@ -243,6 +243,26 @@ public class Notification extends EventObject {
...
@@ -243,6 +243,26 @@ public class Notification extends EventObject {
this
.
message
=
message
;
this
.
message
=
message
;
}
}
/**
* <p>Creates and returns a copy of this object. The copy is created as
* described for {@link Object#clone()}. This means, first, that the
* class of the object will be the same as the class of this object, and,
* second, that the copy is a "shallow copy". Fields of this notification
* are not themselves copied. In particular, the {@linkplain
* #getUserData user data} of the copy is the same object as the
* original.</p>
*
* @return a copy of this object.
*/
@Override
public
Object
clone
()
{
try
{
return
super
.
clone
();
}
catch
(
CloneNotSupportedException
e
)
{
throw
new
AssertionError
(
e
);
}
}
/**
/**
* Sets the source.
* Sets the source.
*
*
...
@@ -285,8 +305,10 @@ public class Notification extends EventObject {
...
@@ -285,8 +305,10 @@ public class Notification extends EventObject {
/**
/**
* Get the notification type.
* Get the notification type.
*
*
* @return The notification type. It's a string expressed in a dot notation similar
* @return The notification type. It's a string expressed in a dot notation
* to Java properties. An example of a notification type is network.alarm.router .
* similar to Java properties. It is recommended that the notification type
* should follow the reverse-domain-name convention used by Java package
* names. An example of a notification type is com.example.alarm.router.
*/
*/
public
String
getType
()
{
public
String
getType
()
{
return
type
;
return
type
;
...
@@ -317,14 +339,25 @@ public class Notification extends EventObject {
...
@@ -317,14 +339,25 @@ public class Notification extends EventObject {
/**
/**
* Get the notification message.
* Get the notification message.
*
*
* @return The message string of this notification object. It contains in a string,
* @return The message string of this notification object.
* which could be the explanation of the notification for displaying to a user
*
*
* @see #setMessage
*/
*/
public
String
getMessage
()
{
public
String
getMessage
()
{
return
message
;
return
message
;
}
}
/**
* Set the notification message.
*
* @param message the new notification message.
*
* @see #getMessage
*/
public
void
setMessage
(
String
message
)
{
this
.
message
=
message
;
}
/**
/**
* Get the user data.
* Get the user data.
*
*
...
@@ -355,6 +388,7 @@ public class Notification extends EventObject {
...
@@ -355,6 +388,7 @@ public class Notification extends EventObject {
*
*
* @return A String representation of this notification.
* @return A String representation of this notification.
*/
*/
@Override
public
String
toString
()
{
public
String
toString
()
{
return
super
.
toString
()+
"[type="
+
type
+
"][message="
+
message
+
"]"
;
return
super
.
toString
()+
"[type="
+
type
+
"][message="
+
message
+
"]"
;
}
}
...
...
src/share/classes/javax/management/QueryNotificationFilter.java
浏览文件 @
6b491fa1
...
@@ -26,7 +26,6 @@
...
@@ -26,7 +26,6 @@
package
javax.management
;
package
javax.management
;
import
com.sun.jmx.mbeanserver.NotificationMBeanSupport
;
import
com.sun.jmx.mbeanserver.NotificationMBeanSupport
;
import
com.sun.jmx.mbeanserver.Util
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
...
@@ -43,6 +42,11 @@ import java.util.Set;
...
@@ -43,6 +42,11 @@ import java.util.Set;
* on both the client and the server in the remote case, so using this class
* on both the client and the server in the remote case, so using this class
* instead is recommended where possible.</p>
* instead is recommended where possible.</p>
*
*
* <p>Because this class was introduced in version 2.0 of the JMX API,
* it may not be present on a remote JMX agent that is running an earlier
* version. The method {@link JMX#getSpecificationVersion
* JMX.getSpecificationVersion} can be used to determine the remote version.</p>
*
* <p>This class uses the {@linkplain Query Query API} to specify the
* <p>This class uses the {@linkplain Query Query API} to specify the
* filtering logic. For example, to select only notifications where the
* filtering logic. For example, to select only notifications where the
* {@linkplain Notification#getType() type} is {@code "com.example.mytype"},
* {@linkplain Notification#getType() type} is {@code "com.example.mytype"},
...
...
src/share/classes/javax/management/event/EventClient.java
浏览文件 @
6b491fa1
...
@@ -29,7 +29,6 @@ import com.sun.jmx.event.DaemonThreadFactory;
...
@@ -29,7 +29,6 @@ import com.sun.jmx.event.DaemonThreadFactory;
import
com.sun.jmx.event.LeaseRenewer
;
import
com.sun.jmx.event.LeaseRenewer
;
import
com.sun.jmx.event.ReceiverBuffer
;
import
com.sun.jmx.event.ReceiverBuffer
;
import
com.sun.jmx.event.RepeatedSingletonJob
;
import
com.sun.jmx.event.RepeatedSingletonJob
;
import
com.sun.jmx.namespace.JMXNamespaceUtils
;
import
com.sun.jmx.mbeanserver.PerThreadGroupPool
;
import
com.sun.jmx.mbeanserver.PerThreadGroupPool
;
import
com.sun.jmx.remote.util.ClassLogger
;
import
com.sun.jmx.remote.util.ClassLogger
;
...
@@ -58,7 +57,6 @@ import javax.management.NotificationBroadcasterSupport;
...
@@ -58,7 +57,6 @@ import javax.management.NotificationBroadcasterSupport;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectName
;
import
javax.management.ObjectName
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.NotificationResult
;
import
javax.management.remote.NotificationResult
;
import
javax.management.remote.TargetedNotification
;
import
javax.management.remote.TargetedNotification
;
...
@@ -129,11 +127,12 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -129,11 +127,12 @@ public class EventClient implements EventConsumer, NotificationManager {
public
static
final
String
NOTIFS_LOST
=
"jmx.event.service.notifs.lost"
;
public
static
final
String
NOTIFS_LOST
=
"jmx.event.service.notifs.lost"
;
/**
/**
* The default lease time, {@value}, in milliseconds.
* The default lease time that EventClient instances will request, in
* milliseconds. This value is {@value}.
*
*
* @see EventClientDelegateMBean#lease
* @see EventClientDelegateMBean#lease
*/
*/
public
static
final
long
DEFAULT_
LEASE_TIMEOUT
=
300000
;
public
static
final
long
DEFAULT_
REQUESTED_LEASE_TIME
=
300000
;
/**
/**
* <p>Constructs a default {@code EventClient} object.</p>
* <p>Constructs a default {@code EventClient} object.</p>
...
@@ -173,7 +172,7 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -173,7 +172,7 @@ public class EventClient implements EventConsumer, NotificationManager {
*/
*/
public
EventClient
(
EventClientDelegateMBean
delegate
)
public
EventClient
(
EventClientDelegateMBean
delegate
)
throws
IOException
{
throws
IOException
{
this
(
delegate
,
null
,
null
,
null
,
DEFAULT_
LEASE_TIMEOUT
);
this
(
delegate
,
null
,
null
,
null
,
DEFAULT_
REQUESTED_LEASE_TIME
);
}
}
/**
/**
...
@@ -196,7 +195,7 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -196,7 +195,7 @@ public class EventClient implements EventConsumer, NotificationManager {
* If {@code null}, a default scheduler will be used.
* If {@code null}, a default scheduler will be used.
* @param requestedLeaseTime The lease time used to keep this client alive
* @param requestedLeaseTime The lease time used to keep this client alive
* in the {@link EventClientDelegateMBean}. A value of zero is equivalent
* in the {@link EventClientDelegateMBean}. A value of zero is equivalent
* to the {@linkplain #DEFAULT_
LEASE_TIMEOUT
default value}.
* to the {@linkplain #DEFAULT_
REQUESTED_LEASE_TIME
default value}.
*
*
* @throws IllegalArgumentException If {@code delegate} is null.
* @throws IllegalArgumentException If {@code delegate} is null.
* @throws IOException If an I/O error occurs when communicating with the
* @throws IOException If an I/O error occurs when communicating with the
...
@@ -213,7 +212,7 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -213,7 +212,7 @@ public class EventClient implements EventConsumer, NotificationManager {
}
}
if
(
requestedLeaseTime
==
0
)
if
(
requestedLeaseTime
==
0
)
requestedLeaseTime
=
DEFAULT_
LEASE_TIMEOUT
;
requestedLeaseTime
=
DEFAULT_
REQUESTED_LEASE_TIME
;
else
if
(
requestedLeaseTime
<
0
)
{
else
if
(
requestedLeaseTime
<
0
)
{
throw
new
IllegalArgumentException
(
throw
new
IllegalArgumentException
(
"Negative lease time: "
+
requestedLeaseTime
);
"Negative lease time: "
+
requestedLeaseTime
);
...
@@ -269,7 +268,13 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -269,7 +268,13 @@ public class EventClient implements EventConsumer, NotificationManager {
new
ScheduledThreadPoolExecutor
(
20
,
daemonThreadFactory
);
new
ScheduledThreadPoolExecutor
(
20
,
daemonThreadFactory
);
executor
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
executor
.
setKeepAliveTime
(
1
,
TimeUnit
.
SECONDS
);
executor
.
allowCoreThreadTimeOut
(
true
);
executor
.
allowCoreThreadTimeOut
(
true
);
executor
.
setRemoveOnCancelPolicy
(
true
);
if
(
setRemoveOnCancelPolicy
!=
null
)
{
try
{
setRemoveOnCancelPolicy
.
invoke
(
executor
,
true
);
}
catch
(
Exception
e
)
{
logger
.
trace
(
"setRemoveOnCancelPolicy"
,
e
);
}
}
// By default, a ScheduledThreadPoolExecutor will keep jobs
// By default, a ScheduledThreadPoolExecutor will keep jobs
// in its queue even after they have been cancelled. They
// in its queue even after they have been cancelled. They
// will only be removed when their scheduled time arrives.
// will only be removed when their scheduled time arrives.
...
@@ -277,12 +282,25 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -277,12 +282,25 @@ public class EventClient implements EventConsumer, NotificationManager {
// this EventClient, this can lead to a moderately large number
// this EventClient, this can lead to a moderately large number
// of objects remaining referenced until the renewal time
// of objects remaining referenced until the renewal time
// arrives. Hence the above call, which removes the job from
// arrives. Hence the above call, which removes the job from
// the queue as soon as it is cancelled.
// the queue as soon as it is cancelled. Since the call is
// new with JDK 7, we invoke it via reflection to make it
// easier to use this code on JDK 6.
return
executor
;
return
executor
;
}
}
};
};
return
leaseRenewerThreadPool
.
getThreadPoolExecutor
(
create
);
return
leaseRenewerThreadPool
.
getThreadPoolExecutor
(
create
);
}
private
static
final
Method
setRemoveOnCancelPolicy
;
static
{
Method
m
;
try
{
m
=
ScheduledThreadPoolExecutor
.
class
.
getMethod
(
"setRemoveOnCancelPolicy"
,
boolean
.
class
);
}
catch
(
Exception
e
)
{
m
=
null
;
}
setRemoveOnCancelPolicy
=
m
;
}
}
/**
/**
...
@@ -1042,7 +1060,7 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -1042,7 +1060,7 @@ public class EventClient implements EventConsumer, NotificationManager {
final
public
EventClient
call
()
throws
Exception
{
final
public
EventClient
call
()
throws
Exception
{
EventClientDelegateMBean
ecd
=
EventClientDelegate
.
getProxy
(
conn
);
EventClientDelegateMBean
ecd
=
EventClientDelegate
.
getProxy
(
conn
);
return
new
EventClient
(
ecd
,
eventRelay
,
null
,
null
,
return
new
EventClient
(
ecd
,
eventRelay
,
null
,
null
,
DEFAULT_
LEASE_TIMEOUT
);
DEFAULT_
REQUESTED_LEASE_TIME
);
}
}
};
};
...
@@ -1080,24 +1098,6 @@ public class EventClient implements EventConsumer, NotificationManager {
...
@@ -1080,24 +1098,6 @@ public class EventClient implements EventConsumer, NotificationManager {
return
clientId
;
return
clientId
;
}
}
/**
* Returns a JMX Connector that will use an {@link EventClient}
* to subscribe for notifications. If the server doesn't have
* an {@link EventClientDelegateMBean}, then the connector will
* use the legacy notification mechanism instead.
*
* @param wrapped The underlying JMX Connector wrapped by the returned
* connector.
*
* @return A JMX Connector that will uses an {@link EventClient}, if
* available.
*
* @see EventClient#getEventClientConnection(MBeanServerConnection)
*/
public
static
JMXConnector
withEventClient
(
final
JMXConnector
wrapped
)
{
return
JMXNamespaceUtils
.
withEventClient
(
wrapped
);
}
private
static
final
PerThreadGroupPool
<
ScheduledThreadPoolExecutor
>
private
static
final
PerThreadGroupPool
<
ScheduledThreadPoolExecutor
>
leaseRenewerThreadPool
=
PerThreadGroupPool
.
make
();
leaseRenewerThreadPool
=
PerThreadGroupPool
.
make
();
}
}
src/share/classes/javax/management/event/EventClientDelegate.java
浏览文件 @
6b491fa1
...
@@ -149,6 +149,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -149,6 +149,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
// of a setMBeanServer on some other forwarder later in the chain.
// of a setMBeanServer on some other forwarder later in the chain.
private
static
class
Forwarder
extends
SingleMBeanForwarder
{
private
static
class
Forwarder
extends
SingleMBeanForwarder
{
private
MBeanServer
loopMBS
;
private
static
class
UnsupportedInvocationHandler
private
static
class
UnsupportedInvocationHandler
implements
InvocationHandler
{
implements
InvocationHandler
{
...
@@ -173,7 +174,11 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -173,7 +174,11 @@ public class EventClientDelegate implements EventClientDelegateMBean {
private
volatile
boolean
madeECD
;
private
volatile
boolean
madeECD
;
Forwarder
()
{
Forwarder
()
{
super
(
OBJECT_NAME
,
makeUnsupportedECD
());
super
(
OBJECT_NAME
,
makeUnsupportedECD
(),
true
);
}
synchronized
void
setLoopMBS
(
MBeanServer
loopMBS
)
{
this
.
loopMBS
=
loopMBS
;
}
}
@Override
@Override
...
@@ -186,7 +191,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -186,7 +191,7 @@ public class EventClientDelegate implements EventClientDelegateMBean {
AccessController
.
doPrivileged
(
AccessController
.
doPrivileged
(
new
PrivilegedAction
<
EventClientDelegate
>()
{
new
PrivilegedAction
<
EventClientDelegate
>()
{
public
EventClientDelegate
run
()
{
public
EventClientDelegate
run
()
{
return
getEventClientDelegate
(
Forwarder
.
this
);
return
getEventClientDelegate
(
loopMBS
);
}
}
});
});
DynamicMBean
mbean
=
new
StandardMBean
(
DynamicMBean
mbean
=
new
StandardMBean
(
...
@@ -208,11 +213,46 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -208,11 +213,46 @@ public class EventClientDelegate implements EventClientDelegateMBean {
* that are targeted for that MBean and handles them itself. All other
* that are targeted for that MBean and handles them itself. All other
* requests are forwarded to the next element in the forwarder chain.</p>
* requests are forwarded to the next element in the forwarder chain.</p>
*
*
* @param nextMBS the next {@code MBeanServer} in the chain of forwarders,
* which might be another {@code MBeanServerForwarder} or a plain {@code
* MBeanServer}. This is the object to which {@code MBeanServer} requests
* that do not concern the {@code EventClientDelegateMBean} are sent.
* It will be the value of {@link MBeanServerForwarder#getMBeanServer()
* getMBeanServer()} on the returned object, and can be changed with {@link
* MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
* must be set to a non-null value before any {@code MBeanServer} requests
* arrive.
*
* @param loopMBS the {@code MBeanServer} to which requests from the
* {@code EventClientDelegateMBean} should be sent. For example,
* when you invoke the {@link EventClientDelegateMBean#addListener
* addListener} operation on the {@code EventClientDelegateMBean}, it will
* result in a call to {@link
* MBeanServer#addNotificationListener(ObjectName, NotificationListener,
* NotificationFilter, Object) addNotificationListener} on this object.
* If this parameter is null, then these requests will be sent to the
* newly-created {@code MBeanServerForwarder}. Usually the parameter will
* either be null or will be the result of {@link
* javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder()
* getSystemMBeanServerForwarder()} for the connector server in which
* this forwarder will be installed.
*
* @return a new {@code MBeanServerForwarder} that simulates the existence
* @return a new {@code MBeanServerForwarder} that simulates the existence
* of an {@code EventClientDelegateMBean}.
* of an {@code EventClientDelegateMBean}.
*
* @see javax.management.remote.JMXConnectorServer#installStandardForwarders
*/
*/
public
static
MBeanServerForwarder
newForwarder
()
{
public
static
MBeanServerForwarder
newForwarder
(
return
new
Forwarder
();
MBeanServer
nextMBS
,
MBeanServer
loopMBS
)
{
Forwarder
mbsf
=
new
Forwarder
();
// We must setLoopMBS before setMBeanServer, because when we
// setMBeanServer that will call getEventClientDelegate(loopMBS).
if
(
loopMBS
==
null
)
loopMBS
=
mbsf
;
mbsf
.
setLoopMBS
(
loopMBS
);
if
(
nextMBS
!=
null
)
mbsf
.
setMBeanServer
(
nextMBS
);
return
mbsf
;
}
}
/**
/**
...
@@ -437,10 +477,9 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -437,10 +477,9 @@ public class EventClientDelegate implements EventClientDelegateMBean {
// private classes
// private classes
// ------------------------------------
// ------------------------------------
private
class
ClientInfo
{
private
class
ClientInfo
{
String
clientId
;
final
String
clientId
;
EventBuffer
buffer
;
final
NotificationListener
clientListener
;
NotificationListener
clientListener
;
final
Map
<
Integer
,
AddedListener
>
listenerInfoMap
=
Map
<
Integer
,
AddedListener
>
listenerInfoMap
=
new
HashMap
<
Integer
,
AddedListener
>();
new
HashMap
<
Integer
,
AddedListener
>();
ClientInfo
(
String
clientId
,
EventForwarder
forwarder
)
{
ClientInfo
(
String
clientId
,
EventForwarder
forwarder
)
{
...
@@ -703,7 +742,8 @@ public class EventClientDelegate implements EventClientDelegateMBean {
...
@@ -703,7 +742,8 @@ public class EventClientDelegate implements EventClientDelegateMBean {
clientInfo
=
clientInfoMap
.
get
(
clientId
);
clientInfo
=
clientInfoMap
.
get
(
clientId
);
if
(
clientInfo
==
null
)
{
if
(
clientInfo
==
null
)
{
throw
new
EventClientNotFoundException
(
"The client is not found."
);
throw
new
EventClientNotFoundException
(
"Client not found (id "
+
clientId
+
")"
);
}
}
return
clientInfo
;
return
clientInfo
;
...
...
src/share/classes/javax/management/event/EventClientDelegateMBean.java
浏览文件 @
6b491fa1
...
@@ -51,7 +51,8 @@ import javax.management.remote.NotificationResult;
...
@@ -51,7 +51,8 @@ import javax.management.remote.NotificationResult;
* and the MBean Server, that will intercept accesses to the Event Client
* and the MBean Server, that will intercept accesses to the Event Client
* Delegate MBean and treat them as the real MBean would. This forwarder is
* Delegate MBean and treat them as the real MBean would. This forwarder is
* inserted by default with the standard RMI Connector Server, and can also
* inserted by default with the standard RMI Connector Server, and can also
* be created explicitly using {@link EventClientDelegate#newForwarder()}.
* be created explicitly using {@link EventClientDelegate#newForwarder
* EventClientDelegate.newForwarder}.
*
*
* <li><p>A variant on the above is to replace the MBean Server that is
* <li><p>A variant on the above is to replace the MBean Server that is
* used locally with a forwarder as described above. Since
* used locally with a forwarder as described above. Since
...
@@ -61,9 +62,7 @@ import javax.management.remote.NotificationResult;
...
@@ -61,9 +62,7 @@ import javax.management.remote.NotificationResult;
*
*
* <pre>
* <pre>
* MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
* MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
* MBeanServerForwarder mbsf = EventClientDelegate.newForwarder();
* mbs = EventClientDelegate.newForwarder(mbs, null);
* mbsf.setMBeanServer(mbs);
* mbs = mbsf;
* // now use mbs just as you did before, but it will have an EventClientDelegate
* // now use mbs just as you did before, but it will have an EventClientDelegate
* </pre>
* </pre>
*
*
...
...
src/share/classes/javax/management/event/EventRelay.java
浏览文件 @
6b491fa1
...
@@ -27,7 +27,6 @@ package javax.management.event;
...
@@ -27,7 +27,6 @@ package javax.management.event;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.concurrent.Executors
;
// for javadoc
import
java.util.concurrent.Executors
;
// for javadoc
import
java.util.concurrent.ScheduledFuture
;
/**
/**
* This interface is used to specify a way to receive
* This interface is used to specify a way to receive
...
...
src/share/classes/javax/management/event/package-info.java
浏览文件 @
6b491fa1
...
@@ -83,8 +83,8 @@
...
@@ -83,8 +83,8 @@
* javax.management.event.EventClientDelegateMBean EventClientDelegateMBean}
* javax.management.event.EventClientDelegateMBean EventClientDelegateMBean}
* must be registered in the MBean Server, or the connector server must
* must be registered in the MBean Server, or the connector server must
* be configured to simulate the existence of this MBean, for example
* be configured to simulate the existence of this MBean, for example
* using {@link javax.management.event.EventClientDelegate#newForwarder
()
* using {@link javax.management.event.EventClientDelegate#newForwarder
* EventClientDelegate.newForwarder
()
}. The standard RMI connector is so
* EventClientDelegate.newForwarder}. The standard RMI connector is so
* configured by default. The {@code EventClientDelegateMBean} documentation
* configured by default. The {@code EventClientDelegateMBean} documentation
* has further details.</p>
* has further details.</p>
*
*
...
...
src/share/classes/javax/management/namespace/JMXNamespaces.java
浏览文件 @
6b491fa1
...
@@ -26,21 +26,19 @@
...
@@ -26,21 +26,19 @@
package
javax.management.namespace
;
package
javax.management.namespace
;
import
com.sun.jmx.defaults.JmxProperties
;
import
com.sun.jmx.defaults.JmxProperties
;
import
com.sun.jmx.namespace.JMXNamespaceUtils
;
import
com.sun.jmx.namespace.ObjectNameRouter
;
import
com.sun.jmx.namespace.ObjectNameRouter
;
import
com.sun.jmx.namespace.serial.RewritingProcessor
;
import
com.sun.jmx.namespace.serial.RewritingProcessor
;
import
com.sun.jmx.namespace.RoutingConnectionProxy
;
import
com.sun.jmx.namespace.RoutingConnectionProxy
;
import
com.sun.jmx.namespace.RoutingServerProxy
;
import
com.sun.jmx.namespace.RoutingServerProxy
;
import
java.io.IOException
;
import
java.util.logging.Level
;
import
java.util.logging.Level
;
import
java.util.logging.Logger
;
import
java.util.logging.Logger
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.MalformedObjectNameException
;
import
javax.management.ObjectName
;
import
javax.management.ObjectName
;
import
javax.management.remote.JMXConnector
;
/**
/**
* Static constants and utility methods to help work with
* Static constants and utility methods to help work with
...
@@ -68,23 +66,6 @@ public class JMXNamespaces {
...
@@ -68,23 +66,6 @@ public class JMXNamespaces {
NAMESPACE_SEPARATOR
.
length
();
NAMESPACE_SEPARATOR
.
length
();
/**
* Returns a connector connected to a sub name space exposed through
* the parent connector.
* @param parent the parent connector.
* @param namespace the {@linkplain javax.management.namespace name space}
* to which the returned connector is
* connected.
* @return A connector connected to a sub name space exposed through
* the parent connector.
**/
public
static
JMXConnector
narrowToNamespace
(
final
JMXConnector
parent
,
final
String
namespace
)
throws
IOException
{
return
JMXNamespaceUtils
.
cd
(
parent
,
namespace
,
true
);
}
/**
/**
* Creates a new {@code MBeanServerConnection} proxy on a
* Creates a new {@code MBeanServerConnection} proxy on a
* {@linkplain javax.management.namespace sub name space}
* {@linkplain javax.management.namespace sub name space}
...
@@ -96,15 +77,18 @@ public class JMXNamespaces {
...
@@ -96,15 +77,18 @@ public class JMXNamespaces {
* name space} in which to narrow.
* name space} in which to narrow.
* @return A new {@code MBeanServerConnection} proxy that shows the content
* @return A new {@code MBeanServerConnection} proxy that shows the content
* of that name space.
* of that name space.
* @throws IllegalArgumentException if the name space does not exist, or
* @throws IllegalArgumentException if either argument is null,
* if a proxy for that name space cannot be created.
* or the name space does not exist, or if a proxy for that name space
* cannot be created. The {@linkplain Throwable#getCause() cause} of
* this exception will be an {@link InstanceNotFoundException} if and only
* if the name space is found not to exist.
*/
*/
public
static
MBeanServerConnection
narrowToNamespace
(
public
static
MBeanServerConnection
narrowToNamespace
(
MBeanServerConnection
parent
,
MBeanServerConnection
parent
,
String
namespace
)
{
String
namespace
)
{
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
"Making MBeanServerConnection for: "
+
namespace
);
LOG
.
finer
(
"Making MBeanServerConnection for: "
+
namespace
);
return
RoutingConnectionProxy
.
cd
(
parent
,
namespac
e
);
return
RoutingConnectionProxy
.
cd
(
parent
,
namespace
,
tru
e
);
}
}
/**
/**
...
@@ -120,13 +104,15 @@ public class JMXNamespaces {
...
@@ -120,13 +104,15 @@ public class JMXNamespaces {
* of that name space.
* of that name space.
* @throws IllegalArgumentException if either argument is null,
* @throws IllegalArgumentException if either argument is null,
* or the name space does not exist, or if a proxy for that name space
* or the name space does not exist, or if a proxy for that name space
* cannot be created.
* cannot be created. The {@linkplain Throwable#getCause() cause} of
* this exception will be an {@link InstanceNotFoundException} if and only
* if the name space is found not to exist.
*/
*/
public
static
MBeanServer
narrowToNamespace
(
MBeanServer
parent
,
public
static
MBeanServer
narrowToNamespace
(
MBeanServer
parent
,
String
namespace
)
{
String
namespace
)
{
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
if
(
LOG
.
isLoggable
(
Level
.
FINER
))
LOG
.
finer
(
"Making
NamespaceServerProxy
for: "
+
namespace
);
LOG
.
finer
(
"Making
MBeanServer
for: "
+
namespace
);
return
RoutingServerProxy
.
cd
(
parent
,
namespac
e
);
return
RoutingServerProxy
.
cd
(
parent
,
namespace
,
tru
e
);
}
}
/**
/**
...
@@ -266,7 +252,7 @@ public class JMXNamespaces {
...
@@ -266,7 +252,7 @@ public class JMXNamespaces {
ObjectNameRouter
.
normalizeNamespacePath
(
namespace
,
false
,
ObjectNameRouter
.
normalizeNamespacePath
(
namespace
,
false
,
true
,
false
);
true
,
false
);
try
{
try
{
// We could use
Util.newObjectName
here - but throwing an
// We could use
ObjectName.valueOf
here - but throwing an
// IllegalArgumentException that contains just the supplied
// IllegalArgumentException that contains just the supplied
// namespace instead of the whole ObjectName seems preferable.
// namespace instead of the whole ObjectName seems preferable.
return
ObjectName
.
getInstance
(
sourcePath
+
return
ObjectName
.
getInstance
(
sourcePath
+
...
...
src/share/classes/javax/management/namespace/JMXRemoteNamespace.java
浏览文件 @
6b491fa1
...
@@ -27,10 +27,10 @@ package javax.management.namespace;
...
@@ -27,10 +27,10 @@ package javax.management.namespace;
import
com.sun.jmx.defaults.JmxProperties
;
import
com.sun.jmx.defaults.JmxProperties
;
import
com.sun.jmx.mbeanserver.Util
;
import
com.sun.jmx.mbeanserver.Util
;
import
com.sun.jmx.namespace.JMXNamespaceUtils
;
import
com.sun.jmx.remote.util.EnvHelp
;
import
com.sun.jmx.remote.util.EnvHelp
;
import
java.io.IOException
;
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.concurrent.atomic.AtomicLong
;
import
java.util.concurrent.atomic.AtomicLong
;
...
@@ -39,6 +39,7 @@ import java.util.logging.Logger;
...
@@ -39,6 +39,7 @@ import java.util.logging.Logger;
import
javax.management.AttributeChangeNotification
;
import
javax.management.AttributeChangeNotification
;
import
javax.management.ClientContext
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanNotificationInfo
;
...
@@ -220,17 +221,26 @@ public class JMXRemoteNamespace
...
@@ -220,17 +221,26 @@ public class JMXRemoteNamespace
initParentOnce
(
this
);
initParentOnce
(
this
);
// URL must not be null.
// URL must not be null.
this
.
jmxURL
=
JMXNamespaceUtils
.
checkNonNull
(
sourceURL
,
"url"
);
if
(
sourceURL
==
null
)
throw
new
IllegalArgumentException
(
"Null URL"
);
this
.
jmxURL
=
sourceURL
;
this
.
broadcaster
=
this
.
broadcaster
=
new
NotificationBroadcasterSupport
(
connectNotification
);
new
NotificationBroadcasterSupport
(
connectNotification
);
// handles options
// handles options
this
.
optionsMap
=
JMXNamespaceUtils
.
unmodifiableMap
(
optionsMap
);
this
.
optionsMap
=
unmodifiableMap
(
optionsMap
);
// handles (dis)connection events
// handles (dis)connection events
this
.
listener
=
new
ConnectionListener
();
this
.
listener
=
new
ConnectionListener
();
}
}
// returns un unmodifiable view of a map.
private
static
<
K
,
V
>
Map
<
K
,
V
>
unmodifiableMap
(
Map
<
K
,
V
>
aMap
)
{
if
(
aMap
==
null
||
aMap
.
isEmpty
())
return
Collections
.
emptyMap
();
return
Collections
.
unmodifiableMap
(
aMap
);
}
/**
/**
* Returns the {@code JMXServiceURL} that is (or will be) used to
* Returns the {@code JMXServiceURL} that is (or will be) used to
* connect to the remote name space. <p>
* connect to the remote name space. <p>
...
@@ -483,106 +493,171 @@ public class JMXRemoteNamespace
...
@@ -483,106 +493,171 @@ public class JMXRemoteNamespace
}
}
}
}
JMXConnector
connect
(
JMXServiceURL
url
,
Map
<
String
,?>
env
)
private
JMXConnector
connect
(
JMXServiceURL
url
,
Map
<
String
,?>
env
)
throws
IOException
{
throws
IOException
{
final
JMXConnector
c
=
newJMXConnector
(
jmxURL
,
env
);
final
JMXConnector
c
=
newJMXConnector
(
url
,
env
);
c
.
connect
(
env
);
c
.
connect
(
env
);
return
c
;
return
c
;
}
}
/**
/**
* Creates a new JMXConnector with the specified {@code url} and
* <p>Creates a new JMXConnector with the specified {@code url} and
* {@code env} options map.
* {@code env} options map. The default implementation of this method
* <p>
* returns {@link JMXConnectorFactory#newJMXConnector
* This method first calls {@link JMXConnectorFactory#newJMXConnector
* JMXConnectorFactory.newJMXConnector(jmxURL, env)}. Subclasses can
* JMXConnectorFactory.newJMXConnector(jmxURL, env)} to obtain a new
* override this method to customize behavior.</p>
* JMX connector, and returns that.
*
* </p>
* @param url The JMXServiceURL of the remote server.
* <p>
* @param optionsMap An options map that will be passed to the
* A subclass of {@link JMXRemoteNamespace} can provide an implementation
* {@link JMXConnectorFactory} when {@linkplain
* that connects to a sub namespace of the remote server by subclassing
* JMXConnectorFactory#newJMXConnector creating} the
* this class in the following way:
* {@link JMXConnector} that can connect to the remote source
* MBean Server.
* @return A JMXConnector to use to connect to the remote server
* @throws IOException if the connector could not be created.
* @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
* @see #JMXRemoteNamespace
*/
protected
JMXConnector
newJMXConnector
(
JMXServiceURL
url
,
Map
<
String
,?>
optionsMap
)
throws
IOException
{
return
JMXConnectorFactory
.
newJMXConnector
(
jmxURL
,
optionsMap
);
}
/**
* <p>Called when a new connection is established using {@link #connect}
* so that subclasses can customize the connection. The default
* implementation of this method effectively does the following:</p>
*
* <pre>
* MBeanServerConnection mbsc = {@link JMXConnector#getMBeanServerConnection()
* jmxc.getMBeanServerConnection()};
* try {
* return {@link ClientContext#withDynamicContext
* ClientContext.withDynamicContext(mbsc)};
* } catch (IllegalArgumentException e) {
* return mbsc;
* }
* </pre>
*
* <p>In other words, it arranges for the client context to be forwarded
* to the remote MBean Server if the remote MBean Server supports contexts;
* otherwise it ignores the client context.</p>
*
* <h4>Example: connecting to a remote namespace</h4>
*
* <p>A subclass that wanted to narrow into a namespace of
* the remote MBeanServer might look like this:</p>
*
* <pre>
* <pre>
* class JMXRemoteSubNamespace extends JMXRemoteNamespace {
* class JMXRemoteSubNamespace extends JMXRemoteNamespace {
* private final String subnamespace;
* private final String subnamespace;
* JMXRemoteSubNamespace(JMXServiceURL url,
*
* Map{@code <String,?>} env, String subnamespace) {
* JMXRemoteSubNamespace(
* super(url,options);
* JMXServiceURL url, Map{@code <String, ?>} env, String subnamespace) {
* super(url, env);
* this.subnamespace = subnamespace;
* this.subnamespace = subnamespace;
* }
* }
* protected JMXConnector newJMXConnector(JMXServiceURL url,
*
* Map<String,?> env) throws IOException {
* {@code @Override}
* final JMXConnector inner = super.newJMXConnector(url,env);
* protected MBeanServerConnection getMBeanServerConnection(
* return {@link JMXNamespaces#narrowToNamespace(JMXConnector,String)
* JMXConnector jmxc) throws IOException {
* JMXNamespaces.narrowToNamespace(inner,subnamespace)};
* MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
* return {@link JMXNamespaces#narrowToNamespace(MBeanServerConnection,String)
* JMXNamespaces.narrowToNamespace(mbsc, subnamespace)};
* }
* }
* }
* }
* </pre>
* </pre>
*
</p>
*
* <
p
>
* <
h4>Example: using the Event Service for notifications</h4
>
*
Some connectors, like the JMXMP connector server defined by the
*
*
version 1.2 of the JMX API may not have been upgraded to use the
*
<p>Some connectors may have been designed to work with an earlier
*
new {@linkplain javax.management.event Event Service} defined in this
*
version of the JMX API, and may not have been upgraded to use
*
version of the JMX API.
*
the {@linkplain javax.management.event Event Service} defined in
*
<p>
*
this version of the JMX API. In that case, and if the remote
*
In that case, and if the remote server to which this JMXRemoteNamespace
*
server to which this JMXRemoteNamespace connects also contains
*
connects also contains namespaces, it may be necessary to configure
*
namespaces, it may be necessary to configure explicitly an {@linkplain
*
explicitly an {@linkplain
*
javax.management.event.EventClientDelegate#newForwarder Event Client
*
javax.management.event.EventClientDelegate#newForwarder()
*
Forwarder} on the remote server side, and to force the use of an {@link
* Event
Client Forwarder} on the remote server side, and to force the use
* Event
Client} on this client side.</p>
*
of an {@link EventClient} on this client side.
*
* <
br>
* <
p>A subclass of {@link JMXRemoteNamespace} can provide an
*
A subclass of {@link JMXRemoteNamespace} can provide an implementation
*
implementation of {@code getMBeanServerConnection} that will force
*
of {@code newJMXConnector} that will force notification subscriptions
*
notification subscriptions to flow through an {@link EventClient} over
*
to flow through an {@link EventClient} over a legacy protocol by
*
a legacy protocol. It can do so by overriding this method in the
*
overriding this method in the following way:
*
following way:</p>
*
</p>
*
* <pre>
* <pre>
* class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
* class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
* JMXRemoteSubNamespaceConnector(JMXServiceURL url,
* JMXRemoteEventClientNamespace(JMXServiceURL url, {@code Map<String,?>} env) {
* Map<String,?> env) {
* super(url, env);
* super(url,options);
* }
* }
* protected JMXConnector newJMXConnector(JMXServiceURL url,
*
* Map<String,?> env) throws IOException {
* {@code @Override}
* final JMXConnector inner = super.newJMXConnector(url,env);
* protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
* return {@link EventClient#withEventClient(
* throws IOException {
* JMXConnector) EventClient.withEventClient(inner)};
* MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
* return EventClient.getEventClientConnection(mbsc);
* }
* }
* }
* }
* </pre>
* </pre>
*
* <p>
* <p>
* Note that the remote server also needs to provide an {@link
* Note that the remote server also needs to provide an {@link
* javax.management.event.EventClientDelegateMBean}: only configuring
* javax.management.event.EventClientDelegateMBean}: configuring only
* the client side (this object) is not enough.<br>
* the client side (this object) is not enough.</p>
* In summary, this technique should be used if the remote server
*
* <p>In summary, this technique should be used if the remote server
* supports JMX namespaces, but uses a JMX Connector Server whose
* supports JMX namespaces, but uses a JMX Connector Server whose
* implementation does not transparently use the new Event Service
* implementation does not transparently use the new Event Service
* (as would be the case with the JMXMPConnectorServer implementation
* (as would be the case with the JMXMPConnectorServer implementation
* from the reference implementation of the JMX Remote API 1.0
* from the reference implementation of the JMX Remote API 1.0
* specification).
* specification).</p>
* </p>
*
* @param url The JMXServiceURL of the remote server.
* @param jmxc the newly-created {@code JMXConnector}.
* @param optionsMap An unmodifiable options map that will be passed to the
*
* {@link JMXConnectorFactory} when {@linkplain
* @return an {@code MBeanServerConnection} connected to the remote
* JMXConnectorFactory#newJMXConnector creating} the
* MBeanServer.
* {@link JMXConnector} that can connect to the remote source
*
* MBean Server.
* @throws IOException if the connection cannot be made. If this method
* @return An unconnected JMXConnector to use to connect to the remote
* throws {@code IOException} then the calling {@link #connect()} method
* server
* will also fail with an {@code IOException}.
* @throws java.io.IOException if the connector could not be created.
*
* @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
* @see #connect
* @see #JMXRemoteNamespace
*/
*/
protected
JMXConnector
newJMXConnector
(
JMXServiceURL
url
,
protected
MBeanServerConnection
getMBeanServerConnection
(
JMXConnector
jmxc
)
Map
<
String
,?>
optionsMap
)
throws
IOException
{
throws
IOException
{
final
JMXConnector
c
=
final
MBeanServerConnection
mbsc
=
jmxc
.
getMBeanServerConnection
();
JMXConnectorFactory
.
newJMXConnector
(
jmxURL
,
optionsMap
);
try
{
// TODO: uncomment this when contexts are added
return
ClientContext
.
withDynamicContext
(
mbsc
);
// return ClientContext.withDynamicContext(c);
}
catch
(
IllegalArgumentException
e
)
{
return
c
;
LOG
.
log
(
Level
.
FINER
,
"ClientContext.withDynamicContext"
,
e
);
return
mbsc
;
}
}
}
/**
* {@inheritDoc}
*
* <p>The sequence of events when this method is called includes,
* effectively, the following code:</p>
*
* <pre>
* JMXServiceURL url = {@link #getJMXServiceURL getJMXServiceURL}();
* JMXConnector jmxc = {@link #newJMXConnector newJMXConnector}(url, env);
* jmxc.connect();
* MBeanServerConnection mbsc = {@link #getMBeanServerConnection(JMXConnector)
* getMBeanServerConnection}(jmxc);
* </pre>
*
* <p>Here, {@code env} is a {@code Map} containing the entries from the
* {@code optionsMap} that was passed to the {@linkplain #JMXRemoteNamespace
* constructor} or to the {@link #newJMXRemoteNamespace newJMXRemoteNamespace}
* factory method.</p>
*
* <p>Subclasses can customize connection behavior by overriding the
* {@code getJMXServiceURL}, {@code newJMXConnector}, or
* {@code getMBeanServerConnection} methods.</p>
*/
public
void
connect
()
throws
IOException
{
public
void
connect
()
throws
IOException
{
LOG
.
fine
(
"connecting..."
);
LOG
.
fine
(
"connecting..."
);
final
Map
<
String
,
Object
>
env
=
final
Map
<
String
,
Object
>
env
=
...
@@ -590,7 +665,7 @@ public class JMXRemoteNamespace
...
@@ -590,7 +665,7 @@ public class JMXRemoteNamespace
try
{
try
{
// XXX: We should probably document this...
// XXX: We should probably document this...
// This allows to specify a loader name - which will be
// This allows to specify a loader name - which will be
// retrieved from the paret MBeanServer.
// retrieved from the pare
n
t MBeanServer.
defaultClassLoader
=
defaultClassLoader
=
EnvHelp
.
resolveServerClassLoader
(
env
,
getMBeanServer
());
EnvHelp
.
resolveServerClassLoader
(
env
,
getMBeanServer
());
}
catch
(
InstanceNotFoundException
x
)
{
}
catch
(
InstanceNotFoundException
x
)
{
...
@@ -604,7 +679,7 @@ public class JMXRemoteNamespace
...
@@ -604,7 +679,7 @@ public class JMXRemoteNamespace
final
JMXConnector
aconn
=
connect
(
url
,
env
);
final
JMXConnector
aconn
=
connect
(
url
,
env
);
final
MBeanServerConnection
msc
;
final
MBeanServerConnection
msc
;
try
{
try
{
msc
=
aconn
.
getMBeanServerConnection
(
);
msc
=
getMBeanServerConnection
(
aconn
);
aconn
.
addConnectionNotificationListener
(
listener
,
null
,
aconn
);
aconn
.
addConnectionNotificationListener
(
listener
,
null
,
aconn
);
}
catch
(
IOException
io
)
{
}
catch
(
IOException
io
)
{
close
(
aconn
);
close
(
aconn
);
...
...
src/share/classes/javax/management/openmbean/CompositeDataSupport.java
浏览文件 @
6b491fa1
...
@@ -33,12 +33,14 @@ import java.io.Serializable;
...
@@ -33,12 +33,14 @@ import java.io.Serializable;
import
java.util.Arrays
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Collections
;
import
java.util.LinkedHashMap
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
java.util.SortedMap
;
import
java.util.SortedMap
;
import
java.util.TreeMap
;
import
java.util.TreeMap
;
// jmx import
// jmx import
import
java.util.TreeSet
;
//
//
...
@@ -60,16 +62,15 @@ public class CompositeDataSupport
...
@@ -60,16 +62,15 @@ public class CompositeDataSupport
* respective values.
* respective values.
* A {@link SortedMap} is used for faster retrieval of elements.
* A {@link SortedMap} is used for faster retrieval of elements.
*/
*/
private
SortedMap
<
String
,
Object
>
contents
=
new
TreeMap
<
String
,
Object
>()
;
private
final
SortedMap
<
String
,
Object
>
contents
;
/**
/**
* @serial The <i>composite type </i> of this <i>composite data</i> instance.
* @serial The <i>composite type </i> of this <i>composite data</i> instance.
*/
*/
private
CompositeType
compositeType
;
private
final
CompositeType
compositeType
;
/**
/**
* <p>
* <p>Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* Constructs a <tt>CompositeDataSupport</tt> instance with the specified
* <tt>compositeType</tt>, whose item values
* <tt>compositeType</tt>, whose item values
* are specified by <tt>itemValues[]</tt>, in the same order as in
* are specified by <tt>itemValues[]</tt>, in the same order as in
* <tt>itemNames[]</tt>.
* <tt>itemNames[]</tt>.
...
@@ -79,103 +80,67 @@ public class CompositeDataSupport
...
@@ -79,103 +80,67 @@ public class CompositeDataSupport
* The items contained in this <tt>CompositeDataSupport</tt> instance are
* The items contained in this <tt>CompositeDataSupport</tt> instance are
* internally stored in a <tt>TreeMap</tt>,
* internally stored in a <tt>TreeMap</tt>,
* thus sorted in ascending lexicographic order of their names, for faster
* thus sorted in ascending lexicographic order of their names, for faster
* retrieval of individual item values.
* retrieval of individual item values.
</p>
*
<p>
*
* The constructor checks that all the constraints listed below for each
*
<p>
The constructor checks that all the constraints listed below for each
* parameter are satisfied,
* parameter are satisfied,
* and throws the appropriate exception if they are not.
* and throws the appropriate exception if they are not.
</p>
*
<p>
*
* @param compositeType the <i>composite type </i> of this <i>composite
* @param compositeType the <i>composite type </i> of this <i>composite
* data</i> instance;
* data</i> instance; must not be null.
* must not be null.
*
* <p>
* @param itemNames <tt>itemNames</tt> must list, in any order, all the
* @param itemNames <tt>itemNames</tt> must list, in any order, all the
* item names defined in <tt>compositeType</tt>;
* item names defined in <tt>compositeType</tt>; the order in which the
* the order in which the names are listed, is used to
* names are listed, is used to match values in <tt>itemValues[]</tt>; must
* match values in <tt>itemValues[]</tt>;
* not be null.
* must not be null or empty.
*
* <p>
* @param itemValues the values of the items, listed in the same order as
* @param itemValues the values of the items, listed in the same order as
* their respective names in <tt>itemNames</tt>;
* their respective names in <tt>itemNames</tt>; each item value can be
* each item value can be null, but if it is non-null it must be
* null, but if it is non-null it must be a valid value for the open type
* a valid value for the open type defined in <tt>compositeType</tt> for the corresponding item;
* defined in <tt>compositeType</tt> for the corresponding item; must be of
* must be of the same size as <tt>itemNames</tt>; must not be null or empty.
* the same size as <tt>itemNames</tt>; must not be null.
* <p>
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty,
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* or one of the elements in <tt>itemNames[]</tt> is a null or empty string,
* <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
* or <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
* of the elements in <tt>itemNames[]</tt> is a null or empty string, or
* <p>
* <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
* @throws OpenDataException <tt>itemNames[]</tt> or <tt>itemValues[]</tt>'s size differs from
*
* the number of items defined in <tt>compositeType</tt>,
* @throws OpenDataException <tt>itemNames[]</tt> or
* or one of the elements in <tt>itemNames[]</tt> does not exist as an item name defined in <tt>compositeType</tt>,
* <tt>itemValues[]</tt>'s size differs from the number of items defined in
* or one of the elements in <tt>itemValues[]</tt> is not a valid value for the corresponding item
* <tt>compositeType</tt>, or one of the elements in <tt>itemNames[]</tt>
* as defined in <tt>compositeType</tt>.
* does not exist as an item name defined in <tt>compositeType</tt>, or one
* <p>
* of the elements in <tt>itemValues[]</tt> is not a valid value for the
* corresponding item as defined in <tt>compositeType</tt>.
*/
*/
public
CompositeDataSupport
(
CompositeType
compositeType
,
String
[]
itemNames
,
Object
[]
itemValues
)
public
CompositeDataSupport
(
CompositeType
compositeType
,
String
[]
itemNames
,
Object
[]
itemValues
)
throws
OpenDataException
{
throws
OpenDataException
{
this
(
makeMap
(
itemNames
,
itemValues
),
compositeType
);
// Check compositeType is not null
//
if
(
compositeType
==
null
)
{
throw
new
IllegalArgumentException
(
"Argument compositeType cannot be null."
);
}
}
// item names defined in compositeType:
private
static
SortedMap
<
String
,
Object
>
makeMap
(
Set
<
String
>
namesSet
=
compositeType
.
keySet
();
String
[]
itemNames
,
Object
[]
itemValues
)
throws
OpenDataException
{
// Check the array itemNames is not null or empty (length!=0) and
// that there is no null element or empty string in it
//
checkForNullElement
(
itemNames
,
"itemNames"
);
checkForEmptyString
(
itemNames
,
"itemNames"
);
// Check the array itemValues is not null or empty (length!=0)
// (NOTE: we allow null values as array elements)
//
if
(
(
itemValues
==
null
)
||
(
itemValues
.
length
==
0
)
)
{
throw
new
IllegalArgumentException
(
"Argument itemValues[] cannot be null or empty."
);
}
// Check that the sizes of the 2 arrays itemNames and itemValues are the same
if
(
itemNames
==
null
||
itemValues
==
null
)
//
throw
new
IllegalArgumentException
(
"Null itemNames or itemValues"
);
if
(
itemNames
.
length
!=
itemValues
.
length
)
{
if
(
itemNames
.
length
!=
itemValues
.
length
)
{
throw
new
IllegalArgumentException
(
"Array arguments itemNames[] and itemValues[] "
+
throw
new
IllegalArgumentException
(
"should be of same length (got "
+
itemNames
.
length
+
"Different lengths: itemNames["
+
itemNames
.
length
+
" and "
+
itemValues
.
length
+
")."
);
"], itemValues["
+
itemValues
.
length
+
"]"
);
}
// Check the size of the 2 arrays is equal to the number of items defined in compositeType
//
if
(
itemNames
.
length
!=
namesSet
.
size
())
{
throw
new
OpenDataException
(
"The size of array arguments itemNames[] and itemValues[] should be equal to the number of items defined"
+
" in argument compositeType (found "
+
itemNames
.
length
+
" elements in itemNames[] and itemValues[],"
+
" expecting "
+
namesSet
.
size
()
+
" elements according to compositeType."
);
}
// Check parameter itemNames[] contains all names defined in the compositeType of this instance
//
if
(
!
Arrays
.
asList
(
itemNames
).
containsAll
(
namesSet
)
)
{
throw
new
OpenDataException
(
"Argument itemNames[] does not contain all names defined in the compositeType of this instance."
);
}
}
// Check each element of itemValues[], if not null, is of the open type defined for the corresponding item
SortedMap
<
String
,
Object
>
map
=
new
TreeMap
<
String
,
Object
>();
//
for
(
int
i
=
0
;
i
<
itemNames
.
length
;
i
++)
{
OpenType
<?>
itemType
;
String
name
=
itemNames
[
i
];
for
(
int
i
=
0
;
i
<
itemValues
.
length
;
i
++)
{
if
(
name
==
null
||
name
.
equals
(
""
))
itemType
=
compositeType
.
getType
(
itemNames
[
i
]);
throw
new
IllegalArgumentException
(
"Null or empty item name"
);
if
(
(
itemValues
[
i
]
!=
null
)
&&
(!
itemType
.
isValue
(
itemValues
[
i
]))
)
{
if
(
map
.
containsKey
(
name
))
throw
new
OpenDataException
(
"Argument's element itemValues["
+
i
+
"]=\""
+
itemValues
[
i
]
+
"\" is not a valid value for"
+
throw
new
OpenDataException
(
"Duplicate item name "
+
name
);
" this item (itemName="
+
itemNames
[
i
]
+
",itemType="
+
itemType
+
")."
);
map
.
put
(
itemNames
[
i
],
itemValues
[
i
]);
}
}
}
// Initialize internal fields: compositeType and contents
return
map
;
//
this
.
compositeType
=
compositeType
;
for
(
int
i
=
0
;
i
<
itemNames
.
length
;
i
++)
{
this
.
contents
.
put
(
itemNames
[
i
],
itemValues
[
i
]);
}
}
}
/**
/**
...
@@ -184,66 +149,101 @@ public class CompositeDataSupport
...
@@ -184,66 +149,101 @@ public class CompositeDataSupport
* are given by the mappings in the map <tt>items</tt>.
* are given by the mappings in the map <tt>items</tt>.
* This constructor converts the keys to a string array and the values to an object array and calls
* This constructor converts the keys to a string array and the values to an object array and calls
* <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
* <tt>CompositeDataSupport(javax.management.openmbean.CompositeType, java.lang.String[], java.lang.Object[])</tt>.
*
<p>
*
* @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
* @param compositeType the <i>composite type </i> of this <i>composite data</i> instance;
* must not be null.
* must not be null.
* <p>
* @param items the mappings of all the item names to their values;
* @param items the mappings of all the item names to their values;
* <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
* <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
* must not be null or empty.
* must not be null.
* <p>
*
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or <tt>items</tt> is null or empty,
* @throws IllegalArgumentException <tt>compositeType</tt> is null, or
* or one of the keys in <tt>items</tt> is a null or empty string,
* <tt>items</tt> is null, or one of the keys in <tt>items</tt> is a null
* or one of the values in <tt>items</tt> is null.
* or empty string.
* <p>
* @throws OpenDataException <tt>items</tt>' size differs from the
* @throws OpenDataException <tt>items</tt>' size differs from the number of items defined in <tt>compositeType</tt>,
* number of items defined in <tt>compositeType</tt>, or one of the
* or one of the keys in <tt>items</tt> does not exist as an item name defined in <tt>compositeType</tt>,
* keys in <tt>items</tt> does not exist as an item name defined in
* or one of the values in <tt>items</tt> is not a valid value for the corresponding item
* <tt>compositeType</tt>, or one of the values in <tt>items</tt>
* as defined in <tt>compositeType</tt>.
* is not a valid value for the corresponding item as defined in
* <p>
* <tt>compositeType</tt>.
* @throws ArrayStoreException one or more keys in <tt>items</tt> is not of the class <tt>java.lang.String</tt>.
* @throws ArrayStoreException one or more keys in <tt>items</tt> is not of
* <p>
* the class <tt>java.lang.String</tt>.
*
* @see #toMap
*/
*/
public
CompositeDataSupport
(
CompositeType
compositeType
,
public
CompositeDataSupport
(
CompositeType
compositeType
,
Map
<
String
,?>
items
)
Map
<
String
,?>
items
)
throws
OpenDataException
{
throws
OpenDataException
{
this
(
makeMap
(
items
),
compositeType
);
}
private
static
SortedMap
<
String
,
Object
>
makeMap
(
Map
<
String
,
?>
items
)
{
if
(
items
==
null
)
throw
new
IllegalArgumentException
(
"Null items map"
);
if
(
items
.
containsKey
(
null
)
||
items
.
containsKey
(
""
))
throw
new
IllegalArgumentException
(
"Null or empty item name"
);
// Let the other constructor do the job, as the call to another constructor must be the first call
SortedMap
<
String
,
Object
>
map
=
new
TreeMap
<
String
,
Object
>();
//
for
(
Object
key
:
items
.
keySet
())
{
this
(
compositeType
,
if
(!(
key
instanceof
String
))
{
(
items
==
null
?
null
:
items
.
keySet
().
toArray
(
new
String
[
items
.
size
()])),
// may raise an ArrayStoreException
throw
new
ArrayStoreException
(
"Item name is not string: "
+
key
);
(
items
==
null
?
null
:
items
.
values
().
toArray
())
);
// This can happen because of erasure. The particular
// exception is a historical artifact - an implementation
// detail that leaked into the API.
}
}
map
.
put
((
String
)
key
,
items
.
get
(
key
));
/**
*
*/
private
static
void
checkForNullElement
(
Object
[]
arg
,
String
argName
)
{
if
(
(
arg
==
null
)
||
(
arg
.
length
==
0
)
)
{
throw
new
IllegalArgumentException
(
"Argument "
+
argName
+
"[] cannot be null or empty."
);
}
}
for
(
int
i
=
0
;
i
<
arg
.
length
;
i
++)
{
return
map
;
if
(
arg
[
i
]
==
null
)
{
throw
new
IllegalArgumentException
(
"Argument's element "
+
argName
+
"["
+
i
+
"] cannot be null."
);
}
}
private
CompositeDataSupport
(
SortedMap
<
String
,
Object
>
items
,
CompositeType
compositeType
)
throws
OpenDataException
{
// Check compositeType is not null
//
if
(
compositeType
==
null
)
{
throw
new
IllegalArgumentException
(
"Argument compositeType cannot be null."
);
}
// item names defined in compositeType:
Set
<
String
>
namesFromType
=
compositeType
.
keySet
();
Set
<
String
>
namesFromItems
=
items
.
keySet
();
// This is just a comparison, but we do it this way for a better
// exception message.
if
(!
namesFromType
.
equals
(
namesFromItems
))
{
Set
<
String
>
extraFromType
=
new
TreeSet
<
String
>(
namesFromType
);
extraFromType
.
removeAll
(
namesFromItems
);
Set
<
String
>
extraFromItems
=
new
TreeSet
<
String
>(
namesFromItems
);
extraFromItems
.
removeAll
(
namesFromType
);
if
(!
extraFromType
.
isEmpty
()
||
!
extraFromItems
.
isEmpty
())
{
throw
new
OpenDataException
(
"Item names do not match CompositeType: "
+
"names in items but not in CompositeType: "
+
extraFromItems
+
"; names in CompositeType but not in items: "
+
extraFromType
);
}
}
}
}
/**
// Check each value, if not null, is of the open type defined for the
*
// corresponding item
*/
for
(
String
name
:
namesFromType
)
{
private
static
void
checkForEmptyString
(
String
[]
arg
,
String
argName
)
{
Object
value
=
items
.
get
(
name
);
for
(
int
i
=
0
;
i
<
arg
.
length
;
i
++)
{
if
(
value
!=
null
)
{
if
(
arg
[
i
].
trim
().
equals
(
""
))
{
OpenType
<?>
itemType
=
compositeType
.
getType
(
name
);
throw
new
IllegalArgumentException
(
if
(!
itemType
.
isValue
(
value
))
{
"Argument's element "
+
argName
+
"["
+
i
+
"] cannot be an empty string."
);
throw
new
OpenDataException
(
"Argument value of wrong type for item "
+
name
+
": value "
+
value
+
", type "
+
itemType
);
}
}
}
}
}
}
// Initialize internal fields: compositeType and contents
//
this
.
compositeType
=
compositeType
;
this
.
contents
=
items
;
}
/**
/**
* Returns the <i>composite type </i> of this <i>composite data</i> instance.
* Returns the <i>composite type </i> of this <i>composite data</i> instance.
*/
*/
...
@@ -328,6 +328,54 @@ public class CompositeDataSupport
...
@@ -328,6 +328,54 @@ public class CompositeDataSupport
return
Collections
.
unmodifiableCollection
(
contents
.
values
());
return
Collections
.
unmodifiableCollection
(
contents
.
values
());
}
}
/**
* <p>Returns a Map representing the contents of the given CompositeData.
* Each item in the CompositeData is represented by an entry in the map,
* where the name and value of the item are the key and value of the entry.
* The returned value is modifiable but modifications to it have no effect
* on the original CompositeData.</p>
*
* <p>For example, if you have a CompositeData {@code cd1} and you want
* to produce another CompositeData {@code cd2} which is the same except
* that the value of its {@code id} item has been changed to 253, you
* could write:</p>
*
* <pre>
* CompositeData cd1 = ...;
* {@code Map<String, Object>} map = CompositeDataSupport.toMap(cd1);
* assert(map.get("id") instanceof Integer);
* map.put("id", 253);
* CompositeData cd2 = {@link #CompositeDataSupport(CompositeType, Map)
* new CompositeDataSupport}(cd1.getCompositeType(), map);
* </pre>
*
* <p>Logically, this method would be a method in the {@link CompositeData}
* interface, but cannot be for compatibility reasons.</p>
*
* @param cd the CompositeData to convert to a Map.
*
* @return a Map that is a copy of the contents of {@code cd}.
*
* @throws IllegalArgumentException if {@code cd} is null.
*
* @see #CompositeDataSupport(CompositeType, Map)
*/
public
static
Map
<
String
,
Object
>
toMap
(
CompositeData
cd
)
{
if
(
cd
==
null
)
throw
new
IllegalArgumentException
(
"Null argument"
);
// If we really wanted, we could check whether cd is a
// CompositeDataSupport and return a copy of cd.contents if so,
// but I don't think that would be substantially faster.
Map
<
String
,
Object
>
map
=
new
LinkedHashMap
<
String
,
Object
>();
CompositeType
ct
=
cd
.
getCompositeType
();
for
(
String
key
:
ct
.
keySet
())
{
Object
value
=
cd
.
get
(
key
);
map
.
put
(
key
,
value
);
}
return
map
;
}
/**
/**
* Compares the specified <var>obj</var> parameter with this
* Compares the specified <var>obj</var> parameter with this
* <code>CompositeDataSupport</code> instance for equality.
* <code>CompositeDataSupport</code> instance for equality.
...
...
src/share/classes/javax/management/package.html
浏览文件 @
6b491fa1
<html>
<html>
<head>
<head>
<title>
javax.management package
</title>
<title>
javax.management package
</title>
<!--
<!--
Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
Copyright 1999-2006 Sun Microsystems, Inc. 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.
...
@@ -24,9 +24,9 @@ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
...
@@ -24,9 +24,9 @@ Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
CA 95054 USA or visit www.sun.com if you need additional information or
CA 95054 USA or visit www.sun.com if you need additional information or
have any questions.
have any questions.
-->
-->
</head>
</head>
<body
bgcolor=
"white"
>
<body
bgcolor=
"white"
>
<p>
Provides the core classes for the Java Management Extensions.
</p>
<p>
Provides the core classes for the Java Management Extensions.
</p>
<p>
The Java Management Extensions
<p>
The Java Management Extensions
...
@@ -407,6 +407,92 @@ have any questions.
...
@@ -407,6 +407,92 @@ have any questions.
So for example an SNMP GET operation might result in a
So for example an SNMP GET operation might result in a
<code>
getAttribute
</code>
on the MBean Server.
</p>
<code>
getAttribute
</code>
on the MBean Server.
</p>
<h3
id=
"interop"
>
Interoperability between versions of the JMX
specification
</h3>
<p>
When a client connects to a server using the JMX Remote
API, it is possible that they do not have the same version
of the JMX specification. The version of the JMX
specification described here is version 2.0. Previous
versions were 1.0, 1.1, 1.2, and 1.4. (There was no 1.3.)
The standard JMX Remote API is defined to work with version
1.2 onwards, so in standards-based deployment the only
interoperability questions that arise concern version 1.2
onwards.
</p>
<p>
Every version of the JMX specification continues to
implement the features of previous versions. So when the
client is running an earlier version than the server, there
should not be any interoperability concerns. The only
exception is the unlikely one where a pre-2.0 client used
the string {@code //} in the domain part of an {@link
javax.management.ObjectName ObjectName}.
</p>
<p>
When the client is running a later version than the server,
certain newer features may not be available, as detailed in
the next sections. The method {@link
javax.management.JMX#getSpecificationVersion
JMX.getSpecificationVersion} can be used to determine the
server version to check if required features are
available.
</p>
<h4
id=
"interop-1.4"
>
If the remote MBean Server is 1.4
</h4>
<ul>
<li><p>
You cannot use {@link
javax.management.QueryNotificationFilter
QueryNotificationFilter} in {@link
javax.management.MBeanServerConnection#addNotificationListener
addNotificationListener} since this class did not exist
in 1.4.
</p>
<li><p>
In an attribute in a query, you cannot access values
inside complex types using dot syntax, for example
{@link javax.management.Query#attr Query.attr}{@code
("HeapMemoryUsage.used")}.
</p>
<li><p>
The packages {@link javax.management.event} and
{@link javax.management.namespace} did not exist in 1.4,
so you cannot remotely create instances of the MBeans
they define.
</p>
<li><p>
Even if the remote MBean Server is 2.0, you cannot in
general suppose that {@link
javax.management.event.EventClient EventClient} or
{@link javax.management.ClientContext ClientContext}
will work there without first checking. If the remote
MBean Server is 1.4 then those checks will return false.
An attempt to use these features without checking will
fail in the same way as for a remote 2.0 that is not
configured to support them.
</p>
</ul>
<h4
id=
"interop-1.2"
>
If the remote MBean Server is 1.2
</h4>
<p><b>
In addition to the above
</b>
,
</p>
<ul>
<li><p>
You cannot use wildcards in a key property of an
{@link javax.management.ObjectName ObjectName}, for
example {@code domain:type=Foo,name=*}. Wildcards that
match whole properties are still allowed, for example
{@code *:*} or {@code *:type=Foo,*}.
</p>
<li><p>
You cannot use {@link
javax.management.Query#isInstanceOf Query.isInstanceOf}
in a query.
</p>
<li><p>
You cannot use dot syntax such as {@code
HeapMemoryUsage.used} in the {@linkplain
javax.management.monitor.Monitor#setObservedAttribute
observed attribute} of a monitor, as described in the
documentation for the {@link javax.management.monitor}
package.
</p>
</ul>
<p
id=
"spec"
>
<p
id=
"spec"
>
@see
<a
href=
"{@docRoot}/../technotes/guides/jmx/index.html"
>
@see
<a
href=
"{@docRoot}/../technotes/guides/jmx/index.html"
>
Java SE 6 Platform documentation on JMX technology
</a>
Java SE 6 Platform documentation on JMX technology
</a>
...
...
src/share/classes/javax/management/remote/JMXConnectorFactory.java
浏览文件 @
6b491fa1
...
@@ -322,10 +322,12 @@ public class JMXConnectorFactory {
...
@@ -322,10 +322,12 @@ public class JMXConnectorFactory {
JMXConnectorProvider
.
class
;
JMXConnectorProvider
.
class
;
final
String
protocol
=
serviceURL
.
getProtocol
();
final
String
protocol
=
serviceURL
.
getProtocol
();
final
String
providerClassName
=
"ClientProvider"
;
final
String
providerClassName
=
"ClientProvider"
;
final
JMXServiceURL
providerURL
=
serviceURL
;
JMXConnectorProvider
provider
=
JMXConnectorProvider
provider
=
getProvider
(
providerURL
,
envcopy
,
getProvider
(
serviceURL
,
envcopy
,
providerClassName
,
providerClassName
,
targetInterface
,
loader
);
targetInterface
,
loader
);
IOException
exception
=
null
;
IOException
exception
=
null
;
if
(
provider
==
null
)
{
if
(
provider
==
null
)
{
...
@@ -336,7 +338,7 @@ public class JMXConnectorFactory {
...
@@ -336,7 +338,7 @@ public class JMXConnectorFactory {
if
(
loader
!=
null
)
{
if
(
loader
!=
null
)
{
try
{
try
{
JMXConnector
connection
=
JMXConnector
connection
=
getConnectorAsService
(
loader
,
service
URL
,
envcopy
);
getConnectorAsService
(
loader
,
provider
URL
,
envcopy
);
if
(
connection
!=
null
)
if
(
connection
!=
null
)
return
connection
;
return
connection
;
}
catch
(
JMXProviderException
e
)
{
}
catch
(
JMXProviderException
e
)
{
...
@@ -345,8 +347,7 @@ public class JMXConnectorFactory {
...
@@ -345,8 +347,7 @@ public class JMXConnectorFactory {
exception
=
e
;
exception
=
e
;
}
}
}
}
provider
=
provider
=
getProvider
(
protocol
,
PROTOCOL_PROVIDER_DEFAULT_PACKAGE
,
getProvider
(
protocol
,
PROTOCOL_PROVIDER_DEFAULT_PACKAGE
,
JMXConnectorFactory
.
class
.
getClassLoader
(),
JMXConnectorFactory
.
class
.
getClassLoader
(),
providerClassName
,
targetInterface
);
providerClassName
,
targetInterface
);
}
}
...
@@ -448,9 +449,10 @@ public class JMXConnectorFactory {
...
@@ -448,9 +449,10 @@ public class JMXConnectorFactory {
getProviderIterator
(
JMXConnectorProvider
.
class
,
loader
);
getProviderIterator
(
JMXConnectorProvider
.
class
,
loader
);
JMXConnector
connection
;
JMXConnector
connection
;
IOException
exception
=
null
;
IOException
exception
=
null
;
while
(
providers
.
hasNext
())
{
while
(
providers
.
hasNext
())
{
JMXConnectorProvider
provider
=
providers
.
next
();
try
{
try
{
connection
=
provider
s
.
next
()
.
newJMXConnector
(
url
,
map
);
connection
=
provider
.
newJMXConnector
(
url
,
map
);
return
connection
;
return
connection
;
}
catch
(
JMXProviderException
e
)
{
}
catch
(
JMXProviderException
e
)
{
throw
e
;
throw
e
;
...
@@ -553,4 +555,5 @@ public class JMXConnectorFactory {
...
@@ -553,4 +555,5 @@ public class JMXConnectorFactory {
private
static
String
protocol2package
(
String
protocol
)
{
private
static
String
protocol2package
(
String
protocol
)
{
return
protocol
.
replace
(
'+'
,
'.'
).
replace
(
'-'
,
'_'
);
return
protocol
.
replace
(
'+'
,
'.'
).
replace
(
'-'
,
'_'
);
}
}
}
}
src/share/classes/javax/management/remote/JMXConnectorServer.java
浏览文件 @
6b491fa1
...
@@ -33,6 +33,7 @@ import java.util.List;
...
@@ -33,6 +33,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.NoSuchElementException
;
import
java.util.NoSuchElementException
;
import
javax.management.ClientContext
;
import
javax.management.MBeanInfo
;
// for javadoc
import
javax.management.MBeanInfo
;
// for javadoc
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanRegistration
;
...
@@ -101,6 +102,56 @@ public abstract class JMXConnectorServer
...
@@ -101,6 +102,56 @@ public abstract class JMXConnectorServer
public
static
final
String
DELEGATE_TO_EVENT_SERVICE
=
public
static
final
String
DELEGATE_TO_EVENT_SERVICE
=
"jmx.remote.delegate.event.service"
;
"jmx.remote.delegate.event.service"
;
/**
* <p>Name of the attribute that specifies whether this connector
* server allows clients to communicate a context with each request.
* The value associated with this attribute, if any, must be a string
* that is equal to {@code "true"} or {@code "false"}, ignoring case.
* If it is {@code "true"}, then the connector server will simulate
* a namespace {@code jmx.context//}, as described in
* {@link ClientContext#newContextForwarder}. This namespace is needed
* for {@link ClientContext#withContext ClientContext.withContext} to
* function correctly.</p>
*
* <p>Not all connector servers will understand this attribute, but the
* standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
* RMI Connector Server} does. For a connector server that understands
* this attribute, the default value is {@code "true"}.</p>
*
* @since 1.7
*/
public
static
final
String
CONTEXT_FORWARDER
=
"jmx.remote.context.forwarder"
;
/**
* <p>Name of the attribute that specifies whether this connector server
* localizes the descriptions in the {@link MBeanInfo} object returned by
* {@link MBeanServer#getMBeanInfo MBeanServer.getMBeanInfo}, based on the
* locale communicated by the client.</p>
*
* <p>The value associated with this attribute, if any, must be a string
* that is equal to {@code "true"} or {@code "false"}, ignoring case.
* If it is {@code "true"}, then the connector server will localize
* {@code MBeanInfo} descriptions as specified in {@link
* ClientContext#newLocalizeMBeanInfoForwarder}.</p>
*
* <p>Not all connector servers will understand this attribute, but the
* standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
* RMI Connector Server} does. For a connector server that understands
* this attribute, the default value is {@code "false"}.</p>
*
* <p>Because localization requires the client to be able to communicate
* its locale, it does not make sense to specify this attribute as
* {@code "true"} if {@link #CONTEXT_FORWARDER} is not also {@code "true"}.
* For a connector server that understands these attributes, specifying
* this inconsistent combination will result in an {@link
* IllegalArgumentException}.</p>
*
* @since 1.7
*/
public
static
final
String
LOCALIZE_MBEAN_INFO_FORWARDER
=
"jmx.remote.localize.mbean.info"
;
/**
/**
* <p>Name of the attribute that specifies whether this connector
* <p>Name of the attribute that specifies whether this connector
* server simulates the existence of the {@link EventClientDelegate}
* server simulates the existence of the {@link EventClientDelegate}
...
@@ -155,7 +206,7 @@ public abstract class JMXConnectorServer
...
@@ -155,7 +206,7 @@ public abstract class JMXConnectorServer
* to, or null if it is not yet attached to an MBean server.
* to, or null if it is not yet attached to an MBean server.
*
*
* @see #setMBeanServerForwarder
* @see #setMBeanServerForwarder
* @see #getSystemMBeanServer
* @see #getSystemMBeanServer
Forwarder
*/
*/
public
synchronized
MBeanServer
getMBeanServer
()
{
public
synchronized
MBeanServer
getMBeanServer
()
{
return
userMBeanServer
;
return
userMBeanServer
;
...
@@ -176,30 +227,36 @@ public abstract class JMXConnectorServer
...
@@ -176,30 +227,36 @@ public abstract class JMXConnectorServer
* this method, the first occurrence in the chain of an object that is
* this method, the first occurrence in the chain of an object that is
* {@linkplain Object#equals equal} to {@code mbsf} will have been
* {@linkplain Object#equals equal} to {@code mbsf} will have been
* removed.</p>
* removed.</p>
*
* @param mbsf the forwarder to remove
* @param mbsf the forwarder to remove
*
* @throws NoSuchElementException if there is no occurrence of {@code mbsf}
* @throws NoSuchElementException if there is no occurrence of {@code mbsf}
* in the chain.
* in the chain.
* @throws IllegalArgumentException if {@code mbsf} is null.
* @throws IllegalArgumentException if {@code mbsf} is null or is the
* {@linkplain #getSystemMBeanServerForwarder() system forwarder}.
*
* @since 1.7
*/
*/
public
synchronized
void
removeMBeanServerForwarder
(
MBeanServerForwarder
mbsf
)
{
public
synchronized
void
removeMBeanServerForwarder
(
MBeanServerForwarder
mbsf
)
{
if
(
mbsf
==
null
)
if
(
mbsf
==
null
)
throw
new
IllegalArgumentException
(
"Invalid null argument: mbsf"
);
throw
new
IllegalArgumentException
(
"Invalid null argument: mbsf"
);
if
(
systemMBeanServerForwarder
.
equals
(
mbsf
))
throw
new
IllegalArgumentException
(
"Cannot remove system forwarder"
);
MBeanServerForwarder
prev
=
null
;
MBeanServerForwarder
prev
=
systemMBeanServerForwarder
;
MBeanServer
curr
=
systemMBeanServer
;
MBeanServer
curr
;
while
(
curr
instanceof
MBeanServerForwarder
&&
!
mbsf
.
equals
(
curr
))
{
while
(
true
)
{
prev
=
(
MBeanServerForwarder
)
curr
;
curr
=
prev
.
getMBeanServer
();
curr
=
prev
.
getMBeanServer
();
}
if
(
mbsf
.
equals
(
curr
))
if
(!(
curr
instanceof
MBeanServerForwarder
))
break
;
if
(
curr
instanceof
MBeanServerForwarder
)
prev
=
(
MBeanServerForwarder
)
curr
;
else
throw
new
NoSuchElementException
(
"MBeanServerForwarder not in chain"
);
throw
new
NoSuchElementException
(
"MBeanServerForwarder not in chain"
);
MBeanServerForwarder
deleted
=
(
MBeanServerForwarder
)
curr
;
}
MBeanServer
next
=
deleted
.
getMBeanServer
();
MBeanServer
next
=
mbsf
.
getMBeanServer
();
if
(
prev
!=
null
)
prev
.
setMBeanServer
(
next
);
prev
.
setMBeanServer
(
next
);
if
(
systemMBeanServer
==
deleted
)
if
(
userMBeanServer
==
mbsf
)
systemMBeanServer
=
next
;
if
(
userMBeanServer
==
deleted
)
userMBeanServer
=
next
;
userMBeanServer
=
next
;
}
}
...
@@ -209,66 +266,63 @@ public abstract class JMXConnectorServer
...
@@ -209,66 +266,63 @@ public abstract class JMXConnectorServer
* the systemMBeanServer and userMBeanServer field declarations.
* the systemMBeanServer and userMBeanServer field declarations.
*/
*/
private
void
insertUserMBeanServer
(
MBeanServer
mbs
)
{
private
void
insertUserMBeanServer
(
MBeanServer
mbs
)
{
MBeanServerForwarder
lastSystemMBSF
=
null
;
MBeanServerForwarder
lastSystemMBSF
=
systemMBeanServerForwarder
;
for
(
MBeanServer
mbsi
=
systemMBeanServer
;
while
(
true
)
{
mbsi
!=
userMBeanServer
;
MBeanServer
mbsi
=
lastSystemMBSF
.
getMBeanServer
();
mbsi
=
lastSystemMBSF
.
getMBeanServer
())
{
if
(
mbsi
==
userMBeanServer
)
break
;
lastSystemMBSF
=
(
MBeanServerForwarder
)
mbsi
;
lastSystemMBSF
=
(
MBeanServerForwarder
)
mbsi
;
}
}
userMBeanServer
=
mbs
;
userMBeanServer
=
mbs
;
if
(
lastSystemMBSF
==
null
)
systemMBeanServer
=
mbs
;
else
lastSystemMBSF
.
setMBeanServer
(
mbs
);
lastSystemMBSF
.
setMBeanServer
(
mbs
);
}
}
/**
/**
* <p>Returns the first item in the chain of system and then user
* <p>Returns the first item in the chain of system and then user
* forwarders. In the simplest case, a {@code JMXConnectorServer}
* forwarders. There is a chain of {@link MBeanServerForwarder}s between
* is connected directly to an {@code MBeanServer}. But there can
* a {@code JMXConnectorServer} and its {@code MBeanServer}. This chain
* also be a chain of {@link MBeanServerForwarder}s between the two.
* consists of two sub-chains: first the <em>system chain</em> and then
* This chain consists of two sub-chains: first the <em>system chain</em>
* the <em>user chain</em>. Incoming requests are given to the first
* and then the <em>user chain</em>. Incoming requests are given to the
* forwarder in the system chain. Each forwarder can handle a request
* first forwarder in the system chain. Each forwarder can handle
* itself, or more usually forward it to the next forwarder, perhaps with
* a request itself, or more usually forward it to the next forwarder,
* some extra behavior such as logging or security checking before or after
* perhaps with some extra behavior such as logging or security
* the forwarding. The last forwarder in the system chain is followed by
* checking before or after the forwarding. The last forwarder in
* the first forwarder in the user chain.</p>
* the system chain is followed by the first forwarder in the user
*
* chain.</p>
* <p>The object returned by this method is the first forwarder in the
*
* system chain. For a given {@code JMXConnectorServer}, this method
* <p>The <em>system chain</em> is usually
* always returns the same object, which simply forwards every request
* defined by a connector server based on the environment Map;
* to the next object in the chain.</p>
* see {@link JMXConnectorServerFactory#newJMXConnectorServer}. Allowing the
*
* connector server to define its forwarders in this way ensures that
* <p>Not all connector servers support a system chain of forwarders,
* they are in the correct order - some forwarders need to be inserted
* although the standard {@linkplain
* before others for correct behavior. It is possible to modify the
* javax.management.remote.rmi.RMIConnectorServer RMI connector
* system chain, for example using {@link #setSystemMBeanServerForwarder} or
* server} does. For those that do not, this method will throw {@code
* {@link #removeMBeanServerForwarder}, but in that case the system
* UnsupportedOperationException}. All
* chain is no longer guaranteed to be correct.</p>
* connector servers do support a user chain of forwarders.</p>
*
* <p>The <em>system chain</em> is usually defined by a
* connector server based on the environment Map; see {@link
* JMXConnectorServerFactory#newJMXConnectorServer
* JMXConnectorServerFactory.newJMXConnectorServer}. Allowing
* the connector server to define its forwarders in this way
* ensures that they are in the correct order - some forwarders
* need to be inserted before others for correct behavior. It is
* possible to modify the system chain, for example using {@code
* connectorServer.getSystemMBeanServerForwarder().setMBeanServer(mbsf)} or
* {@link #removeMBeanServerForwarder removeMBeanServerForwarder}, but in
* that case the system chain is no longer guaranteed to be correct.</p>
*
*
* <p>The <em>user chain</em> is defined by calling {@link
* <p>The <em>user chain</em> is defined by calling {@link
* #setMBeanServerForwarder} to insert forwarders at the head of the user
* #setMBeanServerForwarder setMBeanServerForwarder} to insert forwarders
* chain.</p>
* at the head of the user chain.</p>
*
* <p>If there are no forwarders in either chain, then both
* {@link #getMBeanServer()} and {@code getSystemMBeanServer()} will
* return the {@code MBeanServer} for this connector server. If there
* are forwarders in the user chain but not the system chain, then
* both methods will return the first forwarder in the user chain.
* If there are forwarders in the system chain but not the user chain,
* then {@code getSystemMBeanServer()} will return the first forwarder
* in the system chain, and {@code getMBeanServer()} will return the
* {@code MBeanServer} for this connector server. Finally, if there
* are forwarders in each chain then {@code getSystemMBeanServer()}
* will return the first forwarder in the system chain, and {@code
* getMBeanServer()} will return the first forwarder in the user chain.</p>
*
*
* <p>This code illustrates how the chains can be traversed:</p>
* <p>This code illustrates how the chains can be traversed:</p>
*
*
* <pre>
* <pre>
* JMXConnectorServer cs;
* JMXConnectorServer cs;
* System.out.println("system chain:");
* System.out.println("system chain:");
* MBeanServer mbs = cs.getSystemMBeanServer();
* MBeanServer mbs = cs.getSystemMBeanServer
Forwarder
();
* while (true) {
* while (true) {
* if (mbs == cs.getMBeanServer())
* if (mbs == cs.getMBeanServer())
* System.out.println("user chain:");
* System.out.println("user chain:");
...
@@ -281,65 +335,40 @@ public abstract class JMXConnectorServer
...
@@ -281,65 +335,40 @@ public abstract class JMXConnectorServer
* System.out.println("--MBean Server");
* System.out.println("--MBean Server");
* </pre>
* </pre>
*
*
* <h4>Note for connector server implementors</h4>
*
* <p>Existing connector server implementations can be updated to support
* a system chain of forwarders as follows:</p>
*
* <ul>
* <li><p>Override the {@link #supportsSystemMBeanServerForwarder()}
* method so that it returns true.</p>
*
* <li><p>Call {@link #installStandardForwarders} from the constructor of
* the connector server.</p>
*
* <li><p>Direct incoming requests to the result of {@link
* #getSystemMBeanServerForwarder()} instead of the result of {@link
* #getMBeanServer()}.</p>
* </ul>
*
* @return the first item in the system chain of forwarders.
* @return the first item in the system chain of forwarders.
*
*
* @see #setSystemMBeanServerForwarder
* @throws UnsupportedOperationException if {@link
* #supportsSystemMBeanServerForwarder} returns false.
*
* @see #supportsSystemMBeanServerForwarder
* @see #setMBeanServerForwarder
*
* @since 1.7
*/
*/
public
synchronized
MBeanServer
getSystemMBeanServer
()
{
public
MBeanServerForwarder
getSystemMBeanServerForwarder
()
{
return
systemMBeanServer
;
if
(!
supportsSystemMBeanServerForwarder
())
{
throw
new
UnsupportedOperationException
(
"System MBeanServerForwarder not supported by this "
+
"connector server"
);
}
}
return
systemMBeanServerForwarder
;
/**
* <p>Inserts an object that intercepts requests for the MBean server
* that arrive through this connector server. This object will be
* supplied as the <code>MBeanServer</code> for any new connection
* created by this connector server. Existing connections are
* unaffected.</p>
*
* <p>This method can be called more than once with different
* {@link MBeanServerForwarder} objects. The result is a chain
* of forwarders. The last forwarder added is the first in the chain.</p>
*
* <p>This method modifies the system chain of {@link MBeanServerForwarder}s.
* Usually user code should change the user chain instead, via
* {@link #setMBeanServerForwarder}.</p>
*
* <p>Not all connector servers support a system chain of forwarders.
* Calling this method on a connector server that does not will produce an
* {@link UnsupportedOperationException}.</p>
*
* <p>Suppose {@code mbs} is the result of {@link #getSystemMBeanServer()}
* before calling this method. If {@code mbs} is not null, then
* {@code mbsf.setMBeanServer(mbs)} will be called. If doing so
* produces an exception, this method throws the same exception without
* any other effect. If {@code mbs} is null, or if the call to
* {@code mbsf.setMBeanServer(mbs)} succeeds, then this method will
* return normally and {@code getSystemMBeanServer()} will then return
* {@code mbsf}.</p>
*
* <p>The result of {@link #getMBeanServer()} is unchanged by this method.</p>
*
* @param mbsf the new <code>MBeanServerForwarder</code>.
*
* @throws IllegalArgumentException if the call to {@link
* MBeanServerForwarder#setMBeanServer mbsf.setMBeanServer} fails
* with <code>IllegalArgumentException</code>, or if
* <code>mbsf</code> is null.
*
* @throws UnsupportedOperationException if
* {@link #supportsSystemMBeanServerForwarder} returns false.
*
* @see #getSystemMBeanServer()
*/
public
synchronized
void
setSystemMBeanServerForwarder
(
MBeanServerForwarder
mbsf
)
{
if
(
mbsf
==
null
)
throw
new
IllegalArgumentException
(
"Invalid null argument: mbsf"
);
mustSupportSystemMBSF
();
if
(
systemMBeanServer
!=
null
)
mbsf
.
setMBeanServer
(
systemMBeanServer
);
systemMBeanServer
=
mbsf
;
}
}
/**
/**
...
@@ -350,19 +379,13 @@ public abstract class JMXConnectorServer
...
@@ -350,19 +379,13 @@ public abstract class JMXConnectorServer
*
*
* @return true if this connector server supports the system chain of
* @return true if this connector server supports the system chain of
* forwarders.
* forwarders.
*
* @since 1.7
*/
*/
public
boolean
supportsSystemMBeanServerForwarder
()
{
public
boolean
supportsSystemMBeanServerForwarder
()
{
return
false
;
return
false
;
}
}
private
void
mustSupportSystemMBSF
()
{
if
(!
supportsSystemMBeanServerForwarder
())
{
throw
new
UnsupportedOperationException
(
"System MBeanServerForwarder not supported by this "
+
"connector server"
);
}
}
/**
/**
* <p>Install {@link MBeanServerForwarder}s in the system chain
* <p>Install {@link MBeanServerForwarder}s in the system chain
* based on the attributes in the given {@code Map}. A connector
* based on the attributes in the given {@code Map}. A connector
...
@@ -374,34 +397,90 @@ public abstract class JMXConnectorServer
...
@@ -374,34 +397,90 @@ public abstract class JMXConnectorServer
* <ul>
* <ul>
*
*
* <li>If {@link #EVENT_CLIENT_DELEGATE_FORWARDER} is absent, or is
* <li>If {@link #EVENT_CLIENT_DELEGATE_FORWARDER} is absent, or is
* present with the value {@code "true"}, then a forwarder with the
* present with the value {@code "true"}, then a forwarder
* functionality of {@link EventClientDelegate#newForwarder} is inserted
* equivalent to {@link EventClientDelegate#newForwarder
* at the start of the system chain.</li>
* EventClientDelegate.newForwarder}{@code (sysMBSF.getMBeanServer(),
* sysMBSF)} is inserted at the start of the system chain,
* where {@code sysMBSF} is the object returned by {@link
* #getSystemMBeanServerForwarder()}. </li>
*
* <li>If {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is present with the
* value {@code "true"}, then a forwarder equivalent to
* {@link ClientContext#newLocalizeMBeanInfoForwarder
* ClientContext.newLocalizeMBeanInfoForwarder}{@code
* (sysMBSF.getMBeanServer())} is inserted at the start of the system
* chain.</li>
*
* <li>If {@link #CONTEXT_FORWARDER} is absent, or is present with
* the value {@code "true"}, then a forwarder equivalent to
* {@link ClientContext#newContextForwarder
* ClientContext.newContextForwarder}{@code (sysMSBF.getMBeanServer(),
* sysMBSF)} is inserted at the tart of the system chain.</li>
*
*
* </ul>
* </ul>
*
*
* <p>For {@code EVENT_CLIENT_DELEGATE_FORWARDER}, if the
* <p>For {@code EVENT_CLIENT_DELEGATE_FORWARDER} and {@code
* attribute is absent from the {@code Map} and a system property
* CONTEXT_FORWARDER}, if the attribute is absent from the {@code
* of the same name is defined, then the value of the system
* Map} and a system property of the same name is defined, then
* property is used as if it were in the {@code Map}.
* the value of the system property is used as if it were in the
* {@code Map}.
*
* <p>Since each forwarder is inserted at the start of the chain,
* the final order of the forwarders is the <b>reverse</b> of the order
* above. This is important, because the {@code
* LOCALIZE_MBEAN_INFO_FORWARDER} can only work if the {@code
* CONTEXT_FORWARDER} has already installed the remote client's locale
* in the {@linkplain ClientContext#getContext context} of the current
* thread.</p>
*
*
* <p>Attributes in {@code env} that are not listed above are ignored
* <p>Attributes in {@code env} that are not listed above are ignored
* by this method.</p>
* by this method.</p>
*
*
* @throws UnsupportedOperationException if {@link
* @throws UnsupportedOperationException if {@link
* #supportsSystemMBeanServerForwarder} is false.
* #supportsSystemMBeanServerForwarder} is false.
*
* @throws IllegalArgumentException if the relevant attributes in {@code env} are
* inconsistent, for example if {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is
* {@code "true"} but {@link #CONTEXT_FORWARDER} is {@code "false"}; or
* if one of the attributes has an illegal value.
*
* @since 1.7
*/
*/
protected
void
installStandardForwarders
(
Map
<
String
,
?>
env
)
{
protected
void
installStandardForwarders
(
Map
<
String
,
?>
env
)
{
mustSupportSystemMBSF
();
MBeanServerForwarder
sysMBSF
=
getSystemMBeanServerForwarder
();
// Remember that forwarders must be added in reverse order!
// Remember that forwarders must be added in reverse order!
boolean
ecd
=
EnvHelp
.
computeBooleanFromString
(
boolean
ecd
=
EnvHelp
.
computeBooleanFromString
(
env
,
EVENT_CLIENT_DELEGATE_FORWARDER
,
false
,
true
);
env
,
EVENT_CLIENT_DELEGATE_FORWARDER
,
false
,
true
);
boolean
localize
=
EnvHelp
.
computeBooleanFromString
(
env
,
LOCALIZE_MBEAN_INFO_FORWARDER
,
false
,
false
);
boolean
context
=
EnvHelp
.
computeBooleanFromString
(
env
,
CONTEXT_FORWARDER
,
false
,
true
);
if
(
localize
&&
!
context
)
{
throw
new
IllegalArgumentException
(
"Inconsistent environment parameters: "
+
LOCALIZE_MBEAN_INFO_FORWARDER
+
"=\"true\" requires "
+
CONTEXT_FORWARDER
+
"=\"true\""
);
}
if
(
ecd
)
{
if
(
ecd
)
{
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
();
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
(
setSystemMBeanServerForwarder
(
mbsf
);
sysMBSF
.
getMBeanServer
(),
sysMBSF
);
sysMBSF
.
setMBeanServer
(
mbsf
);
}
if
(
localize
)
{
MBeanServerForwarder
mbsf
=
ClientContext
.
newLocalizeMBeanInfoForwarder
(
sysMBSF
.
getMBeanServer
());
sysMBSF
.
setMBeanServer
(
mbsf
);
}
if
(
context
)
{
MBeanServerForwarder
mbsf
=
ClientContext
.
newContextForwarder
(
sysMBSF
.
getMBeanServer
(),
sysMBSF
);
sysMBSF
.
setMBeanServer
(
mbsf
);
}
}
}
}
...
@@ -473,6 +552,7 @@ public abstract class JMXConnectorServer
...
@@ -473,6 +552,7 @@ public abstract class JMXConnectorServer
*
*
* @return the array of possible notifications.
* @return the array of possible notifications.
*/
*/
@Override
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
final
String
[]
types
=
{
final
String
[]
types
=
{
JMXConnectionNotification
.
OPENED
,
JMXConnectionNotification
.
OPENED
,
...
@@ -684,30 +764,29 @@ public abstract class JMXConnectorServer
...
@@ -684,30 +764,29 @@ public abstract class JMXConnectorServer
* Fields describing the chains of forwarders (MBeanServerForwarders).
* Fields describing the chains of forwarders (MBeanServerForwarders).
* In the general case, the forwarders look something like this:
* In the general case, the forwarders look something like this:
*
*
*
systemMBeanServer
userMBeanServer
*
userMBeanServer
*
|
|
*
|
*
v
v
*
v
*
mbsf1
-> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs
*
systemMBeanServerForwarder
-> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs
*
*
* Here, each mbsfi is an MBeanServerForwarder, and the arrows
* Here, each mbsfi is an MBeanServerForwarder, and the arrows
* illustrate its getMBeanServer() method. The last MBeanServerForwarder
* illustrate its getMBeanServer() method. The last MBeanServerForwarder
* can point to an MBeanServer that is not instanceof MBeanServerForwarder,
* can point to an MBeanServer that is not instanceof MBeanServerForwarder,
* here mbs.
* here mbs.
*
*
* Initially, the chain can be empty if this JMXConnectorServer was
* The system chain is never empty because it always has at least
* constructed without an MBeanServer. In this case, both systemMBS
* systemMBeanServerForwarder. Initially, the user chain can be empty if
* and userMBS will be null. If there is initially an MBeanServer,
* this JMXConnectorServer was constructed without an MBeanServer. In
* then both systemMBS and userMBS will point to it.
* this case, userMBS will be null. If there is initially an MBeanServer,
*
* userMBS will point to it.
* Whenever userMBS is changed, the system chain must be updated. If there
*
* are forwarders in the system chain (between systemMBS and userMBS in the
* Whenever userMBS is changed, the system chain must be updated. Before
* picture above), then the last one must point to the old value of userMBS
* the update, the last forwarder in the system chain points to the old
* (possibly null). It must be updated to point to the new value. If there
* value of userMBS (possibly null). It must be updated to point to
* are no forwarders in the system chain, then systemMBS must be updated to
* the new value. The invariant is that starting from systemMBSF and
* the new value of userMBS. The invariant is that starting from systemMBS
* repeatedly calling MBSF.getMBeanServer() you will end up at userMBS.
* and repeatedly calling MBSF.getMBeanServer() you will end up at
* The implication is that you will not see any MBeanServer object on the
* userMBS. The implication is that you will not see any MBeanServer
* way that is not also an MBeanServerForwarder.
* object on the way that is not also an MBeanServerForwarder.
*
*
* The method insertUserMBeanServer contains the logic to change userMBS
* The method insertUserMBeanServer contains the logic to change userMBS
* and adjust the system chain appropriately.
* and adjust the system chain appropriately.
...
@@ -716,7 +795,7 @@ public abstract class JMXConnectorServer
...
@@ -716,7 +795,7 @@ public abstract class JMXConnectorServer
* MBeanServer, then userMBS becomes that MBeanServer, and the system
* MBeanServer, then userMBS becomes that MBeanServer, and the system
* chain must be updated as just described.
* chain must be updated as just described.
*
*
* When systemMBS is updated, there is no effect on userMBS. The system
* When systemMBS
F
is updated, there is no effect on userMBS. The system
* chain may contain forwarders even though the user chain is empty
* chain may contain forwarders even though the user chain is empty
* (there is no MBeanServer). In that case an attempt to forward an
* (there is no MBeanServer). In that case an attempt to forward an
* incoming request through the chain will fall off the end and fail with a
* incoming request through the chain will fall off the end and fail with a
...
@@ -726,7 +805,8 @@ public abstract class JMXConnectorServer
...
@@ -726,7 +805,8 @@ public abstract class JMXConnectorServer
private
MBeanServer
userMBeanServer
;
private
MBeanServer
userMBeanServer
;
private
MBeanServer
systemMBeanServer
;
private
final
MBeanServerForwarder
systemMBeanServerForwarder
=
new
IdentityMBeanServerForwarder
();
/**
/**
* The name used to registered this server in an MBeanServer.
* The name used to registered this server in an MBeanServer.
...
...
src/share/classes/javax/management/remote/JMXConnectorServerMBean.java
浏览文件 @
6b491fa1
...
@@ -132,7 +132,7 @@ public interface JMXConnectorServerMBean {
...
@@ -132,7 +132,7 @@ public interface JMXConnectorServerMBean {
*
*
* <p>A connector server may support two chains of forwarders,
* <p>A connector server may support two chains of forwarders,
* a system chain and a user chain. See {@link
* a system chain and a user chain. See {@link
* JMXConnectorServer#
s
etSystemMBeanServerForwarder} for details.</p>
* JMXConnectorServer#
g
etSystemMBeanServerForwarder} for details.</p>
*
*
* @param mbsf the new <code>MBeanServerForwarder</code>.
* @param mbsf the new <code>MBeanServerForwarder</code>.
*
*
...
@@ -141,7 +141,7 @@ public interface JMXConnectorServerMBean {
...
@@ -141,7 +141,7 @@ public interface JMXConnectorServerMBean {
* with <code>IllegalArgumentException</code>. This includes the
* with <code>IllegalArgumentException</code>. This includes the
* case where <code>mbsf</code> is null.
* case where <code>mbsf</code> is null.
*
*
* @see JMXConnectorServer#
s
etSystemMBeanServerForwarder
* @see JMXConnectorServer#
g
etSystemMBeanServerForwarder
*/
*/
public
void
setMBeanServerForwarder
(
MBeanServerForwarder
mbsf
);
public
void
setMBeanServerForwarder
(
MBeanServerForwarder
mbsf
);
...
...
src/share/classes/javax/management/remote/rmi/RMIConnector.java
浏览文件 @
6b491fa1
...
@@ -405,7 +405,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable
...
@@ -405,7 +405,7 @@ public class RMIConnector implements JMXConnector, Serializable, JMXAddressable
rmbsc
,
EventClientDelegateMBean
.
OBJECT_NAME
,
rmbsc
,
EventClientDelegateMBean
.
OBJECT_NAME
,
EventClientDelegateMBean
.
class
);
EventClientDelegateMBean
.
class
);
EventClient
ec
=
new
EventClient
(
ecd
,
null
,
defaultExecutor
(),
null
,
EventClient
ec
=
new
EventClient
(
ecd
,
null
,
defaultExecutor
(),
null
,
EventClient
.
DEFAULT_
LEASE_TIMEOUT
);
EventClient
.
DEFAULT_
REQUESTED_LEASE_TIME
);
rmbsc
=
EventConnection
.
Factory
.
make
(
rmbsc
,
ec
);
rmbsc
=
EventConnection
.
Factory
.
make
(
rmbsc
,
ec
);
ec
.
addEventClientListener
(
ec
.
addEventClientListener
(
...
...
src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java
浏览文件 @
6b491fa1
...
@@ -383,7 +383,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
...
@@ -383,7 +383,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
try
{
try
{
if
(
tracing
)
logger
.
trace
(
"start"
,
"setting default class loader"
);
if
(
tracing
)
logger
.
trace
(
"start"
,
"setting default class loader"
);
defaultClassLoader
=
EnvHelp
.
resolveServerClassLoader
(
defaultClassLoader
=
EnvHelp
.
resolveServerClassLoader
(
attributes
,
getSystemMBeanServer
());
attributes
,
getSystemMBeanServer
Forwarder
());
}
catch
(
InstanceNotFoundException
infc
)
{
}
catch
(
InstanceNotFoundException
infc
)
{
IllegalArgumentException
x
=
new
IllegalArgumentException
x
=
new
IllegalArgumentException
(
"ClassLoader not found: "
+
infc
);
IllegalArgumentException
(
"ClassLoader not found: "
+
infc
);
...
@@ -398,7 +398,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
...
@@ -398,7 +398,7 @@ public class RMIConnectorServer extends JMXConnectorServer {
else
else
rmiServer
=
newServer
();
rmiServer
=
newServer
();
rmiServer
.
setMBeanServer
(
getSystemMBeanServer
());
rmiServer
.
setMBeanServer
(
getSystemMBeanServer
Forwarder
());
rmiServer
.
setDefaultClassLoader
(
defaultClassLoader
);
rmiServer
.
setDefaultClassLoader
(
defaultClassLoader
);
rmiServer
.
setRMIConnectorServer
(
this
);
rmiServer
.
setRMIConnectorServer
(
this
);
rmiServer
.
export
();
rmiServer
.
export
();
...
@@ -592,31 +592,6 @@ public class RMIConnectorServer extends JMXConnectorServer {
...
@@ -592,31 +592,6 @@ public class RMIConnectorServer extends JMXConnectorServer {
return
Collections
.
unmodifiableMap
(
map
);
return
Collections
.
unmodifiableMap
(
map
);
}
}
@Override
public
synchronized
void
setMBeanServerForwarder
(
MBeanServerForwarder
mbsf
)
{
MBeanServer
oldSMBS
=
getSystemMBeanServer
();
super
.
setMBeanServerForwarder
(
mbsf
);
if
(
oldSMBS
!=
getSystemMBeanServer
())
updateMBeanServer
();
// If the system chain of MBeanServerForwarders is not empty, then
// there is no need to call rmiServerImpl.setMBeanServer, because
// it is pointing to the head of the system chain and that has not
// changed. (The *end* of the system chain will have been changed
// to point to mbsf.)
}
private
void
updateMBeanServer
()
{
if
(
rmiServerImpl
!=
null
)
rmiServerImpl
.
setMBeanServer
(
getSystemMBeanServer
());
}
@Override
public
synchronized
void
setSystemMBeanServerForwarder
(
MBeanServerForwarder
mbsf
)
{
super
.
setSystemMBeanServerForwarder
(
mbsf
);
updateMBeanServer
();
}
/**
/**
* {@inheritDoc}
* {@inheritDoc}
* @return true, since this connector server does support a system chain
* @return true, since this connector server does support a system chain
...
@@ -631,16 +606,19 @@ public class RMIConnectorServer extends JMXConnectorServer {
...
@@ -631,16 +606,19 @@ public class RMIConnectorServer extends JMXConnectorServer {
here so that they are accessible to other classes in this package
here so that they are accessible to other classes in this package
even though they have protected access. */
even though they have protected access. */
@Override
protected
void
connectionOpened
(
String
connectionId
,
String
message
,
protected
void
connectionOpened
(
String
connectionId
,
String
message
,
Object
userData
)
{
Object
userData
)
{
super
.
connectionOpened
(
connectionId
,
message
,
userData
);
super
.
connectionOpened
(
connectionId
,
message
,
userData
);
}
}
@Override
protected
void
connectionClosed
(
String
connectionId
,
String
message
,
protected
void
connectionClosed
(
String
connectionId
,
String
message
,
Object
userData
)
{
Object
userData
)
{
super
.
connectionClosed
(
connectionId
,
message
,
userData
);
super
.
connectionClosed
(
connectionId
,
message
,
userData
);
}
}
@Override
protected
void
connectionFailed
(
String
connectionId
,
String
message
,
protected
void
connectionFailed
(
String
connectionId
,
String
message
,
Object
userData
)
{
Object
userData
)
{
super
.
connectionFailed
(
connectionId
,
message
,
userData
);
super
.
connectionFailed
(
connectionId
,
message
,
userData
);
...
...
src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java
浏览文件 @
6b491fa1
...
@@ -435,8 +435,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -435,8 +435,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
if
(
streaming
())
{
if
(
streaming
())
{
if
(
chunkLength
!=
-
1
)
{
if
(
chunkLength
!=
-
1
)
{
requests
.
set
(
"Transfer-Encoding"
,
"chunked"
);
requests
.
set
(
"Transfer-Encoding"
,
"chunked"
);
}
else
{
}
else
{
/* fixed content length */
requests
.
set
(
"Content-Length"
,
String
.
valueOf
(
fixedContentLength
));
if
(
fixedContentLengthLong
!=
-
1
)
{
requests
.
set
(
"Content-Length"
,
String
.
valueOf
(
fixedContentLengthLong
));
}
else
if
(
fixedContentLength
!=
-
1
)
{
requests
.
set
(
"Content-Length"
,
String
.
valueOf
(
fixedContentLength
));
}
}
}
}
else
if
(
poster
!=
null
)
{
}
else
if
(
poster
!=
null
)
{
/* add Content-Length & POST/PUT data */
/* add Content-Length & POST/PUT data */
...
@@ -871,11 +877,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -871,11 +877,17 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
ps
=
(
PrintStream
)
http
.
getOutputStream
();
ps
=
(
PrintStream
)
http
.
getOutputStream
();
if
(
streaming
())
{
if
(
streaming
())
{
if
(
strOutputStream
==
null
)
{
if
(
strOutputStream
==
null
)
{
if
(
fixedContentLength
!=
-
1
)
{
if
(
chunkLength
!=
-
1
)
{
/* chunked */
strOutputStream
=
new
StreamingOutputStream
(
ps
,
fixedContentLength
);
strOutputStream
=
new
StreamingOutputStream
(
}
else
if
(
chunkLength
!=
-
1
)
{
new
ChunkedOutputStream
(
ps
,
chunkLength
),
-
1L
);
strOutputStream
=
}
else
{
/* must be fixed content length */
new
StreamingOutputStream
(
new
ChunkedOutputStream
(
ps
,
chunkLength
),
-
1
);
long
length
=
0L
;
if
(
fixedContentLengthLong
!=
-
1
)
{
length
=
fixedContentLengthLong
;
}
else
if
(
fixedContentLength
!=
-
1
)
{
length
=
fixedContentLength
;
}
strOutputStream
=
new
StreamingOutputStream
(
ps
,
length
);
}
}
}
}
return
strOutputStream
;
return
strOutputStream
;
...
@@ -895,7 +907,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -895,7 +907,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
}
}
private
boolean
streaming
()
{
private
boolean
streaming
()
{
return
(
fixedContentLength
!=
-
1
)
||
(
chunkLength
!=
-
1
);
return
(
fixedContentLength
!=
-
1
)
||
(
fixedContentLengthLong
!=
-
1
)
||
(
chunkLength
!=
-
1
);
}
}
/*
/*
...
@@ -2619,8 +2632,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -2619,8 +2632,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
class
StreamingOutputStream
extends
FilterOutputStream
{
class
StreamingOutputStream
extends
FilterOutputStream
{
int
expected
;
long
expected
;
int
written
;
long
written
;
boolean
closed
;
boolean
closed
;
boolean
error
;
boolean
error
;
IOException
errorExcp
;
IOException
errorExcp
;
...
@@ -2631,10 +2644,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -2631,10 +2644,10 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
* In the 2nd case, we make sure the expected number of
* In the 2nd case, we make sure the expected number of
* of bytes are actually written
* of bytes are actually written
*/
*/
StreamingOutputStream
(
OutputStream
os
,
int
expectedLength
)
{
StreamingOutputStream
(
OutputStream
os
,
long
expectedLength
)
{
super
(
os
);
super
(
os
);
expected
=
expectedLength
;
expected
=
expectedLength
;
written
=
0
;
written
=
0
L
;
closed
=
false
;
closed
=
false
;
error
=
false
;
error
=
false
;
}
}
...
@@ -2643,7 +2656,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -2643,7 +2656,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public
void
write
(
int
b
)
throws
IOException
{
public
void
write
(
int
b
)
throws
IOException
{
checkError
();
checkError
();
written
++;
written
++;
if
(
expected
!=
-
1
&&
written
>
expected
)
{
if
(
expected
!=
-
1
L
&&
written
>
expected
)
{
throw
new
IOException
(
"too many bytes written"
);
throw
new
IOException
(
"too many bytes written"
);
}
}
out
.
write
(
b
);
out
.
write
(
b
);
...
@@ -2658,7 +2671,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -2658,7 +2671,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
checkError
();
checkError
();
written
+=
len
;
written
+=
len
;
if
(
expected
!=
-
1
&&
written
>
expected
)
{
if
(
expected
!=
-
1
L
&&
written
>
expected
)
{
out
.
close
();
out
.
close
();
throw
new
IOException
(
"too many bytes written"
);
throw
new
IOException
(
"too many bytes written"
);
}
}
...
@@ -2691,7 +2704,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
...
@@ -2691,7 +2704,7 @@ public class HttpURLConnection extends java.net.HttpURLConnection {
return
;
return
;
}
}
closed
=
true
;
closed
=
true
;
if
(
expected
!=
-
1
)
{
if
(
expected
!=
-
1
L
)
{
/* not chunked */
/* not chunked */
if
(
written
!=
expected
)
{
if
(
written
!=
expected
)
{
error
=
true
;
error
=
true
;
...
...
src/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java
浏览文件 @
6b491fa1
...
@@ -527,6 +527,10 @@ public class HttpsURLConnectionImpl
...
@@ -527,6 +527,10 @@ public class HttpsURLConnectionImpl
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
}
}
public
void
setFixedLengthStreamingMode
(
long
contentLength
)
{
delegate
.
setFixedLengthStreamingMode
(
contentLength
);
}
public
void
setChunkedStreamingMode
(
int
chunklen
)
{
public
void
setChunkedStreamingMode
(
int
chunklen
)
{
delegate
.
setChunkedStreamingMode
(
chunklen
);
delegate
.
setChunkedStreamingMode
(
chunklen
);
}
}
...
...
src/share/classes/sun/security/jgss/GSSContextImpl.java
浏览文件 @
6b491fa1
/*
/*
* Copyright 2000-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2000-200
8
Sun Microsystems, Inc. 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
...
@@ -284,7 +284,8 @@ class GSSContextImpl implements GSSContext {
...
@@ -284,7 +284,8 @@ class GSSContextImpl implements GSSContext {
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
(
100
);
ByteArrayOutputStream
bos
=
new
ByteArrayOutputStream
(
100
);
acceptSecContext
(
new
ByteArrayInputStream
(
inTok
,
offset
,
len
),
acceptSecContext
(
new
ByteArrayInputStream
(
inTok
,
offset
,
len
),
bos
);
bos
);
return
bos
.
toByteArray
();
byte
[]
out
=
bos
.
toByteArray
();
return
(
out
.
length
==
0
)
?
null
:
out
;
}
}
public
void
acceptSecContext
(
InputStream
inStream
,
public
void
acceptSecContext
(
InputStream
inStream
,
...
...
src/share/classes/sun/security/jgss/spnego/SpNegoContext.java
浏览文件 @
6b491fa1
/*
/*
* Copyright 2005-200
6
Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-200
8
Sun Microsystems, Inc. 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
...
@@ -413,13 +413,14 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -413,13 +413,14 @@ public class SpNegoContext implements GSSContextSpi {
// pull out the mechanism token
// pull out the mechanism token
byte
[]
accept_token
=
targToken
.
getResponseToken
();
byte
[]
accept_token
=
targToken
.
getResponseToken
();
if
(
accept_token
==
null
)
{
if
(
accept_token
==
null
)
{
// return wth failure
if
(!
isMechContextEstablished
())
{
// return with failure
throw
new
GSSException
(
errorCode
,
-
1
,
throw
new
GSSException
(
errorCode
,
-
1
,
"mechansi
m token from server is null"
);
"mechanis
m token from server is null"
);
}
}
}
else
{
mechToken
=
GSS_initSecContext
(
accept_token
);
mechToken
=
GSS_initSecContext
(
accept_token
);
}
// verify MIC
// verify MIC
if
(!
GSSUtil
.
useMSInterop
())
{
if
(!
GSSUtil
.
useMSInterop
())
{
byte
[]
micToken
=
targToken
.
getMechListMIC
();
byte
[]
micToken
=
targToken
.
getMechListMIC
();
...
@@ -428,7 +429,6 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -428,7 +429,6 @@ public class SpNegoContext implements GSSContextSpi {
"verification of MIC on MechList Failed!"
);
"verification of MIC on MechList Failed!"
);
}
}
}
}
if
(
isMechContextEstablished
())
{
if
(
isMechContextEstablished
())
{
state
=
STATE_DONE
;
state
=
STATE_DONE
;
retVal
=
mechToken
;
retVal
=
mechToken
;
...
@@ -556,9 +556,6 @@ public class SpNegoContext implements GSSContextSpi {
...
@@ -556,9 +556,6 @@ public class SpNegoContext implements GSSContextSpi {
// get the token for mechanism
// get the token for mechanism
byte
[]
accept_token
=
GSS_acceptSecContext
(
mechToken
);
byte
[]
accept_token
=
GSS_acceptSecContext
(
mechToken
);
if
(
accept_token
==
null
)
{
valid
=
false
;
}
// verify MIC
// verify MIC
if
(!
GSSUtil
.
useMSInterop
()
&&
valid
)
{
if
(!
GSSUtil
.
useMSInterop
()
&&
valid
)
{
...
...
src/share/classes/sun/security/provider/certpath/OCSPResponse.java
浏览文件 @
6b491fa1
...
@@ -151,6 +151,10 @@ class OCSPResponse {
...
@@ -151,6 +151,10 @@ class OCSPResponse {
private
SingleResponse
singleResponse
;
private
SingleResponse
singleResponse
;
// Maximum clock skew in milliseconds (10 minutes) allowed when checking
// validity of OCSP responses
private
static
final
long
MAX_CLOCK_SKEW
=
600000
;
// an array of all of the CRLReasons (used in SingleResponse)
// an array of all of the CRLReasons (used in SingleResponse)
private
static
CRLReason
[]
values
=
CRLReason
.
values
();
private
static
CRLReason
[]
values
=
CRLReason
.
values
();
...
@@ -583,7 +587,9 @@ class OCSPResponse {
...
@@ -583,7 +587,9 @@ class OCSPResponse {
}
}
}
}
Date
now
=
new
Date
();
long
now
=
System
.
currentTimeMillis
();
Date
nowPlusSkew
=
new
Date
(
now
+
MAX_CLOCK_SKEW
);
Date
nowMinusSkew
=
new
Date
(
now
-
MAX_CLOCK_SKEW
);
if
(
DEBUG
!=
null
)
{
if
(
DEBUG
!=
null
)
{
String
until
=
""
;
String
until
=
""
;
if
(
nextUpdate
!=
null
)
{
if
(
nextUpdate
!=
null
)
{
...
@@ -593,8 +599,8 @@ class OCSPResponse {
...
@@ -593,8 +599,8 @@ class OCSPResponse {
thisUpdate
+
until
);
thisUpdate
+
until
);
}
}
// Check that the test date is within the validity interval
// Check that the test date is within the validity interval
if
((
thisUpdate
!=
null
&&
now
.
before
(
thisUpdate
))
||
if
((
thisUpdate
!=
null
&&
now
PlusSkew
.
before
(
thisUpdate
))
||
(
nextUpdate
!=
null
&&
now
.
after
(
nextUpdate
)))
{
(
nextUpdate
!=
null
&&
now
MinusSkew
.
after
(
nextUpdate
)))
{
if
(
DEBUG
!=
null
)
{
if
(
DEBUG
!=
null
)
{
DEBUG
.
println
(
"Response is unreliable: its validity "
+
DEBUG
.
println
(
"Response is unreliable: its validity "
+
...
...
src/share/native/java/util/zip/zip_util.c
浏览文件 @
6b491fa1
...
@@ -273,8 +273,8 @@ static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
...
@@ -273,8 +273,8 @@ static const jlong END_MAXLEN = 0xFFFF + ENDHDR;
/*
/*
* Searches for end of central directory (END) header. The contents of
* Searches for end of central directory (END) header. The contents of
* the END header will be read and placed in endbuf. Returns the file
* the END header will be read and placed in endbuf. Returns the file
* position of the END header, otherwise returns
0
if the END header
* position of the END header, otherwise returns
-1
if the END header
* was not found or
-1 if
an error occurred.
* was not found or an error occurred.
*/
*/
static
jlong
static
jlong
findEND
(
jzfile
*
zip
,
void
*
endbuf
)
findEND
(
jzfile
*
zip
,
void
*
endbuf
)
...
@@ -314,7 +314,7 @@ findEND(jzfile *zip, void *endbuf)
...
@@ -314,7 +314,7 @@ findEND(jzfile *zip, void *endbuf)
}
}
}
}
}
}
return
0
;
/* END header not found */
return
-
1
;
/* END header not found */
}
}
/*
/*
...
@@ -460,9 +460,8 @@ if (1) { zip->msg = message; goto Catch; } else ((void)0)
...
@@ -460,9 +460,8 @@ if (1) { zip->msg = message; goto Catch; } else ((void)0)
/*
/*
* Reads zip file central directory. Returns the file position of first
* Reads zip file central directory. Returns the file position of first
* CEN header, otherwise returns 0 if central directory not found or -1
* CEN header, otherwise returns -1 if an error occured. If zip->msg != NULL
* if an error occurred. If zip->msg != NULL then the error was a zip
* then the error was a zip format error and zip->msg has the error text.
* format error and zip->msg has the error text.
* Always pass in -1 for knownTotal; it's used for a recursive call.
* Always pass in -1 for knownTotal; it's used for a recursive call.
*/
*/
static
jlong
static
jlong
...
@@ -488,9 +487,9 @@ readCEN(jzfile *zip, jint knownTotal)
...
@@ -488,9 +487,9 @@ readCEN(jzfile *zip, jint knownTotal)
/* Get position of END header */
/* Get position of END header */
if
((
endpos
=
findEND
(
zip
,
endbuf
))
==
-
1
)
if
((
endpos
=
findEND
(
zip
,
endbuf
))
==
-
1
)
return
-
1
;
/* system error */
return
-
1
;
/*
no END header or
system error */
if
(
endpos
==
0
)
return
0
;
/*
END header not found
*/
if
(
endpos
==
0
)
return
0
;
/*
only END header present
*/
freeCEN
(
zip
);
freeCEN
(
zip
);
...
...
test/com/sun/net/httpserver/bugs/FixedLengthInputStream.java
浏览文件 @
6b491fa1
...
@@ -23,7 +23,7 @@
...
@@ -23,7 +23,7 @@
/**
/**
* @test
* @test
* @bug 6756771
* @bug 6756771
6755625
* @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
* @summary com.sun.net.httpserver.HttpServer should handle POSTs larger than 2Gig
*/
*/
...
@@ -44,34 +44,16 @@ public class FixedLengthInputStream
...
@@ -44,34 +44,16 @@ public class FixedLengthInputStream
{
{
static
final
long
POST_SIZE
=
4L
*
1024L
*
1024L
*
1024L
;
// 4Gig
static
final
long
POST_SIZE
=
4L
*
1024L
*
1024L
*
1024L
;
// 4Gig
/* Remove when CR 6755625 is fixed */
static
final
String
requestHeaders
=
((
new
StringBuilder
())
.
append
(
"POST /flis/ HTTP/1.1\r\n"
)
.
append
(
"User-Agent: Java/1.7.0\r\n"
)
.
append
(
"Host: localhost\r\n"
)
.
append
(
"Accept: text/html, image/gif, image/jpeg,"
)
.
append
(
" *; q=.2, */*; q=.2\r\n"
)
.
append
(
"Content-Length: 4294967296\r\n\r\n"
)).
toString
();
void
test
(
String
[]
args
)
throws
IOException
{
void
test
(
String
[]
args
)
throws
IOException
{
HttpServer
httpServer
=
startHttpServer
();
HttpServer
httpServer
=
startHttpServer
();
int
port
=
httpServer
.
getAddress
().
getPort
();
int
port
=
httpServer
.
getAddress
().
getPort
();
try
{
try
{
/* Uncomment & when CR 6755625 is fixed, remove socket code
URL
url
=
new
URL
(
"http://localhost:"
+
port
+
"/flis/"
);
URL
url
=
new
URL
(
"http://localhost:"
+
port
+
"/flis/"
);
HttpURLConnection
uc
=
(
HttpURLConnection
)
url
.
openConnection
();
HttpURLConnection
uc
=
(
HttpURLConnection
)
url
.
openConnection
();
uc
.
setDoOutput
(
true
);
uc
.
setDoOutput
(
true
);
uc
.
setRequestMethod
(
"POST"
);
uc
.
setRequestMethod
(
"POST"
);
uc
.
setFixedLengthStreamingMode
(
POST_SIZE
);
uc
.
setFixedLengthStreamingMode
(
POST_SIZE
);
OutputStream
os
=
uc
.
getOutputStream
();
OutputStream
os
=
uc
.
getOutputStream
();
*/
Socket
socket
=
new
Socket
(
"localhost"
,
port
);
OutputStream
os
=
socket
.
getOutputStream
();
PrintStream
ps
=
new
PrintStream
(
os
);
debug
(
"Request: "
+
requestHeaders
);
ps
.
print
(
requestHeaders
);
ps
.
flush
();
/* create a 32K byte array with data to POST */
/* create a 32K byte array with data to POST */
int
thirtyTwoK
=
32
*
1024
;
int
thirtyTwoK
=
32
*
1024
;
...
@@ -84,16 +66,10 @@ public class FixedLengthInputStream
...
@@ -84,16 +66,10 @@ public class FixedLengthInputStream
os
.
write
(
ba
);
os
.
write
(
ba
);
}
}
/* Uncomment & when CR 6755625 is fixed, remove socket code
os
.
close
();
os
.
close
();
InputStream
is
=
uc
.
getInputStream
();
InputStream
is
=
uc
.
getInputStream
();
while
(
is
.
read
(
ba
)
!=
-
1
);
while
(
is
.
read
(
ba
)
!=
-
1
);
is
.
close
();
is
.
close
();
*/
InputStream
is
=
socket
.
getInputStream
();
is
.
read
();
socket
.
close
();
pass
();
pass
();
}
finally
{
}
finally
{
...
...
test/java/security/cert/CertPathValidatorException/GetMessage.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6765046
* @summary check that getMessage(cause) returns cause.toString if cause != null
*/
import
java.security.cert.CertPathValidatorException
;
public
class
GetMessage
{
private
static
volatile
boolean
failed
=
false
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Throwable
[]
causes
=
{
new
Throwable
(),
new
Throwable
(
"message"
),
new
Throwable
(
"message"
,
new
Throwable
())
};
for
(
Throwable
cause:
causes
)
{
CertPathValidatorException
cpve
=
new
CertPathValidatorException
(
cause
);
// from CertPathValidatorException(Throwable cause) spec:
// The detail message is set to (cause==null ? null : cause.toString() )
// (which typically contains the class and detail message of cause).
String
expMsg
=
(
cause
==
null
?
null
:
cause
.
toString
());
String
actualMsg
=
cpve
.
getMessage
();
boolean
msgsEqual
=
(
expMsg
==
null
?
actualMsg
==
null
:
expMsg
.
equals
(
actualMsg
));
if
(!
msgsEqual
)
{
System
.
out
.
println
(
"expected message:"
+
expMsg
);
System
.
out
.
println
(
"getMessage():"
+
actualMsg
);
failed
=
true
;
}
}
if
(
failed
)
{
throw
new
Exception
(
"Some tests FAILED"
);
}
}
}
test/java/util/zip/TestEmptyZip.java
浏览文件 @
6b491fa1
...
@@ -39,34 +39,23 @@ public class TestEmptyZip {
...
@@ -39,34 +39,23 @@ public class TestEmptyZip {
throw
new
Exception
(
"failed to delete "
+
zipName
);
throw
new
Exception
(
"failed to delete "
+
zipName
);
}
}
// Verify 0-length file cannot be read
f
.
createNewFile
();
f
.
createNewFile
();
ZipFile
zf
=
null
;
try
{
try
{
zf
=
new
ZipFile
(
f
);
// Verify 0-length file cannot be read
fail
();
checkCannotRead
(
f
);
}
catch
(
Exception
ex
)
{
check
(
ex
.
getMessage
().
contains
(
"zip file is empty"
));
}
finally
{
if
(
zf
!=
null
)
{
zf
.
close
();
}
}
ZipInputStream
zis
=
null
;
// Verify non-zip file cannot be read
OutputStream
out
=
new
FileOutputStream
(
f
);
try
{
try
{
zis
=
new
ZipInputStream
(
new
FileInputStream
(
f
));
out
.
write
(
"class Foo { }"
.
getBytes
());
ZipEntry
ze
=
zis
.
getNextEntry
();
check
(
ze
==
null
);
}
catch
(
Exception
ex
)
{
unexpected
(
ex
);
}
finally
{
}
finally
{
if
(
zis
!=
null
)
{
out
.
close
();
zis
.
close
();
}
}
}
checkCannotRead
(
f
);
}
finally
{
f
.
delete
();
f
.
delete
();
}
// Verify 0-entries file can be written
// Verify 0-entries file can be written
write
(
f
);
write
(
f
);
...
@@ -78,6 +67,29 @@ public class TestEmptyZip {
...
@@ -78,6 +67,29 @@ public class TestEmptyZip {
f
.
delete
();
f
.
delete
();
}
}
static
void
checkCannotRead
(
File
f
)
throws
IOException
{
try
{
new
ZipFile
(
f
).
close
();
fail
();
}
catch
(
ZipException
ze
)
{
if
(
f
.
length
()
==
0
)
{
check
(
ze
.
getMessage
().
contains
(
"zip file is empty"
));
}
else
{
pass
();
}
}
ZipInputStream
zis
=
null
;
try
{
zis
=
new
ZipInputStream
(
new
FileInputStream
(
f
));
ZipEntry
ze
=
zis
.
getNextEntry
();
check
(
ze
==
null
);
}
catch
(
IOException
ex
)
{
unexpected
(
ex
);
}
finally
{
if
(
zis
!=
null
)
zis
.
close
();
}
}
static
void
write
(
File
f
)
throws
Exception
{
static
void
write
(
File
f
)
throws
Exception
{
ZipOutputStream
zos
=
null
;
ZipOutputStream
zos
=
null
;
try
{
try
{
...
...
test/javax/management/Introspector/AnnotationTest.java
浏览文件 @
6b491fa1
...
@@ -39,7 +39,8 @@ import javax.management.*;
...
@@ -39,7 +39,8 @@ import javax.management.*;
/*
/*
This test checks that annotations produce Descriptor entries as
This test checks that annotations produce Descriptor entries as
specified in javax.management.DescriptorKey. It does two things:
specified in javax.management.DescriptorKey and javax.management.DescriptorField.
It does the following:
- An annotation consisting of an int and a String, each with an
- An annotation consisting of an int and a String, each with an
appropriate @DescriptorKey annotation, is placed on every program
appropriate @DescriptorKey annotation, is placed on every program
...
@@ -61,6 +62,10 @@ import javax.management.*;
...
@@ -61,6 +62,10 @@ import javax.management.*;
The test checks that in each case the corresponding Descriptor
The test checks that in each case the corresponding Descriptor
appears in the appropriate place inside the MBean's MBeanInfo.
appears in the appropriate place inside the MBean's MBeanInfo.
- A @DescriptorFields annotation defining two fields is placed in the
same places and again the test checks that the two fields appear
in the corresponding MBean*Info objects.
- An annotation consisting of enough other types to ensure coverage
- An annotation consisting of enough other types to ensure coverage
is placed on a getter. The test checks that the generated
is placed on a getter. The test checks that the generated
MBeanAttributeInfo contains the corresponding Descriptor. The tested
MBeanAttributeInfo contains the corresponding Descriptor. The tested
...
@@ -78,12 +83,6 @@ import javax.management.*;
...
@@ -78,12 +83,6 @@ import javax.management.*;
public
class
AnnotationTest
{
public
class
AnnotationTest
{
private
static
String
failed
=
null
;
private
static
String
failed
=
null
;
// @Retention(RetentionPolicy.RUNTIME) @Inherited
// @Target(ElementType.METHOD)
// public static @interface DescriptorKey {
// String value();
// }
@Retention
(
RetentionPolicy
.
RUNTIME
)
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
static
@interface
Pair
{
public
static
@interface
Pair
{
@DescriptorKey
(
"x"
)
@DescriptorKey
(
"x"
)
...
@@ -112,11 +111,12 @@ public class AnnotationTest {
...
@@ -112,11 +111,12 @@ public class AnnotationTest {
boolean
[]
booleanArrayValue
();
boolean
[]
booleanArrayValue
();
}
}
/* We use the annotation @Pair(x = 3, y = "foo") everywhere, and this is
/* We use the annotations @Pair(x = 3, y = "foo")
the Descriptor that it should produce: */
and @DescriptorFields({"foo=bar", "baz="}) everywhere, and this is
the Descriptor that they should produce: */
private
static
Descriptor
expectedDescriptor
=
private
static
Descriptor
expectedDescriptor
=
new
ImmutableDescriptor
(
new
String
[]
{
"x"
,
"y"
},
new
ImmutableDescriptor
(
new
String
[]
{
"x"
,
"y"
,
"foo"
,
"baz"
},
new
Object
[]
{
3
,
"foo"
});
new
Object
[]
{
3
,
"foo"
,
"bar"
,
""
});
private
static
Descriptor
expectedFullDescriptor
=
private
static
Descriptor
expectedFullDescriptor
=
new
ImmutableDescriptor
(
new
String
[]
{
new
ImmutableDescriptor
(
new
String
[]
{
...
@@ -136,8 +136,10 @@ public class AnnotationTest {
...
@@ -136,8 +136,10 @@ public class AnnotationTest {
});
});
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
static
interface
ThingMBean
{
public
static
interface
ThingMBean
{
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
@Full
(
classValue
=
Full
.
class
,
@Full
(
classValue
=
Full
.
class
,
enumValue
=
RetentionPolicy
.
RUNTIME
,
enumValue
=
RetentionPolicy
.
RUNTIME
,
booleanValue
=
false
,
booleanValue
=
false
,
...
@@ -149,32 +151,47 @@ public class AnnotationTest {
...
@@ -149,32 +151,47 @@ public class AnnotationTest {
int
getReadOnly
();
int
getReadOnly
();
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
void
setWriteOnly
(
int
x
);
void
setWriteOnly
(
int
x
);
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
getReadWrite1
();
int
getReadWrite1
();
void
setReadWrite1
(
int
x
);
void
setReadWrite1
(
int
x
);
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
getReadWrite2
();
int
getReadWrite2
();
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
void
setReadWrite2
(
int
x
);
void
setReadWrite2
(
int
x
);
int
getReadWrite3
();
int
getReadWrite3
();
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
void
setReadWrite3
(
int
x
);
void
setReadWrite3
(
int
x
);
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
int
operation
(
@Pair
(
x
=
3
,
y
=
"foo"
)
int
p1
,
@DescriptorFields
({
"foo=bar"
,
"baz="
})
@Pair
(
x
=
3
,
y
=
"foo"
)
int
p2
);
int
operation
(
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
p1
,
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
p2
);
}
}
public
static
class
Thing
implements
ThingMBean
{
public
static
class
Thing
implements
ThingMBean
{
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
Thing
()
{}
public
Thing
()
{}
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
public
Thing
(
@Pair
(
x
=
3
,
y
=
"foo"
)
int
p1
)
{}
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
Thing
(
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
p1
)
{}
public
int
getReadOnly
()
{
return
0
;}
public
int
getReadOnly
()
{
return
0
;}
...
@@ -193,14 +210,20 @@ public class AnnotationTest {
...
@@ -193,14 +210,20 @@ public class AnnotationTest {
}
}
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
static
interface
ThingMXBean
extends
ThingMBean
{}
public
static
interface
ThingMXBean
extends
ThingMBean
{}
public
static
class
ThingImpl
implements
ThingMXBean
{
public
static
class
ThingImpl
implements
ThingMXBean
{
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
ThingImpl
()
{}
public
ThingImpl
()
{}
@Pair
(
x
=
3
,
y
=
"foo"
)
@Pair
(
x
=
3
,
y
=
"foo"
)
public
ThingImpl
(
@Pair
(
x
=
3
,
y
=
"foo"
)
int
p1
)
{}
@DescriptorFields
({
"foo=bar"
,
"baz="
})
public
ThingImpl
(
@Pair
(
x
=
3
,
y
=
"foo"
)
@DescriptorFields
({
"foo=bar"
,
"baz="
})
int
p1
)
{}
public
int
getReadOnly
()
{
return
0
;}
public
int
getReadOnly
()
{
return
0
;}
...
@@ -218,6 +241,79 @@ public class AnnotationTest {
...
@@ -218,6 +241,79 @@ public class AnnotationTest {
public
int
operation
(
int
p1
,
int
p2
)
{
return
0
;}
public
int
operation
(
int
p1
,
int
p2
)
{
return
0
;}
}
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
static
@interface
DefaultTest
{
@DescriptorKey
(
value
=
"string1"
,
omitIfDefault
=
true
)
String
string1
()
default
""
;
@DescriptorKey
(
value
=
"string2"
,
omitIfDefault
=
true
)
String
string2
()
default
"tiddly pom"
;
@DescriptorKey
(
value
=
"int"
,
omitIfDefault
=
true
)
int
intx
()
default
23
;
@DescriptorKey
(
value
=
"intarray1"
,
omitIfDefault
=
true
)
int
[]
intArray1
()
default
{};
@DescriptorKey
(
value
=
"intarray2"
,
omitIfDefault
=
true
)
int
[]
intArray2
()
default
{
1
,
2
};
@DescriptorKey
(
value
=
"stringarray1"
,
omitIfDefault
=
true
)
String
[]
stringArray1
()
default
{};
@DescriptorKey
(
value
=
"stringarray2"
,
omitIfDefault
=
true
)
String
[]
stringArray2
()
default
{
"foo"
,
"bar"
};
}
@Retention
(
RetentionPolicy
.
RUNTIME
)
public
static
@interface
Expect
{
String
[]
value
()
default
{};
}
public
static
interface
DefaultMBean
{
@DefaultTest
@Expect
()
public
void
a
();
@DefaultTest
(
string1
=
""
)
@Expect
()
public
void
b
();
@DefaultTest
(
string1
=
"nondefault"
)
@Expect
(
"string1=nondefault"
)
public
void
c
();
@DefaultTest
(
string2
=
"tiddly pom"
)
@Expect
()
public
void
d
();
@DefaultTest
(
intx
=
23
)
@Expect
()
public
void
e
();
@DefaultTest
(
intx
=
34
)
@Expect
(
"int=34"
)
public
void
f
();
@DefaultTest
(
intArray1
={})
@Expect
()
public
void
g
();
@DefaultTest
(
intArray1
={
2
,
3
})
@Expect
(
"intarray1=[2, 3]"
)
public
void
h
();
@DefaultTest
(
intArray2
={})
@Expect
(
"intarray2=[]"
)
public
void
i
();
@DefaultTest
(
stringArray1
={})
@Expect
()
public
void
j
();
@DefaultTest
(
stringArray1
={
"foo"
})
@Expect
(
"stringarray1=[foo]"
)
public
void
k
();
@DefaultTest
(
stringArray2
={})
@Expect
(
"stringarray2=[]"
)
public
void
l
();
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
System
.
out
.
println
(
"Testing that annotations are correctly "
+
System
.
out
.
println
(
"Testing that annotations are correctly "
+
"reflected in Descriptor entries"
);
"reflected in Descriptor entries"
);
...
@@ -225,20 +321,62 @@ public class AnnotationTest {
...
@@ -225,20 +321,62 @@ public class AnnotationTest {
MBeanServer
mbs
=
MBeanServer
mbs
=
java
.
lang
.
management
.
ManagementFactory
.
getPlatformMBeanServer
();
java
.
lang
.
management
.
ManagementFactory
.
getPlatformMBeanServer
();
ObjectName
on
=
new
ObjectName
(
"a:b=c"
);
ObjectName
on
=
new
ObjectName
(
"a:b=c"
);
Thing
thing
=
new
Thing
();
Thing
thing
=
new
Thing
();
mbs
.
registerMBean
(
thing
,
on
);
mbs
.
registerMBean
(
thing
,
on
);
check
(
mbs
,
on
);
check
(
mbs
,
on
);
mbs
.
unregisterMBean
(
on
);
mbs
.
unregisterMBean
(
on
);
ThingImpl
thingImpl
=
new
ThingImpl
();
ThingImpl
thingImpl
=
new
ThingImpl
();
mbs
.
registerMBean
(
thingImpl
,
on
);
mbs
.
registerMBean
(
thingImpl
,
on
);
Descriptor
d
=
mbs
.
getMBeanInfo
(
on
).
getDescriptor
();
if
(!
d
.
getFieldValue
(
"mxbean"
).
equals
(
"true"
))
{
System
.
out
.
println
(
"NOT OK: expected MXBean"
);
failed
=
"Expected MXBean"
;
}
check
(
mbs
,
on
);
check
(
mbs
,
on
);
System
.
out
.
println
();
System
.
out
.
println
(
"Testing that omitIfDefault works"
);
DefaultMBean
defaultImpl
=
(
DefaultMBean
)
Proxy
.
newProxyInstance
(
DefaultMBean
.
class
.
getClassLoader
(),
new
Class
<?>[]
{
DefaultMBean
.
class
},
new
InvocationHandler
(){
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
{
return
null
;
}
});
DynamicMBean
mbean
=
new
StandardMBean
(
defaultImpl
,
DefaultMBean
.
class
);
MBeanOperationInfo
[]
ops
=
mbean
.
getMBeanInfo
().
getOperations
();
for
(
MBeanOperationInfo
op
:
ops
)
{
String
name
=
op
.
getName
();
Expect
expect
=
DefaultMBean
.
class
.
getMethod
(
name
).
getAnnotation
(
Expect
.
class
);
Descriptor
opd
=
op
.
getDescriptor
();
List
<
String
>
fields
=
new
ArrayList
<
String
>();
for
(
String
fieldName
:
opd
.
getFieldNames
())
{
Object
value
=
opd
.
getFieldValue
(
fieldName
);
String
s
=
Arrays
.
deepToString
(
new
Object
[]
{
value
});
s
=
s
.
substring
(
1
,
s
.
length
()
-
1
);
fields
.
add
(
fieldName
+
"="
+
s
);
}
Descriptor
opds
=
new
ImmutableDescriptor
(
fields
.
toArray
(
new
String
[
0
]));
Descriptor
expd
=
new
ImmutableDescriptor
(
expect
.
value
());
if
(
opds
.
equals
(
expd
))
System
.
out
.
println
(
"OK: op "
+
name
+
": "
+
opds
);
else
{
String
failure
=
"Bad descriptor for op "
+
name
+
": "
+
"expected "
+
expd
+
", got "
+
opds
;
System
.
out
.
println
(
"NOT OK: "
+
failure
);
failed
=
failure
;
}
}
System
.
out
.
println
();
if
(
failed
==
null
)
if
(
failed
==
null
)
System
.
out
.
println
(
"Test passed"
);
System
.
out
.
println
(
"Test passed"
);
else
if
(
true
)
throw
new
Exception
(
"TEST FAILED: "
+
failed
);
else
else
System
.
out
.
println
(
"Test disabled until 6221321 implemented"
);
throw
new
Exception
(
"TEST FAILED: "
+
failed
);
}
}
private
static
void
check
(
MBeanServer
mbs
,
ObjectName
on
)
throws
Exception
{
private
static
void
check
(
MBeanServer
mbs
,
ObjectName
on
)
throws
Exception
{
...
@@ -295,151 +433,4 @@ public class AnnotationTest {
...
@@ -295,151 +433,4 @@ public class AnnotationTest {
for
(
DescriptorRead
x
:
xx
)
for
(
DescriptorRead
x
:
xx
)
check
(
x
);
check
(
x
);
}
}
public
static
class
AnnotatedMBean
extends
StandardMBean
{
<
T
>
AnnotatedMBean
(
T
resource
,
Class
<
T
>
interfaceClass
,
boolean
mx
)
{
super
(
resource
,
interfaceClass
,
mx
);
}
private
static
final
String
[]
attrPrefixes
=
{
"get"
,
"set"
,
"is"
};
protected
void
cacheMBeanInfo
(
MBeanInfo
info
)
{
MBeanAttributeInfo
[]
attrs
=
info
.
getAttributes
();
MBeanOperationInfo
[]
ops
=
info
.
getOperations
();
for
(
int
i
=
0
;
i
<
attrs
.
length
;
i
++)
{
MBeanAttributeInfo
attr
=
attrs
[
i
];
String
name
=
attr
.
getName
();
Descriptor
d
=
attr
.
getDescriptor
();
Method
m
;
if
((
m
=
getMethod
(
"get"
+
name
))
!=
null
)
d
=
ImmutableDescriptor
.
union
(
d
,
descriptorFor
(
m
));
if
(
attr
.
getType
().
equals
(
"boolean"
)
&&
(
m
=
getMethod
(
"is"
+
name
))
!=
null
)
d
=
ImmutableDescriptor
.
union
(
d
,
descriptorFor
(
m
));
if
((
m
=
getMethod
(
"set"
+
name
,
attr
))
!=
null
)
d
=
ImmutableDescriptor
.
union
(
d
,
descriptorFor
(
m
));
if
(!
d
.
equals
(
attr
.
getDescriptor
()))
{
attrs
[
i
]
=
new
MBeanAttributeInfo
(
name
,
attr
.
getType
(),
attr
.
getDescription
(),
attr
.
isReadable
(),
attr
.
isWritable
(),
attr
.
isIs
(),
d
);
}
}
for
(
int
i
=
0
;
i
<
ops
.
length
;
i
++)
{
MBeanOperationInfo
op
=
ops
[
i
];
String
name
=
op
.
getName
();
Descriptor
d
=
op
.
getDescriptor
();
MBeanParameterInfo
[]
params
=
op
.
getSignature
();
Method
m
=
getMethod
(
name
,
params
);
if
(
m
!=
null
)
{
d
=
ImmutableDescriptor
.
union
(
d
,
descriptorFor
(
m
));
Annotation
[][]
annots
=
m
.
getParameterAnnotations
();
for
(
int
pi
=
0
;
pi
<
params
.
length
;
pi
++)
{
MBeanParameterInfo
param
=
params
[
pi
];
Descriptor
pd
=
ImmutableDescriptor
.
union
(
param
.
getDescriptor
(),
descriptorFor
(
annots
[
pi
]));
params
[
pi
]
=
new
MBeanParameterInfo
(
param
.
getName
(),
param
.
getType
(),
param
.
getDescription
(),
pd
);
}
op
=
new
MBeanOperationInfo
(
op
.
getName
(),
op
.
getDescription
(),
params
,
op
.
getReturnType
(),
op
.
getImpact
(),
d
);
if
(!
ops
[
i
].
equals
(
op
))
ops
[
i
]
=
op
;
}
}
Descriptor
id
=
descriptorFor
(
getMBeanInterface
());
info
=
new
MBeanInfo
(
info
.
getClassName
(),
info
.
getDescription
(),
attrs
,
info
.
getConstructors
(),
ops
,
info
.
getNotifications
(),
ImmutableDescriptor
.
union
(
id
,
info
.
getDescriptor
()));
super
.
cacheMBeanInfo
(
info
);
}
private
Descriptor
descriptorFor
(
AnnotatedElement
x
)
{
Annotation
[]
annots
=
x
.
getAnnotations
();
return
descriptorFor
(
annots
);
}
private
Descriptor
descriptorFor
(
Annotation
[]
annots
)
{
if
(
annots
.
length
==
0
)
return
ImmutableDescriptor
.
EMPTY_DESCRIPTOR
;
Map
<
String
,
Object
>
descriptorMap
=
new
HashMap
<
String
,
Object
>();
for
(
Annotation
a
:
annots
)
{
Class
<?
extends
Annotation
>
c
=
a
.
annotationType
();
Method
[]
elements
=
c
.
getMethods
();
for
(
Method
element
:
elements
)
{
DescriptorKey
key
=
element
.
getAnnotation
(
DescriptorKey
.
class
);
if
(
key
!=
null
)
{
String
name
=
key
.
value
();
Object
value
;
try
{
value
=
element
.
invoke
(
a
);
}
catch
(
Exception
e
)
{
// we don't expect this
throw
new
RuntimeException
(
e
);
}
Object
oldValue
=
descriptorMap
.
put
(
name
,
value
);
if
(
oldValue
!=
null
&&
!
oldValue
.
equals
(
value
))
{
final
String
msg
=
"Inconsistent values for descriptor field "
+
name
+
" from annotations: "
+
value
+
" :: "
+
oldValue
;
throw
new
IllegalArgumentException
(
msg
);
}
}
}
}
if
(
descriptorMap
.
isEmpty
())
return
ImmutableDescriptor
.
EMPTY_DESCRIPTOR
;
else
return
new
ImmutableDescriptor
(
descriptorMap
);
}
private
Method
getMethod
(
String
name
,
MBeanFeatureInfo
...
params
)
{
Class
<?>
intf
=
getMBeanInterface
();
ClassLoader
loader
=
intf
.
getClassLoader
();
Class
[]
classes
=
new
Class
[
params
.
length
];
for
(
int
i
=
0
;
i
<
params
.
length
;
i
++)
{
MBeanFeatureInfo
param
=
params
[
i
];
Descriptor
d
=
param
.
getDescriptor
();
String
type
=
(
String
)
d
.
getFieldValue
(
"originalType"
);
if
(
type
==
null
)
{
if
(
param
instanceof
MBeanAttributeInfo
)
type
=
((
MBeanAttributeInfo
)
param
).
getType
();
else
type
=
((
MBeanParameterInfo
)
param
).
getType
();
}
Class
<?>
c
=
primitives
.
get
(
type
);
if
(
c
==
null
)
{
try
{
c
=
Class
.
forName
(
type
,
false
,
loader
);
}
catch
(
ClassNotFoundException
e
)
{
return
null
;
}
}
classes
[
i
]
=
c
;
}
try
{
return
intf
.
getMethod
(
name
,
classes
);
}
catch
(
Exception
e
)
{
return
null
;
}
}
private
static
final
Map
<
String
,
Class
<?>>
primitives
=
new
HashMap
<
String
,
Class
<?>>();
static
{
for
(
Class
<?>
c
:
new
Class
[]
{
boolean
.
class
,
byte
.
class
,
short
.
class
,
int
.
class
,
long
.
class
,
float
.
class
,
double
.
class
,
char
.
class
,
void
.
class
})
{
primitives
.
put
(
c
.
getName
(),
c
);
}
}
}
}
}
test/javax/management/MBeanServer/AttributeListMapTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6336968
* @summary Test AttributeList.toMap
* @author Eamonn McManus
*/
import
java.math.BigInteger
;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Map
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
public
class
AttributeListMapTest
{
private
static
String
failure
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
AttributeList
attrs
=
new
AttributeList
(
Arrays
.
asList
(
new
Attribute
(
"Str"
,
"Five"
),
new
Attribute
(
"Int"
,
5
),
new
Attribute
(
"Flt"
,
5.0
)));
Map
<
String
,
Object
>
map
=
attrs
.
toMap
();
final
Map
<
String
,
Object
>
expectMap
=
new
HashMap
<
String
,
Object
>();
for
(
Attribute
attr
:
attrs
.
asList
())
expectMap
.
put
(
attr
.
getName
(),
attr
.
getValue
());
assertEquals
(
"Initial map"
,
expectMap
,
map
);
assertEquals
(
"Initial map size"
,
3
,
map
.
size
());
assertEquals
(
"Name set"
,
expectMap
.
keySet
(),
map
.
keySet
());
assertEquals
(
"Values"
,
new
HashSet
<
Object
>(
expectMap
.
values
()),
new
HashSet
<
Object
>(
map
.
values
()));
assertEquals
(
"Entry set"
,
expectMap
.
entrySet
(),
map
.
entrySet
());
AttributeList
attrs2
=
new
AttributeList
(
map
);
assertEquals
(
"AttributeList from Map"
,
attrs
,
attrs2
);
// This assumes that the Map conserves the order of the attributes,
// which is not specified but true because we use LinkedHashMap.
// Check that toMap fails if the list contains non-Attribute elements.
AttributeList
attrs3
=
new
AttributeList
(
attrs
);
attrs3
.
add
(
"Hello"
);
// allowed but curious
try
{
map
=
attrs3
.
toMap
();
fail
(
"toMap succeeded on list with non-Attribute elements"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for toMap with non-Atttribute elements"
,
IllegalArgumentException
.
class
,
e
.
getClass
());
}
// Check that the Map does not reflect changes made to the list after
// the Map was obtained.
AttributeList
attrs4
=
new
AttributeList
(
attrs
);
map
=
attrs4
.
toMap
();
attrs4
.
add
(
new
Attribute
(
"Big"
,
new
BigInteger
(
"5"
)));
assertEquals
(
"Map after adding element to list"
,
expectMap
,
map
);
// Check that if there is more than one Attribute with the same name
// then toMap() chooses the last of them.
AttributeList
attrs5
=
new
AttributeList
(
attrs
);
attrs5
.
add
(
new
Attribute
(
"Str"
,
"Cinq"
));
map
=
attrs5
.
toMap
();
assertEquals
(
"Size of Map for list with duplicate attribute name"
,
3
,
map
.
size
());
Object
value
=
map
.
get
(
"Str"
);
assertEquals
(
"Value of Str in Map for list with two values for it"
,
"Cinq"
,
value
);
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
private
static
void
assertEquals
(
String
what
,
Object
expect
,
Object
actual
)
{
if
(
eq
(
expect
,
actual
))
System
.
out
.
println
(
"OK: "
+
what
);
else
fail
(
what
+
": expected "
+
expect
+
", got "
+
actual
);
}
private
static
boolean
eq
(
Object
x
,
Object
y
)
{
return
(
x
==
null
)
?
(
y
==
null
)
:
x
.
equals
(
y
);
}
private
static
void
fail
(
String
why
)
{
System
.
out
.
println
(
"FAIL: "
+
why
);
failure
=
why
;
}
}
test/javax/management/MBeanServer/AttributeListTypeSafeTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6336968
* @summary Test adding non-Attribute values to an AttributeList.
* @author Eamonn McManus
*/
import
java.util.Collections
;
import
java.util.List
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
public
class
AttributeListTypeSafeTest
{
private
static
String
failure
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// Test calling asList after adding non-Attribute by various means
for
(
Op
op
:
Op
.
values
())
{
AttributeList
alist
=
new
AttributeList
();
alist
.
add
(
new
Attribute
(
"foo"
,
"bar"
));
doOp
(
alist
,
op
);
String
what
=
"asList() after calling "
+
op
+
" with non-Attribute"
;
try
{
List
<
Attribute
>
lista
=
alist
.
asList
();
fail
(
what
+
": succeeded but should not have"
);
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
"OK: "
+
what
+
": got IllegalArgumentException"
);
}
}
// Test adding non-Attribute by various means after calling asList
for
(
Op
op
:
Op
.
values
())
{
AttributeList
alist
=
new
AttributeList
();
List
<
Attribute
>
lista
=
alist
.
asList
();
lista
.
add
(
new
Attribute
(
"foo"
,
"bar"
));
String
what
=
op
+
" with non-Attribute after calling asList()"
;
try
{
doOp
(
alist
,
op
);
fail
(
what
+
": succeeded but should not have"
);
}
catch
(
IllegalArgumentException
e
)
{
System
.
out
.
println
(
"OK: "
+
what
+
": got IllegalArgumentException"
);
}
}
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
private
static
enum
Op
{
ADD
(
"add(Object)"
),
ADD_AT
(
"add(int, Object)"
),
ADD_ALL
(
"add(Collection)"
),
ADD_ALL_AT
(
"add(int, Collection)"
),
SET
(
"set(int, Object)"
);
private
Op
(
String
what
)
{
this
.
what
=
what
;
}
@Override
public
String
toString
()
{
return
what
;
}
private
final
String
what
;
}
private
static
void
doOp
(
AttributeList
alist
,
Op
op
)
{
Object
x
=
"oops"
;
switch
(
op
)
{
case
ADD:
alist
.
add
(
x
);
break
;
case
ADD_AT:
alist
.
add
(
0
,
x
);
break
;
case
ADD_ALL:
alist
.
add
(
Collections
.
singleton
(
x
));
break
;
case
ADD_ALL_AT:
alist
.
add
(
0
,
Collections
.
singleton
(
x
));
break
;
case
SET:
alist
.
set
(
0
,
x
);
break
;
default
:
throw
new
AssertionError
(
"Case not covered"
);
}
}
private
static
void
fail
(
String
why
)
{
System
.
out
.
println
(
"FAIL: "
+
why
);
failure
=
why
;
}
}
test/javax/management/context/ContextForwarderTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 5072267
* @summary Test that a context forwarder can be created and then installed.
* @author Eamonn McManus
*/
/* The specific thing we're testing for is that the forwarder can be created
* with a null "next", and then installed with a real "next". An earlier
* defect meant that in this case the simulated jmx.context// namespace had a
* null handler that never changed.
*/
import
java.util.HashMap
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.TreeSet
;
import
javax.management.ClientContext
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerFactory
;
import
javax.management.ObjectName
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.JMXConnectorFactory
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServerFactory
;
import
javax.management.remote.JMXServiceURL
;
import
javax.management.remote.MBeanServerForwarder
;
public
class
ContextForwarderTest
{
private
static
String
failure
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
JMXServiceURL
url
=
new
JMXServiceURL
(
"service:jmx:rmi://"
);
Map
<
String
,
String
>
env
=
new
HashMap
<
String
,
String
>();
env
.
put
(
JMXConnectorServer
.
CONTEXT_FORWARDER
,
"false"
);
JMXConnectorServer
cs
=
JMXConnectorServerFactory
.
newJMXConnectorServer
(
url
,
env
,
mbs
);
MBeanServerForwarder
sysMBSF
=
cs
.
getSystemMBeanServerForwarder
();
MBeanServerForwarder
mbsf
=
ClientContext
.
newContextForwarder
(
mbs
,
sysMBSF
);
sysMBSF
.
setMBeanServer
(
mbsf
);
int
localCount
=
mbs
.
getMBeanCount
();
cs
.
start
();
try
{
JMXConnector
cc
=
JMXConnectorFactory
.
connect
(
cs
.
getAddress
());
MBeanServerConnection
mbsc
=
cc
.
getMBeanServerConnection
();
mbsc
=
ClientContext
.
withContext
(
mbsc
,
"foo"
,
"bar"
);
int
contextCount
=
mbsc
.
getMBeanCount
();
if
(
localCount
+
1
!=
contextCount
)
{
fail
(
"Local MBean count %d, context MBean count %d"
,
localCount
,
contextCount
);
}
Set
<
ObjectName
>
localNames
=
new
TreeSet
<
ObjectName
>(
mbs
.
queryNames
(
null
,
null
));
ObjectName
contextNamespaceObjectName
=
new
ObjectName
(
ClientContext
.
NAMESPACE
+
"//:type=JMXNamespace"
);
if
(!
localNames
.
add
(
contextNamespaceObjectName
))
fail
(
"Local names already contained context namespace handler"
);
Set
<
ObjectName
>
contextNames
=
mbsc
.
queryNames
(
null
,
null
);
if
(!
localNames
.
equals
(
contextNames
))
{
fail
(
"Name set differs locally and in context: "
+
"local: %s; context: %s"
,
localNames
,
contextNames
);
}
}
finally
{
cs
.
stop
();
}
if
(
failure
!=
null
)
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
else
System
.
out
.
println
(
"TEST PASSED"
);
}
private
static
void
fail
(
String
msg
,
Object
...
params
)
{
failure
=
String
.
format
(
msg
,
params
);
System
.
out
.
println
(
"FAIL: "
+
failure
);
}
}
test/javax/management/context/ContextTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test ContextTest
* @bug 5072267
* @summary Test client contexts.
* @author Eamonn McManus
* TODO: Try registering with a null name replaced by preRegister (for example
* from the MLet class) and see if it now works.
*/
import
java.lang.management.ManagementFactory
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Queue
;
import
java.util.Set
;
import
java.util.TreeMap
;
import
java.util.concurrent.Callable
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
import
javax.management.ClientContext
;
import
javax.management.DynamicMBean
;
import
javax.management.JMX
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerDelegate
;
import
javax.management.Notification
;
import
javax.management.NotificationBroadcasterSupport
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectInstance
;
import
javax.management.ObjectName
;
import
javax.management.StandardMBean
;
import
javax.management.loading.MLet
;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.remote.MBeanServerForwarder
;
import
static
java
.
util
.
Collections
.
emptyMap
;
import
static
java
.
util
.
Collections
.
singletonMap
;
public
class
ContextTest
{
private
static
String
failure
;
private
static
final
Map
<
String
,
String
>
emptyContext
=
emptyMap
();
public
static
interface
ShowContextMBean
{
public
Map
<
String
,
String
>
getContext
();
public
Map
<
String
,
String
>
getCreationContext
();
public
Set
<
String
>
getCalledOps
();
public
String
getThing
();
public
void
setThing
(
String
x
);
public
int
add
(
int
x
,
int
y
);
}
public
static
class
ShowContext
extends
NotificationBroadcasterSupport
implements
ShowContextMBean
,
MBeanRegistration
{
private
final
Map
<
String
,
String
>
creationContext
;
private
final
Set
<
String
>
calledOps
=
new
HashSet
<
String
>();
public
ShowContext
()
{
creationContext
=
getContext
();
}
public
Map
<
String
,
String
>
getContext
()
{
return
ClientContext
.
getContext
();
}
public
Map
<
String
,
String
>
getCreationContext
()
{
return
creationContext
;
}
public
Set
<
String
>
getCalledOps
()
{
return
calledOps
;
}
public
String
getThing
()
{
return
"x"
;
}
public
void
setThing
(
String
x
)
{
}
public
int
add
(
int
x
,
int
y
)
{
return
x
+
y
;
}
public
ObjectName
preRegister
(
MBeanServer
server
,
ObjectName
name
)
{
assertEquals
(
"preRegister context"
,
creationContext
,
getContext
());
calledOps
.
add
(
"preRegister"
);
return
name
;
}
public
void
postRegister
(
Boolean
registrationDone
)
{
assertEquals
(
"postRegister context"
,
creationContext
,
getContext
());
calledOps
.
add
(
"postRegister"
);
}
// The condition checked here is not guaranteed universally true,
// but is true every time we unregister an instance of this MBean
// in this test.
public
void
preDeregister
()
throws
Exception
{
assertEquals
(
"preDeregister context"
,
creationContext
,
getContext
());
}
public
void
postDeregister
()
{
assertEquals
(
"postDeregister context"
,
creationContext
,
getContext
());
}
// Same remark as for preDeregister
@Override
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
calledOps
.
add
(
"getNotificationInfo"
);
return
super
.
getNotificationInfo
();
}
@Override
public
void
addNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
{
calledOps
.
add
(
"addNotificationListener"
);
super
.
addNotificationListener
(
listener
,
filter
,
handback
);
}
@Override
public
void
removeNotificationListener
(
NotificationListener
listener
)
throws
ListenerNotFoundException
{
calledOps
.
add
(
"removeNL1"
);
super
.
removeNotificationListener
(
listener
);
}
@Override
public
void
removeNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
throws
ListenerNotFoundException
{
calledOps
.
add
(
"removeNL3"
);
super
.
removeNotificationListener
(
listener
,
filter
,
handback
);
}
}
private
static
class
LogRecord
{
final
String
op
;
final
Object
[]
params
;
final
Map
<
String
,
String
>
context
;
LogRecord
(
String
op
,
Object
[]
params
,
Map
<
String
,
String
>
context
)
{
this
.
op
=
op
;
this
.
params
=
params
;
this
.
context
=
context
;
}
@Override
public
String
toString
()
{
return
op
+
Arrays
.
deepToString
(
params
)
+
" "
+
context
;
}
}
/*
* InvocationHandler that forwards all methods to a contained object
* but also records each forwarded method. This allows us to check
* that the appropriate methods were called with the appropriate
* parameters. It's similar to what's typically available in
* Mock Object frameworks.
*/
private
static
class
LogIH
implements
InvocationHandler
{
private
final
Object
wrapped
;
Queue
<
LogRecord
>
log
=
new
LinkedList
<
LogRecord
>();
LogIH
(
Object
wrapped
)
{
this
.
wrapped
=
wrapped
;
}
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
if
(
method
.
getDeclaringClass
()
!=
Object
.
class
)
{
LogRecord
lr
=
new
LogRecord
(
method
.
getName
(),
args
,
ClientContext
.
getContext
());
log
.
add
(
lr
);
}
try
{
return
method
.
invoke
(
wrapped
,
args
);
}
catch
(
InvocationTargetException
e
)
{
throw
e
.
getCause
();
}
}
}
private
static
<
T
>
T
newSnoop
(
Class
<
T
>
wrappedClass
,
LogIH
logIH
)
{
return
wrappedClass
.
cast
(
Proxy
.
newProxyInstance
(
wrappedClass
.
getClassLoader
(),
new
Class
<?>[]
{
wrappedClass
},
logIH
));
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
System
.
out
.
println
(
mbs
.
queryNames
(
null
,
null
));
ObjectName
name
=
new
ObjectName
(
"a:b=c"
);
mbs
.
registerMBean
(
new
ShowContext
(),
name
);
final
ShowContextMBean
show
=
JMX
.
newMBeanProxy
(
mbs
,
name
,
ShowContextMBean
.
class
);
// Test local setting and getting within the MBeanServer
assertEquals
(
"initial context"
,
emptyContext
,
show
.
getContext
());
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"bar"
),
new
Callable
<
Void
>()
{
public
Void
call
()
{
assertEquals
(
"context in doWithContext"
,
singletonMap
(
"foo"
,
"bar"
),
show
.
getContext
());
return
null
;
}
});
assertEquals
(
"initial context after doWithContext"
,
emptyContext
,
show
.
getContext
());
String
got
=
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"baz"
),
new
Callable
<
String
>()
{
public
String
call
()
{
return
ClientContext
.
getContext
().
get
(
"foo"
);
}
});
assertEquals
(
"value extracted from context"
,
"baz"
,
got
);
Map
<
String
,
String
>
combined
=
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"baz"
),
new
Callable
<
Map
<
String
,
String
>>()
{
public
Map
<
String
,
String
>
call
()
throws
Exception
{
return
ClientContext
.
doWithContext
(
singletonMap
(
"fred"
,
"jim"
),
new
Callable
<
Map
<
String
,
String
>>()
{
public
Map
<
String
,
String
>
call
()
{
return
ClientContext
.
getContext
();
}
});
}
});
assertEquals
(
"nested doWithContext context"
,
singletonMap
(
"fred"
,
"jim"
),
combined
);
final
String
ugh
=
"a!\u00c9//*=:\"% "
;
ClientContext
.
doWithContext
(
singletonMap
(
ugh
,
ugh
),
new
Callable
<
Void
>()
{
public
Void
call
()
{
assertEquals
(
"context with tricky encoding"
,
singletonMap
(
ugh
,
ugh
),
show
.
getContext
());
return
null
;
}
});
Map
<
String
,
String
>
ughMap
=
new
TreeMap
<
String
,
String
>();
ughMap
.
put
(
ugh
,
ugh
);
ughMap
.
put
(
"fred"
,
"jim"
);
// Since this is a TreeMap and "fred" is greater than ugh (which begins
// with "a"), we will see the encoding of ugh first in the output string.
String
encoded
=
ClientContext
.
encode
(
ughMap
);
String
expectedUghCoding
=
"a%21%C3%89%2F%2F%2A%3D%3A%22%25+"
;
String
expectedUghMapCoding
=
ClientContext
.
NAMESPACE
+
"//"
+
expectedUghCoding
+
"="
+
expectedUghCoding
+
";fred=jim"
;
assertEquals
(
"hairy context encoded as string"
,
expectedUghMapCoding
,
encoded
);
// Wrap the MBeanServer with a context MBSF so we can test withContext.
// Also check the simulated namespace directly.
LogIH
mbsIH
=
new
LogIH
(
mbs
);
MBeanServer
snoopMBS
=
newSnoop
(
MBeanServer
.
class
,
mbsIH
);
MBeanServerForwarder
ctxMBS
=
ClientContext
.
newContextForwarder
(
snoopMBS
,
null
);
// The MBSF returned by ClientContext is actually a compound of two
// forwarders, but that is supposed to be hidden by changing the
// behaviour of get/setMBeanServer. Check that it is indeed so.
assertEquals
(
"next MBS of context forwarder"
,
snoopMBS
,
ctxMBS
.
getMBeanServer
());
// If the above assertion fails you may get a confusing message
// because the toString() of the two objects is likely to be the same
// so it will look as if they should be equal.
ctxMBS
.
setMBeanServer
(
null
);
assertEquals
(
"next MBS of context forwarder after setting it null"
,
null
,
ctxMBS
.
getMBeanServer
());
ctxMBS
.
setMBeanServer
(
snoopMBS
);
// The MBSF should look the same as the original MBeanServer except
// that it has the JMXNamespace for the simulated namespace.
Set
<
ObjectName
>
origNames
=
mbs
.
queryNames
(
null
,
null
);
Set
<
ObjectName
>
mbsfNames
=
ctxMBS
.
queryNames
(
null
,
null
);
assertEquals
(
"number of MBeans returned by queryNames within forwarder"
,
origNames
.
size
()
+
1
,
mbsfNames
.
size
());
assertEquals
(
"MBeanCount within forwarder"
,
mbsfNames
.
size
(),
ctxMBS
.
getMBeanCount
());
assertCalled
(
mbsIH
,
"queryNames"
,
emptyContext
);
assertCalled
(
mbsIH
,
"getMBeanCount"
,
emptyContext
);
ObjectName
ctxNamespaceName
=
new
ObjectName
(
ClientContext
.
NAMESPACE
+
"//:"
+
JMXNamespace
.
TYPE_ASSIGNMENT
);
origNames
.
add
(
ctxNamespaceName
);
assertEquals
(
"MBeans within forwarder"
,
origNames
,
mbsfNames
);
Set
<
String
>
domains
=
new
HashSet
<
String
>(
Arrays
.
asList
(
ctxMBS
.
getDomains
()));
assertEquals
(
"domains include context namespace MBean"
,
true
,
domains
.
contains
(
ClientContext
.
NAMESPACE
+
"//"
));
assertCalled
(
mbsIH
,
"getDomains"
,
emptyContext
);
// Now test ClientContext.withContext.
MBeanServer
ughMBS
=
ClientContext
.
withContext
(
ctxMBS
,
ugh
,
ugh
);
ShowContextMBean
ughshow
=
JMX
.
newMBeanProxy
(
ughMBS
,
name
,
ShowContextMBean
.
class
);
Map
<
String
,
String
>
ughCtx
=
ughshow
.
getContext
();
Map
<
String
,
String
>
ughExpect
=
singletonMap
(
ugh
,
ugh
);
assertEquals
(
"context seen by MBean accessed within namespace"
,
ughExpect
,
ughCtx
);
assertCalled
(
mbsIH
,
"getAttribute"
,
ughExpect
,
name
,
"Context"
);
MBeanServer
cmbs
=
ClientContext
.
withContext
(
ctxMBS
,
"mickey"
,
"mouse"
);
ShowContextMBean
cshow
=
JMX
.
newMBeanProxy
(
cmbs
,
name
,
ShowContextMBean
.
class
);
assertEquals
(
"context seen by MBean accessed within namespace"
,
singletonMap
(
"mickey"
,
"mouse"
),
cshow
.
getContext
());
MBeanServer
ccmbs
=
ClientContext
.
withContext
(
cmbs
,
"donald"
,
"duck"
);
ShowContextMBean
ccshow
=
JMX
.
newMBeanProxy
(
ccmbs
,
name
,
ShowContextMBean
.
class
);
Map
<
String
,
String
>
disney
=
new
HashMap
<
String
,
String
>();
disney
.
put
(
"mickey"
,
"mouse"
);
disney
.
put
(
"donald"
,
"duck"
);
assertEquals
(
"context seen by MBean in nested namespace"
,
disney
,
ccshow
.
getContext
());
// Test that all MBS ops produce reasonable results
ObjectName
logger
=
new
ObjectName
(
"a:type=Logger"
);
DynamicMBean
showMBean
=
new
StandardMBean
(
new
ShowContext
(),
ShowContextMBean
.
class
);
LogIH
mbeanLogIH
=
new
LogIH
(
showMBean
);
DynamicMBean
logMBean
=
newSnoop
(
DynamicMBean
.
class
,
mbeanLogIH
);
ObjectInstance
loggerOI
=
ccmbs
.
registerMBean
(
logMBean
,
logger
);
assertEquals
(
"ObjectName returned by createMBean"
,
logger
,
loggerOI
.
getObjectName
());
// We get an getMBeanInfo call to determine the className in the
// ObjectInstance to return from registerMBean.
assertCalled
(
mbeanLogIH
,
"getMBeanInfo"
,
disney
);
ccmbs
.
getAttribute
(
logger
,
"Thing"
);
assertCalled
(
mbeanLogIH
,
"getAttribute"
,
disney
);
ccmbs
.
getAttributes
(
logger
,
new
String
[]
{
"Thing"
,
"Context"
});
assertCalled
(
mbeanLogIH
,
"getAttributes"
,
disney
);
ccmbs
.
setAttribute
(
logger
,
new
Attribute
(
"Thing"
,
"bar"
));
assertCalled
(
mbeanLogIH
,
"setAttribute"
,
disney
);
ccmbs
.
setAttributes
(
logger
,
new
AttributeList
(
Arrays
.
asList
(
new
Attribute
(
"Thing"
,
"baz"
))));
assertCalled
(
mbeanLogIH
,
"setAttributes"
,
disney
);
ccmbs
.
getMBeanInfo
(
logger
);
assertCalled
(
mbeanLogIH
,
"getMBeanInfo"
,
disney
);
Set
<
ObjectName
>
names
=
ccmbs
.
queryNames
(
null
,
null
);
Set
<
ObjectName
>
expectedNames
=
new
HashSet
<
ObjectName
>(
Collections
.
singleton
(
MBeanServerDelegate
.
DELEGATE_NAME
));
assertEquals
(
"context namespace query includes expected names"
,
true
,
names
.
containsAll
(
expectedNames
));
Set
<
ObjectName
>
nsNames
=
ccmbs
.
queryNames
(
new
ObjectName
(
"*//:*"
),
null
);
Set
<
ObjectName
>
expectedNsNames
=
new
HashSet
<
ObjectName
>(
Arrays
.
asList
(
new
ObjectName
(
ClientContext
.
NAMESPACE
+
ObjectName
.
NAMESPACE_SEPARATOR
+
":"
+
JMXNamespace
.
TYPE_ASSIGNMENT
)));
assertEquals
(
"context namespace query includes namespace MBean"
,
true
,
nsNames
.
containsAll
(
expectedNsNames
));
Set
<
ObjectInstance
>
insts
=
ccmbs
.
queryMBeans
(
MBeanServerDelegate
.
DELEGATE_NAME
,
null
);
assertEquals
(
"size of set from MBeanServerDelegate query"
,
1
,
insts
.
size
());
assertEquals
(
"ObjectName from MBeanServerDelegate query"
,
MBeanServerDelegate
.
DELEGATE_NAME
,
insts
.
iterator
().
next
().
getObjectName
());
ObjectName
createdName
=
new
ObjectName
(
"a:type=Created"
);
ObjectInstance
createdOI
=
ccmbs
.
createMBean
(
ShowContext
.
class
.
getName
(),
createdName
);
assertEquals
(
"class name from createMBean"
,
ShowContext
.
class
.
getName
(),
createdOI
.
getClassName
());
assertEquals
(
"ObjectName from createMBean"
,
createdName
,
createdOI
.
getObjectName
());
assertEquals
(
"context within createMBean"
,
disney
,
ccmbs
.
getAttribute
(
createdName
,
"CreationContext"
));
NotificationListener
nothingListener
=
new
NotificationListener
()
{
public
void
handleNotification
(
Notification
n
,
Object
h
)
{}
};
ccmbs
.
addNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
removeNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
addNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
removeNotificationListener
(
createdName
,
nothingListener
);
Set
<
String
>
expectedOps
=
new
HashSet
<
String
>(
Arrays
.
asList
(
"preRegister"
,
"postRegister"
,
"addNotificationListener"
,
"removeNL1"
,
"removeNL3"
,
"getNotificationInfo"
));
assertEquals
(
"operations called on MBean"
,
expectedOps
,
ccmbs
.
getAttribute
(
createdName
,
"CalledOps"
));
assertEquals
(
"ClassLoader for MBean"
,
ShowContext
.
class
.
getClassLoader
(),
ccmbs
.
getClassLoaderFor
(
createdName
));
assertEquals
(
"isRegistered"
,
true
,
ccmbs
.
isRegistered
(
createdName
));
assertEquals
(
"isInstanceOf"
,
true
,
ccmbs
.
isInstanceOf
(
createdName
,
ShowContext
.
class
.
getName
()));
assertEquals
(
"isInstanceOf"
,
false
,
ccmbs
.
isInstanceOf
(
createdName
,
DynamicMBean
.
class
.
getName
()));
ccmbs
.
unregisterMBean
(
createdName
);
assertEquals
(
"isRegistered after unregister"
,
false
,
ccmbs
.
isRegistered
(
createdName
));
MLet
mlet
=
new
MLet
();
ObjectName
defaultMLetName
=
new
ObjectName
(
"DefaultDomain:type=MLet"
);
ccmbs
.
registerMBean
(
mlet
,
defaultMLetName
);
assertEquals
(
"getClassLoader"
,
mlet
,
ccmbs
.
getClassLoader
(
defaultMLetName
));
assertEquals
(
"number of MBean operations"
,
0
,
mbeanLogIH
.
log
.
size
());
// Test that contexts still work when we can't combine two encoded contexts.
// Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot
// see that it already contains a context and therefore cannot combine
// into mickey=mouse;donald=duck. We don't actually use the snoop
// capabilities of the returned object -- we just want an opaque
// MBeanServer wrapper
MBeanServer
cmbs2
=
newSnoop
(
MBeanServer
.
class
,
new
LogIH
(
cmbs
));
MBeanServer
ccmbs2
=
ClientContext
.
withContext
(
cmbs2
,
"donald"
,
"duck"
);
assertEquals
(
"context when combination is impossible"
,
disney
,
ccmbs2
.
getAttribute
(
name
,
"Context"
));
// Test failure cases of ClientContext.encode
final
List
<
Map
<
String
,
String
>>
badEncodeArgs
=
Arrays
.
asList
(
null
,
Collections
.<
String
,
String
>
singletonMap
(
null
,
"foo"
),
Collections
.<
String
,
String
>
singletonMap
(
"foo"
,
null
));
for
(
Map
<
String
,
String
>
bad
:
badEncodeArgs
)
{
try
{
String
oops
=
ClientContext
.
encode
(
bad
);
failed
(
"ClientContext.encode("
+
bad
+
") should have failed: "
+
oops
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for ClientContext.encode("
+
bad
+
")"
,
IllegalArgumentException
.
class
,
e
.
getClass
());
}
}
// ADD NEW TESTS HERE ^^^
if
(
failure
!=
null
)
throw
new
Exception
(
failure
);
}
private
static
void
assertEquals
(
String
what
,
Object
x
,
Object
y
)
{
if
(!
equal
(
x
,
y
))
failed
(
what
+
": expected "
+
string
(
x
)
+
"; got "
+
string
(
y
));
}
private
static
boolean
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
y
)
return
true
;
if
(
x
==
null
||
y
==
null
)
return
false
;
if
(
x
.
getClass
().
isArray
())
return
Arrays
.
deepEquals
(
new
Object
[]
{
x
},
new
Object
[]
{
y
});
return
x
.
equals
(
y
);
}
private
static
String
string
(
Object
x
)
{
String
s
=
Arrays
.
deepToString
(
new
Object
[]
{
x
});
return
s
.
substring
(
1
,
s
.
length
()
-
1
);
}
private
static
void
assertCalled
(
LogIH
logIH
,
String
op
,
Map
<
String
,
String
>
expectedContext
)
{
assertCalled
(
logIH
,
op
,
expectedContext
,
(
Object
[])
null
);
}
private
static
void
assertCalled
(
LogIH
logIH
,
String
op
,
Map
<
String
,
String
>
expectedContext
,
Object
...
params
)
{
LogRecord
lr
=
logIH
.
log
.
remove
();
assertEquals
(
"called operation"
,
op
,
lr
.
op
);
if
(
params
!=
null
)
assertEquals
(
"operation parameters"
,
params
,
lr
.
params
);
assertEquals
(
"operation context"
,
expectedContext
,
lr
.
context
);
}
private
static
void
failed
(
String
why
)
{
failure
=
why
;
new
Throwable
(
"FAILED: "
+
why
).
printStackTrace
(
System
.
out
);
}
}
test/javax/management/context/LocaleAwareBroadcasterTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 5072267
* @summary Test that an MBean can handle localized Notification messages.
* @author Eamonn McManus
*/
import
java.util.Collections
;
import
java.util.ListResourceBundle
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.MissingResourceException
;
import
java.util.ResourceBundle
;
import
java.util.concurrent.ArrayBlockingQueue
;
import
java.util.concurrent.BlockingQueue
;
import
java.util.concurrent.Callable
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.ConcurrentMap
;
import
java.util.concurrent.TimeUnit
;
import
javax.management.ClientContext
;
import
javax.management.JMX
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerFactory
;
import
javax.management.Notification
;
import
javax.management.NotificationBroadcasterSupport
;
import
javax.management.NotificationEmitter
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectName
;
import
javax.management.SendNotification
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.JMXConnectorFactory
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServerFactory
;
import
javax.management.remote.JMXServiceURL
;
public
class
LocaleAwareBroadcasterTest
{
static
final
ObjectName
mbeanName
=
ObjectName
.
valueOf
(
"d:type=LocaleAware"
);
static
final
String
messageKey
=
"broken.window"
,
defaultMessage
=
"broken window"
,
frenchMessage
=
"fen\u00eatre bris\u00e9e"
,
irishMessage
=
"fuinneog briste"
;
public
static
class
Bundle
extends
ListResourceBundle
{
@Override
protected
Object
[][]
getContents
()
{
return
new
Object
[][]
{
{
messageKey
,
defaultMessage
},
};
}
}
public
static
class
Bundle_fr
extends
ListResourceBundle
{
@Override
protected
Object
[][]
getContents
()
{
return
new
Object
[][]
{
{
messageKey
,
frenchMessage
},
};
}
}
public
static
class
Bundle_ga
extends
ListResourceBundle
{
@Override
protected
Object
[][]
getContents
()
{
return
new
Object
[][]
{
{
messageKey
,
irishMessage
},
};
}
}
static
volatile
String
failure
;
public
static
interface
LocaleAwareMBean
{
public
void
sendNotification
(
Notification
n
);
}
public
static
class
LocaleAware
implements
LocaleAwareMBean
,
NotificationEmitter
,
SendNotification
{
private
final
ConcurrentMap
<
Locale
,
NotificationBroadcasterSupport
>
localeToEmitter
=
newConcurrentMap
();
public
void
sendNotification
(
Notification
n
)
{
for
(
Map
.
Entry
<
Locale
,
NotificationBroadcasterSupport
>
entry
:
localeToEmitter
.
entrySet
())
{
Notification
localizedNotif
=
localizeNotification
(
n
,
entry
.
getKey
());
entry
.
getValue
().
sendNotification
(
localizedNotif
);
}
}
public
void
addNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
throws
IllegalArgumentException
{
Locale
locale
=
ClientContext
.
getLocale
();
NotificationBroadcasterSupport
broadcaster
;
broadcaster
=
localeToEmitter
.
get
(
locale
);
if
(
broadcaster
==
null
)
{
broadcaster
=
new
NotificationBroadcasterSupport
();
NotificationBroadcasterSupport
old
=
localeToEmitter
.
putIfAbsent
(
locale
,
broadcaster
);
if
(
old
!=
null
)
broadcaster
=
old
;
}
broadcaster
.
addNotificationListener
(
listener
,
filter
,
handback
);
}
public
void
removeNotificationListener
(
NotificationListener
listener
)
throws
ListenerNotFoundException
{
Locale
locale
=
ClientContext
.
getLocale
();
NotificationBroadcasterSupport
broadcaster
=
localeToEmitter
.
get
(
locale
);
if
(
broadcaster
==
null
)
throw
new
ListenerNotFoundException
();
broadcaster
.
removeNotificationListener
(
listener
);
}
public
void
removeNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
throws
ListenerNotFoundException
{
Locale
locale
=
ClientContext
.
getLocale
();
NotificationBroadcasterSupport
broadcaster
=
localeToEmitter
.
get
(
locale
);
if
(
broadcaster
==
null
)
throw
new
ListenerNotFoundException
();
broadcaster
.
removeNotificationListener
(
listener
,
filter
,
handback
);
}
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
return
new
MBeanNotificationInfo
[
0
];
}
}
// Localize notif using the convention that the message looks like
// [resourcebundlename:resourcekey]defaultmessage
// for example [foo.bar.Resources:unknown.problem]
static
Notification
localizeNotification
(
Notification
n
,
Locale
locale
)
{
String
msg
=
n
.
getMessage
();
if
(!
msg
.
startsWith
(
"["
))
return
n
;
int
close
=
msg
.
indexOf
(
']'
);
if
(
close
<
0
)
throw
new
IllegalArgumentException
(
"Bad notification message: "
+
msg
);
int
colon
=
msg
.
indexOf
(
':'
);
if
(
colon
<
0
||
colon
>
close
)
throw
new
IllegalArgumentException
(
"Bad notification message: "
+
msg
);
String
bundleName
=
msg
.
substring
(
1
,
colon
);
String
key
=
msg
.
substring
(
colon
+
1
,
close
);
ClassLoader
loader
=
LocaleAwareBroadcasterTest
.
class
.
getClassLoader
();
ResourceBundle
bundle
=
ResourceBundle
.
getBundle
(
bundleName
,
locale
,
loader
);
try
{
msg
=
bundle
.
getString
(
key
);
}
catch
(
MissingResourceException
e
)
{
msg
=
msg
.
substring
(
close
+
1
);
}
n
=
(
Notification
)
n
.
clone
();
n
.
setMessage
(
msg
);
return
n
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
Locale
.
setDefault
(
new
Locale
(
"en"
));
testLocal
();
testRemote
();
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
static
interface
AddListenerInLocale
{
public
void
addListenerInLocale
(
MBeanServerConnection
mbsc
,
NotificationListener
listener
,
Locale
locale
)
throws
Exception
;
}
private
static
void
testLocal
()
throws
Exception
{
System
.
out
.
println
(
"Test local MBeanServer using doWithContext"
);
MBeanServer
mbs
=
makeMBS
();
AddListenerInLocale
addListener
=
new
AddListenerInLocale
()
{
public
void
addListenerInLocale
(
final
MBeanServerConnection
mbsc
,
final
NotificationListener
listener
,
Locale
locale
)
throws
Exception
{
Map
<
String
,
String
>
localeContext
=
Collections
.
singletonMap
(
ClientContext
.
LOCALE_KEY
,
locale
.
toString
());
ClientContext
.
doWithContext
(
localeContext
,
new
Callable
<
Void
>()
{
public
Void
call
()
throws
Exception
{
mbsc
.
addNotificationListener
(
mbeanName
,
listener
,
null
,
null
);
return
null
;
}
});
}
};
test
(
mbs
,
addListener
);
}
private
static
void
testRemote
()
throws
Exception
{
System
.
out
.
println
(
"Test remote MBeanServer using withLocale"
);
MBeanServer
mbs
=
makeMBS
();
JMXServiceURL
url
=
new
JMXServiceURL
(
"service:jmx:rmi://"
);
JMXConnectorServer
cs
=
JMXConnectorServerFactory
.
newJMXConnectorServer
(
url
,
null
,
mbs
);
cs
.
start
();
JMXServiceURL
addr
=
cs
.
getAddress
();
JMXConnector
cc
=
JMXConnectorFactory
.
connect
(
addr
);
MBeanServerConnection
mbsc
=
cc
.
getMBeanServerConnection
();
AddListenerInLocale
addListenerInLocale
=
new
AddListenerInLocale
()
{
public
void
addListenerInLocale
(
MBeanServerConnection
mbsc
,
NotificationListener
listener
,
Locale
locale
)
throws
Exception
{
mbsc
=
ClientContext
.
withLocale
(
mbsc
,
locale
);
mbsc
.
addNotificationListener
(
mbeanName
,
listener
,
null
,
null
);
}
};
try
{
test
(
mbsc
,
addListenerInLocale
);
}
finally
{
try
{
cc
.
close
();
}
catch
(
Exception
e
)
{}
cs
.
stop
();
}
}
static
class
QueueListener
implements
NotificationListener
{
final
BlockingQueue
<
Notification
>
queue
=
new
ArrayBlockingQueue
<
Notification
>(
10
);
public
void
handleNotification
(
Notification
notification
,
Object
handback
)
{
queue
.
add
(
notification
);
}
}
private
static
void
test
(
MBeanServerConnection
mbsc
,
AddListenerInLocale
addListener
)
throws
Exception
{
QueueListener
defaultListener
=
new
QueueListener
();
QueueListener
frenchListener
=
new
QueueListener
();
QueueListener
irishListener
=
new
QueueListener
();
mbsc
.
addNotificationListener
(
mbeanName
,
defaultListener
,
null
,
null
);
addListener
.
addListenerInLocale
(
mbsc
,
frenchListener
,
new
Locale
(
"fr"
));
addListener
.
addListenerInLocale
(
mbsc
,
irishListener
,
new
Locale
(
"ga"
));
LocaleAwareMBean
proxy
=
JMX
.
newMBeanProxy
(
mbsc
,
mbeanName
,
LocaleAwareMBean
.
class
);
String
notifMsg
=
"["
+
Bundle
.
class
.
getName
()
+
":"
+
messageKey
+
"]"
+
"broken window (default message that should never be seen)"
;
Notification
notif
=
new
Notification
(
"notif.type"
,
mbeanName
,
0L
,
notifMsg
);
proxy
.
sendNotification
(
notif
);
final
Object
[][]
expected
=
{
{
defaultListener
,
defaultMessage
},
{
frenchListener
,
frenchMessage
},
{
irishListener
,
irishMessage
},
};
for
(
Object
[]
exp
:
expected
)
{
QueueListener
ql
=
(
QueueListener
)
exp
[
0
];
String
msg
=
(
String
)
exp
[
1
];
System
.
out
.
println
(
"Checking: "
+
msg
);
Notification
n
=
ql
.
queue
.
poll
(
1
,
TimeUnit
.
SECONDS
);
if
(
n
==
null
)
fail
(
"Did not receive expected notif: "
+
msg
);
if
(!
n
.
getMessage
().
equals
(
msg
))
{
fail
(
"Received notif with wrong message: got "
+
n
.
getMessage
()
+
", expected "
+
msg
);
}
n
=
ql
.
queue
.
poll
(
2
,
TimeUnit
.
MILLISECONDS
);
if
(
n
!=
null
)
fail
(
"Received unexpected extra notif: "
+
n
);
}
}
private
static
MBeanServer
makeMBS
()
throws
Exception
{
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
LocaleAware
aware
=
new
LocaleAware
();
mbs
.
registerMBean
(
aware
,
mbeanName
);
return
mbs
;
}
static
<
K
,
V
>
ConcurrentMap
<
K
,
V
>
newConcurrentMap
()
{
return
new
ConcurrentHashMap
<
K
,
V
>();
}
static
void
fail
(
String
why
)
{
System
.
out
.
println
(
"FAIL: "
+
why
);
failure
=
why
;
}
}
test/javax/management/context/LocaleTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test LocaleTest.java
* @bug 5072267
* @summary Test client locales.
* @author Eamonn McManus
*/
import
java.lang.management.ManagementFactory
;
import
java.util.Collections
;
import
java.util.ListResourceBundle
;
import
java.util.Locale
;
import
java.util.Map
;
import
java.util.ResourceBundle
;
import
java.util.concurrent.Callable
;
import
javax.management.ClientContext
;
import
java.util.Arrays
;
import
javax.management.MBeanServer
;
import
javax.management.ObjectName
;
public
class
LocaleTest
{
private
static
String
failure
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// Test the translation String -> Locale
Locale
[]
locales
=
Locale
.
getAvailableLocales
();
System
.
out
.
println
(
"Testing String->Locale for "
+
locales
.
length
+
" locales"
);
for
(
Locale
loc
:
locales
)
{
Map
<
String
,
String
>
ctx
=
Collections
.
singletonMap
(
ClientContext
.
LOCALE_KEY
,
loc
.
toString
());
Locale
loc2
=
ClientContext
.
doWithContext
(
ctx
,
new
Callable
<
Locale
>()
{
public
Locale
call
()
{
return
ClientContext
.
getLocale
();
}
});
assertEquals
(
loc
,
loc2
);
}
// Test that a locale-sensitive attribute works
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
mbs
=
ClientContext
.
newContextForwarder
(
mbs
,
null
);
ObjectName
name
=
new
ObjectName
(
"a:type=LocaleSensitive"
);
mbs
.
registerMBean
(
new
LocaleSensitive
(),
name
);
Locale
.
setDefault
(
Locale
.
US
);
assertEquals
(
"spectacular failure"
,
mbs
.
getAttribute
(
name
,
"LastProblemDescription"
));
MBeanServer
frmbs
=
ClientContext
.
withContext
(
mbs
,
ClientContext
.
LOCALE_KEY
,
Locale
.
FRANCE
.
toString
());
assertEquals
(
"\u00e9chec r\u00e9tentissant"
,
frmbs
.
getAttribute
(
name
,
"LastProblemDescription"
));
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
}
public
static
interface
LocaleSensitiveMBean
{
public
String
getLastProblemDescription
();
}
public
static
class
LocaleSensitive
implements
LocaleSensitiveMBean
{
public
String
getLastProblemDescription
()
{
Locale
loc
=
ClientContext
.
getLocale
();
ResourceBundle
rb
=
ResourceBundle
.
getBundle
(
MyResources
.
class
.
getName
(),
loc
);
return
rb
.
getString
(
"spectacular"
);
}
}
public
static
class
MyResources
extends
ListResourceBundle
{
protected
Object
[][]
getContents
()
{
return
new
Object
[][]
{
{
"spectacular"
,
"spectacular failure"
},
};
}
}
public
static
class
MyResources_fr
extends
ListResourceBundle
{
protected
Object
[][]
getContents
()
{
return
new
Object
[][]
{
{
"spectacular"
,
"\u00e9chec r\u00e9tentissant"
},
};
}
}
private
static
void
assertEquals
(
Object
x
,
Object
y
)
{
if
(!
equal
(
x
,
y
))
failed
(
"expected "
+
string
(
x
)
+
"; got "
+
string
(
y
));
}
private
static
boolean
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
y
)
return
true
;
if
(
x
==
null
||
y
==
null
)
return
false
;
if
(
x
.
getClass
().
isArray
())
return
Arrays
.
deepEquals
(
new
Object
[]
{
x
},
new
Object
[]
{
y
});
return
x
.
equals
(
y
);
}
private
static
String
string
(
Object
x
)
{
String
s
=
Arrays
.
deepToString
(
new
Object
[]
{
x
});
return
s
.
substring
(
1
,
s
.
length
()
-
1
);
}
private
static
void
failed
(
String
why
)
{
failure
=
why
;
new
Throwable
(
"FAILED: "
+
why
).
printStackTrace
(
System
.
out
);
}
}
test/javax/management/context/LocalizableTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test LocalizableTest
* @bug 5072267 6635499
* @summary Test localizable MBeanInfo using LocalizableMBeanFactory.
* @author Eamonn McManus
*/
import
java.lang.management.ManagementFactory
;
import
java.util.Locale
;
import
java.util.ResourceBundle
;
import
javax.management.ClientContext
;
import
javax.management.Description
;
import
javax.management.JMX
;
import
javax.management.MBeanAttributeInfo
;
import
javax.management.MBeanConstructorInfo
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanOperationInfo
;
import
javax.management.MBeanParameterInfo
;
import
javax.management.MBeanServer
;
import
javax.management.ObjectName
;
import
localizable.MBeanDescriptions_fr
;
import
localizable.Whatsit
;
import
static
localizable
.
WhatsitMBean
.*;
public
class
LocalizableTest
{
// If you change the order of the array elements or their number then
// you must also change these constants.
private
static
final
int
MBEAN
=
0
,
ATTR
=
1
,
OPER
=
2
,
PARAM
=
3
,
CONSTR
=
4
,
CONSTR_PARAM
=
5
;
private
static
final
String
[]
englishDescriptions
=
{
englishMBeanDescription
,
englishAttrDescription
,
englishOperDescription
,
englishParamDescription
,
englishConstrDescription
,
englishConstrParamDescription
,
};
private
static
final
String
[]
defaultDescriptions
=
englishDescriptions
.
clone
();
static
{
defaultDescriptions
[
MBEAN
]
=
defaultMBeanDescription
;
}
private
static
final
String
[]
frenchDescriptions
=
{
frenchMBeanDescription
,
frenchAttrDescription
,
frenchOperDescription
,
frenchParamDescription
,
frenchConstrDescription
,
frenchConstrParamDescription
,
};
private
static
String
failure
;
@Description
(
unlocalizedMBeanDescription
)
public
static
interface
UnlocalizedMBean
{}
public
static
class
Unlocalized
implements
UnlocalizedMBean
{}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
ResourceBundle
frenchBundle
=
new
MBeanDescriptions_fr
();
// The purpose of the previous line is to force that class to be compiled
// when the test is run so it will be available for reflection.
// Yes, we could do this with a @build tag.
MBeanServer
plainMBS
=
ManagementFactory
.
getPlatformMBeanServer
();
MBeanServer
unlocalizedMBS
=
ClientContext
.
newContextForwarder
(
plainMBS
,
null
);
MBeanServer
localizedMBS
=
ClientContext
.
newLocalizeMBeanInfoForwarder
(
plainMBS
);
localizedMBS
=
ClientContext
.
newContextForwarder
(
localizedMBS
,
null
);
ObjectName
name
=
new
ObjectName
(
"a:b=c"
);
Whatsit
whatsit
=
new
Whatsit
();
Object
[][]
locales
=
{
{
null
,
englishDescriptions
},
{
"en"
,
englishDescriptions
},
{
"fr"
,
frenchDescriptions
},
};
for
(
Object
[]
localePair
:
locales
)
{
String
locale
=
(
String
)
localePair
[
0
];
String
[]
localizedDescriptions
=
(
String
[])
localePair
[
1
];
System
.
out
.
println
(
"===Testing locale "
+
locale
+
"==="
);
for
(
boolean
localized
:
new
boolean
[]
{
false
,
true
})
{
String
[]
descriptions
=
localized
?
localizedDescriptions
:
defaultDescriptions
;
MBeanServer
mbs
=
localized
?
localizedMBS
:
unlocalizedMBS
;
System
.
out
.
println
(
"Testing MBean "
+
whatsit
+
" with "
+
"localized="
+
localized
);
mbs
.
registerMBean
(
whatsit
,
name
);
System
.
out
.
println
(
mbs
.
getMBeanInfo
(
name
));
try
{
test
(
mbs
,
name
,
locale
,
descriptions
);
}
catch
(
Exception
e
)
{
fail
(
"Caught exception: "
+
e
);
}
finally
{
mbs
.
unregisterMBean
(
name
);
}
}
}
System
.
out
.
println
(
"===Testing unlocalizable MBean==="
);
Object
mbean
=
new
Unlocalized
();
localizedMBS
.
registerMBean
(
mbean
,
name
);
try
{
MBeanInfo
mbi
=
localizedMBS
.
getMBeanInfo
(
name
);
assertEquals
(
"MBean description"
,
unlocalizedMBeanDescription
,
mbi
.
getDescription
());
}
finally
{
localizedMBS
.
unregisterMBean
(
name
);
}
System
.
out
.
println
(
"===Testing MBeanInfo.localizeDescriptions==="
);
plainMBS
.
registerMBean
(
whatsit
,
name
);
MBeanInfo
mbi
=
plainMBS
.
getMBeanInfo
(
name
);
Locale
french
=
new
Locale
(
"fr"
);
mbi
=
mbi
.
localizeDescriptions
(
french
,
whatsit
.
getClass
().
getClassLoader
());
checkDescriptions
(
mbi
,
frenchDescriptions
);
if
(
failure
==
null
)
System
.
out
.
println
(
"TEST PASSED"
);
else
throw
new
Exception
(
"TEST FAILED: Last failure: "
+
failure
);
}
private
static
void
test
(
MBeanServer
mbs
,
ObjectName
name
,
String
locale
,
String
[]
expectedDescriptions
)
throws
Exception
{
if
(
locale
!=
null
)
mbs
=
ClientContext
.
withLocale
(
mbs
,
new
Locale
(
locale
));
MBeanInfo
mbi
=
mbs
.
getMBeanInfo
(
name
);
checkDescriptions
(
mbi
,
expectedDescriptions
);
}
private
static
void
checkDescriptions
(
MBeanInfo
mbi
,
String
[]
expectedDescriptions
)
{
assertEquals
(
"MBean description"
,
expectedDescriptions
[
MBEAN
],
mbi
.
getDescription
());
MBeanAttributeInfo
mbai
=
mbi
.
getAttributes
()[
0
];
assertEquals
(
"Attribute description"
,
expectedDescriptions
[
ATTR
],
mbai
.
getDescription
());
MBeanOperationInfo
mboi
=
mbi
.
getOperations
()[
0
];
assertEquals
(
"Operation description"
,
expectedDescriptions
[
OPER
],
mboi
.
getDescription
());
MBeanParameterInfo
mbpi
=
mboi
.
getSignature
()[
0
];
assertEquals
(
"Parameter description"
,
expectedDescriptions
[
PARAM
],
mbpi
.
getDescription
());
MBeanConstructorInfo
[]
mbcis
=
mbi
.
getConstructors
();
assertEquals
(
"Number of constructors"
,
2
,
mbcis
.
length
);
for
(
MBeanConstructorInfo
mbci
:
mbcis
)
{
MBeanParameterInfo
[]
mbcpis
=
mbci
.
getSignature
();
String
constrName
=
mbcpis
.
length
+
"-arg constructor"
;
assertEquals
(
constrName
+
" description"
,
expectedDescriptions
[
CONSTR
],
mbci
.
getDescription
());
if
(
mbcpis
.
length
>
0
)
{
assertEquals
(
constrName
+
" parameter description"
,
expectedDescriptions
[
CONSTR_PARAM
],
mbcpis
[
0
].
getDescription
());
}
}
}
private
static
void
assertEquals
(
String
what
,
Object
expect
,
Object
actual
)
{
if
(
expect
.
equals
(
actual
))
System
.
out
.
println
(
"...OK: "
+
what
+
" = "
+
expect
);
else
fail
(
what
+
" should be "
+
expect
+
", was "
+
actual
);
}
private
static
void
fail
(
String
why
)
{
System
.
out
.
println
(
"FAIL: "
+
why
);
failure
=
why
;
}
}
test/javax/management/context/RemoteContextTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007-2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test RemoteContextTest.java
* @bug 5072267
* @summary Test client contexts with namespaces.
* @author Eamonn McManus, Daniel Fuchs
*/
import
java.lang.management.ManagementFactory
;
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.net.URLEncoder
;
import
java.util.Arrays
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.LinkedList
;
import
java.util.Map
;
import
java.util.Queue
;
import
java.util.Set
;
import
java.util.concurrent.Callable
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
import
javax.management.ClientContext
;
import
javax.management.DynamicMBean
;
import
javax.management.JMX
;
import
javax.management.ListenerNotFoundException
;
import
javax.management.MBeanNotificationInfo
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerDelegate
;
import
javax.management.Notification
;
import
javax.management.NotificationBroadcasterSupport
;
import
javax.management.NotificationFilter
;
import
javax.management.NotificationListener
;
import
javax.management.ObjectInstance
;
import
javax.management.ObjectName
;
import
javax.management.StandardMBean
;
import
javax.management.loading.MLet
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.namespace.JMXRemoteNamespace
;
import
javax.management.namespace.JMXNamespace
;
import
static
java
.
util
.
Collections
.
singletonMap
;
import
javax.management.MBeanServerFactory
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServerFactory
;
import
javax.management.remote.JMXServiceURL
;
public
class
RemoteContextTest
{
private
static
String
failure
;
public
static
interface
ShowContextMBean
{
public
Map
<
String
,
String
>
getContext
();
public
Map
<
String
,
String
>
getCreationContext
();
public
Set
<
String
>
getCalledOps
();
public
String
getThing
();
public
void
setThing
(
String
x
);
public
int
add
(
int
x
,
int
y
);
}
public
static
class
ShowContext
extends
NotificationBroadcasterSupport
implements
ShowContextMBean
,
MBeanRegistration
{
private
final
Map
<
String
,
String
>
creationContext
;
private
final
Set
<
String
>
calledOps
=
new
HashSet
<
String
>();
public
ShowContext
()
{
creationContext
=
getContext
();
}
public
Map
<
String
,
String
>
getContext
()
{
return
ClientContext
.
getContext
();
}
public
Map
<
String
,
String
>
getCreationContext
()
{
return
creationContext
;
}
public
Set
<
String
>
getCalledOps
()
{
return
calledOps
;
}
public
String
getThing
()
{
return
"x"
;
}
public
void
setThing
(
String
x
)
{
}
public
int
add
(
int
x
,
int
y
)
{
return
x
+
y
;
}
public
ObjectName
preRegister
(
MBeanServer
server
,
ObjectName
name
)
{
assertEquals
(
creationContext
,
getContext
());
calledOps
.
add
(
"preRegister"
);
return
name
;
}
public
void
postRegister
(
Boolean
registrationDone
)
{
assertEquals
(
creationContext
,
getContext
());
calledOps
.
add
(
"postRegister"
);
}
// The condition checked here is not guaranteed universally true,
// but is true every time we unregister an instance of this MBean
// in this test.
public
void
preDeregister
()
throws
Exception
{
assertEquals
(
creationContext
,
getContext
());
}
public
void
postDeregister
()
{
assertEquals
(
creationContext
,
getContext
());
}
// Same remark as for preDeregister
@Override
public
MBeanNotificationInfo
[]
getNotificationInfo
()
{
calledOps
.
add
(
"getNotificationInfo"
);
return
super
.
getNotificationInfo
();
}
@Override
public
void
addNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
{
calledOps
.
add
(
"addNotificationListener"
);
super
.
addNotificationListener
(
listener
,
filter
,
handback
);
}
@Override
public
void
removeNotificationListener
(
NotificationListener
listener
)
throws
ListenerNotFoundException
{
calledOps
.
add
(
"removeNL1"
);
super
.
removeNotificationListener
(
listener
);
}
@Override
public
void
removeNotificationListener
(
NotificationListener
listener
,
NotificationFilter
filter
,
Object
handback
)
throws
ListenerNotFoundException
{
calledOps
.
add
(
"removeNL3"
);
super
.
removeNotificationListener
(
listener
,
filter
,
handback
);
}
}
private
static
class
LogRecord
{
final
String
op
;
final
Object
[]
params
;
final
Map
<
String
,
String
>
context
;
LogRecord
(
String
op
,
Object
[]
params
,
Map
<
String
,
String
>
context
)
{
this
.
op
=
op
;
this
.
params
=
params
;
this
.
context
=
context
;
}
@Override
public
String
toString
()
{
return
op
+
Arrays
.
deepToString
(
params
)
+
" "
+
context
;
}
}
private
static
class
LogIH
implements
InvocationHandler
{
private
final
Object
wrapped
;
Queue
<
LogRecord
>
log
=
new
LinkedList
<
LogRecord
>();
LogIH
(
Object
wrapped
)
{
this
.
wrapped
=
wrapped
;
}
public
Object
invoke
(
Object
proxy
,
Method
method
,
Object
[]
args
)
throws
Throwable
{
if
(
method
.
getDeclaringClass
()
!=
Object
.
class
)
{
LogRecord
lr
=
new
LogRecord
(
method
.
getName
(),
args
,
ClientContext
.
getContext
());
log
.
add
(
lr
);
}
try
{
return
method
.
invoke
(
wrapped
,
args
);
}
catch
(
InvocationTargetException
e
)
{
throw
e
.
getCause
();
}
}
}
private
static
<
T
>
T
newSnoop
(
Class
<
T
>
wrappedClass
,
LogIH
logIH
)
{
return
wrappedClass
.
cast
(
Proxy
.
newProxyInstance
(
wrappedClass
.
getClassLoader
(),
new
Class
<?>[]
{
wrappedClass
},
logIH
));
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
final
String
subnamespace
=
"sub"
;
final
ObjectName
locname
=
new
ObjectName
(
"a:b=c"
);
final
ObjectName
name
=
JMXNamespaces
.
insertPath
(
subnamespace
,
locname
);
final
MBeanServer
mbs
=
ClientContext
.
newContextForwarder
(
ManagementFactory
.
getPlatformMBeanServer
(),
null
);
final
MBeanServer
sub
=
ClientContext
.
newContextForwarder
(
MBeanServerFactory
.
newMBeanServer
(),
null
);
final
JMXServiceURL
anonym
=
new
JMXServiceURL
(
"rmi"
,
null
,
0
);
final
Map
<
String
,
Object
>
env
=
Collections
.
emptyMap
();
final
Map
<
String
,
String
>
emptyContext
=
Collections
.
emptyMap
();
final
JMXConnectorServer
srv
=
JMXConnectorServerFactory
.
newJMXConnectorServer
(
anonym
,
env
,
sub
);
sub
.
registerMBean
(
new
ShowContext
(),
locname
);
srv
.
start
();
try
{
JMXRemoteNamespace
subns
=
JMXRemoteNamespace
.
newJMXRemoteNamespace
(
srv
.
getAddress
(),
null
);
mbs
.
registerMBean
(
subns
,
JMXNamespaces
.
getNamespaceObjectName
(
"sub"
));
mbs
.
invoke
(
JMXNamespaces
.
getNamespaceObjectName
(
"sub"
),
"connect"
,
null
,
null
);
final
ShowContextMBean
show
=
JMX
.
newMBeanProxy
(
mbs
,
name
,
ShowContextMBean
.
class
);
assertEquals
(
emptyContext
,
show
.
getContext
());
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"bar"
),
new
Callable
<
Void
>()
{
public
Void
call
()
{
assertEquals
(
singletonMap
(
"foo"
,
"bar"
),
show
.
getContext
());
return
null
;
}
});
assertEquals
(
emptyContext
,
show
.
getContext
());
String
got
=
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"baz"
),
new
Callable
<
String
>()
{
public
String
call
()
{
return
ClientContext
.
getContext
().
get
(
"foo"
);
}
});
assertEquals
(
"baz"
,
got
);
Map
<
String
,
String
>
combined
=
ClientContext
.
doWithContext
(
singletonMap
(
"foo"
,
"baz"
),
new
Callable
<
Map
<
String
,
String
>>()
{
public
Map
<
String
,
String
>
call
()
throws
Exception
{
return
ClientContext
.
doWithContext
(
singletonMap
(
"fred"
,
"jim"
),
new
Callable
<
Map
<
String
,
String
>>()
{
public
Map
<
String
,
String
>
call
()
{
return
ClientContext
.
getContext
();
}
});
}
});
assertEquals
(
singletonMap
(
"fred"
,
"jim"
),
combined
);
final
String
ugh
=
"a!?//*=:\"% "
;
ClientContext
.
doWithContext
(
singletonMap
(
ugh
,
ugh
),
new
Callable
<
Void
>()
{
public
Void
call
()
{
assertEquals
(
Collections
.
singletonMap
(
ugh
,
ugh
),
ClientContext
.
getContext
());
return
null
;
}
});
// Basic withContext tests
LogIH
mbsIH
=
new
LogIH
(
mbs
);
MBeanServer
snoopMBS
=
newSnoop
(
MBeanServer
.
class
,
mbsIH
);
MBeanServer
ughMBS
=
ClientContext
.
withContext
(
snoopMBS
,
ugh
,
ugh
);
// ughMBS is never referenced but we check that the withContext call
// included a call to snoopMBS.isRegistered.
String
encodedUgh
=
URLEncoder
.
encode
(
ugh
,
"UTF-8"
).
replace
(
"*"
,
"%2A"
);
ObjectName
expectedName
=
new
ObjectName
(
ClientContext
.
NAMESPACE
+
ObjectName
.
NAMESPACE_SEPARATOR
+
encodedUgh
+
"="
+
encodedUgh
+
ObjectName
.
NAMESPACE_SEPARATOR
+
":"
+
JMXNamespace
.
TYPE_ASSIGNMENT
);
assertCalled
(
mbsIH
,
"isRegistered"
,
new
Object
[]
{
expectedName
},
emptyContext
);
// Test withDynamicContext
MBeanServerConnection
dynamicSnoop
=
ClientContext
.
withDynamicContext
(
snoopMBS
);
assertCalled
(
mbsIH
,
"isRegistered"
,
new
Object
[]
{
JMXNamespaces
.
getNamespaceObjectName
(
ClientContext
.
NAMESPACE
)
},
emptyContext
);
final
ShowContextMBean
dynamicShow
=
JMX
.
newMBeanProxy
(
dynamicSnoop
,
name
,
ShowContextMBean
.
class
);
assertEquals
(
Collections
.
emptyMap
(),
dynamicShow
.
getContext
());
assertCalled
(
mbsIH
,
"getAttribute"
,
new
Object
[]
{
name
,
"Context"
},
emptyContext
);
Map
<
String
,
String
>
expectedDynamic
=
Collections
.
singletonMap
(
"gladstone"
,
"gander"
);
Map
<
String
,
String
>
dynamic
=
ClientContext
.
doWithContext
(
expectedDynamic
,
new
Callable
<
Map
<
String
,
String
>>()
{
public
Map
<
String
,
String
>
call
()
throws
Exception
{
return
dynamicShow
.
getContext
();
}
});
assertEquals
(
expectedDynamic
,
dynamic
);
ObjectName
expectedDynamicName
=
new
ObjectName
(
ClientContext
.
encode
(
expectedDynamic
)
+
ObjectName
.
NAMESPACE_SEPARATOR
+
name
);
assertCalled
(
mbsIH
,
"getAttribute"
,
new
Object
[]
{
expectedDynamicName
,
"Context"
},
dynamic
);
MBeanServer
cmbs
=
ClientContext
.
withContext
(
mbs
,
"mickey"
,
"mouse"
);
ShowContextMBean
cshow
=
JMX
.
newMBeanProxy
(
cmbs
,
name
,
ShowContextMBean
.
class
);
assertEquals
(
Collections
.
singletonMap
(
"mickey"
,
"mouse"
),
cshow
.
getContext
());
MBeanServer
ccmbs
=
ClientContext
.
withContext
(
cmbs
,
"donald"
,
"duck"
);
ShowContextMBean
ccshow
=
JMX
.
newMBeanProxy
(
ccmbs
,
name
,
ShowContextMBean
.
class
);
Map
<
String
,
String
>
disney
=
new
HashMap
<
String
,
String
>();
disney
.
put
(
"mickey"
,
"mouse"
);
disney
.
put
(
"donald"
,
"duck"
);
assertEquals
(
disney
,
ccshow
.
getContext
());
// Test that all MBS ops produce reasonable results
ObjectName
logger
=
new
ObjectName
(
"a:type=Logger"
);
DynamicMBean
showMBean
=
new
StandardMBean
(
new
ShowContext
(),
ShowContextMBean
.
class
);
LogIH
mbeanLogIH
=
new
LogIH
(
showMBean
);
DynamicMBean
logMBean
=
newSnoop
(
DynamicMBean
.
class
,
mbeanLogIH
);
ObjectInstance
loggerOI
=
ccmbs
.
registerMBean
(
logMBean
,
logger
);
assertEquals
(
logger
,
loggerOI
.
getObjectName
());
// We get a getMBeanInfo call to determine the className in the
// ObjectInstance to return from registerMBean.
assertCalled
(
mbeanLogIH
,
"getMBeanInfo"
,
disney
);
ccmbs
.
getAttribute
(
logger
,
"Thing"
);
assertCalled
(
mbeanLogIH
,
"getAttribute"
,
disney
);
ccmbs
.
getAttributes
(
logger
,
new
String
[]
{
"Thing"
,
"Context"
});
assertCalled
(
mbeanLogIH
,
"getAttributes"
,
disney
);
ccmbs
.
setAttribute
(
logger
,
new
Attribute
(
"Thing"
,
"bar"
));
assertCalled
(
mbeanLogIH
,
"setAttribute"
,
disney
);
ccmbs
.
setAttributes
(
logger
,
new
AttributeList
(
Arrays
.
asList
(
new
Attribute
(
"Thing"
,
"baz"
))));
assertCalled
(
mbeanLogIH
,
"setAttributes"
,
disney
);
ccmbs
.
getMBeanInfo
(
logger
);
assertCalled
(
mbeanLogIH
,
"getMBeanInfo"
,
disney
);
Set
<
ObjectName
>
names
=
ccmbs
.
queryNames
(
null
,
null
);
Set
<
ObjectName
>
expectedNames
=
new
HashSet
<
ObjectName
>(
Collections
.
singleton
(
MBeanServerDelegate
.
DELEGATE_NAME
));
expectedNames
.
removeAll
(
names
);
assertEquals
(
0
,
expectedNames
.
size
());
Set
<
ObjectName
>
nsNames
=
ccmbs
.
queryNames
(
new
ObjectName
(
"**?*?//:*"
),
null
);
Set
<
ObjectName
>
expectedNsNames
=
new
HashSet
<
ObjectName
>(
Arrays
.
asList
(
new
ObjectName
(
ClientContext
.
NAMESPACE
+
ObjectName
.
NAMESPACE_SEPARATOR
+
":"
+
JMXNamespace
.
TYPE_ASSIGNMENT
)));
expectedNsNames
.
removeAll
(
nsNames
);
assertEquals
(
0
,
expectedNsNames
.
size
());
Set
<
ObjectInstance
>
insts
=
ccmbs
.
queryMBeans
(
MBeanServerDelegate
.
DELEGATE_NAME
,
null
);
assertEquals
(
1
,
insts
.
size
());
assertEquals
(
MBeanServerDelegate
.
DELEGATE_NAME
,
insts
.
iterator
().
next
().
getObjectName
());
ObjectName
createdName
=
new
ObjectName
(
"a:type=Created"
);
ObjectInstance
createdOI
=
ccmbs
.
createMBean
(
ShowContext
.
class
.
getName
(),
createdName
);
assertEquals
(
ShowContext
.
class
.
getName
(),
createdOI
.
getClassName
());
assertEquals
(
createdName
,
createdOI
.
getObjectName
());
assertEquals
(
disney
,
ccmbs
.
getAttribute
(
createdName
,
"CreationContext"
));
NotificationListener
nothingListener
=
new
NotificationListener
()
{
public
void
handleNotification
(
Notification
n
,
Object
h
)
{}
};
ccmbs
.
addNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
removeNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
addNotificationListener
(
createdName
,
nothingListener
,
null
,
null
);
ccmbs
.
removeNotificationListener
(
createdName
,
nothingListener
);
Set
<
String
>
expectedOps
=
new
HashSet
<
String
>(
Arrays
.
asList
(
"preRegister"
,
"postRegister"
,
"addNotificationListener"
,
"removeNL1"
,
"removeNL3"
,
"getNotificationInfo"
));
assertEquals
(
expectedOps
,
ccmbs
.
getAttribute
(
createdName
,
"CalledOps"
));
assertEquals
(
ShowContext
.
class
.
getClassLoader
(),
ccmbs
.
getClassLoaderFor
(
createdName
));
assertEquals
(
true
,
ccmbs
.
isRegistered
(
createdName
));
assertEquals
(
true
,
ccmbs
.
isInstanceOf
(
createdName
,
ShowContext
.
class
.
getName
()));
assertEquals
(
false
,
ccmbs
.
isInstanceOf
(
createdName
,
DynamicMBean
.
class
.
getName
()));
ccmbs
.
unregisterMBean
(
createdName
);
assertEquals
(
false
,
ccmbs
.
isRegistered
(
createdName
));
MLet
mlet
=
new
MLet
();
ObjectName
defaultMLetName
=
new
ObjectName
(
"DefaultDomain:type=MLet"
);
ccmbs
.
registerMBean
(
mlet
,
defaultMLetName
);
assertEquals
(
mlet
,
ccmbs
.
getClassLoader
(
defaultMLetName
));
assertEquals
(
0
,
mbeanLogIH
.
log
.
size
());
// Test that contexts still work when we can't combine two encoded contexts.
// Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot
// see that it already contains a context and therefore cannot combine
// into mickey=mouse;donald=duck. We don't actually use the snoop
// capabilities of the returned object -- we just want an opaque
// MBeanServer wrapper
MBeanServer
cmbs2
=
newSnoop
(
MBeanServer
.
class
,
new
LogIH
(
cmbs
));
MBeanServer
ccmbs2
=
ClientContext
.
withContext
(
cmbs2
,
"donald"
,
"duck"
);
assertEquals
(
disney
,
ccmbs2
.
getAttribute
(
name
,
"Context"
));
// ADD NEW TESTS HERE ^^^
if
(
failure
!=
null
)
throw
new
Exception
(
failure
);
}
finally
{
srv
.
stop
();
}
}
private
static
void
assertEquals
(
Object
x
,
Object
y
)
{
if
(!
equal
(
x
,
y
))
failed
(
"expected "
+
string
(
x
)
+
"; got "
+
string
(
y
));
}
private
static
boolean
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
y
)
return
true
;
if
(
x
==
null
||
y
==
null
)
return
false
;
if
(
x
.
getClass
().
isArray
())
return
Arrays
.
deepEquals
(
new
Object
[]
{
x
},
new
Object
[]
{
y
});
return
x
.
equals
(
y
);
}
private
static
String
string
(
Object
x
)
{
String
s
=
Arrays
.
deepToString
(
new
Object
[]
{
x
});
return
s
.
substring
(
1
,
s
.
length
()
-
1
);
}
private
static
void
assertCalled
(
LogIH
logIH
,
String
op
,
Map
<
String
,
String
>
expectedContext
)
{
assertCalled
(
logIH
,
op
,
null
,
expectedContext
);
}
private
static
void
assertCalled
(
LogIH
logIH
,
String
op
,
Object
[]
params
,
Map
<
String
,
String
>
expectedContext
)
{
LogRecord
lr
=
logIH
.
log
.
remove
();
assertEquals
(
op
,
lr
.
op
);
if
(
params
!=
null
)
assertEquals
(
params
,
lr
.
params
);
assertEquals
(
expectedContext
,
lr
.
context
);
}
private
static
void
failed
(
String
why
)
{
failure
=
why
;
new
Throwable
(
"FAILED: "
+
why
).
printStackTrace
(
System
.
out
);
}
}
test/javax/management/context/localizable/MBeanDescriptions.properties
0 → 100644
浏览文件 @
6b491fa1
# This is the default description ResourceBundle for MBeans in this package.
# Resources here override the descriptions specified with @Description
# but only when localization is happening and when there is not a more
# specific resource for the description (for example from MBeanDescriptions_fr).
WhatsitMBean.mbean
=
A whatsit
# This must be the same as WhatsitMBean.englishMBeanDescription for the
# purposes of this test.
test/javax/management/context/localizable/MBeanDescriptions_fr.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
localizable
;
import
java.util.ListResourceBundle
;
import
static
localizable
.
WhatsitMBean
.*;
public
class
MBeanDescriptions_fr
extends
ListResourceBundle
{
@Override
protected
Object
[][]
getContents
()
{
String
constrProp
=
"WhatsitMBean.constructor."
+
Whatsit
.
class
.
getName
();
return
new
Object
[][]
{
{
"WhatsitMBean.mbean"
,
frenchMBeanDescription
},
{
"WhatsitMBean.attribute.Whatsit"
,
frenchAttrDescription
},
{
"WhatsitMBean.operation.frob"
,
frenchOperDescription
},
{
"WhatsitMBean.operation.frob.p1"
,
frenchParamDescription
},
{
constrProp
,
frenchConstrDescription
},
{
constrProp
+
".p1"
,
frenchConstrParamDescription
},
};
}
}
test/javax/management/context/localizable/Whatsit.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
localizable
;
import
javax.management.Description
;
public
class
Whatsit
implements
WhatsitMBean
{
/**
* Attribute : NewAttribute0
*/
private
String
newAttribute0
;
@Description
(
englishConstrDescription
)
public
Whatsit
()
{}
@Description
(
englishConstrDescription
)
public
Whatsit
(
@Description
(
englishConstrParamDescription
)
int
type
)
{}
public
String
getWhatsit
()
{
return
"whatsit"
;
}
public
void
frob
(
String
whatsit
)
{
}
/**
* Get Tiddly
*/
public
String
getNewAttribute0
()
{
return
newAttribute0
;
}
/**
* Set Tiddly
*/
public
void
setNewAttribute0
(
String
value
)
{
newAttribute0
=
value
;
}
}
test/javax/management/context/localizable/WhatsitMBean.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package
localizable
;
import
javax.management.Description
;
@Description
(
WhatsitMBean
.
defaultMBeanDescription
)
public
interface
WhatsitMBean
{
public
static
final
String
defaultMBeanDescription
=
"Default whatsit MBean description"
,
englishMBeanDescription
=
"A whatsit"
,
// Previous description appears in MBeanDescriptions.properties
// so it overrides the @Description when that file is used.
frenchMBeanDescription
=
"Un bidule"
,
englishAttrDescription
=
"The whatsit"
,
frenchAttrDescription
=
"Le bidule"
,
englishOperDescription
=
"Frob the whatsit"
,
frenchOperDescription
=
"Frober le bidule"
,
englishParamDescription
=
"The whatsit to frob"
,
frenchParamDescription
=
"Le bidule \u00e0 frober"
,
englishConstrDescription
=
"Make a whatsit"
,
frenchConstrDescription
=
"Fabriquer un bidule"
,
englishConstrParamDescription
=
"Type of whatsit to make"
,
frenchConstrParamDescription
=
"Type de bidule \u00e0 fabriquer"
,
unlocalizedMBeanDescription
=
"Unlocalized MBean"
;
@Description
(
englishAttrDescription
)
public
String
getWhatsit
();
@Description
(
englishOperDescription
)
public
void
frob
(
@Description
(
englishParamDescription
)
String
whatsit
);
}
test/javax/management/eventService/CustomForwarderTest.java
浏览文件 @
6b491fa1
...
@@ -200,8 +200,7 @@ public class CustomForwarderTest {
...
@@ -200,8 +200,7 @@ public class CustomForwarderTest {
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
();
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
(
mbs
,
null
);
mbsf
.
setMBeanServer
(
mbs
);
mbs
=
mbsf
;
mbs
=
mbsf
;
// for 1.5
// for 1.5
...
...
test/javax/management/eventService/EventClientExecutorTest.java
浏览文件 @
6b491fa1
...
@@ -65,8 +65,7 @@ public class EventClientExecutorTest {
...
@@ -65,8 +65,7 @@ public class EventClientExecutorTest {
new
NamedThreadFactory
(
"LEASE"
));
new
NamedThreadFactory
(
"LEASE"
));
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
();
MBeanServerForwarder
mbsf
=
EventClientDelegate
.
newForwarder
(
mbs
,
null
);
mbsf
.
setMBeanServer
(
mbs
);
mbs
=
mbsf
;
mbs
=
mbsf
;
EventClientDelegateMBean
ecd
=
EventClientDelegate
.
getProxy
(
mbs
);
EventClientDelegateMBean
ecd
=
EventClientDelegate
.
getProxy
(
mbs
);
...
...
test/javax/management/eventService/EventManagerTest.java
浏览文件 @
6b491fa1
...
@@ -98,7 +98,7 @@ public class EventManagerTest {
...
@@ -98,7 +98,7 @@ public class EventManagerTest {
succeed
&=
test
(
new
EventClient
(
ecd
,
succeed
&=
test
(
new
EventClient
(
ecd
,
new
RMIPushEventRelay
(
ecd
),
new
RMIPushEventRelay
(
ecd
),
null
,
null
,
null
,
null
,
EventClient
.
DEFAULT_
LEASE_TIMEOUT
));
EventClient
.
DEFAULT_
REQUESTED_LEASE_TIME
));
conn
.
close
();
conn
.
close
();
server
.
stop
();
server
.
stop
();
...
...
test/javax/management/eventService/ListenerTest.java
浏览文件 @
6b491fa1
...
@@ -99,7 +99,7 @@ public class ListenerTest {
...
@@ -99,7 +99,7 @@ public class ListenerTest {
succeed
&=
test
(
new
EventClient
(
ecd
,
succeed
&=
test
(
new
EventClient
(
ecd
,
new
RMIPushEventRelay
(
ecd
),
new
RMIPushEventRelay
(
ecd
),
null
,
null
,
null
,
null
,
EventClient
.
DEFAULT_
LEASE_TIMEOUT
));
EventClient
.
DEFAULT_
REQUESTED_LEASE_TIME
));
conn
.
close
();
conn
.
close
();
server
.
stop
();
server
.
stop
();
...
...
test/javax/management/eventService/NotSerializableNotifTest.java
浏览文件 @
6b491fa1
...
@@ -95,7 +95,7 @@ public class NotSerializableNotifTest {
...
@@ -95,7 +95,7 @@ public class NotSerializableNotifTest {
FetchingEventRelay
.
DEFAULT_MAX_NOTIFICATIONS
,
FetchingEventRelay
.
DEFAULT_MAX_NOTIFICATIONS
,
null
);
null
);
EventClient
ec
=
new
EventClient
(
ecd
,
eventRelay
,
null
,
null
,
EventClient
ec
=
new
EventClient
(
ecd
,
eventRelay
,
null
,
null
,
EventClient
.
DEFAULT_
LEASE_TIMEOUT
);
EventClient
.
DEFAULT_
REQUESTED_LEASE_TIME
);
// add listener from the client side
// add listener from the client side
Listener
listener
=
new
Listener
();
Listener
listener
=
new
Listener
();
...
...
test/javax/management/eventService/UsingEventService.java
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
/*
* @test UsingEventService.java 1.10 08/01/22
* @test UsingEventService.java 1.10 08/01/22
* @bug 5108776
* @bug 5108776
...
...
test/javax/management/namespace/EventWithNamespaceControlTest.java
浏览文件 @
6b491fa1
...
@@ -85,6 +85,7 @@ public class EventWithNamespaceControlTest extends EventWithNamespaceTest {
...
@@ -85,6 +85,7 @@ public class EventWithNamespaceControlTest extends EventWithNamespaceTest {
}
}
}
}
@Override
public
Map
<
String
,
?>
getServerMap
()
{
public
Map
<
String
,
?>
getServerMap
()
{
Map
<
String
,
?>
retValue
=
Collections
.
emptyMap
();
Map
<
String
,
?>
retValue
=
Collections
.
emptyMap
();
return
retValue
;
return
retValue
;
...
...
test/javax/management/namespace/JMXNamespaceSecurityTest.java
浏览文件 @
6b491fa1
...
@@ -51,6 +51,7 @@ import javax.management.namespace.JMXDomain;
...
@@ -51,6 +51,7 @@ import javax.management.namespace.JMXDomain;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.ClientContext
;
/**
/**
*
*
...
...
test/javax/management/namespace/JMXNamespaceViewTest.java
浏览文件 @
6b491fa1
...
@@ -42,6 +42,7 @@ import java.util.HashSet;
...
@@ -42,6 +42,7 @@ import java.util.HashSet;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.Set
;
import
javax.management.ClientContext
;
import
javax.management.JMException
;
import
javax.management.JMException
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanRegistration
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServer
;
...
@@ -62,11 +63,6 @@ import javax.management.remote.JMXServiceURL;
...
@@ -62,11 +63,6 @@ import javax.management.remote.JMXServiceURL;
*/
*/
public
class
JMXNamespaceViewTest
{
public
class
JMXNamespaceViewTest
{
// TODO: Remove this when contexts are added.
public
static
class
ClientContext
{
public
final
static
String
NAMESPACE
=
"jmx.context"
;
}
/**
/**
* Describe the configuration of a namespace
* Describe the configuration of a namespace
*/
*/
...
...
test/javax/management/namespace/JMXRemoteTargetNamespace.java
浏览文件 @
6b491fa1
...
@@ -68,13 +68,7 @@ public class JMXRemoteTargetNamespace extends JMXRemoteNamespace {
...
@@ -68,13 +68,7 @@ public class JMXRemoteTargetNamespace extends JMXRemoteNamespace {
public
JMXRemoteTargetNamespace
(
JMXServiceURL
sourceURL
,
public
JMXRemoteTargetNamespace
(
JMXServiceURL
sourceURL
,
Map
<
String
,?>
optionsMap
,
String
sourceNamespace
)
{
Map
<
String
,?>
optionsMap
,
String
sourceNamespace
)
{
this
(
sourceURL
,
optionsMap
,
sourceNamespace
,
false
);
super
(
sourceURL
,
optionsMap
);
}
public
JMXRemoteTargetNamespace
(
JMXServiceURL
sourceURL
,
Map
<
String
,?>
optionsMap
,
String
sourceNamespace
,
boolean
createEventClient
)
{
super
(
sourceURL
,
optionsMap
);
this
.
sourceNamespace
=
sourceNamespace
;
this
.
sourceNamespace
=
sourceNamespace
;
this
.
createEventClient
=
createEventClient
(
optionsMap
);
this
.
createEventClient
=
createEventClient
(
optionsMap
);
}
}
...
@@ -92,14 +86,14 @@ public class JMXRemoteTargetNamespace extends JMXRemoteNamespace {
...
@@ -92,14 +86,14 @@ public class JMXRemoteTargetNamespace extends JMXRemoteNamespace {
}
}
@Override
@Override
protected
JMXConnector
newJMXConnector
(
JMXServiceURL
url
,
protected
MBeanServerConnection
getMBeanServerConnection
(
JMXConnector
jmxc
)
Map
<
String
,
?>
env
)
throws
IOException
{
throws
IOException
{
JMXConnector
sup
=
super
.
newJMXConnector
(
url
,
env
);
MBeanServerConnection
mbsc
=
super
.
getMBeanServerConnection
(
jmxc
);
if
(
sourceNamespace
==
null
||
""
.
equals
(
sourceNamespace
)
)
if
(
sourceNamespace
!=
null
&&
sourceNamespace
.
length
()
>
0
)
return
sup
;
mbsc
=
JMXNamespaces
.
narrowToNamespace
(
mbsc
,
sourceNamespace
)
;
if
(
createEventClient
)
if
(
createEventClient
)
sup
=
EventClient
.
withEventClient
(
sup
);
mbsc
=
EventClient
.
getEventClientConnection
(
mbsc
);
return
JMXNamespaces
.
narrowToNamespace
(
sup
,
sourceNamespace
)
;
return
mbsc
;
}
}
...
...
test/javax/management/namespace/NamespaceNotificationsTest.java
浏览文件 @
6b491fa1
...
@@ -206,18 +206,10 @@ public class NamespaceNotificationsTest {
...
@@ -206,18 +206,10 @@ public class NamespaceNotificationsTest {
aconn
.
addNotificationListener
(
deep
,
listener
,
null
,
deep
);
aconn
.
addNotificationListener
(
deep
,
listener
,
null
,
deep
);
final
JMXServiceURL
urlx
=
new
JMXServiceURL
(
url1
.
toString
());
MBeanServerConnection
iconn
=
System
.
out
.
println
(
"conn: "
+
urlx
);
JMXNamespaces
.
narrowToNamespace
(
aconn
,
"server1//server1"
);
final
JMXConnector
jc2
=
JMXNamespaces
.
narrowToNamespace
(
MBeanServerConnection
bconn
=
JMXConnectorFactory
.
connect
(
urlx
),
"server1//server1"
);
JMXNamespaces
.
narrowToNamespace
(
aconn
,
"server3"
);
final
JMXConnector
jc3
=
JMXNamespaces
.
narrowToNamespace
(
jc2
,
"server3"
);
jc3
.
connect
();
System
.
out
.
println
(
"JC#3: "
+
((
jc3
instanceof
JMXAddressable
)?
((
JMXAddressable
)
jc3
).
getAddress
():
jc3
.
toString
()));
final
MBeanServerConnection
bconn
=
jc3
.
getMBeanServerConnection
();
final
ObjectName
shallow
=
final
ObjectName
shallow
=
new
ObjectName
(
"bush:"
+
new
ObjectName
(
"bush:"
+
deep
.
getKeyPropertyListString
());
deep
.
getKeyPropertyListString
());
...
...
test/javax/management/namespace/NullDomainObjectNameTest.java
浏览文件 @
6b491fa1
...
@@ -155,7 +155,7 @@ public class NullDomainObjectNameTest {
...
@@ -155,7 +155,7 @@ public class NullDomainObjectNameTest {
// namespace.
// namespace.
//
//
RoutingServerProxy
proxy
=
RoutingServerProxy
proxy
=
new
RoutingServerProxy
(
sub
,
""
,
"faked"
,
fals
e
);
new
RoutingServerProxy
(
sub
,
""
,
"faked"
,
tru
e
);
// These should fail because the ObjectName doesn't start
// These should fail because the ObjectName doesn't start
// with "faked//"
// with "faked//"
...
...
test/javax/management/namespace/NullObjectNameTest.java
浏览文件 @
6b491fa1
...
@@ -162,7 +162,7 @@ public class NullObjectNameTest {
...
@@ -162,7 +162,7 @@ public class NullObjectNameTest {
// this case.
// this case.
//
//
RoutingServerProxy
proxy
=
RoutingServerProxy
proxy
=
new
RoutingServerProxy
(
sub
,
""
,
"faked"
,
fals
e
);
new
RoutingServerProxy
(
sub
,
""
,
"faked"
,
tru
e
);
final
ObjectInstance
moi3
=
final
ObjectInstance
moi3
=
proxy
.
registerMBean
(
new
MyWombat
(),
null
);
proxy
.
registerMBean
(
new
MyWombat
(),
null
);
System
.
out
.
println
(
moi3
.
getObjectName
().
toString
()+
System
.
out
.
println
(
moi3
.
getObjectName
().
toString
()+
...
...
test/javax/management/openmbean/CompositeDataStringTest.java
浏览文件 @
6b491fa1
...
@@ -21,19 +21,19 @@
...
@@ -21,19 +21,19 @@
* have any questions.
* have any questions.
*/
*/
import
javax.management.openmbean.CompositeType
;
import
javax.management.openmbean.OpenType
;
import
javax.management.openmbean.SimpleType
;
/*
/*
* @test
* @test
* @bug 6610174
* @bug 6610174
* @summary Test that CompositeDataSupport.toString() represents arrays correctly
* @summary Test that CompositeDataSupport.toString() represents arrays correctly
* @author Eamonn McManus
* @author Eamonn McManus
*/
*/
import
javax.management.openmbean.ArrayType
;
import
javax.management.openmbean.ArrayType
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeDataSupport
;
import
javax.management.openmbean.CompositeDataSupport
;
import
javax.management.openmbean.CompositeType
;
import
javax.management.openmbean.OpenType
;
import
javax.management.openmbean.SimpleType
;
public
class
CompositeDataStringTest
{
public
class
CompositeDataStringTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
...
...
test/javax/management/openmbean/CompositeDataToMapTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6750472 6752563
* @summary Test CompositeDataSupport.toMap.
* @author Eamonn McManus
* @run main/othervm -ea CompositeDataToMapTest
*/
import
java.lang.reflect.InvocationHandler
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Proxy
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.management.openmbean.CompositeData
;
import
javax.management.openmbean.CompositeDataSupport
;
import
javax.management.openmbean.CompositeType
;
import
javax.management.openmbean.OpenType
;
import
javax.management.openmbean.SimpleType
;
public
class
CompositeDataToMapTest
{
private
static
class
IdentityInvocationHandler
implements
InvocationHandler
{
private
final
Object
wrapped
;
public
IdentityInvocationHandler
(
Object
wrapped
)
{
this
.
wrapped
=
wrapped
;
}
public
Object
invoke
(
Object
proxy
,
Method
m
,
Object
[]
args
)
throws
Throwable
{
try
{
return
m
.
invoke
(
wrapped
,
args
);
}
catch
(
InvocationTargetException
e
)
{
throw
e
.
getCause
();
}
}
}
private
static
<
T
>
T
wrap
(
T
x
,
Class
<
T
>
intf
)
{
InvocationHandler
ih
=
new
IdentityInvocationHandler
(
x
);
return
intf
.
cast
(
Proxy
.
newProxyInstance
(
intf
.
getClassLoader
(),
new
Class
<?>[]
{
intf
},
ih
));
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
if
(!
CompositeDataToMapTest
.
class
.
desiredAssertionStatus
())
throw
new
AssertionError
(
"Must be run with -ea"
);
CompositeType
emptyCT
=
new
CompositeType
(
"empty"
,
"empty"
,
new
String
[
0
],
new
String
[
0
],
new
OpenType
<?>[
0
]);
CompositeData
emptyCD
=
new
CompositeDataSupport
(
emptyCT
,
Collections
.<
String
,
Object
>
emptyMap
());
assert
CompositeDataSupport
.
toMap
(
emptyCD
).
isEmpty
()
:
"Empty CD produces empty Map"
;
CompositeData
emptyCD2
=
new
CompositeDataSupport
(
emptyCT
,
new
String
[
0
],
new
Object
[
0
]);
assert
emptyCD
.
equals
(
emptyCD2
)
:
"Empty CD can be constructed two ways"
;
CompositeType
namedNumberCT
=
new
CompositeType
(
"NamedNumber"
,
"NamedNumber"
,
new
String
[]
{
"name"
,
"number"
},
new
String
[]
{
"name"
,
"number"
},
new
OpenType
<?>[]
{
SimpleType
.
STRING
,
SimpleType
.
INTEGER
});
Map
<
String
,
Object
>
namedNumberMap
=
new
HashMap
<
String
,
Object
>();
namedNumberMap
.
put
(
"name"
,
"Deich"
);
namedNumberMap
.
put
(
"number"
,
10
);
CompositeData
namedNumberCD
=
new
CompositeDataSupport
(
namedNumberCT
,
namedNumberMap
);
assert
CompositeDataSupport
.
toMap
(
namedNumberCD
).
equals
(
namedNumberMap
)
:
"Map survives passage through CompositeData"
;
namedNumberCD
=
wrap
(
namedNumberCD
,
CompositeData
.
class
);
assert
CompositeDataSupport
.
toMap
(
namedNumberCD
).
equals
(
namedNumberMap
)
:
"Map survives passage through wrapped CompositeData"
;
namedNumberMap
=
CompositeDataSupport
.
toMap
(
namedNumberCD
);
namedNumberMap
.
put
(
"name"
,
"Ceathar"
);
namedNumberMap
.
put
(
"number"
,
4
);
namedNumberCD
=
new
CompositeDataSupport
(
namedNumberCT
,
namedNumberMap
);
assert
CompositeDataSupport
.
toMap
(
namedNumberCD
).
equals
(
namedNumberMap
)
:
"Modified Map survives passage through CompositeData"
;
try
{
namedNumberMap
=
CompositeDataSupport
.
toMap
(
null
);
assert
false
:
"Null toMap arg provokes exception"
;
}
catch
(
Exception
e
)
{
assert
e
instanceof
IllegalArgumentException
:
"Exception for null toMap arg is IllegalArgumentException"
;
}
}
}
test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java
浏览文件 @
6b491fa1
...
@@ -86,16 +86,20 @@ public class ForwarderChainTest {
...
@@ -86,16 +86,20 @@ public class ForwarderChainTest {
test
(
cs
,
mbs
);
test
(
cs
,
mbs
);
System
.
out
.
println
(
"===Remove any leftover forwarders==="
);
System
.
out
.
println
(
"===Remove any leftover forwarders==="
);
while
(
cs
.
getSystemMBeanServer
()
instanceof
MBeanServerForwarder
)
{
MBeanServerForwarder
systemMBSF
=
cs
.
getSystemMBeanServerForwarder
();
MBeanServerForwarder
mbsf
=
// Real code would just do systemMBSF.setMBeanServer(mbs).
(
MBeanServerForwarder
)
cs
.
getSystemMBeanServer
();
while
(
true
)
{
cs
.
removeMBeanServerForwarder
(
mbsf
);
MBeanServer
xmbs
=
systemMBSF
.
getMBeanServer
();
if
(!(
xmbs
instanceof
MBeanServerForwarder
))
break
;
cs
.
removeMBeanServerForwarder
((
MBeanServerForwarder
)
xmbs
);
}
}
expectChain
(
cs
,
"U"
,
mbs
);
expectChain
(
cs
,
"U"
,
mbs
);
System
.
out
.
println
(
"===Ensure forwarders are called==="
);
System
.
out
.
println
(
"===Ensure forwarders are called==="
);
cs
.
setMBeanServerForwarder
(
forwarders
[
0
]);
cs
.
setMBeanServerForwarder
(
forwarders
[
0
]);
cs
.
setSystemMBeanServerForwarder
(
forwarders
[
1
]);
systemMBSF
.
setMBeanServer
(
forwarders
[
1
]);
forwarders
[
1
].
setMBeanServer
(
forwarders
[
0
]);
expectChain
(
cs
,
"1U0"
,
mbs
);
expectChain
(
cs
,
"1U0"
,
mbs
);
cs
.
start
();
cs
.
start
();
if
(
forwarders
[
0
].
defaultDomainCount
!=
0
||
if
(
forwarders
[
0
].
defaultDomainCount
!=
0
||
...
@@ -125,8 +129,8 @@ public class ForwarderChainTest {
...
@@ -125,8 +129,8 @@ public class ForwarderChainTest {
private
static
void
test
(
JMXConnectorServer
cs
,
MBeanServer
end
)
{
private
static
void
test
(
JMXConnectorServer
cs
,
MBeanServer
end
)
{
// A newly-created connector server might have system forwarders,
// A newly-created connector server might have system forwarders,
// so get rid of those.
// so get rid of those.
while
(
cs
.
getSystemMBeanServer
()
!=
cs
.
getMBeanServer
())
MBeanServerForwarder
systemMBSF
=
cs
.
getSystemMBeanServerForwarder
();
cs
.
removeMBeanServerForwarder
((
MBeanServerForwarder
)
cs
.
getSystem
MBeanServer
());
systemMBSF
.
setMBeanServer
(
cs
.
get
MBeanServer
());
expectChain
(
cs
,
"U"
,
end
);
expectChain
(
cs
,
"U"
,
end
);
...
@@ -139,7 +143,8 @@ public class ForwarderChainTest {
...
@@ -139,7 +143,8 @@ public class ForwarderChainTest {
expectChain
(
cs
,
"U10"
,
end
);
expectChain
(
cs
,
"U10"
,
end
);
System
.
out
.
println
(
"Add a system forwarder"
);
System
.
out
.
println
(
"Add a system forwarder"
);
cs
.
setSystemMBeanServerForwarder
(
forwarders
[
2
]);
forwarders
[
2
].
setMBeanServer
(
systemMBSF
.
getMBeanServer
());
systemMBSF
.
setMBeanServer
(
forwarders
[
2
]);
expectChain
(
cs
,
"2U10"
,
end
);
expectChain
(
cs
,
"2U10"
,
end
);
System
.
out
.
println
(
"Add another user forwarder"
);
System
.
out
.
println
(
"Add another user forwarder"
);
...
@@ -147,7 +152,8 @@ public class ForwarderChainTest {
...
@@ -147,7 +152,8 @@ public class ForwarderChainTest {
expectChain
(
cs
,
"2U310"
,
end
);
expectChain
(
cs
,
"2U310"
,
end
);
System
.
out
.
println
(
"Add another system forwarder"
);
System
.
out
.
println
(
"Add another system forwarder"
);
cs
.
setSystemMBeanServerForwarder
(
forwarders
[
4
]);
forwarders
[
4
].
setMBeanServer
(
systemMBSF
.
getMBeanServer
());
systemMBSF
.
setMBeanServer
(
forwarders
[
4
]);
expectChain
(
cs
,
"42U310"
,
end
);
expectChain
(
cs
,
"42U310"
,
end
);
System
.
out
.
println
(
"Remove the first user forwarder"
);
System
.
out
.
println
(
"Remove the first user forwarder"
);
...
@@ -215,9 +221,8 @@ public class ForwarderChainTest {
...
@@ -215,9 +221,8 @@ public class ForwarderChainTest {
}
}
case
2
:
{
// add it to the system chain
case
2
:
{
// add it to the system chain
System
.
out
.
println
(
"Add "
+
c
+
" to system chain"
);
System
.
out
.
println
(
"Add "
+
c
+
" to system chain"
);
if
(
cs
.
getSystemMBeanServer
()
==
null
)
mbsf
.
setMBeanServer
(
systemMBSF
.
getMBeanServer
());
mbsf
.
setMBeanServer
(
null
);
systemMBSF
.
setMBeanServer
(
mbsf
);
cs
.
setSystemMBeanServerForwarder
(
mbsf
);
chain
=
c
+
chain
;
chain
=
c
+
chain
;
break
;
break
;
}
}
...
@@ -240,7 +245,7 @@ public class ForwarderChainTest {
...
@@ -240,7 +245,7 @@ public class ForwarderChainTest {
private
static
void
expectChain
(
private
static
void
expectChain
(
JMXConnectorServer
cs
,
String
chain
,
MBeanServer
end
)
{
JMXConnectorServer
cs
,
String
chain
,
MBeanServer
end
)
{
System
.
out
.
println
(
"...expected chain: "
+
chain
);
System
.
out
.
println
(
"...expected chain: "
+
chain
);
MBeanServer
curr
=
cs
.
getSystemMBeanServer
();
MBeanServer
curr
=
cs
.
getSystemMBeanServer
Forwarder
().
getMBeanServer
();
int
i
=
0
;
int
i
=
0
;
while
(
i
<
chain
.
length
())
{
while
(
i
<
chain
.
length
())
{
char
c
=
chain
.
charAt
(
i
);
char
c
=
chain
.
charAt
(
i
);
...
...
test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java
浏览文件 @
6b491fa1
...
@@ -26,6 +26,7 @@ import java.util.ArrayList;
...
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import
java.util.HashMap
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Map
;
import
javax.management.ClientContext
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServer
;
import
javax.management.event.EventClientDelegate
;
import
javax.management.event.EventClientDelegate
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServer
;
...
@@ -62,13 +63,23 @@ public class StandardForwardersTest {
...
@@ -62,13 +63,23 @@ public class StandardForwardersTest {
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
MBeanServer
mbs
=
ManagementFactory
.
getPlatformMBeanServer
();
MBeanServerForwarder
ctxFwd
=
ClientContext
.
newContextForwarder
(
mbs
,
null
);
Forwarder
ctx
=
new
Forwarder
(
JMXConnectorServer
.
CONTEXT_FORWARDER
,
true
,
ctxFwd
.
getClass
());
MBeanServerForwarder
locFwd
=
ClientContext
.
newLocalizeMBeanInfoForwarder
(
mbs
);
Forwarder
loc
=
new
Forwarder
(
JMXConnectorServer
.
LOCALIZE_MBEAN_INFO_FORWARDER
,
false
,
locFwd
.
getClass
());
MBeanServerForwarder
ecdFwd
=
MBeanServerForwarder
ecdFwd
=
EventClientDelegate
.
newForwarder
();
EventClientDelegate
.
newForwarder
(
mbs
,
null
);
Forwarder
ecd
=
new
Forwarder
(
Forwarder
ecd
=
new
Forwarder
(
JMXConnectorServer
.
EVENT_CLIENT_DELEGATE_FORWARDER
,
true
,
JMXConnectorServer
.
EVENT_CLIENT_DELEGATE_FORWARDER
,
true
,
ecdFwd
.
getClass
());
ecdFwd
.
getClass
());
Forwarder
[]
forwarders
=
{
ecd
};
Forwarder
[]
forwarders
=
{
ctx
,
loc
,
ecd
};
// Now go through every combination of forwarders. Each forwarder
// Now go through every combination of forwarders. Each forwarder
// may be explicitly enabled, explicitly disabled, or left to its
// may be explicitly enabled, explicitly disabled, or left to its
...
@@ -154,9 +165,11 @@ public class StandardForwardersTest {
...
@@ -154,9 +165,11 @@ public class StandardForwardersTest {
}
}
MBeanServer
stop
=
cs
.
getMBeanServer
();
MBeanServer
stop
=
cs
.
getMBeanServer
();
List
<
Class
<?>>
foundClasses
=
new
ArrayList
<
Class
<?>>();
List
<
Class
<?>>
foundClasses
=
new
ArrayList
<
Class
<?>>();
for
(
MBeanServer
mbs
=
cs
.
getSystemMBeanServer
();
mbs
!=
stop
;
for
(
MBeanServer
mbs
=
cs
.
getSystemMBeanServerForwarder
().
getMBeanServer
();
mbs
=
((
MBeanServerForwarder
)
mbs
).
getMBeanServer
())
mbs
!=
stop
;
mbs
=
((
MBeanServerForwarder
)
mbs
).
getMBeanServer
())
{
foundClasses
.
add
(
mbs
.
getClass
());
foundClasses
.
add
(
mbs
.
getClass
());
}
if
(!
expectedClasses
.
equals
(
foundClasses
))
{
if
(!
expectedClasses
.
equals
(
foundClasses
))
{
fail
(
"Incorrect forwarder chain: expected "
+
expectedClasses
+
fail
(
"Incorrect forwarder chain: expected "
+
expectedClasses
+
"; found "
+
foundClasses
);
"; found "
+
foundClasses
);
...
@@ -165,9 +178,12 @@ public class StandardForwardersTest {
...
@@ -165,9 +178,12 @@ public class StandardForwardersTest {
// env is consistent if either (a) localizer is not enabled or (b)
// env is consistent if either (a) localizer is not enabled or (b)
// localizer is enabled and context is enabled.
// localizer is enabled and context is enabled.
// Neither of those is present in this codebase so env is always consistent.
private
static
boolean
isConsistent
(
Map
<
String
,
String
>
env
)
{
private
static
boolean
isConsistent
(
Map
<
String
,
String
>
env
)
{
return
true
;
String
ctxS
=
env
.
get
(
JMXConnectorServer
.
CONTEXT_FORWARDER
);
boolean
ctx
=
(
ctxS
==
null
)
?
true
:
Boolean
.
parseBoolean
(
ctxS
);
String
locS
=
env
.
get
(
JMXConnectorServer
.
LOCALIZE_MBEAN_INFO_FORWARDER
);
boolean
loc
=
(
locS
==
null
)
?
false
:
Boolean
.
parseBoolean
(
locS
);
return
!
loc
||
ctx
;
}
}
private
static
void
fail
(
String
why
)
{
private
static
void
fail
(
String
why
)
{
...
...
test/javax/management/remote/mandatory/provider/ProviderTest.java
浏览文件 @
6b491fa1
...
@@ -46,6 +46,8 @@ import javax.management.MBeanServer;
...
@@ -46,6 +46,8 @@ import javax.management.MBeanServer;
/*
/*
* Tests jar services provider are called
* Tests jar services provider are called
*/
*/
import
provider.JMXConnectorProviderImpl
;
import
provider.JMXConnectorServerProviderImpl
;
public
class
ProviderTest
{
public
class
ProviderTest
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
System
.
out
.
println
(
"Starting ProviderTest"
);
System
.
out
.
println
(
"Starting ProviderTest"
);
...
@@ -56,8 +58,14 @@ public class ProviderTest {
...
@@ -56,8 +58,14 @@ public class ProviderTest {
dotest
(
url
,
mbs
);
dotest
(
url
,
mbs
);
if
(!
provider
.
JMXConnectorProviderImpl
.
called
()
||
boolean
clientCalled
=
provider
.
JMXConnectorProviderImpl
.
called
();
!
provider
.
JMXConnectorServerProviderImpl
.
called
())
{
boolean
serverCalled
=
provider
.
JMXConnectorServerProviderImpl
.
called
();
boolean
ok
=
clientCalled
&&
serverCalled
;
if
(!
ok
)
{
if
(!
clientCalled
)
System
.
out
.
println
(
"Client provider not called"
);
if
(!
serverCalled
)
System
.
out
.
println
(
"Server provider not called"
);
System
.
out
.
println
(
"Test Failed"
);
System
.
out
.
println
(
"Test Failed"
);
System
.
exit
(
1
);
System
.
exit
(
1
);
}
}
...
...
test/javax/management/remote/mandatory/subjectDelegation/SimpleStandard.java
浏览文件 @
6b491fa1
...
@@ -75,7 +75,7 @@ public class SimpleStandard
...
@@ -75,7 +75,7 @@ public class SimpleStandard
* @return the current value of the "State" attribute.
* @return the current value of the "State" attribute.
*/
*/
public
String
getState
()
{
public
String
getState
()
{
checkSubject
();
checkSubject
(
"getState"
);
return
state
;
return
state
;
}
}
...
@@ -85,7 +85,7 @@ public class SimpleStandard
...
@@ -85,7 +85,7 @@ public class SimpleStandard
* @param <VAR>s</VAR> the new value of the "State" attribute.
* @param <VAR>s</VAR> the new value of the "State" attribute.
*/
*/
public
void
setState
(
String
s
)
{
public
void
setState
(
String
s
)
{
checkSubject
();
checkSubject
(
"setState"
);
state
=
s
;
state
=
s
;
nbChanges
++;
nbChanges
++;
}
}
...
@@ -97,7 +97,7 @@ public class SimpleStandard
...
@@ -97,7 +97,7 @@ public class SimpleStandard
* @return the current value of the "NbChanges" attribute.
* @return the current value of the "NbChanges" attribute.
*/
*/
public
int
getNbChanges
()
{
public
int
getNbChanges
()
{
checkSubject
();
checkSubject
(
"getNbChanges"
);
return
nbChanges
;
return
nbChanges
;
}
}
...
@@ -106,7 +106,7 @@ public class SimpleStandard
...
@@ -106,7 +106,7 @@ public class SimpleStandard
* attributes of the "SimpleStandard" standard MBean.
* attributes of the "SimpleStandard" standard MBean.
*/
*/
public
void
reset
()
{
public
void
reset
()
{
checkSubject
();
checkSubject
(
"reset"
);
AttributeChangeNotification
acn
=
AttributeChangeNotification
acn
=
new
AttributeChangeNotification
(
this
,
new
AttributeChangeNotification
(
this
,
0
,
0
,
...
@@ -149,18 +149,18 @@ public class SimpleStandard
...
@@ -149,18 +149,18 @@ public class SimpleStandard
* Check that the principal contained in the Subject is of
* Check that the principal contained in the Subject is of
* type JMXPrincipal and refers to the principalName identity.
* type JMXPrincipal and refers to the principalName identity.
*/
*/
private
void
checkSubject
()
{
private
void
checkSubject
(
String
op
)
{
AccessControlContext
acc
=
AccessController
.
getContext
();
AccessControlContext
acc
=
AccessController
.
getContext
();
Subject
subject
=
Subject
.
getSubject
(
acc
);
Subject
subject
=
Subject
.
getSubject
(
acc
);
Set
principals
=
subject
.
getPrincipals
();
Set
principals
=
subject
.
getPrincipals
();
Principal
principal
=
(
Principal
)
principals
.
iterator
().
next
();
Principal
principal
=
(
Principal
)
principals
.
iterator
().
next
();
if
(!(
principal
instanceof
JMXPrincipal
))
if
(!(
principal
instanceof
JMXPrincipal
))
throw
new
SecurityException
(
"
Authenticated subject contains "
+
throw
new
SecurityException
(
op
+
":
Authenticated subject contains "
+
"invalid principal type = "
+
"invalid principal type = "
+
principal
.
getClass
().
getName
());
principal
.
getClass
().
getName
());
String
identity
=
principal
.
getName
();
String
identity
=
principal
.
getName
();
if
(!
identity
.
equals
(
principalName
))
if
(!
identity
.
equals
(
principalName
))
throw
new
SecurityException
(
"
Authenticated subject contains "
+
throw
new
SecurityException
(
op
+
":
Authenticated subject contains "
+
"invalid principal name = "
+
identity
);
"invalid principal name = "
+
identity
);
}
}
...
...
test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6750008
* @summary Test JMX.getSpecificationVersion
* @author Eamonn McManus
*/
import
java.io.IOException
;
import
java.util.Collections
;
import
java.util.ListIterator
;
import
java.util.Set
;
import
javax.management.Attribute
;
import
javax.management.AttributeList
;
import
javax.management.AttributeNotFoundException
;
import
javax.management.DynamicMBean
;
import
javax.management.InstanceNotFoundException
;
import
javax.management.InvalidAttributeValueException
;
import
javax.management.JMX
;
import
javax.management.MBeanException
;
import
javax.management.MBeanInfo
;
import
javax.management.MBeanServer
;
import
javax.management.MBeanServerConnection
;
import
javax.management.MBeanServerDelegate
;
import
javax.management.MBeanServerDelegateMBean
;
import
javax.management.MBeanServerFactory
;
import
javax.management.ObjectName
;
import
javax.management.ReflectionException
;
import
javax.management.StandardMBean
;
import
javax.management.namespace.JMXNamespace
;
import
javax.management.namespace.JMXNamespaces
;
import
javax.management.namespace.MBeanServerSupport
;
import
javax.management.remote.JMXConnector
;
import
javax.management.remote.JMXConnectorFactory
;
import
javax.management.remote.JMXConnectorServer
;
import
javax.management.remote.JMXConnectorServerFactory
;
import
javax.management.remote.JMXServiceURL
;
public
class
JMXSpecVersionTest
{
private
static
String
failure
;
private
static
final
Object
POISON_PILL
=
new
Object
();
private
static
class
FakeDelegate
implements
DynamicMBean
{
private
final
Object
specVersion
;
private
final
DynamicMBean
delegate
=
new
StandardMBean
(
new
MBeanServerDelegate
(),
MBeanServerDelegateMBean
.
class
,
false
);
FakeDelegate
(
Object
specVersion
)
{
this
.
specVersion
=
specVersion
;
}
public
Object
getAttribute
(
String
attribute
)
throws
AttributeNotFoundException
,
MBeanException
,
ReflectionException
{
if
(
"SpecificationVersion"
.
equals
(
attribute
))
{
if
(
specVersion
==
POISON_PILL
)
throw
new
AttributeNotFoundException
(
attribute
);
else
return
specVersion
;
}
else
return
delegate
.
getAttribute
(
attribute
);
}
public
void
setAttribute
(
Attribute
attribute
)
throws
AttributeNotFoundException
,
InvalidAttributeValueException
,
MBeanException
,
ReflectionException
{
delegate
.
setAttribute
(
attribute
);
}
public
AttributeList
getAttributes
(
String
[]
attributes
)
{
AttributeList
list
=
delegate
.
getAttributes
(
attributes
);
for
(
ListIterator
<
Attribute
>
it
=
list
.
asList
().
listIterator
();
it
.
hasNext
();
)
{
Attribute
attr
=
it
.
next
();
if
(
attr
.
getName
().
equals
(
"SpecificationVersion"
))
{
it
.
remove
();
if
(
specVersion
!=
POISON_PILL
)
{
attr
=
new
Attribute
(
attr
.
getName
(),
specVersion
);
it
.
add
(
attr
);
}
}
}
return
list
;
}
public
AttributeList
setAttributes
(
AttributeList
attributes
)
{
return
delegate
.
setAttributes
(
attributes
);
}
public
Object
invoke
(
String
actionName
,
Object
[]
params
,
String
[]
signature
)
throws
MBeanException
,
ReflectionException
{
return
delegate
.
invoke
(
actionName
,
params
,
signature
);
}
public
MBeanInfo
getMBeanInfo
()
{
throw
new
UnsupportedOperationException
(
"Not supported yet."
);
}
}
private
static
class
MBeanServerWithVersion
extends
MBeanServerSupport
{
private
final
DynamicMBean
delegate
;
public
MBeanServerWithVersion
(
Object
specVersion
)
{
this
.
delegate
=
new
FakeDelegate
(
specVersion
);
}
@Override
public
DynamicMBean
getDynamicMBeanFor
(
ObjectName
name
)
throws
InstanceNotFoundException
{
if
(
MBeanServerDelegate
.
DELEGATE_NAME
.
equals
(
name
))
return
delegate
;
else
throw
new
InstanceNotFoundException
(
name
);
}
@Override
protected
Set
<
ObjectName
>
getNames
()
{
return
Collections
.
singleton
(
MBeanServerDelegate
.
DELEGATE_NAME
);
}
}
private
static
class
EmptyMBeanServer
extends
MBeanServerSupport
{
@Override
public
DynamicMBean
getDynamicMBeanFor
(
ObjectName
name
)
throws
InstanceNotFoundException
{
throw
new
InstanceNotFoundException
(
name
);
}
@Override
protected
Set
<
ObjectName
>
getNames
()
{
return
Collections
.
emptySet
();
}
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
MBeanServer
mbs
=
MBeanServerFactory
.
newMBeanServer
();
JMXServiceURL
url
=
new
JMXServiceURL
(
"service:jmx:rmi:///"
);
JMXConnectorServer
cs
=
JMXConnectorServerFactory
.
newJMXConnectorServer
(
url
,
null
,
mbs
);
cs
.
start
();
String
realVersion
=
(
String
)
mbs
.
getAttribute
(
MBeanServerDelegate
.
DELEGATE_NAME
,
"SpecificationVersion"
);
assertEquals
(
"Reported local version"
,
realVersion
,
JMX
.
getSpecificationVersion
(
mbs
,
null
));
assertEquals
(
"Reported local version >= \"2.0\""
,
true
,
(
realVersion
.
compareTo
(
"2.0"
)
>=
0
));
JMXConnector
cc
=
JMXConnectorFactory
.
connect
(
cs
.
getAddress
());
MBeanServerConnection
mbsc
=
cc
.
getMBeanServerConnection
();
assertEquals
(
"Reported remote version"
,
realVersion
,
JMX
.
getSpecificationVersion
(
mbsc
,
null
));
cc
.
close
();
try
{
String
brokenVersion
=
JMX
.
getSpecificationVersion
(
mbsc
,
null
);
fail
(
"JMX.getSpecificationVersion succeded over closed connection"
+
" (returned "
+
brokenVersion
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for closed connection"
,
IOException
.
class
,
e
.
getClass
());
}
try
{
String
brokenVersion
=
JMX
.
getSpecificationVersion
(
new
EmptyMBeanServer
(),
null
);
fail
(
"JMX.getSpecificationVersion succeded with empty MBean Server"
+
" (returned "
+
brokenVersion
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for empty MBean Server"
,
IOException
.
class
,
e
.
getClass
());
}
try
{
String
brokenVersion
=
JMX
.
getSpecificationVersion
(
null
,
null
);
fail
(
"JMX.getSpecificationVersion succeded with null MBean Server"
+
" (returned "
+
brokenVersion
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for null MBean Server"
,
IllegalArgumentException
.
class
,
e
.
getClass
());
}
MBeanServer
mbs1_2
=
new
MBeanServerWithVersion
(
"1.2"
);
String
version1_2
=
JMX
.
getSpecificationVersion
(
mbs1_2
,
null
);
assertEquals
(
"Version for 1.2 MBean Server"
,
"1.2"
,
version1_2
);
// It's completely nutty for an MBean Server to return null as the
// value of its spec version, and we don't actually say what happens
// in that case, but in fact we return the null to the caller.
MBeanServer
mbs_null
=
new
MBeanServerWithVersion
(
null
);
String
version_null
=
JMX
.
getSpecificationVersion
(
mbs_null
,
null
);
assertEquals
(
"Version for MBean Server that declares null spec version"
,
null
,
version_null
);
try
{
MBeanServer
mbs1_2_float
=
new
MBeanServerWithVersion
(
1.2f
);
String
version1_2_float
=
JMX
.
getSpecificationVersion
(
mbs1_2_float
,
null
);
fail
(
"JMX.getSpecificationVersion succeeded with version 1.2f"
+
" (returned "
+
version1_2_float
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for non-string version (1.2f)"
,
IOException
.
class
,
e
.
getClass
());
}
try
{
MBeanServer
mbs_missing
=
new
MBeanServerWithVersion
(
POISON_PILL
);
String
version_missing
=
JMX
.
getSpecificationVersion
(
mbs_missing
,
null
);
fail
(
"JMX.getSpecificationVersion succeeded with null version"
+
" (returned "
+
version_missing
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for missing version"
,
IOException
.
class
,
e
.
getClass
());
}
ObjectName
wildcardNamespaceName
=
new
ObjectName
(
"foo//*//bar//baz:k=v"
);
try
{
String
brokenVersion
=
JMX
.
getSpecificationVersion
(
mbsc
,
wildcardNamespaceName
);
fail
(
"JMX.getSpecificationVersion succeeded with wildcard namespace"
+
" (returned "
+
brokenVersion
+
")"
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for wildcard namespace"
,
IllegalArgumentException
.
class
,
e
.
getClass
());
}
String
sub1_2namespace
=
"blibby"
;
JMXNamespace
sub1_2
=
new
JMXNamespace
(
mbs1_2
);
ObjectName
sub1_2name
=
JMXNamespaces
.
getNamespaceObjectName
(
sub1_2namespace
);
mbs
.
registerMBean
(
sub1_2
,
sub1_2name
);
String
sub1_2namespaceHandlerVersion
=
JMX
.
getSpecificationVersion
(
mbs
,
sub1_2name
);
assertEquals
(
"Spec version of namespace handler"
,
realVersion
,
sub1_2namespaceHandlerVersion
);
// The namespace handler is in the top-level namespace so its
// version should not be 1.2.
for
(
String
nameInSub
:
new
String
[]
{
"*:*"
,
"d:k=v"
})
{
ObjectName
subName
=
new
ObjectName
(
sub1_2namespace
+
"//"
+
nameInSub
);
String
subVersion
=
JMX
.
getSpecificationVersion
(
mbs
,
subName
);
assertEquals
(
"Spec version in 1.2 namespace ("
+
nameInSub
+
")"
,
"1.2"
,
subVersion
);
}
mbs
.
unregisterMBean
(
sub1_2name
);
for
(
String
noSuchNamespace
:
new
String
[]
{
sub1_2namespace
+
"//*:*"
,
sub1_2namespace
+
"//d:k=v"
,
})
{
try
{
String
brokenVersion
=
JMX
.
getSpecificationVersion
(
mbs
,
new
ObjectName
(
noSuchNamespace
));
fail
(
"JMX.getSpecificationVersion succeeded with missing "
+
"namespace ("
+
noSuchNamespace
+
" -> "
+
brokenVersion
);
}
catch
(
Exception
e
)
{
assertEquals
(
"Exception for missing namespace"
,
IOException
.
class
,
e
.
getClass
());
}
}
if
(
failure
!=
null
)
throw
new
Exception
(
"TEST FAILED: "
+
failure
);
System
.
out
.
println
(
"TEST PASSED"
);
}
private
static
void
assertEquals
(
String
what
,
Object
expect
,
Object
actual
)
{
if
(
equal
(
expect
,
actual
))
System
.
out
.
println
(
"OK: "
+
what
+
": "
+
expect
);
else
fail
(
what
+
": expected "
+
expect
+
", got "
+
actual
);
}
private
static
boolean
equal
(
Object
x
,
Object
y
)
{
if
(
x
==
null
)
return
(
y
==
null
);
else
return
x
.
equals
(
y
);
}
private
static
void
fail
(
String
why
)
{
System
.
out
.
println
(
"FAILED: "
+
why
);
failure
=
why
;
}
}
test/sun/security/krb5/auto/Context.java
浏览文件 @
6b491fa1
...
@@ -109,13 +109,22 @@ public class Context {
...
@@ -109,13 +109,22 @@ public class Context {
out
.
s
=
new
Subject
();
out
.
s
=
new
Subject
();
Krb5LoginModule
krb5
=
new
Krb5LoginModule
();
Krb5LoginModule
krb5
=
new
Krb5LoginModule
();
Map
<
String
,
String
>
map
=
new
HashMap
<
String
,
String
>();
Map
<
String
,
String
>
map
=
new
HashMap
<
String
,
String
>();
map
.
put
(
"tryFirstPass"
,
"true"
);
if
(
storeKey
)
{
map
.
put
(
"storeKey"
,
"true"
);
}
Map
<
String
,
Object
>
shared
=
new
HashMap
<
String
,
Object
>();
Map
<
String
,
Object
>
shared
=
new
HashMap
<
String
,
Object
>();
if
(
pass
!=
null
)
{
map
.
put
(
"useFirstPass"
,
"true"
);
shared
.
put
(
"javax.security.auth.login.name"
,
user
);
shared
.
put
(
"javax.security.auth.login.name"
,
user
);
shared
.
put
(
"javax.security.auth.login.password"
,
pass
);
shared
.
put
(
"javax.security.auth.login.password"
,
pass
);
}
else
{
map
.
put
(
"doNotPrompt"
,
"true"
);
map
.
put
(
"useTicketCache"
,
"true"
);
if
(
user
!=
null
)
{
map
.
put
(
"principal"
,
user
);
}
}
if
(
storeKey
)
{
map
.
put
(
"storeKey"
,
"true"
);
}
krb5
.
initialize
(
out
.
s
,
null
,
shared
,
map
);
krb5
.
initialize
(
out
.
s
,
null
,
shared
,
map
);
krb5
.
login
();
krb5
.
login
();
...
@@ -360,6 +369,10 @@ public class Context {
...
@@ -360,6 +369,10 @@ public class Context {
if
(
me
.
x
.
isEstablished
())
{
if
(
me
.
x
.
isEstablished
())
{
me
.
f
=
true
;
me
.
f
=
true
;
System
.
out
.
println
(
c
.
name
+
" side established"
);
System
.
out
.
println
(
c
.
name
+
" side established"
);
if
(
input
!=
null
)
{
throw
new
Exception
(
"Context established but "
+
"still receive token at "
+
c
.
name
);
}
return
null
;
return
null
;
}
else
{
}
else
{
System
.
out
.
println
(
c
.
name
+
" call initSecContext"
);
System
.
out
.
println
(
c
.
name
+
" call initSecContext"
);
...
@@ -374,6 +387,10 @@ public class Context {
...
@@ -374,6 +387,10 @@ public class Context {
if
(
me
.
x
.
isEstablished
())
{
if
(
me
.
x
.
isEstablished
())
{
me
.
f
=
true
;
me
.
f
=
true
;
System
.
out
.
println
(
s
.
name
+
" side established"
);
System
.
out
.
println
(
s
.
name
+
" side established"
);
if
(
input
!=
null
)
{
throw
new
Exception
(
"Context established but "
+
"still receive token at "
+
s
.
name
);
}
return
null
;
return
null
;
}
else
{
}
else
{
System
.
out
.
println
(
s
.
name
+
" called acceptSecContext"
);
System
.
out
.
println
(
s
.
name
+
" called acceptSecContext"
);
...
...
test/sun/security/krb5/auto/KDC.java
浏览文件 @
6b491fa1
...
@@ -32,6 +32,7 @@ import java.util.*;
...
@@ -32,6 +32,7 @@ import java.util.*;
import
java.util.concurrent.*
;
import
java.util.concurrent.*
;
import
sun.security.krb5.*
;
import
sun.security.krb5.*
;
import
sun.security.krb5.internal.*
;
import
sun.security.krb5.internal.*
;
import
sun.security.krb5.internal.ccache.CredentialsCache
;
import
sun.security.krb5.internal.crypto.KeyUsage
;
import
sun.security.krb5.internal.crypto.KeyUsage
;
import
sun.security.krb5.internal.ktab.KeyTab
;
import
sun.security.krb5.internal.ktab.KeyTab
;
import
sun.security.util.DerInputStream
;
import
sun.security.util.DerInputStream
;
...
@@ -765,7 +766,29 @@ public class KDC {
...
@@ -765,7 +766,29 @@ public class KDC {
DerOutputStream
out
=
new
DerOutputStream
();
DerOutputStream
out
=
new
DerOutputStream
();
out
.
write
(
DerValue
.
createTag
(
DerValue
.
TAG_APPLICATION
,
out
.
write
(
DerValue
.
createTag
(
DerValue
.
TAG_APPLICATION
,
true
,
(
byte
)
Krb5
.
KRB_AS_REP
),
asRep
.
asn1Encode
());
true
,
(
byte
)
Krb5
.
KRB_AS_REP
),
asRep
.
asn1Encode
());
return
out
.
toByteArray
();
byte
[]
result
=
out
.
toByteArray
();
// Added feature:
// Write the current issuing TGT into a ccache file specified
// by the system property below.
String
ccache
=
System
.
getProperty
(
"test.kdc.save.ccache"
);
if
(
ccache
!=
null
)
{
asRep
.
encKDCRepPart
=
enc_part
;
sun
.
security
.
krb5
.
internal
.
ccache
.
Credentials
credentials
=
new
sun
.
security
.
krb5
.
internal
.
ccache
.
Credentials
(
asRep
);
asReq
.
reqBody
.
cname
.
setRealm
(
getRealm
());
CredentialsCache
cache
=
CredentialsCache
.
create
(
asReq
.
reqBody
.
cname
,
ccache
);
if
(
cache
==
null
)
{
throw
new
IOException
(
"Unable to create the cache file "
+
ccache
);
}
cache
.
update
(
credentials
);
cache
.
save
();
new
File
(
ccache
).
deleteOnExit
();
}
return
result
;
}
catch
(
KrbException
ke
)
{
}
catch
(
KrbException
ke
)
{
ke
.
printStackTrace
(
System
.
out
);
ke
.
printStackTrace
(
System
.
out
);
KRBError
kerr
=
ke
.
getError
();
KRBError
kerr
=
ke
.
getError
();
...
...
test/sun/security/krb5/auto/LoginModuleOptions.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6765491
* @summary Krb5LoginModule a little too restrictive, and the doc is not clear.
*/
import
com.sun.security.auth.module.Krb5LoginModule
;
import
java.io.IOException
;
import
java.util.HashMap
;
import
java.util.Map
;
import
javax.security.auth.Subject
;
import
javax.security.auth.callback.Callback
;
import
javax.security.auth.callback.CallbackHandler
;
import
javax.security.auth.callback.NameCallback
;
import
javax.security.auth.callback.PasswordCallback
;
import
javax.security.auth.callback.UnsupportedCallbackException
;
public
class
LoginModuleOptions
{
private
static
final
String
NAME
=
"javax.security.auth.login.name"
;
private
static
final
String
PWD
=
"javax.security.auth.login.password"
;
public
static
void
main
(
String
[]
args
)
throws
Exception
{
OneKDC
kdc
=
new
OneKDC
(
null
);
kdc
.
addPrincipal
(
"foo"
,
"bar"
.
toCharArray
());
kdc
.
writeKtab
(
OneKDC
.
KTAB
);
// rewrite to add foo
// All 4 works: keytab, shared state, callback, cache
login
(
null
,
"useKeyTab"
,
"true"
,
"principal"
,
"dummy"
);
login
(
null
,
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
OneKDC
.
PASS
);
System
.
setProperty
(
"test.kdc.save.ccache"
,
"krbcc"
);
login
(
new
MyCallback
(
OneKDC
.
USER
,
OneKDC
.
PASS
));
// save the cache
System
.
clearProperty
(
"test.kdc.save.ccache"
);
login
(
null
,
"useTicketCache"
,
"true"
,
"ticketCache"
,
"krbcc"
);
// Fallbacks
// 1. ccache -> keytab
login
(
null
,
"useTicketCache"
,
"true"
,
"ticketCache"
,
"krbcc_non_exists"
,
"useKeyTab"
,
"true"
,
"principal"
,
"dummy"
);
// 2. keytab -> shared
login
(
null
,
"useKeyTab"
,
"true"
,
"principal"
,
"dummy"
,
"keyTab"
,
"ktab_non_exist"
,
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
OneKDC
.
PASS
);
// 3. shared -> callback
// 3.1. useFirstPass, no callback
boolean
failed
=
false
;
try
{
login
(
new
MyCallback
(
OneKDC
.
USER
,
OneKDC
.
PASS
),
"useFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
"haha"
.
toCharArray
());
}
catch
(
Exception
e
)
{
failed
=
true
;
}
if
(!
failed
)
{
throw
new
Exception
(
"useFirstPass should not fallback to callback"
);
}
// 3.2. tryFirstPass, has callback
login
(
new
MyCallback
(
OneKDC
.
USER
,
OneKDC
.
PASS
),
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
"haha"
.
toCharArray
());
// Preferences of type
// 1. ccache preferred to keytab
login
(
new
MyCallback
(
"foo"
,
null
),
"useTicketCache"
,
"true"
,
"ticketCache"
,
"krbcc"
,
"useKeyTab"
,
"true"
);
// 2. keytab preferred to shared. This test case is not exactly correct,
// because principal=dummy would shadow the PWD setting in the shared
// state. So by only looking at the final authentication user name
// (which is how this program does), there's no way to tell if keyTab
// is picked first, or shared is tried first but fallback to keytab.
login
(
null
,
"useKeyTab"
,
"true"
,
"principal"
,
"dummy"
,
"tryFirstPass"
,
"true"
,
NAME
,
"foo"
,
PWD
,
"bar"
.
toCharArray
());
// 3. shared preferred to callback
login
(
new
MyCallback
(
"foo"
,
"bar"
.
toCharArray
()),
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
OneKDC
.
PASS
);
// Preferences of username
// 1. principal preferred to NAME (NAME can be wrong or missing)
login
(
null
,
"principal"
,
OneKDC
.
USER
,
"tryFirstPass"
,
"true"
,
NAME
,
"someone_else"
,
PWD
,
OneKDC
.
PASS
);
login
(
null
,
"principal"
,
OneKDC
.
USER
,
"tryFirstPass"
,
"true"
,
PWD
,
OneKDC
.
PASS
);
// 2. NAME preferred to callback
login
(
new
MyCallback
(
"someone_else"
,
OneKDC
.
PASS
),
"principal"
,
OneKDC
.
USER
);
// 3. With tryFirstPass, NAME preferred to callback
login
(
new
MyCallback
(
"someone_else"
,
null
),
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
OneKDC
.
PASS
);
// 3.1. you must provide a NAME (when there's no principal)
failed
=
false
;
try
{
login
(
new
MyCallback
(
OneKDC
.
USER
,
null
),
"tryFirstPass"
,
"true"
,
PWD
,
OneKDC
.
PASS
);
}
catch
(
Exception
e
)
{
failed
=
true
;
}
if
(!
failed
)
{
throw
new
Exception
(
"useFirstPass must provide a NAME"
);
}
// 3.2 Hybrid, you can use NAME as "", and provide it using callback.
// I don't think this is designed.
login
(
new
MyCallback
(
OneKDC
.
USER
,
null
),
"tryFirstPass"
,
"true"
,
NAME
,
""
,
PWD
,
OneKDC
.
PASS
);
// Test for the bug fix: doNotPrompt can be true if tryFirstPass=true
login
(
null
,
"doNotPrompt"
,
"true"
,
"storeKey"
,
"true"
,
"tryFirstPass"
,
"true"
,
NAME
,
OneKDC
.
USER
,
PWD
,
OneKDC
.
PASS
);
}
static
void
login
(
CallbackHandler
callback
,
Object
...
options
)
throws
Exception
{
Krb5LoginModule
krb5
=
new
Krb5LoginModule
();
Subject
subject
=
new
Subject
();
Map
<
String
,
String
>
map
=
new
HashMap
<
String
,
String
>();
Map
<
String
,
Object
>
shared
=
new
HashMap
<
String
,
Object
>();
int
count
=
options
.
length
/
2
;
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
String
key
=
(
String
)
options
[
2
*
i
];
Object
value
=
options
[
2
*
i
+
1
];
if
(
key
.
startsWith
(
"javax"
))
{
shared
.
put
(
key
,
value
);
}
else
{
map
.
put
(
key
,
(
String
)
value
);
}
}
krb5
.
initialize
(
subject
,
callback
,
shared
,
map
);
krb5
.
login
();
krb5
.
commit
();
if
(!
subject
.
getPrincipals
().
iterator
().
next
()
.
getName
().
startsWith
(
OneKDC
.
USER
))
{
throw
new
Exception
(
"The authenticated is not "
+
OneKDC
.
USER
);
}
}
static
class
MyCallback
implements
CallbackHandler
{
private
String
name
;
private
char
[]
password
;
public
MyCallback
(
String
name
,
char
[]
password
)
{
this
.
name
=
name
;
this
.
password
=
password
;
}
public
void
handle
(
Callback
[]
callbacks
)
{
for
(
Callback
callback
:
callbacks
)
{
System
.
err
.
println
(
callback
);
if
(
callback
instanceof
NameCallback
)
{
System
.
err
.
println
(
"name is "
+
name
);
((
NameCallback
)
callback
).
setName
(
name
);
}
if
(
callback
instanceof
PasswordCallback
)
{
System
.
err
.
println
(
"pass is "
+
new
String
(
password
));
((
PasswordCallback
)
callback
).
setPassword
(
password
);
}
}
}
}
}
test/sun/security/krb5/auto/NonMutualSpnego.java
0 → 100644
浏览文件 @
6b491fa1
/*
* Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6733095
* @summary Failure when SPNEGO request non-Mutual
*/
import
sun.security.jgss.GSSUtil
;
public
class
NonMutualSpnego
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
// Create and start the KDC
new
OneKDC
(
null
).
writeJAASConf
();
new
NonMutualSpnego
().
go
();
}
void
go
()
throws
Exception
{
Context
c
=
Context
.
fromJAAS
(
"client"
);
Context
s
=
Context
.
fromJAAS
(
"server"
);
c
.
startAsClient
(
OneKDC
.
SERVER
,
GSSUtil
.
GSS_SPNEGO_MECH_OID
);
c
.
x
().
requestMutualAuth
(
false
);
s
.
startAsServer
(
GSSUtil
.
GSS_SPNEGO_MECH_OID
);
Context
.
handshake
(
c
,
s
);
Context
.
transmit
(
"i say high --"
,
c
,
s
);
Context
.
transmit
(
" you say low"
,
s
,
c
);
c
.
dispose
();
s
.
dispose
();
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录