|
Java example source code file (OldMBeanServerTest.java)
The OldMBeanServerTest.java Java example source code/* * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.management.ManagementFactory; import java.lang.ref.WeakReference; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.Callable; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.IntrospectionException; import javax.management.InvalidAttributeValueException; import javax.management.ListenerNotFoundException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanRegistration; import javax.management.MBeanRegistrationException; import javax.management.MBeanServer; import javax.management.MBeanServerBuilder; import javax.management.MBeanServerConnection; import javax.management.MBeanServerDelegate; import javax.management.MBeanServerFactory; import javax.management.MBeanServerNotification; import javax.management.MalformedObjectNameException; import javax.management.NotCompliantMBeanException; import javax.management.Notification; import javax.management.NotificationBroadcaster; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectInstance; import javax.management.ObjectName; import javax.management.OperationsException; import javax.management.QueryEval; import javax.management.QueryExp; import javax.management.ReflectionException; import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.StandardMBean; import javax.management.loading.ClassLoaderRepository; import javax.management.remote.JMXConnector; import javax.management.remote.JMXConnectorFactory; import javax.management.remote.JMXConnectorServer; import javax.management.remote.JMXConnectorServerFactory; import javax.management.remote.JMXServiceURL; /* * @test OldMBeanServerTest.java * @bug 5072268 * @summary Test that nothing assumes a post-1.2 MBeanServer * @author Eamonn McManus * @run main/othervm -ea OldMBeanServerTest */ /* * We defined the MBeanServerBuilder class and the associated system * property javax.management.builder.initial in version 1.2 of the JMX * spec. That amounts to a guarantee that someone can set the property * to an MBeanServer that only knows about JMX 1.2 semantics, and if they * only do JMX 1.2 operations, everything should work. This test is a * sanity check that ensures we don't inadvertently make any API changes * that stop that from being true. It includes a complete (if slow) * MBeanServer implementation. That implementation doesn't replicate the * mandated exception behaviour everywhere, though, since there's lots of * arbitrary cruft in that. Also, the behaviour of concurrent unregisterMBean * calls is incorrect in detail. */ public class OldMBeanServerTest { private static MBeanServerConnection mbsc; private static String failure; public static void main(String[] args) throws Exception { if (!OldMBeanServerTest.class.desiredAssertionStatus()) throw new Exception("Test must be run with -ea"); System.setProperty("javax.management.builder.initial", OldMBeanServerBuilder.class.getName()); assert MBeanServerFactory.newMBeanServer() instanceof OldMBeanServer; System.out.println("=== RUNNING TESTS WITH LOCAL MBEANSERVER ==="); runTests(new Callable<MBeanServerConnection>() { public MBeanServerConnection call() { return MBeanServerFactory.newMBeanServer(); } }, null); System.out.println("=== RUNNING TESTS THROUGH CONNECTOR ==="); ConnectionBuilder builder = new ConnectionBuilder(); runTests(builder, builder); if (failure == null) System.out.println("TEST PASSED"); else throw new Exception("TEST FAILED: " + failure); } private static class ConnectionBuilder implements Callable<MBeanServerConnection>, Runnable { private JMXConnector connector; public MBeanServerConnection call() { MBeanServer mbs = MBeanServerFactory.newMBeanServer(); try { JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://"); JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer( url, null, mbs); cs.start(); JMXServiceURL addr = cs.getAddress(); connector = JMXConnectorFactory.connect(addr); return connector.getMBeanServerConnection(); } catch (IOException e) { throw new RuntimeException(e); } } public void run() { if (connector != null) { try { connector.close(); } catch (IOException e) { throw new RuntimeException(e); } } } } private static void runTests( Callable<MBeanServerConnection> maker, Runnable breaker) throws Exception { for (Method m : OldMBeanServerTest.class.getDeclaredMethods()) { if (Modifier.isStatic(m.getModifiers()) && m.getName().startsWith("test") && m.getParameterTypes().length == 0) { ExpectException expexc = m.getAnnotation(ExpectException.class); mbsc = maker.call(); try { m.invoke(null); if (expexc != null) { failure = m.getName() + " did not got expected exception " + expexc.value().getName(); System.out.println(failure); } else System.out.println(m.getName() + " OK"); } catch (InvocationTargetException ite) { Throwable t = ite.getCause(); String prob = null; if (expexc != null) { if (expexc.value().isInstance(t)) { System.out.println(m.getName() + " OK (got expected " + expexc.value().getName() + ")"); } else prob = "got wrong exception"; } else prob = "got exception"; if (prob != null) { failure = m.getName() + ": " + prob + " " + t.getClass().getName(); System.out.println(failure); t.printStackTrace(System.out); } } finally { if (breaker != null) breaker.run(); } } } } @Retention(RetentionPolicy.RUNTIME) private static @interface ExpectException { Class<? extends Exception> value(); } public static interface BoringMBean { public String getName(); public int add(int x, int y); } // This class is Serializable so we can createMBean a StandardMBean // that contains it. Not recommended practice in general -- // should we have a StandardMBean constructor that takes a class // name and constructor parameters? public static class Boring implements BoringMBean, Serializable { public String getName() { return "Jessica"; } public int add(int x, int y) { return x + y; } } public static interface BoringNotifierMBean extends BoringMBean { public void send(); } public static class BoringNotifier extends Boring implements BoringNotifierMBean, NotificationBroadcaster { private final NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport(); public void addNotificationListener( NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { nbs.addNotificationListener(listener, filter, handback); } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { nbs.removeNotificationListener(listener); } public MBeanNotificationInfo[] getNotificationInfo() { return null; } public void send() { Notification n = new Notification("type.type", this, 0L); nbs.sendNotification(n); } } private static class CountListener implements NotificationListener { volatile int count; public void handleNotification(Notification n, Object h) { if (h == null) h = 1; count += (Integer) h; } void waitForCount(int expect) throws InterruptedException { long deadline = System.currentTimeMillis() + 2000L; while (count < expect && System.currentTimeMillis() < deadline) Thread.sleep(1); assert count == expect; } } private static void testBasic() throws Exception { CountListener countListener = new CountListener(); mbsc.addNotificationListener( MBeanServerDelegate.DELEGATE_NAME, countListener, null, null); assert countListener.count == 0; ObjectName name = new ObjectName("a:b=c"); if (mbsc instanceof MBeanServer) ((MBeanServer) mbsc).registerMBean(new Boring(), name); else mbsc.createMBean(Boring.class.getName(), name); countListener.waitForCount(1); assert mbsc.isRegistered(name); assert mbsc.queryNames(null, null).contains(name); assert mbsc.getAttribute(name, "Name").equals("Jessica"); assert mbsc.invoke( name, "add", new Object[] {2, 3}, new String[] {"int", "int"}) .equals(5); mbsc.unregisterMBean(name); countListener.waitForCount(2); assert !mbsc.isRegistered(name); assert !mbsc.queryNames(null, null).contains(name); mbsc.createMBean(BoringNotifier.class.getName(), name); countListener.waitForCount(3); CountListener boringListener = new CountListener(); class AlwaysNotificationFilter implements NotificationFilter { public boolean isNotificationEnabled(Notification notification) { return true; } } mbsc.addNotificationListener( name, boringListener, new AlwaysNotificationFilter(), 5); mbsc.invoke(name, "send", null, null); boringListener.waitForCount(5); } private static void testPrintAttrs() throws Exception { printAttrs(mbsc, null); } private static void testPlatformMBeanServer() throws Exception { MBeanServer pmbs = ManagementFactory.getPlatformMBeanServer(); assert pmbs instanceof OldMBeanServer; // Preceding assertion could be violated if at some stage we wrap // the Platform MBeanServer. In that case we can still check that // it is ultimately an OldMBeanServer for example by adding a // counter to getAttribute and checking that it is incremented // when we call pmbs.getAttribute. printAttrs(pmbs, UnsupportedOperationException.class); ObjectName memoryMXBeanName = new ObjectName(ManagementFactory.MEMORY_MXBEAN_NAME); pmbs.invoke(memoryMXBeanName, "gc", null, null); } private static void printAttrs( MBeanServerConnection mbsc1, Class<? extends Exception> expectX) throws Exception { Set<ObjectName> names = mbsc1.queryNames(null, null); for (ObjectName name : names) { System.out.println(name + ":"); MBeanInfo mbi = mbsc1.getMBeanInfo(name); MBeanAttributeInfo[] mbais = mbi.getAttributes(); for (MBeanAttributeInfo mbai : mbais) { String attr = mbai.getName(); Object value; try { value = mbsc1.getAttribute(name, attr); } catch (Exception e) { if (expectX != null && expectX.isInstance(e)) value = "<" + e + ">"; else throw e; } String s = " " + attr + " = " + value; if (s.length() > 80) s = s.substring(0, 77) + "..."; System.out.println(s); } } } private static void testJavaxManagementStandardMBean() throws Exception { ObjectName name = new ObjectName("a:b=c"); Object mbean = new StandardMBean(new Boring(), BoringMBean.class); mbsc.createMBean( StandardMBean.class.getName(), name, new Object[] {new Boring(), BoringMBean.class}, new String[] {Object.class.getName(), Class.class.getName()}); assert mbsc.getAttribute(name, "Name").equals("Jessica"); assert mbsc.invoke( name, "add", new Object[] {2, 3}, new String[] {"int", "int"}) .equals(5); mbsc.unregisterMBean(name); } private static void testConnector() throws Exception { } public static class OldMBeanServerBuilder extends MBeanServerBuilder { public MBeanServer newMBeanServer( String defaultDomain, MBeanServer outer, MBeanServerDelegate delegate) { return new OldMBeanServer(defaultDomain, delegate); } } public static class OldMBeanServer implements MBeanServer { // We pretend there's a ClassLoader MBean representing the Class Loader // Repository and intercept references to it where necessary to keep up // the pretence. This allows us to fake the right behaviour for // the omitted-ClassLoader versions of createMBean and instantiate // (which are not the same as passing a null for the ClassLoader parameter // of the versions that have one). private static final ObjectName clrName; static { try { clrName = new ObjectName("JMImplementation:type=ClassLoaderRepository"); } catch (MalformedObjectNameException e) { throw new RuntimeException(e); } } private final ConcurrentMap<ObjectName, DynamicMBean> mbeans = new ConcurrentHashMap<ObjectName, DynamicMBean>(); private final ConcurrentMap<ObjectName, ListenerTable> listenerMap = new ConcurrentHashMap<ObjectName, ListenerTable>(); private final String defaultDomain; private final MBeanServerDelegate delegate; private final ClassLoaderRepositoryImpl clr = new ClassLoaderRepositoryImpl(); OldMBeanServer(String defaultDomain, MBeanServerDelegate delegate) { this.defaultDomain = defaultDomain; this.delegate = delegate; try { registerMBean(delegate, MBeanServerDelegate.DELEGATE_NAME); } catch (Exception e) { throw new RuntimeException(e); } } public ObjectInstance createMBean(String className, ObjectName name) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException { return createMBean(className, name, null, null); } public ObjectInstance createMBean( String className, ObjectName name, ObjectName loaderName) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { return createMBean(className, name, loaderName, null, null); } public ObjectInstance createMBean( String className, ObjectName name, Object[] params, String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException { try { return createMBean(className, name, clrName, params, signature); } catch (InstanceNotFoundException ex) { throw new RuntimeException(ex); // can't happen } } public ObjectInstance createMBean( String className, ObjectName name, ObjectName loaderName, Object[] params, String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException { Object mbean = instantiate(className, loaderName, params, signature); return registerMBean(mbean, name); } private void forbidJMImpl(ObjectName name) { if (name.getDomain().equals("JMImplementation") && mbeans.containsKey(MBeanServerDelegate.DELEGATE_NAME)) throw new IllegalArgumentException("JMImplementation reserved"); } public ObjectInstance registerMBean(Object object, ObjectName name) throws InstanceAlreadyExistsException, MBeanRegistrationException, NotCompliantMBeanException { forbidJMImpl(name); if (name.isPattern()) throw new IllegalArgumentException(name.toString()); // This is the only place we check for wildcards. Since you // can't register a wildcard name, other operations that supply // one will get InstanceNotFoundException when they look it up. DynamicMBean mbean; if (object instanceof DynamicMBean) mbean = (DynamicMBean) object; else mbean = standardToDynamic(object); MBeanRegistration reg = mbeanRegistration(object); try { name = reg.preRegister(this, name); } catch (Exception e) { throw new MBeanRegistrationException(e); } DynamicMBean put = mbeans.putIfAbsent(name, mbean); if (put != null) { reg.postRegister(false); throw new InstanceAlreadyExistsException(name.toString()); } reg.postRegister(true); if (object instanceof ClassLoader) clr.addLoader((ClassLoader) object); Notification n = new MBeanServerNotification( MBeanServerNotification.REGISTRATION_NOTIFICATION, MBeanServerDelegate.DELEGATE_NAME, 0, name); delegate.sendNotification(n); String className = mbean.getMBeanInfo().getClassName(); return new ObjectInstance(name, className); } public void unregisterMBean(ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException { forbidJMImpl(name); DynamicMBean mbean = getMBean(name); if (mbean == null) throw new InstanceNotFoundException(name.toString()); MBeanRegistration reg = mbeanRegistration(mbean); try { reg.preDeregister(); } catch (Exception e) { throw new MBeanRegistrationException(e); } if (!mbeans.remove(name, mbean)) throw new InstanceNotFoundException(name.toString()); // This is incorrect because we've invoked preDeregister Object userMBean = getUserMBean(mbean); if (userMBean instanceof ClassLoader) clr.removeLoader((ClassLoader) userMBean); Notification n = new MBeanServerNotification( MBeanServerNotification.REGISTRATION_NOTIFICATION, MBeanServerDelegate.DELEGATE_NAME, 0, name); delegate.sendNotification(n); reg.postDeregister(); } public ObjectInstance getObjectInstance(ObjectName name) throws InstanceNotFoundException { DynamicMBean mbean = getMBean(name); return new ObjectInstance(name, mbean.getMBeanInfo().getClassName()); } private static class TrueQueryExp implements QueryExp { public boolean apply(ObjectName name) { return true; } public void setMBeanServer(MBeanServer s) {} } private static final QueryExp trueQuery = new TrueQueryExp(); public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) { Set<ObjectInstance> instances = newSet(); if (name == null) name = ObjectName.WILDCARD; if (query == null) query = trueQuery; MBeanServer oldMBS = QueryEval.getMBeanServer(); try { query.setMBeanServer(this); for (ObjectName n : mbeans.keySet()) { if (name.apply(n)) { try { if (query.apply(n)) instances.add(getObjectInstance(n)); } catch (Exception e) { // OK: Ignore this MBean in the result } } } } finally { query.setMBeanServer(oldMBS); } return instances; } public Set<ObjectName> queryNames(ObjectName name, QueryExp query) { Set<ObjectInstance> instances = queryMBeans(name, query); Set<ObjectName> names = newSet(); for (ObjectInstance instance : instances) names.add(instance.getObjectName()); return names; } public boolean isRegistered(ObjectName name) { return mbeans.containsKey(name); } public Integer getMBeanCount() { return mbeans.size(); } public Object getAttribute(ObjectName name, String attribute) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException { return getMBean(name).getAttribute(attribute); } public AttributeList getAttributes(ObjectName name, String[] attributes) throws InstanceNotFoundException, ReflectionException { return getMBean(name).getAttributes(attributes); } public void setAttribute(ObjectName name, Attribute attribute) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { getMBean(name).setAttribute(attribute); } public AttributeList setAttributes( ObjectName name, AttributeList attributes) throws InstanceNotFoundException, ReflectionException { return getMBean(name).setAttributes(attributes); } public Object invoke( ObjectName name, String operationName, Object[] params, String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException { return getMBean(name).invoke(operationName, params, signature); } public String getDefaultDomain() { return defaultDomain; } public String[] getDomains() { Set<String> domains = newSet(); for (ObjectName name : mbeans.keySet()) domains.add(name.getDomain()); return domains.toArray(new String[0]); } // ClassCastException if MBean is not a NotificationBroadcaster public void addNotificationListener( ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException { NotificationBroadcaster userMBean = (NotificationBroadcaster) getUserMBean(name); NotificationListener wrappedListener = wrappedListener(name, userMBean, listener); userMBean.addNotificationListener(wrappedListener, filter, handback); } public void addNotificationListener( ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException { NotificationListener nl = (NotificationListener) getUserMBean(listener); addNotificationListener(name, nl, filter, handback); } public void removeNotificationListener( ObjectName name, ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException { NotificationListener nl = (NotificationListener) getUserMBean(listener); removeNotificationListener(name, nl); } public void removeNotificationListener( ObjectName name, ObjectName listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException { NotificationListener nl = (NotificationListener) getUserMBean(listener); removeNotificationListener(name, nl, filter, handback); } public void removeNotificationListener( ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException { NotificationBroadcaster userMBean = (NotificationBroadcaster) getUserMBean(name); NotificationListener wrappedListener = wrappedListener(name, userMBean, listener); userMBean.removeNotificationListener(wrappedListener); } public void removeNotificationListener( ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException { NotificationEmitter userMBean = (NotificationEmitter) getMBean(name); NotificationListener wrappedListener = wrappedListener(name, userMBean, listener); userMBean.removeNotificationListener(wrappedListener, filter, handback); } public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, IntrospectionException, ReflectionException { return getMBean(name).getMBeanInfo(); } public boolean isInstanceOf(ObjectName name, String className) throws InstanceNotFoundException { DynamicMBean mbean = getMBean(name); String mbeanClassName = mbean.getMBeanInfo().getClassName(); if (className.equals(mbeanClassName)) return true; ClassLoader loader = getUserMBean(mbean).getClass().getClassLoader(); try { Class<?> mbeanClass = Class.forName(mbeanClassName, false, loader); Class<?> isInstClass = Class.forName(className, false, loader); return isInstClass.isAssignableFrom(mbeanClass); } catch (ClassNotFoundException e) { return false; } } public Object instantiate(String className) throws ReflectionException, MBeanException { return instantiate(className, null, null); } public Object instantiate(String className, ObjectName loaderName) throws ReflectionException, MBeanException, InstanceNotFoundException { return instantiate(className, loaderName, null, null); } public Object instantiate( String className, Object[] params, String[] signature) throws ReflectionException, MBeanException { try { return instantiate(className, clrName, params, signature); } catch (InstanceNotFoundException e) { throw new RuntimeException(e); // can't happen } } public Object instantiate( String className, ObjectName loaderName, Object[] params, String[] signature) throws ReflectionException, MBeanException, InstanceNotFoundException { if (params == null) params = new Object[0]; if (signature == null) signature = new String[0]; ClassLoader loader; if (loaderName == null) loader = this.getClass().getClassLoader(); else if (loaderName.equals(clrName)) loader = clr; else loader = (ClassLoader) getMBean(loaderName); Class<?> c; try { c = Class.forName(className, false, loader); } catch (ClassNotFoundException e) { throw new ReflectionException(e); } Constructor[] constrs = c.getConstructors(); Constructor found = null; findconstr: for (Constructor constr : constrs) { Class<?>[] cTypes = constr.getParameterTypes(); if (cTypes.length == signature.length) { for (int i = 0; i < cTypes.length; i++) { if (!cTypes[i].getName().equals(signature[i])) continue findconstr; } found = constr; break findconstr; } } if (found == null) { Exception x = new NoSuchMethodException( className + Arrays.toString(signature)); throw new ReflectionException(x); } return invokeSomething(found, null, params); } @Deprecated public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException, OperationsException { throw new UnsupportedOperationException(); } @Deprecated public ObjectInputStream deserialize(String className, byte[] data) throws OperationsException, ReflectionException { throw new UnsupportedOperationException(); } @Deprecated public ObjectInputStream deserialize( String className, ObjectName loaderName, byte[] data) throws InstanceNotFoundException, OperationsException, ReflectionException { throw new UnsupportedOperationException(); } public ClassLoader getClassLoaderFor(ObjectName mbeanName) throws InstanceNotFoundException { DynamicMBean mbean = getMBean(mbeanName); Object userMBean = getUserMBean(mbean); return userMBean.getClass().getClassLoader(); } public ClassLoader getClassLoader(ObjectName loaderName) throws InstanceNotFoundException { return (ClassLoader) getMBean(loaderName); } public ClassLoaderRepository getClassLoaderRepository() { return new ClassLoaderRepository() { public Class<?> loadClass(String className) throws ClassNotFoundException { return clr.loadClass(className); } public Class<?> loadClassWithout( ClassLoader exclude, String className) throws ClassNotFoundException { return clr.loadClassWithout(exclude, className); } public Class<?> loadClassBefore( ClassLoader stop, String className) throws ClassNotFoundException { return clr.loadClassBefore(stop, className); } }; } private static class ClassLoaderRepositoryImpl extends ClassLoader implements ClassLoaderRepository { private List<ClassLoader> loaders = newList(); { loaders.add(this.getClass().getClassLoader()); // We also behave as if the system class loader were in // the repository, since we do nothing to stop delegation // to the parent, which is the system class loader, and // that delegation happens before our findClass is called. } void addLoader(ClassLoader loader) { loaders.add(loader); } void removeLoader(ClassLoader loader) { if (!loaders.remove(loader)) throw new RuntimeException("Loader was not in CLR!"); } public Class<?> loadClassWithout( ClassLoader exclude, String className) throws ClassNotFoundException { return loadClassWithoutBefore(exclude, null, className); } public Class<?> loadClassBefore(ClassLoader stop, String className) throws ClassNotFoundException { return loadClassWithoutBefore(null, stop, className); } private Class<?> loadClassWithoutBefore( ClassLoader exclude, ClassLoader stop, String className) throws ClassNotFoundException { for (ClassLoader loader : loaders) { if (loader == exclude) continue; if (loader == stop) break; try { return Class.forName(className, false, loader); } catch (ClassNotFoundException e) { // OK: try others } } throw new ClassNotFoundException(className); } @Override protected Class<?> findClass(String className) throws ClassNotFoundException { return loadClassWithout(null, className); } } /* There is zero or one ListenerTable per MBean. * The ListenerTable stuff is complicated. We want to rewrite the * source of notifications so that if the source of a notification * from the MBean X is a reference to X itself, it gets replaced * by X's ObjectName. To do this, we wrap the user's listener in * a RewriteListener. But if the same listener is added a second * time (perhaps with a different filter or handback) we must * reuse the same RewriteListener so that the two-argument * removeNotificationListener(ObjectName,NotificationListener) will * correctly remove both listeners. This means we must remember the * mapping from listener to WrappedListener. But if the MBean * discards its listeners (as a result of removeNL or spontaneously) * then we don't want to keep a reference to the WrappedListener. * So we have tons of WeakReferences. The key in the ListenerTable * is an IdentityListener, which wraps the user's listener to ensure * that identity and not equality is used during the lookup, even if * the user's listener has an equals method. The value in the * ListenerTable is a WeakReference wrapping a RewriteListener wrapping * the same IdentityListener. Since the RewriteListener is what is * added to the user's MBean, the WeakReference won't disappear as long * as the MBean still has this listener. And since it references the * IdentityListener, that won't disappear either. But once the * RewriteListener is no longer referenced by the user's MBean, * there's nothing to stop its WeakReference from being cleared, * and then corresponding IdentityListener that is now only weakly * referenced from the key in the table. */ private static class ListenerTable extends WeakHashMap<NotificationListener, WeakReference<NotificationListener>> { } private static class IdentityListener implements NotificationListener { private final NotificationListener userListener; IdentityListener(NotificationListener userListener) { this.userListener = userListener; } public void handleNotification( Notification notification, Object handback) { userListener.handleNotification(notification, handback); } @Override public boolean equals(Object o) { return (this == o); } @Override public int hashCode() { return System.identityHashCode(this); } } private static class RewriteListener implements NotificationListener { private final ObjectName name; private final Object userMBean; private final NotificationListener userListener; RewriteListener( ObjectName name, Object userMBean, NotificationListener userListener) { this.name = name; this.userMBean = userMBean; this.userListener = userListener; } public void handleNotification( Notification notification, Object handback) { if (notification.getSource() == userMBean) notification.setSource(name); userListener.handleNotification(notification, handback); } } private NotificationListener wrappedListener( ObjectName name, Object userMBean, NotificationListener userListener) throws InstanceNotFoundException { ListenerTable table = new ListenerTable(); ListenerTable oldTable = listenerMap.putIfAbsent(name, table); if (oldTable != null) table = oldTable; NotificationListener identityListener = new IdentityListener(userListener); synchronized (table) { NotificationListener rewriteListener = null; WeakReference<NotificationListener> wr = table.get(identityListener); if (wr != null) rewriteListener = wr.get(); if (rewriteListener == null) { rewriteListener = new RewriteListener( name, userMBean, identityListener); wr = new WeakReference<NotificationListener>(rewriteListener); table.put(identityListener, wr); } return rewriteListener; } } private DynamicMBean getMBean(ObjectName name) throws InstanceNotFoundException { DynamicMBean mbean = mbeans.get(name); if (mbean == null) throw new InstanceNotFoundException(name.toString()); return mbean; } private static interface WrapDynamicMBean extends DynamicMBean { public Object getWrappedMBean(); } private static class StandardWrapper implements WrapDynamicMBean, MBeanRegistration { private final Map<String, AttrMethods> attrMap = newMap(); private final Map<String, List Other Java examples (source code examples)Here is a short list of links related to this Java OldMBeanServerTest.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2024 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.