23 * have any questions. |
23 * have any questions. |
24 */ |
24 */ |
25 |
25 |
26 package com.sun.jmx.interceptor; |
26 package com.sun.jmx.interceptor; |
27 |
27 |
28 // java import |
28 |
29 import java.util.ArrayList; |
29 // JMX RI |
30 import java.util.Iterator; |
30 import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; |
31 import java.util.List; |
31 import com.sun.jmx.mbeanserver.DynamicMBean2; |
32 import java.util.logging.Level; |
32 import com.sun.jmx.mbeanserver.Introspector; |
33 import java.util.Set; |
33 import com.sun.jmx.mbeanserver.MBeanInjector; |
34 import java.util.HashSet; |
34 import com.sun.jmx.mbeanserver.MBeanInstantiator; |
35 import java.util.WeakHashMap; |
35 import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository; |
|
36 import com.sun.jmx.mbeanserver.NamedObject; |
|
37 import com.sun.jmx.mbeanserver.NotifySupport; |
|
38 import com.sun.jmx.mbeanserver.Repository; |
|
39 import com.sun.jmx.mbeanserver.Repository.RegistrationContext; |
|
40 import com.sun.jmx.mbeanserver.Util; |
|
41 import com.sun.jmx.remote.util.EnvHelp; |
|
42 |
36 import java.lang.ref.WeakReference; |
43 import java.lang.ref.WeakReference; |
37 import java.security.AccessControlContext; |
44 import java.security.AccessControlContext; |
|
45 import java.security.AccessController; |
38 import java.security.Permission; |
46 import java.security.Permission; |
|
47 import java.security.PrivilegedAction; |
39 import java.security.ProtectionDomain; |
48 import java.security.ProtectionDomain; |
40 import java.security.AccessController; |
49 import java.util.ArrayList; |
41 import java.security.PrivilegedAction; |
50 import java.util.HashSet; |
|
51 import java.util.Iterator; |
|
52 import java.util.LinkedList; |
|
53 import java.util.List; |
|
54 import java.util.Queue; |
|
55 import java.util.Set; |
|
56 import java.util.WeakHashMap; |
|
57 import java.util.logging.Level; |
42 |
58 |
43 // JMX import |
59 // JMX import |
44 import javax.management.Attribute; |
60 import javax.management.Attribute; |
45 import javax.management.AttributeList; |
61 import javax.management.AttributeList; |
46 import javax.management.AttributeNotFoundException; |
62 import javax.management.AttributeNotFoundException; |
47 import javax.management.DynamicMBean; |
63 import javax.management.DynamicMBean; |
|
64 import javax.management.DynamicWrapperMBean; |
48 import javax.management.InstanceAlreadyExistsException; |
65 import javax.management.InstanceAlreadyExistsException; |
49 import javax.management.InstanceNotFoundException; |
66 import javax.management.InstanceNotFoundException; |
50 import javax.management.IntrospectionException; |
67 import javax.management.IntrospectionException; |
51 import javax.management.InvalidAttributeValueException; |
68 import javax.management.InvalidAttributeValueException; |
52 import javax.management.JMRuntimeException; |
69 import javax.management.JMRuntimeException; |
53 import javax.management.ListenerNotFoundException; |
70 import javax.management.ListenerNotFoundException; |
54 import javax.management.MalformedObjectNameException; |
|
55 import javax.management.MBeanException; |
71 import javax.management.MBeanException; |
56 import javax.management.MBeanInfo; |
72 import javax.management.MBeanInfo; |
57 import javax.management.MBeanPermission; |
73 import javax.management.MBeanPermission; |
58 import javax.management.MBeanRegistration; |
74 import javax.management.MBeanRegistration; |
59 import javax.management.MBeanRegistrationException; |
75 import javax.management.MBeanRegistrationException; |
62 import javax.management.MBeanServerNotification; |
78 import javax.management.MBeanServerNotification; |
63 import javax.management.MBeanTrustPermission; |
79 import javax.management.MBeanTrustPermission; |
64 import javax.management.NotCompliantMBeanException; |
80 import javax.management.NotCompliantMBeanException; |
65 import javax.management.Notification; |
81 import javax.management.Notification; |
66 import javax.management.NotificationBroadcaster; |
82 import javax.management.NotificationBroadcaster; |
|
83 import javax.management.NotificationBroadcasterSupport; |
67 import javax.management.NotificationEmitter; |
84 import javax.management.NotificationEmitter; |
68 import javax.management.NotificationFilter; |
85 import javax.management.NotificationFilter; |
69 import javax.management.NotificationListener; |
86 import javax.management.NotificationListener; |
70 import javax.management.ObjectInstance; |
87 import javax.management.ObjectInstance; |
71 import javax.management.ObjectName; |
88 import javax.management.ObjectName; |
73 import javax.management.QueryExp; |
90 import javax.management.QueryExp; |
74 import javax.management.ReflectionException; |
91 import javax.management.ReflectionException; |
75 import javax.management.RuntimeErrorException; |
92 import javax.management.RuntimeErrorException; |
76 import javax.management.RuntimeMBeanException; |
93 import javax.management.RuntimeMBeanException; |
77 import javax.management.RuntimeOperationsException; |
94 import javax.management.RuntimeOperationsException; |
78 |
95 import javax.management.namespace.JMXNamespace; |
79 // JMX RI |
|
80 import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER; |
|
81 import com.sun.jmx.mbeanserver.DynamicMBean2; |
|
82 import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository; |
|
83 import com.sun.jmx.mbeanserver.MBeanInstantiator; |
|
84 import com.sun.jmx.mbeanserver.Repository; |
|
85 import com.sun.jmx.mbeanserver.NamedObject; |
|
86 import com.sun.jmx.mbeanserver.Introspector; |
|
87 import com.sun.jmx.mbeanserver.MBeanInjector; |
|
88 import com.sun.jmx.mbeanserver.NotifySupport; |
|
89 import com.sun.jmx.mbeanserver.Repository.RegistrationContext; |
|
90 import com.sun.jmx.mbeanserver.Util; |
|
91 import com.sun.jmx.remote.util.EnvHelp; |
|
92 import javax.management.DynamicWrapperMBean; |
|
93 import javax.management.NotificationBroadcasterSupport; |
|
94 |
96 |
95 /** |
97 /** |
96 * This is the default class for MBean manipulation on the agent side. It |
98 * This is the default class for MBean manipulation on the agent side. It |
97 * contains the methods necessary for the creation, registration, and |
99 * contains the methods necessary for the creation, registration, and |
98 * deletion of MBeans as well as the access methods for registered MBeans. |
100 * deletion of MBeans as well as the access methods for registered MBeans. |
111 * <BR> |
113 * <BR> |
112 * <CODE>JMImplementation:type=MBeanServerDelegate</CODE>. |
114 * <CODE>JMImplementation:type=MBeanServerDelegate</CODE>. |
113 * |
115 * |
114 * @since 1.5 |
116 * @since 1.5 |
115 */ |
117 */ |
116 public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor { |
118 public class DefaultMBeanServerInterceptor |
|
119 extends MBeanServerInterceptorSupport { |
117 |
120 |
118 /** The MBeanInstantiator object used by the |
121 /** The MBeanInstantiator object used by the |
119 * DefaultMBeanServerInterceptor */ |
122 * DefaultMBeanServerInterceptor */ |
120 private final transient MBeanInstantiator instantiator; |
123 private final transient MBeanInstantiator instantiator; |
121 |
124 |
122 /** The MBean server object that is associated to the |
125 /** The MBean server object that is associated to the |
123 * DefaultMBeanServerInterceptor */ |
126 * DefaultMBeanServerInterceptor */ |
124 private transient MBeanServer server = null; |
127 private transient MBeanServer server = null; |
125 |
128 |
126 /** The MBean server object taht associated to the |
129 /** The MBean server delegate object that is associated to the |
127 * DefaultMBeanServerInterceptor */ |
130 * DefaultMBeanServerInterceptor */ |
128 private final transient MBeanServerDelegate delegate; |
131 private final transient MBeanServerDelegate delegate; |
129 |
132 |
130 /** The Repository object used by the DefaultMBeanServerInterceptor */ |
133 /** The Repository object used by the DefaultMBeanServerInterceptor */ |
131 private final transient Repository repository; |
134 private final transient Repository repository; |
136 WeakHashMap<ListenerWrapper, WeakReference<ListenerWrapper>> |
139 WeakHashMap<ListenerWrapper, WeakReference<ListenerWrapper>> |
137 listenerWrappers = |
140 listenerWrappers = |
138 new WeakHashMap<ListenerWrapper, |
141 new WeakHashMap<ListenerWrapper, |
139 WeakReference<ListenerWrapper>>(); |
142 WeakReference<ListenerWrapper>>(); |
140 |
143 |
|
144 private final NamespaceDispatchInterceptor dispatcher; |
|
145 |
141 /** The default domain of the object names */ |
146 /** The default domain of the object names */ |
142 private final String domain; |
147 private final String domain; |
143 |
148 |
144 /** True if the repository perform queries, false otherwise */ |
149 /** The mbeanServerName */ |
145 private boolean queryByRepo; |
150 private final String mbeanServerName; |
146 |
151 |
147 /** The sequence number identifyng the notifications sent */ |
152 /** The sequence number identifying the notifications sent */ |
148 // Now sequence number is handled by MBeanServerDelegate. |
153 // Now sequence number is handled by MBeanServerDelegate. |
149 // private int sequenceNumber=0; |
154 // private int sequenceNumber=0; |
150 |
155 |
151 /** |
156 /** |
152 * Creates a DefaultMBeanServerInterceptor with the specified |
157 * Creates a DefaultMBeanServerInterceptor with the specified |
160 * with the new MBeanServer. The new MBeanServer must register |
165 * with the new MBeanServer. The new MBeanServer must register |
161 * this MBean in its MBean repository. |
166 * this MBean in its MBean repository. |
162 * @param instantiator The MBeanInstantiator that will be used to |
167 * @param instantiator The MBeanInstantiator that will be used to |
163 * instantiate MBeans and take care of class loading issues. |
168 * instantiate MBeans and take care of class loading issues. |
164 * @param repository The repository to use for this MBeanServer. |
169 * @param repository The repository to use for this MBeanServer. |
|
170 * @param dispatcher The dispatcher used by this MBeanServer |
165 */ |
171 */ |
166 public DefaultMBeanServerInterceptor(MBeanServer outer, |
172 public DefaultMBeanServerInterceptor(MBeanServer outer, |
167 MBeanServerDelegate delegate, |
173 MBeanServerDelegate delegate, |
168 MBeanInstantiator instantiator, |
174 MBeanInstantiator instantiator, |
169 Repository repository) { |
175 Repository repository, |
|
176 NamespaceDispatchInterceptor dispatcher) { |
170 if (outer == null) throw new |
177 if (outer == null) throw new |
171 IllegalArgumentException("outer MBeanServer cannot be null"); |
178 IllegalArgumentException("outer MBeanServer cannot be null"); |
172 if (delegate == null) throw new |
179 if (delegate == null) throw new |
173 IllegalArgumentException("MBeanServerDelegate cannot be null"); |
180 IllegalArgumentException("MBeanServerDelegate cannot be null"); |
174 if (instantiator == null) throw new |
181 if (instantiator == null) throw new |
179 this.server = outer; |
186 this.server = outer; |
180 this.delegate = delegate; |
187 this.delegate = delegate; |
181 this.instantiator = instantiator; |
188 this.instantiator = instantiator; |
182 this.repository = repository; |
189 this.repository = repository; |
183 this.domain = repository.getDefaultDomain(); |
190 this.domain = repository.getDefaultDomain(); |
|
191 this.dispatcher = dispatcher; |
|
192 this.mbeanServerName = Util.getMBeanServerSecurityName(delegate); |
184 } |
193 } |
185 |
194 |
186 public ObjectInstance createMBean(String className, ObjectName name) |
195 public ObjectInstance createMBean(String className, ObjectName name) |
187 throws ReflectionException, InstanceAlreadyExistsException, |
196 throws ReflectionException, InstanceAlreadyExistsException, |
188 MBeanRegistrationException, MBeanException, |
197 MBeanRegistrationException, MBeanException, |
257 } |
266 } |
258 |
267 |
259 name = nonDefaultDomain(name); |
268 name = nonDefaultDomain(name); |
260 } |
269 } |
261 |
270 |
262 checkMBeanPermission(className, null, null, "instantiate"); |
271 checkMBeanPermission(mbeanServerName,className, null, null, "instantiate"); |
263 checkMBeanPermission(className, null, name, "registerMBean"); |
272 checkMBeanPermission(mbeanServerName,className, null, name, "registerMBean"); |
264 |
273 |
265 /* Load the appropriate class. */ |
274 /* Load the appropriate class. */ |
266 if (withDefaultLoaderRepository) { |
275 if (withDefaultLoaderRepository) { |
267 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { |
276 if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) { |
268 MBEANSERVER_LOGGER.logp(Level.FINER, |
277 MBEANSERVER_LOGGER.logp(Level.FINER, |
431 throws InstanceNotFoundException, MBeanRegistrationException { |
440 throws InstanceNotFoundException, MBeanRegistrationException { |
432 |
441 |
433 DynamicMBean instance = getMBean(name); |
442 DynamicMBean instance = getMBean(name); |
434 // may throw InstanceNotFoundException |
443 // may throw InstanceNotFoundException |
435 |
444 |
436 checkMBeanPermission(instance, null, name, "unregisterMBean"); |
445 checkMBeanPermission(mbeanServerName, instance, null, name, |
|
446 "unregisterMBean"); |
437 |
447 |
438 if (instance instanceof MBeanRegistration) |
448 if (instance instanceof MBeanRegistration) |
439 preDeregisterInvoke((MBeanRegistration) instance); |
449 preDeregisterInvoke((MBeanRegistration) instance); |
440 |
450 |
441 final Object resource = getResource(instance); |
451 final Object resource = getResource(instance); |
465 throws InstanceNotFoundException { |
475 throws InstanceNotFoundException { |
466 |
476 |
467 name = nonDefaultDomain(name); |
477 name = nonDefaultDomain(name); |
468 DynamicMBean instance = getMBean(name); |
478 DynamicMBean instance = getMBean(name); |
469 |
479 |
470 checkMBeanPermission(instance, null, name, "getObjectInstance"); |
480 checkMBeanPermission(mbeanServerName, |
|
481 instance, null, name, "getObjectInstance"); |
471 |
482 |
472 final String className = getClassName(instance); |
483 final String className = getClassName(instance); |
473 |
484 |
474 return new ObjectInstance(name, className); |
485 return new ObjectInstance(name, className); |
475 } |
486 } |
477 public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { |
488 public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { |
478 SecurityManager sm = System.getSecurityManager(); |
489 SecurityManager sm = System.getSecurityManager(); |
479 if (sm != null) { |
490 if (sm != null) { |
480 // Check if the caller has the right to invoke 'queryMBeans' |
491 // Check if the caller has the right to invoke 'queryMBeans' |
481 // |
492 // |
482 checkMBeanPermission((String) null, null, null, "queryMBeans"); |
493 checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryMBeans"); |
483 |
494 |
484 // Perform query without "query". |
495 // Perform query without "query". |
485 // |
496 // |
486 Set<ObjectInstance> list = queryMBeansImpl(name, null); |
497 Set<ObjectInstance> list = queryMBeansImpl(name, null); |
487 |
498 |
490 // |
501 // |
491 Set<ObjectInstance> allowedList = |
502 Set<ObjectInstance> allowedList = |
492 new HashSet<ObjectInstance>(list.size()); |
503 new HashSet<ObjectInstance>(list.size()); |
493 for (ObjectInstance oi : list) { |
504 for (ObjectInstance oi : list) { |
494 try { |
505 try { |
495 checkMBeanPermission(oi.getClassName(), null, |
506 checkMBeanPermission(mbeanServerName,oi.getClassName(), null, |
496 oi.getObjectName(), "queryMBeans"); |
507 oi.getObjectName(), "queryMBeans"); |
497 allowedList.add(oi); |
508 allowedList.add(oi); |
498 } catch (SecurityException e) { |
509 } catch (SecurityException e) { |
499 // OK: Do not add this ObjectInstance to the list |
510 // OK: Do not add this ObjectInstance to the list |
500 } |
511 } |
514 QueryExp query) { |
525 QueryExp query) { |
515 // Query the MBeans on the repository |
526 // Query the MBeans on the repository |
516 // |
527 // |
517 Set<NamedObject> list = repository.query(name, query); |
528 Set<NamedObject> list = repository.query(name, query); |
518 |
529 |
519 if (queryByRepo) { |
|
520 // The repository performs the filtering |
|
521 query = null; |
|
522 } |
|
523 |
|
524 return (objectInstancesFromFilteredNamedObjects(list, query)); |
530 return (objectInstancesFromFilteredNamedObjects(list, query)); |
525 } |
531 } |
526 |
532 |
527 public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { |
533 public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { |
528 Set<ObjectName> queryList; |
534 Set<ObjectName> queryList; |
529 SecurityManager sm = System.getSecurityManager(); |
535 SecurityManager sm = System.getSecurityManager(); |
530 if (sm != null) { |
536 if (sm != null) { |
531 // Check if the caller has the right to invoke 'queryNames' |
537 // Check if the caller has the right to invoke 'queryNames' |
532 // |
538 // |
533 checkMBeanPermission((String) null, null, null, "queryNames"); |
539 checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryNames"); |
534 |
540 |
535 // Perform query without "query". |
541 // Perform query without "query". |
536 // |
542 // |
537 Set<ObjectInstance> list = queryMBeansImpl(name, null); |
543 Set<ObjectInstance> list = queryMBeansImpl(name, null); |
538 |
544 |
541 // |
547 // |
542 Set<ObjectInstance> allowedList = |
548 Set<ObjectInstance> allowedList = |
543 new HashSet<ObjectInstance>(list.size()); |
549 new HashSet<ObjectInstance>(list.size()); |
544 for (ObjectInstance oi : list) { |
550 for (ObjectInstance oi : list) { |
545 try { |
551 try { |
546 checkMBeanPermission(oi.getClassName(), null, |
552 checkMBeanPermission(mbeanServerName, oi.getClassName(), null, |
547 oi.getObjectName(), "queryNames"); |
553 oi.getObjectName(), "queryNames"); |
548 allowedList.add(oi); |
554 allowedList.add(oi); |
549 } catch (SecurityException e) { |
555 } catch (SecurityException e) { |
550 // OK: Do not add this ObjectInstance to the list |
556 // OK: Do not add this ObjectInstance to the list |
551 } |
557 } |
587 "Object name cannot be null"); |
588 "Object name cannot be null"); |
588 } |
589 } |
589 |
590 |
590 name = nonDefaultDomain(name); |
591 name = nonDefaultDomain(name); |
591 |
592 |
592 // /* Permission check */ |
593 /* No Permission check */ |
593 // checkMBeanPermission(null, null, name, "isRegistered"); |
594 // isRegistered is always unchecked as per JMX spec. |
594 |
595 |
595 return (repository.contains(name)); |
596 return (repository.contains(name)); |
596 } |
597 } |
597 |
598 |
598 public String[] getDomains() { |
599 public String[] getDomains() { |
599 SecurityManager sm = System.getSecurityManager(); |
600 SecurityManager sm = System.getSecurityManager(); |
600 if (sm != null) { |
601 if (sm != null) { |
601 // Check if the caller has the right to invoke 'getDomains' |
602 // Check if the caller has the right to invoke 'getDomains' |
602 // |
603 // |
603 checkMBeanPermission((String) null, null, null, "getDomains"); |
604 checkMBeanPermission(mbeanServerName, (String) null, null, null, "getDomains"); |
604 |
605 |
605 // Return domains |
606 // Return domains |
606 // |
607 // |
607 String[] domains = repository.getDomains(); |
608 String[] domains = repository.getDomains(); |
608 |
609 |
610 // on each specific domain in the list. |
611 // on each specific domain in the list. |
611 // |
612 // |
612 List<String> result = new ArrayList<String>(domains.length); |
613 List<String> result = new ArrayList<String>(domains.length); |
613 for (int i = 0; i < domains.length; i++) { |
614 for (int i = 0; i < domains.length; i++) { |
614 try { |
615 try { |
615 ObjectName domain = Util.newObjectName(domains[i] + ":x=x"); |
616 ObjectName dom = |
616 checkMBeanPermission((String) null, null, domain, "getDomains"); |
617 Util.newObjectName(domains[i] + ":x=x"); |
|
618 checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains"); |
617 result.add(domains[i]); |
619 result.add(domains[i]); |
618 } catch (SecurityException e) { |
620 } catch (SecurityException e) { |
619 // OK: Do not add this domain to the list |
621 // OK: Do not add this domain to the list |
620 } |
622 } |
621 } |
623 } |
700 else { |
703 else { |
701 final String classname = getClassName(instance); |
704 final String classname = getClassName(instance); |
702 |
705 |
703 // Check if the caller has the right to invoke 'getAttribute' |
706 // Check if the caller has the right to invoke 'getAttribute' |
704 // |
707 // |
705 checkMBeanPermission(classname, null, name, "getAttribute"); |
708 checkMBeanPermission(mbeanServerName, classname, null, name, "getAttribute"); |
706 |
709 |
707 // Check if the caller has the right to invoke 'getAttribute' |
710 // Check if the caller has the right to invoke 'getAttribute' |
708 // on each specific attribute |
711 // on each specific attribute |
709 // |
712 // |
710 List<String> allowedList = |
713 List<String> allowedList = |
711 new ArrayList<String>(attributes.length); |
714 new ArrayList<String>(attributes.length); |
712 for (String attr : attributes) { |
715 for (String attr : attributes) { |
713 try { |
716 try { |
714 checkMBeanPermission(classname, attr, |
717 checkMBeanPermission(mbeanServerName, classname, attr, |
715 name, "getAttribute"); |
718 name, "getAttribute"); |
716 allowedList.add(attr); |
719 allowedList.add(attr); |
717 } catch (SecurityException e) { |
720 } catch (SecurityException e) { |
718 // OK: Do not add this attribute to the list |
721 // OK: Do not add this attribute to the list |
719 } |
722 } |
720 } |
723 } |
721 allowedAttributes = allowedList.toArray(new String[0]); |
724 allowedAttributes = |
|
725 allowedList.toArray(new String[allowedList.size()]); |
722 } |
726 } |
723 |
727 |
724 try { |
728 try { |
725 return instance.getAttributes(allowedAttributes); |
729 return instance.getAttributes(allowedAttributes); |
726 } catch (Throwable t) { |
730 } catch (Throwable t) { |
754 "setAttribute", "ObjectName = " + name + |
758 "setAttribute", "ObjectName = " + name + |
755 ", Attribute = " + attribute.getName()); |
759 ", Attribute = " + attribute.getName()); |
756 } |
760 } |
757 |
761 |
758 DynamicMBean instance = getMBean(name); |
762 DynamicMBean instance = getMBean(name); |
759 checkMBeanPermission(instance, attribute.getName(), |
763 checkMBeanPermission(mbeanServerName, instance, attribute.getName(), |
760 name, "setAttribute"); |
764 name, "setAttribute"); |
761 |
765 |
762 try { |
766 try { |
763 instance.setAttribute(attribute); |
767 instance.setAttribute(attribute); |
764 } catch (AttributeNotFoundException e) { |
768 } catch (AttributeNotFoundException e) { |
797 else { |
801 else { |
798 String classname = getClassName(instance); |
802 String classname = getClassName(instance); |
799 |
803 |
800 // Check if the caller has the right to invoke 'setAttribute' |
804 // Check if the caller has the right to invoke 'setAttribute' |
801 // |
805 // |
802 checkMBeanPermission(classname, null, name, "setAttribute"); |
806 checkMBeanPermission(mbeanServerName, classname, null, name, "setAttribute"); |
803 |
807 |
804 // Check if the caller has the right to invoke 'setAttribute' |
808 // Check if the caller has the right to invoke 'setAttribute' |
805 // on each specific attribute |
809 // on each specific attribute |
806 // |
810 // |
807 allowedAttributes = new AttributeList(attributes.size()); |
811 allowedAttributes = new AttributeList(attributes.size()); |
808 for (Iterator i = attributes.iterator(); i.hasNext();) { |
812 for (Iterator i = attributes.iterator(); i.hasNext();) { |
809 try { |
813 try { |
810 Attribute attribute = (Attribute) i.next(); |
814 Attribute attribute = (Attribute) i.next(); |
811 checkMBeanPermission(classname, attribute.getName(), |
815 checkMBeanPermission(mbeanServerName, classname, attribute.getName(), |
812 name, "setAttribute"); |
816 name, "setAttribute"); |
813 allowedAttributes.add(attribute); |
817 allowedAttributes.add(attribute); |
814 } catch (SecurityException e) { |
818 } catch (SecurityException e) { |
815 // OK: Do not add this attribute to the list |
819 // OK: Do not add this attribute to the list |
816 } |
820 } |
830 ReflectionException { |
834 ReflectionException { |
831 |
835 |
832 name = nonDefaultDomain(name); |
836 name = nonDefaultDomain(name); |
833 |
837 |
834 DynamicMBean instance = getMBean(name); |
838 DynamicMBean instance = getMBean(name); |
835 checkMBeanPermission(instance, operationName, name, "invoke"); |
839 checkMBeanPermission(mbeanServerName, instance, operationName, |
|
840 name, "invoke"); |
836 try { |
841 try { |
837 return instance.invoke(operationName, params, signature); |
842 return instance.invoke(operationName, params, signature); |
838 } catch (Throwable t) { |
843 } catch (Throwable t) { |
839 rethrowMaybeMBeanException(t); |
844 rethrowMaybeMBeanException(t); |
840 throw new AssertionError(); |
845 throw new AssertionError(); |
932 MBEANSERVER_LOGGER.logp(Level.FINER, |
937 MBEANSERVER_LOGGER.logp(Level.FINER, |
933 DefaultMBeanServerInterceptor.class.getName(), |
938 DefaultMBeanServerInterceptor.class.getName(), |
934 "registerMBean", "ObjectName = " + name); |
939 "registerMBean", "ObjectName = " + name); |
935 } |
940 } |
936 |
941 |
937 ObjectName logicalName = name; |
942 ObjectName logicalName = preRegister(mbean, server, name); |
938 logicalName = preRegister(mbean, server, name); |
|
939 |
943 |
940 // preRegister returned successfully, so from this point on we |
944 // preRegister returned successfully, so from this point on we |
941 // must call postRegister(false) if there is any problem. |
945 // must call postRegister(false) if there is any problem. |
942 boolean registered = false; |
946 boolean registered = false; |
943 boolean registerFailed = false; |
947 boolean registerFailed = false; |
959 } |
963 } |
960 } |
964 } |
961 |
965 |
962 if (logicalName != name && logicalName != null) { |
966 if (logicalName != name && logicalName != null) { |
963 logicalName = |
967 logicalName = |
964 ObjectName.getInstance(nonDefaultDomain(logicalName)); |
968 ObjectName.getInstance(nonDefaultDomain(logicalName)); |
965 } |
969 } |
966 |
970 |
967 checkMBeanPermission(classname, null, logicalName, "registerMBean"); |
971 checkMBeanPermission(mbeanServerName, classname, null, logicalName, |
|
972 "registerMBean"); |
968 |
973 |
969 if (logicalName == null) { |
974 if (logicalName == null) { |
970 final RuntimeException wrapped = |
975 final RuntimeException wrapped = |
971 new IllegalArgumentException("No object name specified"); |
976 new IllegalArgumentException("No object name specified"); |
972 throw new RuntimeOperationsException(wrapped, |
977 throw new RuntimeOperationsException(wrapped, |
973 "Exception occurred trying to register the MBean"); |
978 "Exception occurred trying to register the MBean"); |
974 } |
979 } |
975 |
980 |
976 final Object resource = getResource(mbean); |
981 final Object resource = getResource(mbean); |
977 |
982 |
978 // Register the MBean with the repository. |
983 // Register the MBean with the repository. |
985 // In case of success, we also need to call context.done() at the |
990 // In case of success, we also need to call context.done() at the |
986 // end of this method. |
991 // end of this method. |
987 // |
992 // |
988 context = registerWithRepository(resource, mbean, logicalName); |
993 context = registerWithRepository(resource, mbean, logicalName); |
989 |
994 |
|
995 |
990 registerFailed = false; |
996 registerFailed = false; |
991 registered = true; |
997 registered = true; |
|
998 |
992 } finally { |
999 } finally { |
993 try { |
1000 try { |
994 postRegister(logicalName, mbean, registered, registerFailed); |
1001 postRegister(logicalName, mbean, registered, registerFailed); |
995 } finally { |
1002 } finally { |
996 if (registered) context.done(); |
1003 if (registered && context!=null) context.done(); |
997 } |
1004 } |
998 } |
1005 } |
999 return new ObjectInstance(logicalName, classname); |
1006 return new ObjectInstance(logicalName, classname); |
1000 } |
1007 } |
1001 |
1008 |
1002 private static void throwMBeanRegistrationException(Throwable t, String where) |
1009 private static void throwMBeanRegistrationException(Throwable t, String where) |
1003 throws MBeanRegistrationException { |
1010 throws MBeanRegistrationException { |
1004 try { |
1011 if (t instanceof RuntimeException) { |
1005 throw t; |
1012 throw new RuntimeMBeanException((RuntimeException)t, |
1006 } catch (RuntimeException e) { |
1013 "RuntimeException thrown " + where); |
1007 throw new RuntimeMBeanException( |
1014 } else if (t instanceof Error) { |
1008 e, "RuntimeException thrown " + where); |
1015 throw new RuntimeErrorException((Error)t, |
1009 } catch (Error er) { |
1016 "Error thrown " + where); |
1010 throw new RuntimeErrorException(er, "Error thrown " + where); |
1017 } else if (t instanceof MBeanRegistrationException) { |
1011 } catch (MBeanRegistrationException r) { |
1018 throw (MBeanRegistrationException)t; |
1012 throw r; |
1019 } else if (t instanceof Exception) { |
1013 } catch (Exception ex) { |
1020 throw new MBeanRegistrationException((Exception)t, |
1014 throw new MBeanRegistrationException(ex, "Exception thrown " + where); |
1021 "Exception thrown " + where); |
1015 } catch (Throwable t1) { |
1022 } else // neither Error nor Exception?? |
1016 throw new RuntimeException(t); // neither Error nor Exception?? |
1023 throw new RuntimeException(t); |
1017 } |
|
1018 } |
1024 } |
1019 |
1025 |
1020 private static ObjectName preRegister( |
1026 private static ObjectName preRegister( |
1021 DynamicMBean mbean, MBeanServer mbs, ObjectName name) |
1027 DynamicMBean mbean, MBeanServer mbs, ObjectName name) |
1022 throws InstanceAlreadyExistsException, MBeanRegistrationException { |
1028 throws InstanceAlreadyExistsException, MBeanRegistrationException { |
1228 DefaultMBeanServerInterceptor.class.getName(), |
1234 DefaultMBeanServerInterceptor.class.getName(), |
1229 "addNotificationListener", "ObjectName = " + name); |
1235 "addNotificationListener", "ObjectName = " + name); |
1230 } |
1236 } |
1231 |
1237 |
1232 DynamicMBean instance = getMBean(name); |
1238 DynamicMBean instance = getMBean(name); |
1233 checkMBeanPermission(instance, null, name, "addNotificationListener"); |
1239 checkMBeanPermission(mbeanServerName, instance, null, |
|
1240 name, "addNotificationListener"); |
1234 |
1241 |
1235 NotificationBroadcaster broadcaster = |
1242 NotificationBroadcaster broadcaster = |
1236 getNotificationBroadcaster(name, instance, |
1243 getNotificationBroadcaster(name, instance, |
1237 NotificationBroadcaster.class); |
1244 NotificationBroadcaster.class); |
1238 |
1245 |
1365 DefaultMBeanServerInterceptor.class.getName(), |
1372 DefaultMBeanServerInterceptor.class.getName(), |
1366 "removeNotificationListener", "ObjectName = " + name); |
1373 "removeNotificationListener", "ObjectName = " + name); |
1367 } |
1374 } |
1368 |
1375 |
1369 DynamicMBean instance = getMBean(name); |
1376 DynamicMBean instance = getMBean(name); |
1370 checkMBeanPermission(instance, null, name, |
1377 checkMBeanPermission(mbeanServerName, instance, null, name, |
1371 "removeNotificationListener"); |
1378 "removeNotificationListener"); |
1372 |
1379 |
1373 /* We could simplify the code by assigning broadcaster after |
1380 /* We could simplify the code by assigning broadcaster after |
1374 assigning listenerWrapper, but that would change the error |
1381 assigning listenerWrapper, but that would change the error |
1375 behavior when both the broadcaster and the listener are |
1382 behavior when both the broadcaster and the listener are |
1436 } |
1443 } |
1437 if (mbi == null) |
1444 if (mbi == null) |
1438 throw new JMRuntimeException("MBean " + name + |
1445 throw new JMRuntimeException("MBean " + name + |
1439 "has no MBeanInfo"); |
1446 "has no MBeanInfo"); |
1440 |
1447 |
1441 checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo"); |
1448 checkMBeanPermission(mbeanServerName, mbi.getClassName(), null, name, "getMBeanInfo"); |
1442 |
1449 |
1443 return mbi; |
1450 return mbi; |
1444 } |
1451 } |
1445 |
1452 |
1446 public boolean isInstanceOf(ObjectName name, String className) |
1453 public boolean isInstanceOf(ObjectName name, String className) |
1447 throws InstanceNotFoundException { |
1454 throws InstanceNotFoundException { |
1448 |
1455 |
1449 DynamicMBean instance = getMBean(name); |
1456 final DynamicMBean instance = getMBean(name); |
1450 checkMBeanPermission(instance, null, name, "isInstanceOf"); |
1457 checkMBeanPermission(mbeanServerName, |
|
1458 instance, null, name, "isInstanceOf"); |
1451 |
1459 |
1452 try { |
1460 try { |
1453 Object resource = getResource(instance); |
1461 Object resource = getResource(instance); |
1454 |
1462 |
1455 final String resourceClassName = |
1463 final String resourceClassName = |
1496 */ |
1504 */ |
1497 public ClassLoader getClassLoaderFor(ObjectName mbeanName) |
1505 public ClassLoader getClassLoaderFor(ObjectName mbeanName) |
1498 throws InstanceNotFoundException { |
1506 throws InstanceNotFoundException { |
1499 |
1507 |
1500 DynamicMBean instance = getMBean(mbeanName); |
1508 DynamicMBean instance = getMBean(mbeanName); |
1501 checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor"); |
1509 checkMBeanPermission(mbeanServerName, instance, null, mbeanName, |
|
1510 "getClassLoaderFor"); |
1502 return getResourceLoader(instance); |
1511 return getResourceLoader(instance); |
1503 } |
1512 } |
1504 |
1513 |
1505 /** |
1514 /** |
1506 * <p>Return the named {@link java.lang.ClassLoader}. |
1515 * <p>Return the named {@link java.lang.ClassLoader}. |
1511 */ |
1520 */ |
1512 public ClassLoader getClassLoader(ObjectName loaderName) |
1521 public ClassLoader getClassLoader(ObjectName loaderName) |
1513 throws InstanceNotFoundException { |
1522 throws InstanceNotFoundException { |
1514 |
1523 |
1515 if (loaderName == null) { |
1524 if (loaderName == null) { |
1516 checkMBeanPermission((String) null, null, null, "getClassLoader"); |
1525 checkMBeanPermission(mbeanServerName, (String) null, null, null, "getClassLoader"); |
1517 return server.getClass().getClassLoader(); |
1526 return server.getClass().getClassLoader(); |
1518 } |
1527 } |
1519 |
1528 |
1520 DynamicMBean instance = getMBean(loaderName); |
1529 DynamicMBean instance = getMBean(loaderName); |
1521 checkMBeanPermission(instance, null, loaderName, "getClassLoader"); |
1530 checkMBeanPermission(mbeanServerName, instance, null, loaderName, |
|
1531 "getClassLoader"); |
1522 |
1532 |
1523 Object resource = getResource(instance); |
1533 Object resource = getResource(instance); |
1524 |
1534 |
1525 /* Check if the given MBean is a ClassLoader */ |
1535 /* Check if the given MBean is a ClassLoader */ |
1526 if (!(resource instanceof ClassLoader)) |
1536 if (!(resource instanceof ClassLoader)) |
1815 return ((DynamicMBean2) mbean).getClassName(); |
1825 return ((DynamicMBean2) mbean).getClassName(); |
1816 else |
1826 else |
1817 return mbean.getMBeanInfo().getClassName(); |
1827 return mbean.getMBeanInfo().getClassName(); |
1818 } |
1828 } |
1819 |
1829 |
1820 private static void checkMBeanPermission(DynamicMBean mbean, |
1830 private static void checkMBeanPermission(String mbeanServerName, |
|
1831 DynamicMBean mbean, |
1821 String member, |
1832 String member, |
1822 ObjectName objectName, |
1833 ObjectName objectName, |
1823 String actions) { |
1834 String actions) { |
1824 SecurityManager sm = System.getSecurityManager(); |
1835 SecurityManager sm = System.getSecurityManager(); |
1825 if (sm != null) { |
1836 if (sm != null) { |
1826 checkMBeanPermission(safeGetClassName(mbean), |
1837 checkMBeanPermission(mbeanServerName, |
|
1838 safeGetClassName(mbean), |
1827 member, |
1839 member, |
1828 objectName, |
1840 objectName, |
1829 actions); |
1841 actions); |
1830 } |
1842 } |
1831 } |
1843 } |
1832 |
1844 |
1833 private static void checkMBeanPermission(String classname, |
1845 private static void checkMBeanPermission(String mbeanServerName, |
|
1846 String classname, |
1834 String member, |
1847 String member, |
1835 ObjectName objectName, |
1848 ObjectName objectName, |
1836 String actions) { |
1849 String actions) { |
1837 SecurityManager sm = System.getSecurityManager(); |
1850 SecurityManager sm = System.getSecurityManager(); |
1838 if (sm != null) { |
1851 if (sm != null) { |
1839 Permission perm = new MBeanPermission(classname, |
1852 Permission perm = new MBeanPermission(mbeanServerName, |
|
1853 classname, |
1840 member, |
1854 member, |
1841 objectName, |
1855 objectName, |
1842 actions); |
1856 actions); |
1843 sm.checkPermission(perm); |
1857 sm.checkPermission(perm); |
1844 } |
1858 } |
1900 final DynamicMBean object, |
1914 final DynamicMBean object, |
1901 final ObjectName logicalName) |
1915 final ObjectName logicalName) |
1902 throws InstanceAlreadyExistsException, |
1916 throws InstanceAlreadyExistsException, |
1903 MBeanRegistrationException { |
1917 MBeanRegistrationException { |
1904 |
1918 |
|
1919 // this will throw an exception if the pair (resource, logicalName) |
|
1920 // violates namespace conventions - for instance, if logicalName |
|
1921 // ends with // but resource is not a JMXNamespace. |
|
1922 // |
|
1923 checkResourceObjectNameConstraints(resource, logicalName); |
|
1924 |
1905 // Creates a registration context, if needed. |
1925 // Creates a registration context, if needed. |
1906 // |
1926 // |
1907 final ResourceContext context = |
1927 final ResourceContext context = |
1908 makeResourceContextFor(resource, logicalName); |
1928 makeResourceContextFor(resource, logicalName); |
1909 |
1929 |
1963 } |
1983 } |
1964 |
1984 |
1965 sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION, |
1985 sendNotification(MBeanServerNotification.UNREGISTRATION_NOTIFICATION, |
1966 logicalName); |
1986 logicalName); |
1967 return context; |
1987 return context; |
|
1988 } |
|
1989 |
|
1990 |
|
1991 /** |
|
1992 * Checks that the ObjectName is legal with regards to the |
|
1993 * type of the MBean resource. |
|
1994 * If the MBean name is domain:type=JMXDomain, the |
|
1995 * MBean must be a JMXDomain. |
|
1996 * If the MBean name is namespace//:type=JMXNamespace, the |
|
1997 * MBean must be a JMXNamespace. |
|
1998 * If the MBean is a JMXDomain, its name |
|
1999 * must be domain:type=JMXDomain. |
|
2000 * If the MBean is a JMXNamespace, its name |
|
2001 * must be namespace//:type=JMXNamespace. |
|
2002 */ |
|
2003 private void checkResourceObjectNameConstraints(Object resource, |
|
2004 ObjectName logicalName) |
|
2005 throws MBeanRegistrationException { |
|
2006 try { |
|
2007 dispatcher.checkLocallyRegistrable(resource, logicalName); |
|
2008 } catch (Throwable x) { |
|
2009 DefaultMBeanServerInterceptor.throwMBeanRegistrationException(x, "validating ObjectName"); |
|
2010 } |
|
2011 } |
|
2012 |
|
2013 /** |
|
2014 * Registers a JMXNamespace with the dispatcher. |
|
2015 * This method is called by the ResourceContext from within the |
|
2016 * repository lock. |
|
2017 * @param namespace The JMXNamespace |
|
2018 * @param logicalName The JMXNamespaceMBean ObjectName |
|
2019 * @param postQueue A queue that will be processed after postRegister. |
|
2020 */ |
|
2021 private void addJMXNamespace(JMXNamespace namespace, |
|
2022 final ObjectName logicalName, |
|
2023 final Queue<Runnable> postQueue) { |
|
2024 dispatcher.addNamespace(logicalName, namespace, postQueue); |
|
2025 } |
|
2026 |
|
2027 /** |
|
2028 * Unregisters a JMXNamespace from the dispatcher. |
|
2029 * This method is called by the ResourceContext from within the |
|
2030 * repository lock. |
|
2031 * @param namespace The JMXNamespace |
|
2032 * @param logicalName The JMXNamespaceMBean ObjectName |
|
2033 * @param postQueue A queue that will be processed after postDeregister. |
|
2034 */ |
|
2035 private void removeJMXNamespace(JMXNamespace namespace, |
|
2036 final ObjectName logicalName, |
|
2037 final Queue<Runnable> postQueue) { |
|
2038 dispatcher.removeNamespace(logicalName, namespace, postQueue); |
1968 } |
2039 } |
1969 |
2040 |
1970 /** |
2041 /** |
1971 * Registers a ClassLoader with the CLR. |
2042 * Registers a ClassLoader with the CLR. |
1972 * This method is called by the ResourceContext from within the |
2043 * This method is called by the ResourceContext from within the |
2018 clr.removeClassLoader(logicalName); |
2089 clr.removeClassLoader(logicalName); |
2019 } |
2090 } |
2020 } |
2091 } |
2021 } |
2092 } |
2022 |
2093 |
|
2094 |
|
2095 /** |
|
2096 * Creates a ResourceContext for a JMXNamespace MBean. |
|
2097 * The resource context makes it possible to add the JMXNamespace to |
|
2098 * (ResourceContext.registering) or resp. remove the JMXNamespace from |
|
2099 * (ResourceContext.unregistered) the NamespaceDispatchInterceptor |
|
2100 * when the associated MBean is added to or resp. removed from the |
|
2101 * repository. |
|
2102 * Note: JMXDomains are special sub classes of JMXNamespaces and |
|
2103 * are also handled by this object. |
|
2104 * |
|
2105 * @param namespace The JMXNamespace MBean being registered or |
|
2106 * unregistered. |
|
2107 * @param logicalName The name of the JMXNamespace MBean. |
|
2108 * @return a ResourceContext that takes in charge the addition or removal |
|
2109 * of the namespace to or from the NamespaceDispatchInterceptor. |
|
2110 */ |
|
2111 private ResourceContext createJMXNamespaceContext( |
|
2112 final JMXNamespace namespace, |
|
2113 final ObjectName logicalName) { |
|
2114 final Queue<Runnable> doneTaskQueue = new LinkedList<Runnable>(); |
|
2115 return new ResourceContext() { |
|
2116 |
|
2117 public void registering() { |
|
2118 addJMXNamespace(namespace, logicalName, doneTaskQueue); |
|
2119 } |
|
2120 |
|
2121 public void unregistered() { |
|
2122 removeJMXNamespace(namespace, logicalName, |
|
2123 doneTaskQueue); |
|
2124 } |
|
2125 |
|
2126 public void done() { |
|
2127 for (Runnable r : doneTaskQueue) { |
|
2128 try { |
|
2129 r.run(); |
|
2130 } catch (RuntimeException x) { |
|
2131 MBEANSERVER_LOGGER.log(Level.FINE, |
|
2132 "Failed to process post queue for "+ |
|
2133 logicalName, x); |
|
2134 } |
|
2135 } |
|
2136 } |
|
2137 }; |
|
2138 } |
|
2139 |
2023 /** |
2140 /** |
2024 * Creates a ResourceContext for a ClassLoader MBean. |
2141 * Creates a ResourceContext for a ClassLoader MBean. |
2025 * The resource context makes it possible to add the ClassLoader to |
2142 * The resource context makes it possible to add the ClassLoader to |
2026 * (ResourceContext.registering) or resp. remove the ClassLoader from |
2143 * (ResourceContext.registering) or resp. remove the ClassLoader from |
2027 * (ResourceContext.unregistered) the CLR |
2144 * (ResourceContext.unregistered) the CLR |
2063 * @param logicalName The name of the associated MBean. |
2180 * @param logicalName The name of the associated MBean. |
2064 * @return |
2181 * @return |
2065 */ |
2182 */ |
2066 private ResourceContext makeResourceContextFor(Object resource, |
2183 private ResourceContext makeResourceContextFor(Object resource, |
2067 ObjectName logicalName) { |
2184 ObjectName logicalName) { |
|
2185 if (resource instanceof JMXNamespace) { |
|
2186 return createJMXNamespaceContext((JMXNamespace) resource, |
|
2187 logicalName); |
|
2188 } |
2068 if (resource instanceof ClassLoader) { |
2189 if (resource instanceof ClassLoader) { |
2069 return createClassLoaderContext((ClassLoader) resource, |
2190 return createClassLoaderContext((ClassLoader) resource, |
2070 logicalName); |
2191 logicalName); |
2071 } |
2192 } |
2072 return ResourceContext.NONE; |
2193 return ResourceContext.NONE; |
2073 } |
2194 } |
|
2195 |
|
2196 |
2074 } |
2197 } |