mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-23 04:24:49 +02:00
6747899: jmx namespaces: hooks for permission checks should be defined in HandlerInterceptor
Reviewed-by: emcmanus
This commit is contained in:
parent
a1e4e3ec94
commit
38e8cbedc6
2 changed files with 174 additions and 151 deletions
|
@ -135,7 +135,11 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public AttributeList getAttributes(ObjectName name, String[] attributes)
|
public AttributeList getAttributes(ObjectName name, String[] attributes)
|
||||||
throws InstanceNotFoundException, ReflectionException {
|
throws InstanceNotFoundException, ReflectionException {
|
||||||
try {
|
try {
|
||||||
return super.getAttributes(name, attributes);
|
final String[] authorized =
|
||||||
|
checkAttributes(name,attributes,"getAttribute");
|
||||||
|
final AttributeList attrList =
|
||||||
|
super.getAttributes(name,authorized);
|
||||||
|
return attrList;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"getAttributes",name,attributes);
|
throw handleIOException(ex,"getAttributes",name,attributes);
|
||||||
}
|
}
|
||||||
|
@ -185,7 +189,8 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public void removeNotificationListener(ObjectName name, ObjectName listener)
|
public void removeNotificationListener(ObjectName name, ObjectName listener)
|
||||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||||
try {
|
try {
|
||||||
super.removeNotificationListener(name, listener);
|
check(name,null,"removeNotificationListener");
|
||||||
|
super.removeNotificationListener(name,listener);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"removeNotificationListener",name,listener);
|
throw handleIOException(ex,"removeNotificationListener",name,listener);
|
||||||
}
|
}
|
||||||
|
@ -205,7 +210,9 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
@Override
|
@Override
|
||||||
public String[] getDomains() {
|
public String[] getDomains() {
|
||||||
try {
|
try {
|
||||||
return super.getDomains();
|
check(null,null,"getDomains");
|
||||||
|
final String[] domains = super.getDomains();
|
||||||
|
return checkDomains(domains,"getDomains");
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"getDomains");
|
throw handleIOException(ex,"getDomains");
|
||||||
}
|
}
|
||||||
|
@ -228,7 +235,10 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
InvalidAttributeValueException, MBeanException,
|
InvalidAttributeValueException, MBeanException,
|
||||||
ReflectionException {
|
ReflectionException {
|
||||||
try {
|
try {
|
||||||
super.setAttribute(name, attribute);
|
check(name,
|
||||||
|
(attribute==null?null:attribute.getName()),
|
||||||
|
"setAttribute");
|
||||||
|
super.setAttribute(name,attribute);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"setAttribute",name, attribute);
|
throw handleIOException(ex,"setAttribute",name, attribute);
|
||||||
}
|
}
|
||||||
|
@ -237,8 +247,10 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
// From MBeanServerConnection: catch & handles IOException
|
// From MBeanServerConnection: catch & handles IOException
|
||||||
@Override
|
@Override
|
||||||
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
|
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
|
||||||
|
if (name == null) name=ObjectName.WILDCARD;
|
||||||
try {
|
try {
|
||||||
return super.queryNames(name, query);
|
checkPattern(name,null,"queryNames");
|
||||||
|
return super.queryNames(name,query);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"queryNames",name, query);
|
throw handleIOException(ex,"queryNames",name, query);
|
||||||
}
|
}
|
||||||
|
@ -247,8 +259,10 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
// From MBeanServerConnection: catch & handles IOException
|
// From MBeanServerConnection: catch & handles IOException
|
||||||
@Override
|
@Override
|
||||||
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
|
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
|
||||||
|
if (name == null) name=ObjectName.WILDCARD;
|
||||||
try {
|
try {
|
||||||
return super.queryMBeans(name, query);
|
checkPattern(name,null,"queryMBeans");
|
||||||
|
return super.queryMBeans(name,query);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"queryMBeans",name, query);
|
throw handleIOException(ex,"queryMBeans",name, query);
|
||||||
}
|
}
|
||||||
|
@ -259,6 +273,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public boolean isInstanceOf(ObjectName name, String className)
|
public boolean isInstanceOf(ObjectName name, String className)
|
||||||
throws InstanceNotFoundException {
|
throws InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name, null, "isInstanceOf");
|
||||||
return super.isInstanceOf(name, className);
|
return super.isInstanceOf(name, className);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"isInstanceOf",name, className);
|
throw handleIOException(ex,"isInstanceOf",name, className);
|
||||||
|
@ -272,6 +287,8 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
MBeanRegistrationException, MBeanException,
|
MBeanRegistrationException, MBeanException,
|
||||||
NotCompliantMBeanException {
|
NotCompliantMBeanException {
|
||||||
try {
|
try {
|
||||||
|
checkCreate(name, className, "instantiate");
|
||||||
|
checkCreate(name, className, "registerMBean");
|
||||||
return super.createMBean(className, name);
|
return super.createMBean(className, name);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"createMBean",className, name);
|
throw handleIOException(ex,"createMBean",className, name);
|
||||||
|
@ -286,6 +303,8 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
MBeanRegistrationException, MBeanException,
|
MBeanRegistrationException, MBeanException,
|
||||||
NotCompliantMBeanException, InstanceNotFoundException {
|
NotCompliantMBeanException, InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
checkCreate(name, className, "instantiate");
|
||||||
|
checkCreate(name, className, "registerMBean");
|
||||||
return super.createMBean(className, name, loaderName);
|
return super.createMBean(className, name, loaderName);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"createMBean",className, name, loaderName);
|
throw handleIOException(ex,"createMBean",className, name, loaderName);
|
||||||
|
@ -298,6 +317,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
throws MBeanException, AttributeNotFoundException,
|
throws MBeanException, AttributeNotFoundException,
|
||||||
InstanceNotFoundException, ReflectionException {
|
InstanceNotFoundException, ReflectionException {
|
||||||
try {
|
try {
|
||||||
|
check(name, attribute, "getAttribute");
|
||||||
return super.getAttribute(name, attribute);
|
return super.getAttribute(name, attribute);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"getAttribute",name, attribute);
|
throw handleIOException(ex,"getAttribute",name, attribute);
|
||||||
|
@ -310,6 +330,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
NotificationFilter filter, Object handback)
|
NotificationFilter filter, Object handback)
|
||||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name,null,"removeNotificationListener");
|
||||||
super.removeNotificationListener(name, listener, filter, handback);
|
super.removeNotificationListener(name, listener, filter, handback);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"removeNotificationListener",name,
|
throw handleIOException(ex,"removeNotificationListener",name,
|
||||||
|
@ -324,6 +345,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
Object handback)
|
Object handback)
|
||||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name,null,"removeNotificationListener");
|
||||||
super.removeNotificationListener(name, listener, filter, handback);
|
super.removeNotificationListener(name, listener, filter, handback);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"removeNotificationListener",name,
|
throw handleIOException(ex,"removeNotificationListener",name,
|
||||||
|
@ -337,6 +359,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
NotificationListener listener)
|
NotificationListener listener)
|
||||||
throws InstanceNotFoundException, ListenerNotFoundException {
|
throws InstanceNotFoundException, ListenerNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name,null,"removeNotificationListener");
|
||||||
super.removeNotificationListener(name, listener);
|
super.removeNotificationListener(name, listener);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"removeNotificationListener",name,
|
throw handleIOException(ex,"removeNotificationListener",name,
|
||||||
|
@ -350,6 +373,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
NotificationListener listener, NotificationFilter filter,
|
NotificationListener listener, NotificationFilter filter,
|
||||||
Object handback) throws InstanceNotFoundException {
|
Object handback) throws InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name,null,"addNotificationListener");
|
||||||
super.addNotificationListener(name, listener, filter, handback);
|
super.addNotificationListener(name, listener, filter, handback);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"addNotificationListener",name,
|
throw handleIOException(ex,"addNotificationListener",name,
|
||||||
|
@ -363,6 +387,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
NotificationFilter filter, Object handback)
|
NotificationFilter filter, Object handback)
|
||||||
throws InstanceNotFoundException {
|
throws InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name,null,"addNotificationListener");
|
||||||
super.addNotificationListener(name, listener, filter, handback);
|
super.addNotificationListener(name, listener, filter, handback);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"addNotificationListener",name,
|
throw handleIOException(ex,"addNotificationListener",name,
|
||||||
|
@ -385,6 +410,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public void unregisterMBean(ObjectName name)
|
public void unregisterMBean(ObjectName name)
|
||||||
throws InstanceNotFoundException, MBeanRegistrationException {
|
throws InstanceNotFoundException, MBeanRegistrationException {
|
||||||
try {
|
try {
|
||||||
|
check(name, null, "unregisterMBean");
|
||||||
super.unregisterMBean(name);
|
super.unregisterMBean(name);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"unregisterMBean",name);
|
throw handleIOException(ex,"unregisterMBean",name);
|
||||||
|
@ -397,6 +423,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
throws InstanceNotFoundException, IntrospectionException,
|
throws InstanceNotFoundException, IntrospectionException,
|
||||||
ReflectionException {
|
ReflectionException {
|
||||||
try {
|
try {
|
||||||
|
check(name, null, "getMBeanInfo");
|
||||||
return super.getMBeanInfo(name);
|
return super.getMBeanInfo(name);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"getMBeanInfo",name);
|
throw handleIOException(ex,"getMBeanInfo",name);
|
||||||
|
@ -408,6 +435,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public ObjectInstance getObjectInstance(ObjectName name)
|
public ObjectInstance getObjectInstance(ObjectName name)
|
||||||
throws InstanceNotFoundException {
|
throws InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
check(name, null, "getObjectInstance");
|
||||||
return super.getObjectInstance(name);
|
return super.getObjectInstance(name);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"getObjectInstance",name);
|
throw handleIOException(ex,"getObjectInstance",name);
|
||||||
|
@ -422,6 +450,8 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
MBeanRegistrationException, MBeanException,
|
MBeanRegistrationException, MBeanException,
|
||||||
NotCompliantMBeanException {
|
NotCompliantMBeanException {
|
||||||
try {
|
try {
|
||||||
|
checkCreate(name, className, "instantiate");
|
||||||
|
checkCreate(name, className, "registerMBean");
|
||||||
return super.createMBean(className, name, params, signature);
|
return super.createMBean(className, name, params, signature);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"createMBean",className, name,
|
throw handleIOException(ex,"createMBean",className, name,
|
||||||
|
@ -437,6 +467,8 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
MBeanRegistrationException, MBeanException,
|
MBeanRegistrationException, MBeanException,
|
||||||
NotCompliantMBeanException, InstanceNotFoundException {
|
NotCompliantMBeanException, InstanceNotFoundException {
|
||||||
try {
|
try {
|
||||||
|
checkCreate(name, className, "instantiate");
|
||||||
|
checkCreate(name, className, "registerMBean");
|
||||||
return super.createMBean(className, name, loaderName, params,
|
return super.createMBean(className, name, loaderName, params,
|
||||||
signature);
|
signature);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
|
@ -450,7 +482,9 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
public AttributeList setAttributes(ObjectName name,AttributeList attributes)
|
public AttributeList setAttributes(ObjectName name,AttributeList attributes)
|
||||||
throws InstanceNotFoundException, ReflectionException {
|
throws InstanceNotFoundException, ReflectionException {
|
||||||
try {
|
try {
|
||||||
return super.setAttributes(name, attributes);
|
final AttributeList authorized =
|
||||||
|
checkAttributes(name, attributes, "setAttribute");
|
||||||
|
return super.setAttributes(name, authorized);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"setAttributes",name, attributes);
|
throw handleIOException(ex,"setAttributes",name, attributes);
|
||||||
}
|
}
|
||||||
|
@ -462,6 +496,7 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
String[] signature)
|
String[] signature)
|
||||||
throws InstanceNotFoundException, MBeanException, ReflectionException {
|
throws InstanceNotFoundException, MBeanException, ReflectionException {
|
||||||
try {
|
try {
|
||||||
|
check(name, operationName, "invoke");
|
||||||
return super.invoke(name, operationName, params, signature);
|
return super.invoke(name, operationName, params, signature);
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
throw handleIOException(ex,"invoke",name, operationName,
|
throw handleIOException(ex,"invoke",name, operationName,
|
||||||
|
@ -582,4 +617,118 @@ public abstract class HandlerInterceptor<T extends JMXNamespace>
|
||||||
"Not supported in this namespace: "+namespace));
|
"Not supported in this namespace: "+namespace));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A result might be excluded for security reasons.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
boolean excludesFromResult(ObjectName targetName, String queryMethod) {
|
||||||
|
return !checkQuery(targetName, queryMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// Hooks for checking permissions
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is a hook to implement permission checking in subclasses.
|
||||||
|
* A subclass may override this method and throw a {@link
|
||||||
|
* SecurityException} if the permission is denied.
|
||||||
|
*
|
||||||
|
* @param routingName The name of the MBean in the enclosing context.
|
||||||
|
* This is of the form {@code <namespace>//<ObjectName>}.
|
||||||
|
* @param member The {@link
|
||||||
|
* javax.management.namespace.JMXNamespacePermission#getMember member}
|
||||||
|
* name.
|
||||||
|
* @param action The {@link
|
||||||
|
* javax.management.namespace.JMXNamespacePermission#getActions action}
|
||||||
|
* name.
|
||||||
|
* @throws SecurityException if the caller doesn't have the permission
|
||||||
|
* to perform the given action on the MBean pointed to
|
||||||
|
* by routingName.
|
||||||
|
*/
|
||||||
|
abstract void check(ObjectName routingName,
|
||||||
|
String member, String action);
|
||||||
|
|
||||||
|
// called in createMBean and registerMBean
|
||||||
|
abstract void checkCreate(ObjectName routingName, String className,
|
||||||
|
String action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a hook to implement permission checking in subclasses.
|
||||||
|
*
|
||||||
|
* Checks that the caller has sufficient permission for returning
|
||||||
|
* information about {@code sourceName} in {@code action}.
|
||||||
|
*
|
||||||
|
* Subclass may override this method and return false if the caller
|
||||||
|
* doesn't have sufficient permissions.
|
||||||
|
*
|
||||||
|
* @param routingName The name of the MBean to include or exclude from
|
||||||
|
* the query, expressed in the enclosing context.
|
||||||
|
* This is of the form {@code <namespace>//<ObjectName>}.
|
||||||
|
* @param action one of "queryNames" or "queryMBeans"
|
||||||
|
* @return true if {@code sourceName} can be returned.
|
||||||
|
*/
|
||||||
|
abstract boolean checkQuery(ObjectName routingName, String action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is a hook to implement permission checking in subclasses.
|
||||||
|
*
|
||||||
|
* @param routingName The name of the MBean in the enclosing context.
|
||||||
|
* This is of the form {@code <namespace>//<ObjectName>}.
|
||||||
|
* @param attributes The list of attributes to check permission for.
|
||||||
|
* @param action one of "getAttribute" or "setAttribute"
|
||||||
|
* @return The list of attributes for which the callers has the
|
||||||
|
* appropriate {@link
|
||||||
|
* javax.management.namespace.JMXNamespacePermission}.
|
||||||
|
* @throws SecurityException if the caller doesn't have the permission
|
||||||
|
* to perform {@code action} on the MBean pointed to by routingName.
|
||||||
|
*/
|
||||||
|
abstract String[] checkAttributes(ObjectName routingName,
|
||||||
|
String[] attributes, String action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is a hook to implement permission checking in subclasses.
|
||||||
|
*
|
||||||
|
* @param routingName The name of the MBean in the enclosing context.
|
||||||
|
* This is of the form {@code <namespace>//<ObjectName>}.
|
||||||
|
* @param attributes The list of attributes to check permission for.
|
||||||
|
* @param action one of "getAttribute" or "setAttribute"
|
||||||
|
* @return The list of attributes for which the callers has the
|
||||||
|
* appropriate {@link
|
||||||
|
* javax.management.namespace.JMXNamespacePermission}.
|
||||||
|
* @throws SecurityException if the caller doesn't have the permission
|
||||||
|
* to perform {@code action} on the MBean pointed to by routingName.
|
||||||
|
*/
|
||||||
|
abstract AttributeList checkAttributes(ObjectName routingName,
|
||||||
|
AttributeList attributes, String action);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is a hook to implement permission checking in subclasses.
|
||||||
|
* Checks that the caller as the necessary permissions to view the
|
||||||
|
* given domain. If not remove the domains for which the caller doesn't
|
||||||
|
* have permission from the list.
|
||||||
|
* <p>
|
||||||
|
* By default, this method always returns {@code domains}
|
||||||
|
*
|
||||||
|
* @param domains The domains to return.
|
||||||
|
* @param action "getDomains"
|
||||||
|
* @return a filtered list of domains.
|
||||||
|
*/
|
||||||
|
String[] checkDomains(String[] domains, String action) {
|
||||||
|
return domains;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A priori check for queryNames/queryMBeans/
|
||||||
|
void checkPattern(ObjectName routingPattern,
|
||||||
|
String member, String action) {
|
||||||
|
// pattern is checked only at posteriori by checkQuery.
|
||||||
|
// checking it a priori usually doesn't work, because ObjectName.apply
|
||||||
|
// does not work between two patterns.
|
||||||
|
// We only check that we have the permission requested for 'action'.
|
||||||
|
check(null,null,action);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,11 +161,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
throws InstanceNotFoundException, ReflectionException, IOException {
|
throws InstanceNotFoundException, ReflectionException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
final String[] authorized =
|
return source().getAttributes(sourceName, attributes);
|
||||||
checkAttributes(name,attributes,"getAttribute");
|
|
||||||
final AttributeList attrList =
|
|
||||||
source().getAttributes(sourceName,authorized);
|
|
||||||
return attrList;
|
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
@ -178,7 +174,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
IOException {
|
IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, operationName, "invoke");
|
|
||||||
final Object result =
|
final Object result =
|
||||||
source().invoke(sourceName,operationName,params,
|
source().invoke(sourceName,operationName,params,
|
||||||
signature);
|
signature);
|
||||||
|
@ -194,7 +189,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
IOException {
|
IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, null, "unregisterMBean");
|
|
||||||
source().unregisterMBean(sourceName);
|
source().unregisterMBean(sourceName);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -207,7 +201,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
ReflectionException, IOException {
|
ReflectionException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, null, "getMBeanInfo");
|
|
||||||
return source().getMBeanInfo(sourceName);
|
return source().getMBeanInfo(sourceName);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -219,7 +212,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
throws InstanceNotFoundException, IOException {
|
throws InstanceNotFoundException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, null, "getObjectInstance");
|
|
||||||
return processOutputInstance(
|
return processOutputInstance(
|
||||||
source().getObjectInstance(sourceName));
|
source().getObjectInstance(sourceName));
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -246,9 +238,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
ReflectionException, IOException {
|
ReflectionException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name,
|
|
||||||
(attribute==null?null:attribute.getName()),
|
|
||||||
"setAttribute");
|
|
||||||
source().setAttribute(sourceName,attribute);
|
source().setAttribute(sourceName,attribute);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -266,8 +255,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
// Loader Name is already a sourceLoaderName.
|
// Loader Name is already a sourceLoaderName.
|
||||||
final ObjectName sourceLoaderName = loaderName;
|
final ObjectName sourceLoaderName = loaderName;
|
||||||
try {
|
try {
|
||||||
checkCreate(name, className, "instantiate");
|
|
||||||
checkCreate(name, className, "registerMBean");
|
|
||||||
final ObjectInstance instance =
|
final ObjectInstance instance =
|
||||||
source().createMBean(className,sourceName,
|
source().createMBean(className,sourceName,
|
||||||
sourceLoaderName,
|
sourceLoaderName,
|
||||||
|
@ -286,8 +273,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
NotCompliantMBeanException, IOException {
|
NotCompliantMBeanException, IOException {
|
||||||
final ObjectName sourceName = newSourceMBeanName(name);
|
final ObjectName sourceName = newSourceMBeanName(name);
|
||||||
try {
|
try {
|
||||||
checkCreate(name, className, "instantiate");
|
|
||||||
checkCreate(name, className, "registerMBean");
|
|
||||||
return processOutputInstance(source().createMBean(className,
|
return processOutputInstance(source().createMBean(className,
|
||||||
sourceName,params,signature));
|
sourceName,params,signature));
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -305,8 +290,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
// Loader Name is already a source Loader Name.
|
// Loader Name is already a source Loader Name.
|
||||||
final ObjectName sourceLoaderName = loaderName;
|
final ObjectName sourceLoaderName = loaderName;
|
||||||
try {
|
try {
|
||||||
checkCreate(name, className, "instantiate");
|
|
||||||
checkCreate(name, className, "registerMBean");
|
|
||||||
return processOutputInstance(source().createMBean(className,
|
return processOutputInstance(source().createMBean(className,
|
||||||
sourceName,sourceLoaderName));
|
sourceName,sourceLoaderName));
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -321,8 +304,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
NotCompliantMBeanException, IOException {
|
NotCompliantMBeanException, IOException {
|
||||||
final ObjectName sourceName = newSourceMBeanName(name);
|
final ObjectName sourceName = newSourceMBeanName(name);
|
||||||
try {
|
try {
|
||||||
checkCreate(name, className, "instantiate");
|
|
||||||
checkCreate(name, className, "registerMBean");
|
|
||||||
return processOutputInstance(source().
|
return processOutputInstance(source().
|
||||||
createMBean(className,sourceName));
|
createMBean(className,sourceName));
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -336,7 +317,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
InstanceNotFoundException, ReflectionException, IOException {
|
InstanceNotFoundException, ReflectionException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, attribute, "getAttribute");
|
|
||||||
return source().getAttribute(sourceName,attribute);
|
return source().getAttribute(sourceName,attribute);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -348,7 +328,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
throws InstanceNotFoundException, IOException {
|
throws InstanceNotFoundException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name, null, "isInstanceOf");
|
|
||||||
return source().isInstanceOf(sourceName,className);
|
return source().isInstanceOf(sourceName,className);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -360,10 +339,8 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
throws InstanceNotFoundException, ReflectionException, IOException {
|
throws InstanceNotFoundException, ReflectionException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
final AttributeList authorized =
|
|
||||||
checkAttributes(name, attributes, "setAttribute");
|
|
||||||
return source().
|
return source().
|
||||||
setAttributes(sourceName,authorized);
|
setAttributes(sourceName,attributes);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
@ -376,7 +353,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
for (ObjectInstance i : sources) {
|
for (ObjectInstance i : sources) {
|
||||||
try {
|
try {
|
||||||
final ObjectInstance target = processOutputInstance(i);
|
final ObjectInstance target = processOutputInstance(i);
|
||||||
if (!checkQuery(target.getObjectName(), "queryMBeans"))
|
if (excludesFromResult(target.getObjectName(), "queryMBeans"))
|
||||||
continue;
|
continue;
|
||||||
result.add(target);
|
result.add(target);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
|
@ -415,7 +392,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
for (ObjectName n : sourceNames) {
|
for (ObjectName n : sourceNames) {
|
||||||
try {
|
try {
|
||||||
final ObjectName targetName = toTarget(n);
|
final ObjectName targetName = toTarget(n);
|
||||||
if (!checkQuery(targetName, "queryNames")) continue;
|
if (excludesFromResult(targetName, "queryNames")) continue;
|
||||||
names.add(targetName);
|
names.add(targetName);
|
||||||
} catch (Exception x) {
|
} catch (Exception x) {
|
||||||
if (LOG.isLoggable(Level.FINE)) {
|
if (LOG.isLoggable(Level.FINE)) {
|
||||||
|
@ -435,7 +412,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
if (name == null) name=ObjectName.WILDCARD;
|
if (name == null) name=ObjectName.WILDCARD;
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
checkPattern(name,null,"queryMBeans");
|
|
||||||
return processOutputInstances(
|
return processOutputInstances(
|
||||||
source().queryMBeans(sourceName,query));
|
source().queryMBeans(sourceName,query));
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -450,7 +426,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
if (name == null) name=ObjectName.WILDCARD;
|
if (name == null) name=ObjectName.WILDCARD;
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
checkPattern(name,null,"queryNames");
|
|
||||||
final Set<ObjectName> tmp = source().queryNames(sourceName,query);
|
final Set<ObjectName> tmp = source().queryNames(sourceName,query);
|
||||||
final Set<ObjectName> out = processOutputNames(tmp);
|
final Set<ObjectName> out = processOutputNames(tmp);
|
||||||
//System.err.println("queryNames: out: "+out);
|
//System.err.println("queryNames: out: "+out);
|
||||||
|
@ -467,7 +442,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
ListenerNotFoundException, IOException {
|
ListenerNotFoundException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name,null,"removeNotificationListener");
|
|
||||||
source().removeNotificationListener(sourceName,listener);
|
source().removeNotificationListener(sourceName,listener);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -481,7 +455,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
// Listener name is already a source listener name.
|
// Listener name is already a source listener name.
|
||||||
try {
|
try {
|
||||||
check(name,null,"addNotificationListener");
|
|
||||||
source().addNotificationListener(sourceName,listener,
|
source().addNotificationListener(sourceName,listener,
|
||||||
filter,handback);
|
filter,handback);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -495,7 +468,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
Object handback) throws InstanceNotFoundException, IOException {
|
Object handback) throws InstanceNotFoundException, IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name,null,"addNotificationListener");
|
|
||||||
source().addNotificationListener(sourceName, listener, filter,
|
source().addNotificationListener(sourceName, listener, filter,
|
||||||
handback);
|
handback);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -512,7 +484,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
IOException {
|
IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name,null,"removeNotificationListener");
|
|
||||||
source().removeNotificationListener(sourceName,listener,filter,
|
source().removeNotificationListener(sourceName,listener,filter,
|
||||||
handback);
|
handback);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -527,7 +498,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
IOException {
|
IOException {
|
||||||
final ObjectName sourceName = toSourceOrRuntime(name);
|
final ObjectName sourceName = toSourceOrRuntime(name);
|
||||||
try {
|
try {
|
||||||
check(name,null,"removeNotificationListener");
|
|
||||||
source().removeNotificationListener(sourceName,listener,
|
source().removeNotificationListener(sourceName,listener,
|
||||||
filter,handback);
|
filter,handback);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
|
@ -543,7 +513,6 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
// listener name is already a source name...
|
// listener name is already a source name...
|
||||||
final ObjectName sourceListener = listener;
|
final ObjectName sourceListener = listener;
|
||||||
try {
|
try {
|
||||||
check(name,null,"removeNotificationListener");
|
|
||||||
source().removeNotificationListener(sourceName,sourceListener);
|
source().removeNotificationListener(sourceName,sourceListener);
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
|
@ -562,9 +531,7 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
// from MBeanServerConnection
|
// from MBeanServerConnection
|
||||||
public String[] getDomains() throws IOException {
|
public String[] getDomains() throws IOException {
|
||||||
try {
|
try {
|
||||||
check(null,null,"getDomains");
|
return source().getDomains();
|
||||||
final String[] domains = source().getDomains();
|
|
||||||
return checkDomains(domains,"getDomains");
|
|
||||||
} catch (RuntimeException ex) {
|
} catch (RuntimeException ex) {
|
||||||
throw makeCompliantRuntimeException(ex);
|
throw makeCompliantRuntimeException(ex);
|
||||||
}
|
}
|
||||||
|
@ -579,115 +546,22 @@ public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnecti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// Hooks for checking permissions
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is a hook to implement permission checking in subclasses.
|
* Returns true if the given targetName must be excluded from the
|
||||||
* By default, this method does nothing and simply returns
|
* query result.
|
||||||
* {@code attribute}.
|
* In this base class, always return {@code false}.
|
||||||
|
* By default all object names returned by the sources are
|
||||||
|
* transmitted to the caller - there is no filtering.
|
||||||
*
|
*
|
||||||
* @param routingName The name of the MBean in the enclosing context.
|
* @param name A target object name expressed in the caller's
|
||||||
* This is of the form {@code <namespace>//<ObjectName>}.
|
* context. In the case of cascading, where the source
|
||||||
* @param attributes The list of attributes to check permission for.
|
* is a sub agent mounted on e.g. namespace "foo",
|
||||||
* @param action one of "getAttribute" or "setAttribute"
|
* that would be a name prefixed by "foo//"...
|
||||||
* @return The list of attributes for which the callers has the
|
* @param queryMethod either "queryNames" or "queryMBeans".
|
||||||
* appropriate {@link
|
* @return true if the name must be excluded.
|
||||||
* javax.management.namespace.JMXNamespacePermission}.
|
|
||||||
*/
|
*/
|
||||||
String[] checkAttributes(ObjectName routingName,
|
boolean excludesFromResult(ObjectName targetName, String queryMethod) {
|
||||||
String[] attributes, String action) {
|
return false;
|
||||||
check(routingName,null,action);
|
|
||||||
return attributes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is a hook to implement permission checking in subclasses.
|
|
||||||
* By default, this method does nothing and simply returns
|
|
||||||
* {@code attribute}.
|
|
||||||
*
|
|
||||||
* @param routingName The name of the MBean in the enclosing context.
|
|
||||||
* This is of the form {@code <namespace>//<ObjectName>}.
|
|
||||||
* @param attributes The list of attributes to check permission for.
|
|
||||||
* @param action one of "getAttribute" or "setAttribute"
|
|
||||||
* @return The list of attributes for which the callers has the
|
|
||||||
* appropriate {@link
|
|
||||||
* javax.management.namespace.JMXNamespacePermission}.
|
|
||||||
*/
|
|
||||||
AttributeList checkAttributes(ObjectName routingName,
|
|
||||||
AttributeList attributes, String action) {
|
|
||||||
check(routingName,null,action);
|
|
||||||
return attributes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is a hook to implement permission checking in subclasses.
|
|
||||||
* By default, this method does nothing.
|
|
||||||
* A subclass may override this method and throw a {@link
|
|
||||||
* SecurityException} if the permission is denied.
|
|
||||||
*
|
|
||||||
* @param routingName The name of the MBean in the enclosing context.
|
|
||||||
* This is of the form {@code <namespace>//<ObjectName>}.
|
|
||||||
* @param member The {@link
|
|
||||||
* javax.management.namespace.JMXNamespacePermission#getMember member}
|
|
||||||
* name.
|
|
||||||
* @param action The {@link
|
|
||||||
* javax.management.namespace.JMXNamespacePermission#getActions action}
|
|
||||||
* name.
|
|
||||||
*/
|
|
||||||
void check(ObjectName routingName,
|
|
||||||
String member, String action) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// called in createMBean and registerMBean
|
|
||||||
void checkCreate(ObjectName routingName, String className,
|
|
||||||
String action) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// A priori check for queryNames/queryMBeans/
|
|
||||||
void checkPattern(ObjectName routingPattern,
|
|
||||||
String member, String action) {
|
|
||||||
// pattern is checked only at posteriori by checkQuery.
|
|
||||||
// checking it a priori usually doesn't work, because ObjectName.apply
|
|
||||||
// does not work between two patterns.
|
|
||||||
// We only check that we have the permission requested for 'action'.
|
|
||||||
check(null,null,action);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This is a hook to implement permission checking in subclasses.
|
|
||||||
*
|
|
||||||
* Checks that the caller has sufficient permission for returning
|
|
||||||
* information about {@code sourceName} in {@code action}.
|
|
||||||
*
|
|
||||||
* By default always return true. Subclass may override this method
|
|
||||||
* and return false if the caller doesn't have sufficient permissions.
|
|
||||||
*
|
|
||||||
* @param routingName The name of the MBean to include or exclude from
|
|
||||||
* the query, expressed in the enclosing context.
|
|
||||||
* This is of the form {@code <namespace>//<ObjectName>}.
|
|
||||||
* @param action one of "queryNames" or "queryMBeans"
|
|
||||||
* @return true if {@code sourceName} can be returned.
|
|
||||||
*/
|
|
||||||
boolean checkQuery(ObjectName routingName, String action) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method is a hook to implement permission checking in subclasses.
|
|
||||||
* Checks that the caller as the necessary permissions to view the
|
|
||||||
* given domain. If not remove the domains for which the caller doesn't
|
|
||||||
* have permission from the list.
|
|
||||||
* <p>
|
|
||||||
* By default, this method always returns {@code domains}
|
|
||||||
*
|
|
||||||
* @param domains The domains to return.
|
|
||||||
* @param action "getDomains"
|
|
||||||
* @return a filtered list of domains.
|
|
||||||
*/
|
|
||||||
String[] checkDomains(String[] domains, String action) {
|
|
||||||
return domains;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue