📄 defaultmbeanserverinterceptor.java
字号:
* <li>Finally, if the <code>object</code> implements the * MBeanRegistration interface, it invokes postRegister() * on the object.</li> * </ul> * @param object A reference to a MBean compliant object. * @param name The ObjectName of the <code>object</code> MBean. * @return the actual ObjectName with which the object was registered. * @exception InstanceAlreadyExistsException if an object is already * registered with that name. * @exception MBeanRegistrationException if an exception occurs during * registration. **/ protected ObjectInstance registerObject(String classname, Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { if (object == null) { final RuntimeException wrapped = new IllegalArgumentException("Cannot add null object"); throw new RuntimeOperationsException(wrapped, "Exception occured trying to register the MBean"); } name = nonDefaultDomain(name); if (isTraceOn()) { trace(dbgTag, "registerMBean", "ObjectName = " + name); } ObjectName logicalName = name; if (object instanceof MBeanRegistration) { logicalName = meta.preRegisterInvoker(object, name, server); if (logicalName != name && logicalName != null) { logicalName = ObjectName.getInstance(nonDefaultDomain(logicalName)); } } /* Permission check */ checkMBeanPermission(classname, null, logicalName, "registerMBean"); final ObjectInstance result; if (logicalName!=null) { result = makeObjectInstance(classname, object, logicalName); internal_addObject(object, logicalName); } else { if (object instanceof MBeanRegistration ) { meta.postRegisterInvoker(object, false); } final RuntimeException wrapped = new IllegalArgumentException("No object name specified"); throw new RuntimeOperationsException(wrapped, "Exception occured trying to register the MBean"); } if (object instanceof MBeanRegistration) meta.postRegisterInvoker(object, true); /** * Checks if the newly registered MBean is a ClassLoader * If so, tell the ClassLoaderRepository (CLR) about it. We do * this even if the object is a PrivateClassLoader. In that * case, the CLR remembers the loader for use when it is * explicitly named (e.g. as the loader in createMBean) but * does not add it to the list that is consulted by * ClassLoaderRepository.loadClass. */ if (object instanceof ClassLoader) { final ModifiableClassLoaderRepository clr = instantiator.getClassLoaderRepository(); if (clr == null) { final RuntimeException wrapped = new IllegalArgumentException( "Dynamic addition of class loaders is not supported"); throw new RuntimeOperationsException(wrapped, "Exception occured trying to register the MBean as a class loader"); } clr.addClassLoader(logicalName, (ClassLoader)object); } return result; } /** * Register an object from within createMBean(). * This method wrapps registerObject() and is only called from within * createMBean(). * It calls directly registerObject(). Its only purpose is to provide * hooks for derived classes. **/ protected ObjectInstance registerCreatedObject(String classname, Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { return registerObject(classname,object,name); } /** * Gets a specific MBean controlled by the DefaultMBeanServerInterceptor. * The name must have a non-default domain. */ private Object getMBean(ObjectName name) throws InstanceNotFoundException { if (name == null) { throw new RuntimeOperationsException(new IllegalArgumentException("Object name cannot be null"), "Exception occured trying to get an MBean"); } Object obj = null; synchronized(this) { obj = repository.retrieve(name); if (obj == null) { if (isTraceOn()) { trace("getMBean", name+": Found no object"); } throw new InstanceNotFoundException(name.toString()); } } return obj; } private ObjectName nonDefaultDomain(ObjectName name) { if (name == null || name.getDomain().length() > 0) return name; /* The ObjectName looks like ":a=b", and that's what its toString() will return in this implementation. So we can just stick the default domain in front of it to get a non-default-domain name. We depend on the fact that toString() works like that and that it leaves wildcards in place (so we can detect an error if one is supplied where it shouldn't be). */ final String completeName = domain + name; try { return new ObjectName(completeName); } catch (MalformedObjectNameException e) { final String msg = "Unexpected default domain problem: " + completeName + ": " + e; throw new IllegalArgumentException(msg); } } public String getDefaultDomain() { return domain; } /* * Notification handling. * * This is not trivial, because the MBeanServer translates the * source of a received notification from a reference to an MBean * into the ObjectName of that MBean. While that does make * notification sending easier for MBean writers, it comes at a * considerable cost. We need to replace the source of a * notification, which is basically wrong if there are also * listeners registered directly with the MBean (without going * through the MBean server). We also need to wrap the listener * supplied by the client of the MBeanServer with a listener that * performs the substitution before forwarding. This is why we * strongly discourage people from putting MBean references in the * source of their notifications. Instead they should arrange to * put the ObjectName there themselves. * * However, existing code relies on the substitution, so we are * stuck with it. * * Here's how we handle it. When you add a listener, we make a * ListenerWrapper around it. We look that up in the * listenerWrappers map, and if there was already a wrapper for * that listener with the given ObjectName, we reuse it. This map * is a WeakHashMap, so a listener that is no longer registered * with any MBean can be garbage collected. * * We cannot use simpler solutions such as always creating a new * wrapper or always registering the same listener with the MBean * and using the handback to find the client's original listener. * The reason is that we need to support the removeListener * variant that removes all (listener,filter,handback) triples on * a broadcaster that have a given listener. And we do not have * any way to inspect a broadcaster's internal list of triples. * So the same client listener must always map to the same * listener registered with the broadcaster. * * Another possible solution would be to map from ObjectName to * list of listener wrappers (or IdentityHashMap of listener * wrappers), making this list the first time a listener is added * on a given MBean, and removing it when the MBean is removed. * This is probably more costly in memory, but could be useful if * some day we don't want to rely on weak references. */ public void addNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException { // ------------------------------ // ------------------------------ if (isTraceOn()) { trace("addNotificationListener", "obj= " + name); } /* Permission check */ Object instance = getMBean(name); String classname = null; try { classname = meta.getMBeanClassName(instance); } catch (IntrospectionException e) { classname = null; } catch (NotCompliantMBeanException e) { classname = null; } checkMBeanPermission(classname, null, name, "addNotificationListener"); NotificationBroadcaster broadcaster; if (!(instance instanceof NotificationBroadcaster)) { throw new RuntimeOperationsException(new IllegalArgumentException(name.getCanonicalName() ), "The MBean " + name.getCanonicalName() + " does not implement the NotificationBroadcaster interface"); } broadcaster = (NotificationBroadcaster) instance; // ------------------ // Check listener // ------------------ if (listener == null) { throw new RuntimeOperationsException(new IllegalArgumentException("Null listener"),"Null listener"); } NotificationListener listenerWrapper = getListenerWrapper(listener, name, instance, true); broadcaster.addNotificationListener(listenerWrapper, filter, handback); } public void addNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException { // ------------------------------ // ------------------------------ // ---------------- // Get listener object // ---------------- Object instance = getMBean(listener); if (!(instance instanceof NotificationListener)) { throw new RuntimeOperationsException(new IllegalArgumentException(listener.getCanonicalName()), "The MBean " + listener.getCanonicalName() + "does not implement the NotificationListener interface") ; } // ---------------- // Add a listener on an MBean // ---------------- if (isTraceOn()) { trace("addNotificationListener", "obj= " + name + " listener= " + listener); } server.addNotificationListener(name,(NotificationListener) instance, filter, handback) ; } public void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException { removeNotificationListener(name, listener, null, null, true); } public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException { removeNotificationListener(name, listener, filter, handback, false); } public void removeNotificationListener(ObjectName name, ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException { NotificationListener instance = getListener(listener); if (isTraceOn()) { trace("removeNotificationListener", "obj= " + name + " listener= " + listener); } server.removeNotificationListener(name, instance); } public void removeNotificationListener(ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException { NotificationListener instance = getListener(listener); if (isTraceOn()) { trace("removeNotificationListener", "obj= " + name + " listener= " + listener); } server.removeNotificationListener(name, instance, filter, handback); } private NotificationListener getListener(ObjectName listener) throws ListenerNotFoundException { // ---------------- // Get listener object // ---------------- final Object instance; try { instance = getMBean(listener); } catch (InstanceNotFoundException e) { throw new ListenerNotFoundException(e.getMessage()) ; } if (!(instance instanceof NotificationListener)) { final RuntimeException exc = new IllegalArgumentException(listener.getCanonicalName()); final String msg = "MBean " + listener.getCanonicalName() + " does not " + "implement " + NotificationListener.class.getName(); throw new RuntimeOperationsException(exc, msg); } return (NotificationListener) instance; } private void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback, boolean removeAll) throws InstanceNotFoundException, ListenerNotFoundException { if (isTraceOn()) { trace("removeNotificationListener", "obj= " + name); } /* Permission check */ Object instance = getMBean(name); String classname = null; try { classname = meta.getMBeanClassName(instance); } catch (IntrospectionException e) { classname = null; } catch (NotCompliantMBeanException e) { classname = null; } checkMBeanPermission(classname, null, name, "removeNotificationListener"); /* We could simplify the code by assigning broadcaster after assigning listenerWrapper, but that would change the error behaviour when both the broadcaster and the listener are erroneous. */ NotificationBroadcaster broadcaster = null; NotificationEmitter emitter = null; if (removeAll) { if (!(instance instanceof NotificationBroadcaster)) { final RuntimeException exc = new IllegalArgumentException(name.getCanonicalName()); final String msg = "MBean " + name.getCanonicalName() + " does not " + "implement " + NotificationBroadcaster.class.getName(); throw new RuntimeOperationsException(exc, msg); } broadcaster = (NotificationBroadcaster) instance; } else { if (!(instance instanceof NotificationEmitter)) { final RuntimeException exc = new IllegalArgumentException(name.getCanonicalName()); final String msg = "MBean " + name.getCanonicalName() + " does not " + "implement " + NotificationEmitter.class.getName(); throw new RuntimeOperationsException(exc, msg); } emitter = (NotificationEmitter) instance; } NotificationListener listenerWrapper = getListenerWrapper(listener, name, instance, false); if (listenerWrapper == null) throw new ListenerNotFoundException("Unknown listener"); if (removeAll) broadcaster.removeNotificationListener(listenerWrapper); else { emitter.removeNotificationListener(listenerWrapper, filter, handback); } } public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, IntrospectionException, ReflectionException { // ------------------------------ // ------------------------------ Object moi = getMBean(name); final MBeanInfo mbi = meta.getMBeanInfo(moi); if (mbi == null) throw new JMRuntimeException("MBean " + name + "has no MBeanInfo"); /* Permission check */ checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo"); return mbi; } public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException { /* Permission check */ Object instance = getMBean(name); String classname = null; try { classname = meta.getMBeanClassName(instance); } catch (IntrospectionException e) { classname = null; } catch (NotCompliantMBeanException e) { classname = null; } checkMBeanPermission(classname, null, name, "isInstanceOf"); try { return meta.isInstanceOf(instance, className); } catch (ReflectionException e) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -