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]

Reply via email to