/* * (c) Rob Gordon 2005 */ package org.oddjob.jmx.handlers; import java.io.Serializable; import java.lang.reflect.UndeclaredThrowableException; import java.util.ArrayList; import java.util.List; import javax.management.MBeanAttributeInfo; import javax.management.MBeanException; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.Notification; import javax.management.ObjectName; import javax.management.ReflectionException; import org.oddjob.arooa.convert.ArooaConversionException; import org.oddjob.arooa.reflect.ArooaPropertyException; import org.oddjob.arooa.registry.BeanDirectory; import org.oddjob.arooa.registry.BeanDirectoryOwner; import org.oddjob.arooa.registry.ServerId; import org.oddjob.jmx.RemoteDirectory; import org.oddjob.jmx.RemoteDirectoryOwner; import org.oddjob.jmx.RemoteOperation; import org.oddjob.jmx.client.ClientHandlerResolver; import org.oddjob.jmx.client.ClientInterfaceHandlerFactory; import org.oddjob.jmx.client.ClientSideToolkit; import org.oddjob.jmx.client.HandlerVersion; import org.oddjob.jmx.client.SimpleHandlerResolver; import org.oddjob.jmx.server.JMXOperationPlus; import org.oddjob.jmx.server.ServerInterfaceHandler; import org.oddjob.jmx.server.ServerInterfaceHandlerFactory; import org.oddjob.jmx.server.ServerSideToolkit; public class BeanDirectoryHandlerFactory implements ServerInterfaceHandlerFactory<BeanDirectoryOwner, RemoteDirectoryOwner> { public static final HandlerVersion VERSION = new HandlerVersion(1, 0); private static final JMXOperationPlus<ServerId> SERVER_ID = new JMXOperationPlus<ServerId>( "serverId", "Get ServerId.", ServerId.class, MBeanOperationInfo.INFO); private static final JMXOperationPlus<ObjectName[]> LIST = new JMXOperationPlus<ObjectName[]>( "beansList", "List Beans.", ObjectName[].class, MBeanOperationInfo.INFO); private static final JMXOperationPlus<String> ID_FOR = new JMXOperationPlus<String>( "beansIdFor", "Id For ObjectName.", String.class, MBeanOperationInfo.INFO) .addParam("objectName", ObjectName.class, "The object name."); private static final JMXOperationPlus<Object> LOOKUP = new JMXOperationPlus<Object>( "beansLookup", "Object lookup.", Object.class, MBeanOperationInfo.INFO) .addParam("id", String.class, "The id."); private static final JMXOperationPlus<Object> LOOKUP_TYPE = new JMXOperationPlus<Object>( "beansLookupType", "Object lookup.", Object.class, MBeanOperationInfo.INFO) .addParam("id", String.class, "The id.") .addParam("type", Class.class, "The type."); public Class<BeanDirectoryOwner> interfaceClass() { return BeanDirectoryOwner.class; } public MBeanAttributeInfo[] getMBeanAttributeInfo() { return new MBeanAttributeInfo[0]; } public MBeanOperationInfo[] getMBeanOperationInfo() { return new MBeanOperationInfo[] { SERVER_ID.getOpInfo(), LIST.getOpInfo(), ID_FOR.getOpInfo(), LOOKUP.getOpInfo(), LOOKUP_TYPE.getOpInfo() }; } public MBeanNotificationInfo[] getMBeanNotificationInfo() { return new MBeanNotificationInfo[0]; } public ClientHandlerResolver<RemoteDirectoryOwner> clientHandlerFactory() { return new SimpleHandlerResolver<RemoteDirectoryOwner>( ClientBeanDirectoryHandlerFactory.class.getName(), VERSION); } public static class ClientBeanDirectoryHandlerFactory implements ClientInterfaceHandlerFactory<RemoteDirectoryOwner> { public Class<RemoteDirectoryOwner> interfaceClass() { return RemoteDirectoryOwner.class; } public HandlerVersion getVersion() { return VERSION; } public RemoteDirectoryOwner createClientHandler(RemoteDirectoryOwner ignored, ClientSideToolkit toolkit) { return new ClientBeanDirectoryHandler(toolkit); } } static class ClientBeanDirectoryHandler implements RemoteDirectoryOwner { private final ClientSideToolkit toolkit; ClientBeanDirectoryHandler(ClientSideToolkit toolkit) { this.toolkit = toolkit; } public RemoteDirectory provideBeanDirectory() { return new RemoteDirectory() { private ServerId serverId; public Object lookup(String path) { try { Object result = toolkit.invoke(LOOKUP, new Object[] { path }); if (result instanceof Carrier) { return toolkit.getClientSession().create( ((Carrier) result).getObjectName()); } else { return result; } } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } public <T> T lookup(String path, Class<T> required) throws ArooaConversionException { try { Object result = toolkit.invoke(LOOKUP_TYPE, new Object[] { path, required }); if (result instanceof Carrier) { result = toolkit.getClientSession().create( ((Carrier) result).getObjectName()); } return required.cast(result); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } public String getIdFor(Object bean) { ObjectName objectName = toolkit.getClientSession().nameFor(bean); if (objectName == null) { return null; } try { return toolkit.invoke(ID_FOR, new Object[] { objectName }); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } public <T> Iterable<T> getAllByType(Class<T> type) { try { ObjectName[] names = toolkit.invoke(LIST, new Object[] { type }); if (names == null) { return new ArrayList<T>(); } List<T> results = new ArrayList<T>(); for (ObjectName objectName : names) { Object object = toolkit.getClientSession().create( objectName); if (object == null) { continue; } results.add(type.cast(object)); } return results; } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } public ServerId getServerId() { if (serverId == null) { try { this.serverId = toolkit.invoke(SERVER_ID, new Object[] {}); } catch (Throwable e) { throw new UndeclaredThrowableException(e); } } return serverId; } }; } } public ServerInterfaceHandler createServerHandler(BeanDirectoryOwner directory, ServerSideToolkit serverToolkit) { ServerBeanDirectoryHandler handler = new ServerBeanDirectoryHandler( directory, serverToolkit); return handler; } class ServerBeanDirectoryHandler implements ServerInterfaceHandler { private final BeanDirectoryOwner directoryOwner; private final ServerSideToolkit serverToolkit; ServerBeanDirectoryHandler(BeanDirectoryOwner directory, ServerSideToolkit ojmb) { this.directoryOwner = directory; this.serverToolkit = ojmb; } public Notification[] getLastNotifications() { return null; } public Object invoke(RemoteOperation<?> operation, Object[] params) throws MBeanException, ReflectionException, ArooaPropertyException { if (SERVER_ID.equals(operation)) { return serverToolkit.getContext().getServerId(); } BeanDirectory directory = directoryOwner.provideBeanDirectory(); if (directory == null) { return null; } if (LIST.equals(operation)) { Class<?> type = (Class<?>) params[0]; Iterable<?> all = directory.getAllByType(type); List<ObjectName> names = new ArrayList<ObjectName>(); for (Object object : all) { ObjectName name = serverToolkit.getServerSession().nameFor(object); if (name != null) { names.add(name); } } return names.toArray(new ObjectName[0]); } if (ID_FOR.equals(operation)) { ObjectName objectName = (ObjectName) params[0]; Object object = serverToolkit.getServerSession().objectFor(objectName); if (object == null) { // This will happen when a job tree is changin quicker on the server than // the client can keep up with. return null; } else { String id = directory.getIdFor(object); return id; } } if (LOOKUP.equals(operation)) { String path = (String) params[0]; Object object = directory.lookup(path); if (object == null) { return null; } ObjectName objectName = serverToolkit.getServerSession().nameFor(object); if (objectName != null) { return new Carrier(objectName); } else { return object; } } if (LOOKUP_TYPE.equals(operation)) { String path = (String) params[0]; Class<?> type = (Class<?>) params[1]; Object object = null; try { object = directory.lookup(path, type); } catch (ArooaConversionException e) { throw new MBeanException(e); } if (object == null) { return null; } ObjectName objectName = serverToolkit.getServerSession().nameFor(object); if (objectName != null) { return new Carrier(objectName); } else { return object; } } throw new ReflectionException(new IllegalStateException( "invoked for an unknown method."), operation.toString()); } public void destroy() { } } static class Carrier implements Serializable { private static final long serialVersionUID = 2009061500L; private final ObjectName objectName; Carrier(ObjectName objectName) { this.objectName = objectName; } ObjectName getObjectName() { return objectName; } } }