ceki 01/09/24 15:16:27 Added: src/java/org/apache/log4j/jmx AbstractDynamicMBean.java Agent.java AppenderDynamicMBean.java HierarchyDynamicMBean.java LayoutDynamicMBean.java LoggerDynamicMBean.java T.java Log: Initial version of the jmx extensions. Revision Changes Path 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/AbstractDynamicMBean.java Index: AbstractDynamicMBean.java =================================================================== package org.apache.log4j.jmx; //import java.lang.reflect.Constructor; import java.util.Iterator; import javax.management.DynamicMBean; import javax.management.AttributeList; import javax.management.Attribute; import javax.management.RuntimeOperationsException; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.ObjectName; import javax.management.NotificationBroadcasterSupport; import org.apache.log4j.Logger; public abstract class AbstractDynamicMBean implements DynamicMBean, MBeanRegistration { String dClassName; MBeanServer server; /** * Enables the to get the values of several attributes of the Dynamic MBean. */ public AttributeList getAttributes(String[] attributeNames) { // Check attributeNames is not null to avoid NullPointerException later on if (attributeNames == null) { throw new RuntimeOperationsException( new IllegalArgumentException("attributeNames[] cannot be null"), "Cannot invoke a getter of " + dClassName); } AttributeList resultList = new AttributeList(); // if attributeNames is empty, return an empty result list if (attributeNames.length == 0) return resultList; // build the result attribute list for (int i=0 ; i<attributeNames.length ; i++){ try { Object value = getAttribute((String) attributeNames[i]); resultList.add(new Attribute(attributeNames[i],value)); } catch (Exception e) { e.printStackTrace(); } } return(resultList); } /** * Sets the values of several attributes of the Dynamic MBean, and returns the * list of attributes that have been set. */ public AttributeList setAttributes(AttributeList attributes) { // Check attributes is not null to avoid NullPointerException later on if (attributes == null) { throw new RuntimeOperationsException( new IllegalArgumentException("AttributeList attributes cannot be null"), "Cannot invoke a setter of " + dClassName); } AttributeList resultList = new AttributeList(); // if attributeNames is empty, nothing more to do if (attributes.isEmpty()) return resultList; // for each attribute, try to set it and add to the result list if successfull for (Iterator i = attributes.iterator(); i.hasNext();) { Attribute attr = (Attribute) i.next(); try { setAttribute(attr); String name = attr.getName(); Object value = getAttribute(name); resultList.add(new Attribute(name,value)); } catch(Exception e) { e.printStackTrace(); } } return(resultList); } protected abstract Logger getLogger(); public void postDeregister() { getLogger().debug("postDeregister is called."); } public void postRegister(java.lang.Boolean registrationDone) { } public void preDeregister() { getLogger().debug("preDeregister called."); } public ObjectName preRegister(MBeanServer server, ObjectName name) { getLogger().debug("preRegister called. Server="+server+ ", name="+name); this.server = server; return name; } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/Agent.java Index: Agent.java =================================================================== package org.apache.log4j.jmx; import javax.management.ObjectName; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.MalformedObjectNameException; import com.sun.jdmk.comm.HtmlAdaptorServer; import org.apache.log4j.Category; public class Agent { static Category log = Category.getInstance(Agent.class); public Agent() { } public void start() { MBeanServer server = MBeanServerFactory.createMBeanServer(); HtmlAdaptorServer html = new HtmlAdaptorServer(); try { log.info("Registering HtmlAdaptorServer instance."); server.registerMBean(html, new ObjectName("Adaptor:name=html,port=8082")); log.info("Registering HierarchyDynamicMBean instance."); HierarchyDynamicMBean hdm = new HierarchyDynamicMBean(); server.registerMBean(hdm, new ObjectName("log4j:hiearchy=default")); } catch(Exception e) { log.error("Problem while regitering MBeans instances.", e); return; } html.start(); } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/AppenderDynamicMBean.java Index: AppenderDynamicMBean.java =================================================================== package org.apache.log4j.jmx; import java.lang.reflect.Constructor; import org.apache.log4j.*; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.spi.OptionHandler; import java.util.Vector; import java.util.Hashtable; import java.lang.reflect.Method; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanNotificationInfo; import javax.management.ObjectName; import javax.management.MBeanInfo; import javax.management.Attribute; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.MBeanException; import javax.management.AttributeNotFoundException; import javax.management.RuntimeOperationsException; import javax.management.ReflectionException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import java.beans.Introspector; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.beans.IntrospectionException; public class AppenderDynamicMBean extends AbstractDynamicMBean { private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; private Vector dAttributes = new Vector(); private String dClassName = this.getClass().getName(); private Hashtable dynamicProps = new Hashtable(5); private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[2]; private String dDescription = "This MBean acts as a management facade for log4j appenders."; // This category instance is for logging. private static Logger cat = Logger.getLogger(AppenderDynamicMBean.class); // We wrap this appender instance. private Appender appender; public AppenderDynamicMBean(Appender appender) throws IntrospectionException { this.appender = appender; buildDynamicMBeanInfo(); } private void buildDynamicMBeanInfo() throws IntrospectionException { Constructor[] constructors = this.getClass().getConstructors(); dConstructors[0] = new MBeanConstructorInfo( "AppenderDynamicMBean(): Constructs a AppenderDynamicMBean instance", constructors[0]); BeanInfo bi = Introspector.getBeanInfo(appender.getClass()); PropertyDescriptor[] pd = bi.getPropertyDescriptors(); int size = pd.length; for(int i = 0; i < size; i++) { String name = pd[i].getName(); Method readMethod = pd[i].getReadMethod(); Method writeMethod = pd[i].getWriteMethod(); if(readMethod != null) { Class returnClass = readMethod.getReturnType(); if(isSupportedType(returnClass)) { String returnClassName; if(returnClass.isAssignableFrom(Priority.class)) { returnClassName = "java.lang.String"; } else { returnClassName = returnClass.getName(); } dAttributes.add(new MBeanAttributeInfo(name, returnClassName, "Dynamic", true, writeMethod != null, false)); dynamicProps.put(name, new B(readMethod, writeMethod)); } } } MBeanParameterInfo[] params = new MBeanParameterInfo[0]; dOperations[0] = new MBeanOperationInfo("activateOptions", "activateOptions(): add an appender", params, "void", MBeanOperationInfo.ACTION); params = new MBeanParameterInfo[1]; params[0] = new MBeanParameterInfo("layout class", "java.lang.String", "layout class"); dOperations[1] = new MBeanOperationInfo("setLayout", "setLayout(): add a layout", params, "void", MBeanOperationInfo.ACTION); } private boolean isSupportedType(Class clazz) { if(clazz.isPrimitive()) { return true; } if(clazz == String.class) { return true; } if(clazz.isAssignableFrom(Priority.class)) { return true; } return false; } public MBeanInfo getMBeanInfo() { cat.debug("getMBeanInfo called."); MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()]; dAttributes.toArray(attribs); return new MBeanInfo(dClassName, dDescription, attribs, dConstructors, dOperations, new MBeanNotificationInfo[0]); } public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if(operationName.equals("activateOptions") && appender instanceof OptionHandler) { OptionHandler oh = (OptionHandler) appender; oh.activateOptions(); return "Options activated."; } else if (operationName.equals("setLayout")) { Layout layout = (Layout) OptionConverter.instantiateByClassName((String) params[0], Layout.class, null); appender.setLayout(layout); registerLayoutMBean(layout); } return null; } void registerLayoutMBean(Layout layout) { if(layout == null) return; String name = appender.getName()+",layout="+layout.getClass().getName(); cat.debug("Adding LayoutMBean:"+name); ObjectName objectName = null; try { LayoutDynamicMBean appenderMBean = new LayoutDynamicMBean(layout); objectName = new ObjectName("log4j:appender="+name); server.registerMBean(appenderMBean, objectName); dAttributes.add(new MBeanAttributeInfo("appender="+name, "javax.management.ObjectName", "The "+name+" layout.", true, true, false)); } catch(Exception e) { cat.error("Could not add DynamicLayoutMBean for ["+name+"].", e); } } protected Logger getLogger() { return cat; } public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attributeName is not null to avoid NullPointerException later on if (attributeName == null) { throw new RuntimeOperationsException(new IllegalArgumentException( "Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } cat.debug("getAttribute called with ["+attributeName+"]."); if(attributeName.startsWith("appender="+appender.getName()+",layout")) { try { return new ObjectName("log4j:"+attributeName ); } catch(Exception e) { cat.error("attributeName", e); } } B b = (B) dynamicProps.get(attributeName); //cat.debug("----name="+attributeName+", b="+b); if(b != null && b.readMethod != null) { try { return b.readMethod.invoke(appender, null); } catch(Exception e) { return null; } } // If attributeName has not been recognized throw an AttributeNotFoundException throw(new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + dClassName)); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute is not null to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of " + dClassName + " with null attribute"); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke the setter of "+dClassName+ " with null attribute name"); } B b = (B) dynamicProps.get(name); if(b != null && b.writeMethod != null) { Object[] o = new Object[1]; Class[] params = b.writeMethod.getParameterTypes(); if(params[0] == org.apache.log4j.Priority.class) { value = OptionConverter.toLevel((String) value, (Level) getAttribute(name)); } o[0] = value; try { b.writeMethod.invoke(appender, o); } catch(Exception e) { cat.error("FIXME", e); } } else if(name.endsWith(".layout")) { } else { throw(new AttributeNotFoundException("Attribute " + name + " not found in " + this.getClass().getName())); } } public ObjectName preRegister(MBeanServer server, ObjectName name) { cat.debug("preRegister called. Server="+server+ ", name="+name); this.server = server; registerLayoutMBean(appender.getLayout()); return name; } } class B { Method readMethod; Method writeMethod; B(Method readMethod, Method writeMethod) { this.readMethod = readMethod; this.writeMethod = writeMethod; } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/HierarchyDynamicMBean.java Index: HierarchyDynamicMBean.java =================================================================== package org.apache.log4j.jmx; import java.lang.reflect.Constructor; import org.apache.log4j.Hierarchy; import org.apache.log4j.Appender; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.log4j.spi.HierarchyEventListener; import org.apache.log4j.spi.LoggerRepository; import org.apache.log4j.helpers.OptionConverter; import java.util.Vector; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.management.MBeanInfo; import javax.management.Attribute; import javax.management.MBeanServer; import javax.management.MBeanException; import javax.management.AttributeNotFoundException; import javax.management.RuntimeOperationsException; import javax.management.ReflectionException; import javax.management.InvalidAttributeValueException; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationBroadcaster; import javax.management.Notification; import javax.management.NotificationListener; import javax.management.NotificationFilter; import javax.management.NotificationFilterSupport; import javax.management.ListenerNotFoundException; public class HierarchyDynamicMBean extends AbstractDynamicMBean implements HierarchyEventListener, NotificationBroadcaster { static final String ADD_APPENDER = "addAppender."; static final String ENABLE = "enable"; private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1]; private Vector vAttributes = new Vector(); private String dClassName = this.getClass().getName(); private String dDescription = "This MBean acts as a management facade for org.apache.log4j.Hierarchy."; private NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport(); private LoggerRepository hierarchy; private static Logger log = Logger.getInstance(HierarchyDynamicMBean.class); public HierarchyDynamicMBean() { hierarchy = LogManager.getLoggerRepository(); buildDynamicMBeanInfo(); } private void buildDynamicMBeanInfo() { Constructor[] constructors = this.getClass().getConstructors(); dConstructors[0] = new MBeanConstructorInfo( "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance", constructors[0]); vAttributes.add(new MBeanAttributeInfo("enable", "java.lang.String", "The \"enable\" state of the hiearchy.", true, true, false)); MBeanParameterInfo[] params = new MBeanParameterInfo[1]; params[0] = new MBeanParameterInfo("name", "java.lang.String", "Create a logger MBean" ); dOperations[0] = new MBeanOperationInfo("addLoggerMBean", "addLoggerMBean(): add a loggerMBean", params , "javax.management.ObjectName", MBeanOperationInfo.ACTION); } public ObjectName addLoggerMBean(String name) { Logger cat = Logger.exists(name); if(cat != null) { return addLoggerMBean(cat); } else { return null; } } ObjectName addLoggerMBean(Logger logger) { String name = logger.getName(); ObjectName objectName = null; try { LoggerDynamicMBean loggerMBean = new LoggerDynamicMBean(logger); objectName = new ObjectName("log4j", "logger", name); server.registerMBean(loggerMBean, objectName); NotificationFilterSupport nfs = new NotificationFilterSupport(); nfs.enableType(ADD_APPENDER+logger.getName()); log.debug("---Adding logger ["+name+"] as listener."); nbs.addNotificationListener(loggerMBean, nfs, null); vAttributes.add(new MBeanAttributeInfo("logger="+name, "javax.management.ObjectName", "The "+name+" logger.", true, true, // this makes the object // clickable false)); } catch(Exception e) { log.error("Couls not add loggerMBean for ["+name+"]."); } return objectName; } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, java.lang.Object handback) { nbs.addNotificationListener(listener, filter, handback); } protected Logger getLogger() { return log; } public MBeanInfo getMBeanInfo() { //cat.debug("getMBeanInfo called."); MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[vAttributes.size()]; vAttributes.toArray(attribs); return new MBeanInfo(dClassName, dDescription, attribs, dConstructors, dOperations, new MBeanNotificationInfo[0]); } public MBeanNotificationInfo[] getNotificationInfo(){ return nbs.getNotificationInfo(); } public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if (operationName == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Operation name cannot be null"), "Cannot invoke a null operation in " + dClassName); } // Check for a recognized operation name and call the corresponding operation if(operationName.equals("addLoggerMBean")) { return addLoggerMBean((String)params[0]); } else { throw new ReflectionException( new NoSuchMethodException(operationName), "Cannot find the operation " + operationName + " in " + dClassName); } } public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attributeName is not null to avoid NullPointerException later on if (attributeName == null) { throw new RuntimeOperationsException(new IllegalArgumentException( "Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } log.debug("Called getAttribute with ["+attributeName+"]."); // Check for a recognized attributeName and call the corresponding getter if (attributeName.equals(ENABLE)) { return hierarchy.getEnable(); } else if(attributeName.startsWith("logger")) { int k = attributeName.indexOf("%3D"); String val = attributeName; if(k > 0) { val = attributeName.substring(0, k)+'='+ attributeName.substring(k+3); } try { return new ObjectName("log4j:"+val); } catch(Exception e) { log.error("Could not create ObjectName" + val); } } // If attributeName has not been recognized throw an AttributeNotFoundException throw(new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + dClassName)); } public void addAppenderEvent(Logger logger, Appender appender) { log.debug("addAppenderEvent called: logger="+logger.getName()+ ", appender="+appender.getName()); Notification n = new Notification(ADD_APPENDER+logger.getName(), this, 0); n.setUserData(appender); log.debug("sending notification."); nbs.sendNotification(n); } public void removeAppenderEvent(Logger cat, Appender appender) { log.debug("removeAppenderCalled: logger="+cat.getName()+ ", appender="+appender.getName()); } public void postRegister(java.lang.Boolean registrationDone) { log.debug("postRegister is called."); hierarchy.addHierarchyEventListener(this); Logger root = hierarchy.getRootLogger(); addLoggerMBean(root); } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { nbs.removeNotificationListener(listener); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute is not null to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of "+dClassName+" with null attribute"); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke the setter of "+dClassName+ " with null attribute name"); } if(name.equals(ENABLE)) { Level l = OptionConverter.toLevel((String) value, hierarchy.getEnable()); hierarchy.enable(l); } } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/LayoutDynamicMBean.java Index: LayoutDynamicMBean.java =================================================================== package org.apache.log4j.jmx; import java.lang.reflect.Constructor; import org.apache.log4j.Hierarchy; import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.log4j.Layout; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.spi.OptionHandler; import java.util.Vector; import java.util.Hashtable; import java.lang.reflect.Method; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanNotificationInfo; import javax.management.ObjectName; import javax.management.MBeanInfo; import javax.management.Attribute; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.MBeanException; import javax.management.AttributeNotFoundException; import javax.management.RuntimeOperationsException; import javax.management.ReflectionException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import java.beans.Introspector; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.beans.IntrospectionException; public class LayoutDynamicMBean extends AbstractDynamicMBean { private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; private Vector dAttributes = new Vector(); private String dClassName = this.getClass().getName(); private Hashtable dynamicProps = new Hashtable(5); private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1]; private String dDescription = "This MBean acts as a management facade for log4j layouts."; // This category instance is for logging. private static Logger cat = Logger.getLogger(LayoutDynamicMBean.class); // We wrap this layout instance. private Layout layout; public LayoutDynamicMBean(Layout layout) throws IntrospectionException { this.layout = layout; buildDynamicMBeanInfo(); } private void buildDynamicMBeanInfo() throws IntrospectionException { Constructor[] constructors = this.getClass().getConstructors(); dConstructors[0] = new MBeanConstructorInfo( "LayoutDynamicMBean(): Constructs a LayoutDynamicMBean instance", constructors[0]); BeanInfo bi = Introspector.getBeanInfo(layout.getClass()); PropertyDescriptor[] pd = bi.getPropertyDescriptors(); int size = pd.length; for(int i = 0; i < size; i++) { String name = pd[i].getName(); Method readMethod = pd[i].getReadMethod(); Method writeMethod = pd[i].getWriteMethod(); if(readMethod != null) { Class returnClass = readMethod.getReturnType(); if(isSupportedType(returnClass)) { String returnClassName; if(returnClass.isAssignableFrom(Level.class)) { returnClassName = "java.lang.String"; } else { returnClassName = returnClass.getName(); } dAttributes.add(new MBeanAttributeInfo(name, returnClassName, "Dynamic", true, writeMethod != null, false)); dynamicProps.put(name, new B(readMethod, writeMethod)); } } } MBeanParameterInfo[] params = new MBeanParameterInfo[0]; dOperations[0] = new MBeanOperationInfo("activateOptions", "activateOptions(): add an layout", params, "void", MBeanOperationInfo.ACTION); } private boolean isSupportedType(Class clazz) { if(clazz.isPrimitive()) { return true; } if(clazz == String.class) { return true; } if(clazz.isAssignableFrom(Level.class)) { return true; } return false; } public MBeanInfo getMBeanInfo() { cat.debug("getMBeanInfo called."); MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()]; dAttributes.toArray(attribs); return new MBeanInfo(dClassName, dDescription, attribs, dConstructors, dOperations, new MBeanNotificationInfo[0]); } public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if(operationName.equals("activateOptions") && layout instanceof OptionHandler) { OptionHandler oh = (OptionHandler) layout; oh.activateOptions(); return "Options activated."; } return null; } protected Logger getLogger() { return cat; } public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attributeName is not null to avoid NullPointerException later on if (attributeName == null) { throw new RuntimeOperationsException(new IllegalArgumentException( "Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } B b = (B) dynamicProps.get(attributeName); cat.debug("----name="+attributeName+", b="+b); if(b != null && b.readMethod != null) { try { return b.readMethod.invoke(layout, null); } catch(Exception e) { return null; } } // If attributeName has not been recognized throw an AttributeNotFoundException throw(new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + dClassName)); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute is not null to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of " + dClassName + " with null attribute"); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke the setter of "+dClassName+ " with null attribute name"); } B b = (B) dynamicProps.get(name); if(b != null && b.writeMethod != null) { Object[] o = new Object[1]; Class[] params = b.writeMethod.getParameterTypes(); if(params[0] == org.apache.log4j.Priority.class) { value = OptionConverter.toLevel((String) value, (Level) getAttribute(name)); } o[0] = value; try { b.writeMethod.invoke(layout, o); } catch(Exception e) { cat.error("FIXME", e); } } else { throw(new AttributeNotFoundException("Attribute " + name + " not found in " + this.getClass().getName())); } } } class B { Method readMethod; Method writeMethod; B(Method readMethod, Method writeMethod) { this.readMethod = readMethod; this.writeMethod = writeMethod; } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/LoggerDynamicMBean.java Index: LoggerDynamicMBean.java =================================================================== package org.apache.log4j.jmx; import java.lang.reflect.Constructor; import org.apache.log4j.Hierarchy; import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.log4j.Appender; import org.apache.log4j.helpers.OptionConverter; import java.util.Vector; import java.util.Enumeration; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import javax.management.ObjectName; import javax.management.MBeanInfo; import javax.management.Attribute; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.MBeanException; import javax.management.AttributeNotFoundException; import javax.management.RuntimeOperationsException; import javax.management.ReflectionException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanRegistration; import javax.management.NotificationListener; import javax.management.Notification; public class LoggerDynamicMBean extends AbstractDynamicMBean implements NotificationListener { private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1]; private Vector dAttributes = new Vector(); private String dClassName = this.getClass().getName(); private String dDescription = "This MBean acts as a management facade for a org.apache.log4j.Logger instance."; // This Logger instance is for logging. private static Logger cat = Logger.getLogger(LoggerDynamicMBean.class); // We wrap this Logger instance. private Logger logger; public LoggerDynamicMBean(Logger logger) { this.logger = logger; buildDynamicMBeanInfo(); } public void handleNotification(Notification notification, Object handback) { cat.debug("Received notification: "+notification.getType()); registerAppenderMBean((Appender) notification.getUserData() ); } private void buildDynamicMBeanInfo() { Constructor[] constructors = this.getClass().getConstructors(); dConstructors[0] = new MBeanConstructorInfo( "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance", constructors[0]); dAttributes.add(new MBeanAttributeInfo("name", "java.lang.String", "The name of this Logger.", true, false, false)); dAttributes.add(new MBeanAttributeInfo("priority", "java.lang.String", "The priority of this logger.", true, true, false)); MBeanParameterInfo[] params = new MBeanParameterInfo[2]; params[0] = new MBeanParameterInfo("class name", "java.lang.String", "add an appender to this logger"); params[1] = new MBeanParameterInfo("appender name", "java.lang.String", "name of the appender"); dOperations[0] = new MBeanOperationInfo("addAppender", "addAppender(): add an appender", params, "void", MBeanOperationInfo.ACTION); } protected Logger getLogger() { return logger; } public MBeanInfo getMBeanInfo() { //cat.debug("getMBeanInfo called."); MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()]; dAttributes.toArray(attribs); MBeanInfo mb = new MBeanInfo(dClassName, dDescription, attribs, dConstructors, dOperations, new MBeanNotificationInfo[0]); //cat.debug("getMBeanInfo exit."); return mb; } public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if(operationName.equals("addAppender")) { addAppender((String) params[0], (String) params[1]); return "Hello world."; } return null; } public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attributeName is not null to avoid NullPointerException later on if (attributeName == null) { throw new RuntimeOperationsException(new IllegalArgumentException( "Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } // Check for a recognized attributeName and call the corresponding getter if (attributeName.equals("name")) { return logger.getName(); } else if(attributeName.equals("priority")) { Level l = logger.getLevel(); if(l == null) { return null; } else { return l.toString(); } } else if(attributeName.startsWith("appender=")) { try { return new ObjectName("log4j:"+attributeName ); } catch(Exception e) { cat.error("Could not create ObjectName" + attributeName); } } // If attributeName has not been recognized throw an AttributeNotFoundException throw(new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + dClassName)); } void addAppender(String appenderClass, String appenderName) { cat.debug("addAppender called with "+appenderClass+", "+appenderName); Appender appender = (Appender) OptionConverter.instantiateByClassName(appenderClass, org.apache.log4j.Appender.class, null); appender.setName(appenderName); logger.addAppender(appender); //appenderMBeanRegistration(); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute is not null to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of " + dClassName + " with null attribute"); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke the setter of "+dClassName+ " with null attribute name"); } if(name.equals("priority")) { if (value instanceof String) { String s = (String) value; Level p = logger.getLevel(); if(s.equalsIgnoreCase("NULL")) { p = null; } else { p = OptionConverter.toLevel(s, p); } logger.setPriority(p); } } else { throw(new AttributeNotFoundException("Attribute " + name + " not found in " + this.getClass().getName())); } } void appenderMBeanRegistration() { Enumeration enum = logger.getAllAppenders(); while(enum.hasMoreElements()) { Appender appender = (Appender) enum.nextElement(); registerAppenderMBean(appender); } } void registerAppenderMBean(Appender appender) { String name = appender.getName(); cat.debug("Adding AppenderMBean for appender named "+name); ObjectName objectName = null; try { AppenderDynamicMBean appenderMBean = new AppenderDynamicMBean(appender); objectName = new ObjectName("log4j", "appender", name); server.registerMBean(appenderMBean, objectName); dAttributes.add(new MBeanAttributeInfo("appender="+name, "javax.management.ObjectName", "The "+name+" appender.", true, true, false)); } catch(Exception e) { cat.error("Could not add appenderMBean for ["+name+"].", e); } } public void postRegister(java.lang.Boolean registrationDone) { appenderMBeanRegistration(); } } 1.1 jakarta-log4j/src/java/org/apache/log4j/jmx/T.java Index: T.java =================================================================== import org.apache.log4j.jmx.Agent; import org.apache.log4j.Category; import org.apache.log4j.BasicConfigurator; import org.apache.log4j.*; public class T { public static void main(String[] args) { Category cat = Category.getInstance(T.class); Layout layout = new PatternLayout("%r %p [%t] %c - %m%n"); ConsoleAppender consoleAppender = new ConsoleAppender(layout); consoleAppender.setName("console"); BasicConfigurator.configure(consoleAppender); Agent agent = new Agent(); agent.start(); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]