User: squirest Date: 02/02/25 18:02:59 Added: src/main/org/jboss/mx/capability AbstractInvocationDispatcher.java DispatcherFactory.java DynamicMBeanDispatcher.java MBeanDelegate.java ReflectedMBeanDispatcher.java ResourceDelegate.java ResourceInvoker.java Removed: src/main/org/jboss/mx/capability AttributeProvider.java MBeanAdapter.java MBeanCapability.java OperationProvider.java StandardMBeanAdapter.java Log: moved and removed stuff. new items will go into capability until a better home can be found Revision Changes Path 1.1 jmx/src/main/org/jboss/mx/capability/AbstractInvocationDispatcher.java Index: AbstractInvocationDispatcher.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import org.jboss.mx.interceptor.InvocationException; import org.jboss.mx.interceptor.MBeanInvocation; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.Notification; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.RuntimeOperationsException; /** * Convenient base class for MBeanDelegates that receive MBeanInvocations * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public abstract class AbstractInvocationDispatcher implements MBeanDelegate { public Object invoke(MBeanInvocation invocation) throws InvocationException { try { Object[] args = invocation.getArgs(); switch (invocation.getOpcode()) { case MBeanInvocation.OPCODE_INVOKE: return this.invoke((String) args[0], (Object[]) args[1], (String[]) args[2]); case MBeanInvocation.OPCODE_GETATTRIBUTE: return this.getAttribute((String) args[0]); case MBeanInvocation.OPCODE_GETATTRIBUTES: return this.getAttributes((String[]) args[0]); case MBeanInvocation.OPCODE_SETATTRIBUTE: this.setAttribute((Attribute) args[0]); return null; case MBeanInvocation.OPCODE_SETATTRIBUTES: return this.setAttributes((AttributeList) args[0]); case MBeanInvocation.OPCODE_GETMBEANINFO: return this.getMBeanInfo(); case MBeanInvocation.OPCODE_ADDNOTIFICATIONLISTENER: this.addNotificationListener((NotificationListener) args[0], (NotificationFilter) args[1], args[2]); return null; case MBeanInvocation.OPCODE_REMOVENOTIFICATIONLISTENER: this.removeNotificationListener((NotificationListener) args[0]); return null; case MBeanInvocation.OPCODE_GETNOTIFICATIONINFO: return this.getNotificationInfo(); case MBeanInvocation.OPCODE_HANDLENOTIFICATION: this.handleNotification((Notification) args[0], args[1]); return null; default: String message = "Invalid Opcode: " + invocation.getOpcode(); throw new InvocationException(new RuntimeOperationsException(new IllegalArgumentException(message)), message); } } catch (InvocationException e) { // just rethrow it throw e; } catch (ClassCastException e) { // FIXME - spec doesn't explicitly mention CCE as wrappable by RuntimeOpEx - is this ok tho? String message = "Exception while unpacking arguments for Opcode: " + MBeanInvocation.REVERSE_OPCODES[invocation.getOpcode()]; throw new InvocationException(new RuntimeOperationsException(e, message), message); } catch (ArrayIndexOutOfBoundsException e) { String message = "Exception while unpacking arguments for Opcode: " + MBeanInvocation.REVERSE_OPCODES[invocation.getOpcode()]; throw new InvocationException(new RuntimeOperationsException(e, message), message); } catch (Exception e) { throw new InvocationException(e, "Exception caught in MBeanTarget.invoke()"); } catch (Error e) { throw new InvocationException(e, "Error caught in MBeanTarget.invoke()"); } } } 1.1 jmx/src/main/org/jboss/mx/capability/DispatcherFactory.java Index: DispatcherFactory.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import org.jboss.mx.metadata.AOResolver; import org.jboss.mx.metadata.MethodMapper; import javax.management.DynamicMBean; import javax.management.IntrospectionException; import javax.management.MBeanAttributeInfo; import javax.management.MBeanInfo; import javax.management.MBeanOperationInfo; import java.lang.reflect.Method; /** * Creates and binds a dispatcher * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public class DispatcherFactory { /** * Creates a Dispatcher for a DynamicMBean */ public static MBeanDelegate create(DynamicMBean mbean) { return new DynamicMBeanDispatcher(mbean); } /** * Creates a Dispatcher for an arbitrary resource. Useful for when you don't care * about the AOResolver. */ public static MBeanDelegate create(MBeanInfo info, Object resource) throws IntrospectionException { return create(info, resource, new AOResolver(info)); } /** * Creates a dispatcher for an arbitrary resource using the named AOResolver. */ public static MBeanDelegate create(MBeanInfo info, Object resource, AOResolver resolver) throws IntrospectionException { if (null == info) { throw new IllegalArgumentException("info cannot be null"); } if (null == resolver) { throw new IllegalArgumentException("resolver cannot be null"); } if (null == resource) { throw new IllegalArgumentException("resource cannot be null"); } MethodMapper mmap = new MethodMapper(resource.getClass()); ReflectedMBeanDispatcher dispatcher = new ReflectedMBeanDispatcher(info, resolver, resource); MBeanAttributeInfo[] attributes = info.getAttributes(); for (int i = 0; i < attributes.length; i++) { MBeanAttributeInfo attribute = attributes[i]; Method getter = null; Method setter = null; if (attribute.isReadable()) { getter = mmap.lookupGetter(attribute); if (getter == null) { throw new IntrospectionException("no getter method found for attribute: " + attribute.getName()); } } if (attribute.isWritable()) { setter = mmap.lookupSetter(attribute); if (setter == null) { throw new IntrospectionException("no setter method found for attribute: " + attribute.getName()); } } dispatcher.bindAttributeAt(i, getter, setter); } MBeanOperationInfo[] operations = info.getOperations(); for (int i = 0; i < operations.length; i++) { MBeanOperationInfo operation = operations[i]; Method method = mmap.lookupOperation(operation); if (method == null) { throw new IntrospectionException("no method found for operation: " + operation.getName()); // FIXME better error! } dispatcher.bindOperationAt(i, method); } return dispatcher; } } 1.1 jmx/src/main/org/jboss/mx/capability/DynamicMBeanDispatcher.java Index: DynamicMBeanDispatcher.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.InvalidAttributeValueException; import javax.management.ListenerNotFoundException; import javax.management.MBeanException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.Notification; import javax.management.NotificationBroadcaster; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ReflectionException; import javax.management.RuntimeOperationsException; /** * This is an InvocationDispatcher which delegates invokes to a DynamicMBean resource. * It's suitable for use as the managed resource of a ModelMBean. * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public class DynamicMBeanDispatcher extends AbstractInvocationDispatcher { private DynamicMBean resource = null; private boolean isBroadcaster = false; private boolean isListener = false; private String resourceClassName = null; public DynamicMBeanDispatcher(DynamicMBean resource) { if (null == resource) { throw new IllegalArgumentException("resource cannot be null"); } if (resource instanceof NotificationBroadcaster) { this.isBroadcaster = true; } if (resource instanceof NotificationListener) { this.isListener = true; } this.resource = resource; this.resourceClassName = resource.getClass().getName(); } public boolean resourceIsNotificationBroadcaster() { return isBroadcaster; } public boolean resourceIsNotificationListener() { return isListener; } public String getResourceClassName() { return resourceClassName; } public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { return resource.getAttribute(attribute); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { resource.setAttribute(attribute); } public AttributeList getAttributes(String[] attributes) { return resource.getAttributes(attributes); } public AttributeList setAttributes(AttributeList attributes) { return resource.setAttributes(attributes); } public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException { return resource.invoke(actionName, params, signature); } public MBeanInfo getMBeanInfo() { return resource.getMBeanInfo(); } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { if (isBroadcaster) { ((NotificationBroadcaster) resource).addNotificationListener(listener, filter, handback); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { if (isBroadcaster) { ((NotificationBroadcaster) resource).removeNotificationListener(listener); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public MBeanNotificationInfo[] getNotificationInfo() { if (isBroadcaster) { return ((NotificationBroadcaster) resource).getNotificationInfo(); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public void handleNotification(Notification notification, Object handback) { if (isListener) { ((NotificationListener) resource).handleNotification(notification, handback); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationListener")); } } } 1.1 jmx/src/main/org/jboss/mx/capability/MBeanDelegate.java Index: MBeanDelegate.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import javax.management.DynamicMBean; import javax.management.NotificationBroadcaster; import javax.management.NotificationListener; /** * An MBeanDelegate knows how to be used via one of the JMX standard interfaces * as well as how to dispatch ResourceInvoker.invoke() calls. * * The MBeanServerImpl uses this interface to dispatch calls to a registered MBean via * the DynamicMBean, NotificationBroadcaster and NotificationListener methods. * * It is important to note that in the case of an interceptor chain, both the head and tail of * the chain will implement this interface. The difference is that at the head, the * implementation will direct calls <i>into</i> the ResourceInvoker.invoke() method while at * the tail, the implementation will dispatch calls <i>from</i> ResourceInvoker.invoke() to * the relevant DynamicMBean, NotificationBroadcaster or NotificationListener method. * * This ensures a resource can be used with or without an invocation chain. * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public interface MBeanDelegate extends ResourceDelegate, DynamicMBean, NotificationBroadcaster, NotificationListener { } 1.1 jmx/src/main/org/jboss/mx/capability/ReflectedMBeanDispatcher.java Index: ReflectedMBeanDispatcher.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import org.jboss.mx.metadata.AOResolver; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; 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.Notification; import javax.management.NotificationBroadcaster; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ReflectionException; import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import javax.management.RuntimeOperationsException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Iterator; /** * Directs MBean and ResourceInvoker calls to underlying resource via reflection. * It's suitable for use as a StandardMBean or as the resource for a ModelMBean. * * However, in the latter case the ModelMBean itself is expected to manage the * MBeanInfo. This makes sense when you consider that any cached attributes must * be returned in the ModelMBeanAttributeInfo descriptors anyhow. * * FIXME THS - currently this class only supports one resource object. I'm actually * expecting that JMX1.1 will remove support for multiple target objects from the * ModelMBean specification. * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public class ReflectedMBeanDispatcher extends AbstractInvocationDispatcher { private Object resource = null; private AOResolver resolver = null; private MBeanConstructorInfo[] constructorInfo = null; private MBeanAttributeInfo[] attributeInfo = null; private MBeanOperationInfo[] operationInfo = null; private Method[] operations = null; private MethodPair[] attributes = null; private boolean isBroadcaster = false; private boolean isListener = false; private String resourceClassName = null; private String resourceDescription = null; public ReflectedMBeanDispatcher(MBeanInfo mbinfo, AOResolver resolver, Object resource) { if (null == resource) { throw new IllegalArgumentException("resource cannot be null"); } if (null == mbinfo) { throw new IllegalArgumentException("MBeanInfo cannot be null"); } if (null == resolver) { throw new IllegalArgumentException("AOresolver cannot be null"); } if (resource instanceof NotificationBroadcaster) { this.isBroadcaster = true; } if (resource instanceof NotificationListener) { this.isListener = true; } this.resource = resource; this.resolver = resolver; this.resourceClassName = mbinfo.getClassName(); this.resourceDescription = mbinfo.getDescription(); this.constructorInfo = mbinfo.getConstructors(); this.attributeInfo = mbinfo.getAttributes(); this.operationInfo = mbinfo.getOperations(); this.operations = new Method[operationInfo.length]; this.attributes = new MethodPair[attributeInfo.length]; } public void bindOperationAt(int position, Method method) { try { operations[position] = method; } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("position out of bounds: " + position); } } public void bindAttributeAt(int position, Method getter, Method setter) { try { attributes[position] = new MethodPair(getter, setter); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("position out of bounds: " + position); } } public boolean resourceIsNotificationBroadcaster() { return isBroadcaster; } public boolean resourceIsNotificationListener() { return isListener; } public String getResourceClassName() { return resourceClassName; } public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException { if (null == attribute) { throw new RuntimeOperationsException(new IllegalArgumentException("attribute cannot be null")); } Method m = null; try { m = attributes[resolver.lookup(attribute).intValue()].getter; return m.invoke(resource, new Object[0]); } catch (NullPointerException e) { throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found"); } catch (ArrayIndexOutOfBoundsException e) { throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found"); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof RuntimeException) { throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean when getting attribute '" + attribute + "'"); } else if (t instanceof Exception) { throw new MBeanException((Exception) t, "Exception in MBean when getting attribute '" + attribute + "'"); } else // it's an error { throw new RuntimeErrorException((Error) t, "Error in MBean when getting attribute '" + attribute + "'"); } } catch (IllegalArgumentException e) { throw new AttributeNotFoundException("Readable attribute '" + attribute + "' not found"); } catch (Exception e) // assume all other exceptions are reflection related { throw new ReflectionException(e, "Exception in AttributeProvider for getting '" + attribute + "'"); } catch (Error e) { throw new RuntimeErrorException(e, "Error in AttributeProvider for getting '" + attribute + "'"); } } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { if (null == attribute) { throw new RuntimeOperationsException(new IllegalArgumentException("attribute cannot be null")); } Method m = null; try { m = attributes[resolver.lookup(attribute.getName()).intValue()].setter; m.invoke(resource, new Object[]{attribute.getValue()}); } catch (NullPointerException e) { throw new AttributeNotFoundException("Writable attribute '" + attribute.getName() + "' not found"); } catch (ArrayIndexOutOfBoundsException e) { throw new AttributeNotFoundException("Writable attribute '" + attribute.getName() + "' not found"); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof RuntimeException) { throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean when setting attribute '" + attribute.getName() + "'"); } else if (t instanceof Exception) { throw new MBeanException((Exception) t, "Exception in MBean when setting attribute '" + attribute.getName() + "'"); } else // it's an error { throw new RuntimeErrorException((Error) t, "Error in MBean when setting attribute '" + attribute.getName() + "'"); } } catch (IllegalArgumentException e) { String valueType = (null == attribute.getValue()) ? "<null value>" : attribute.getValue().getClass().getName(); throw new InvalidAttributeValueException("Attribute value mismatch while setting '" + attribute.getName() + "': " + valueType); } catch (Exception e) // assume all other exceptions are reflection related { throw new ReflectionException(e, "Exception in AttributeProvider for setting '" + attribute.getName() + "'"); } catch (Error e) { throw new RuntimeErrorException(e, "Error in AttributeProvider for setting '" + attribute.getName() + "'"); } } public AttributeList getAttributes(String[] attributes) { if (null == attributes) { throw new RuntimeOperationsException(new IllegalArgumentException("attributes array cannot be null")); } AttributeList list = new AttributeList(); for (int i = 0; i < attributes.length; i++) { try { list.add(new Attribute(attributes[i], getAttribute(attributes[i]))); } catch (Throwable e) { // QUERY - do we *really* just ignore all problems? } } return list; } public AttributeList setAttributes(AttributeList attributes) { if (null == attributes) { throw new RuntimeOperationsException(new IllegalArgumentException("attribute list cannot be null")); } AttributeList list = new AttributeList(); for (Iterator iterator = attributes.iterator(); iterator.hasNext();) { Attribute toSet = (Attribute) iterator.next(); try { setAttribute(toSet); list.add(toSet); } catch (Throwable e) { // QUERY - do we *really* just ignore all problems? } } return list; } public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException { Method m = null; try { m = operations[resolver.lookup(actionName, signature).intValue()]; return m.invoke(resource, params); } catch (NullPointerException e) { throw new ReflectionException(new NoSuchMethodException("Unable to locate method for: " + opKeyString(actionName, signature))); } catch (ArrayIndexOutOfBoundsException e) { throw new ReflectionException(new NoSuchMethodException("Unable to locate method for: " + opKeyString(actionName, signature))); } catch (InvocationTargetException e) { Throwable t = e.getTargetException(); if (t instanceof RuntimeException) { throw new RuntimeMBeanException((RuntimeException) t, "RuntimeException in MBean operation '" + opKeyString(actionName, signature) + "'"); } else if (t instanceof Exception) { throw new MBeanException((Exception) t, "Exception in MBean operation '" + opKeyString(actionName, signature) + "'"); } else // it's an error { throw new RuntimeErrorException((Error) t, "Error in MBean operation '" + opKeyString(actionName, signature) + "'"); } } catch (Exception e) // assume all other exceptions are reflection related { throw new ReflectionException(e, "Exception when calling method for '" + opKeyString(actionName, signature) + "'"); } catch (Error e) { throw new RuntimeErrorException(e, "Error when calling method for '" + opKeyString(actionName, signature) + "'"); } } public MBeanInfo getMBeanInfo() { return new MBeanInfo(resourceClassName, resourceDescription, attributeInfo, constructorInfo, operationInfo, (isBroadcaster) ? this.getNotificationInfo() : new MBeanNotificationInfo[0]); } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException { if (isBroadcaster) { ((NotificationBroadcaster) resource).addNotificationListener(listener, filter, handback); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { if (isBroadcaster) { ((NotificationBroadcaster) resource).removeNotificationListener(listener); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public MBeanNotificationInfo[] getNotificationInfo() { if (isBroadcaster) { return ((NotificationBroadcaster) resource).getNotificationInfo(); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationBroadcaster")); } } public void handleNotification(Notification notification, Object handback) { if (isListener) { ((NotificationListener) resource).handleNotification(notification, handback); } else { throw new RuntimeOperationsException(new UnsupportedOperationException("resource is not a NotificationListener")); } } // ONLY used for friendly exceptions! protected final String opKeyString(String name, String[] signature) { StringBuffer buf = new StringBuffer(name).append('('); if (null != signature) { for (int i = 0; i < signature.length; i++) { buf.append(',').append(signature[i]); // the ; char ensures uniqueness } } return buf.append(')').toString(); } public static class MethodPair { public Method getter = null; public Method setter = null; public MethodPair(Method getter, Method setter) { this.getter = getter; this.setter = setter; } } } 1.1 jmx/src/main/org/jboss/mx/capability/ResourceDelegate.java Index: ResourceDelegate.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; /** * A ResourceDelegate knows how to dispatch ResourceInvoker.invoke(MBeanInvocation) * methods. Because opcodes in MBeanInvocation include NotificationBroadcaster and * NotificationListener methods, the delegate must be able to say whether those * operations are supported. * * The intention is that if an MBean that implements this interface is * registered in the server then all calls to the MBean will be routed via * the ResourceInvoker.invoke() method. * * See the MBeanDelegate for more info on how this all fits together. * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public interface ResourceDelegate extends ResourceInvoker { boolean resourceIsNotificationBroadcaster(); boolean resourceIsNotificationListener(); String getResourceClassName(); } 1.1 jmx/src/main/org/jboss/mx/capability/ResourceInvoker.java Index: ResourceInvoker.java =================================================================== /* * JBoss, the OpenSource J2EE webOS * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.mx.capability; import org.jboss.mx.interceptor.InvocationException; import org.jboss.mx.interceptor.MBeanInvocation; /** * Interface which I expect to be shared by interceptors and dispatchers * * @author <a href="mailto:[EMAIL PROTECTED]">Trevor Squires</a>. */ public interface ResourceInvoker { public Object invoke(MBeanInvocation i) throws InvocationException; }
_______________________________________________ Jboss-development mailing list [EMAIL PROTECTED] https://lists.sourceforge.net/lists/listinfo/jboss-development