View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.log4j.jmx;
    19
    20  import org.apache.log4j.Appender;
    21  import org.apache.log4j.Level;
    22  import org.apache.log4j.Logger;
    23  import org.apache.log4j.helpers.OptionConverter;
    24
    25  import javax.management.Attribute;
    26  import javax.management.AttributeNotFoundException;
    27  import javax.management.InvalidAttributeValueException;
    28  import javax.management.JMException;
    29  import javax.management.MBeanAttributeInfo;
    30  import javax.management.MBeanConstructorInfo;
    31  import javax.management.MBeanException;
    32  import javax.management.MBeanInfo;
    33  import javax.management.MBeanNotificationInfo;
    34  import javax.management.MBeanOperationInfo;
    35  import javax.management.MBeanParameterInfo;
    36  import javax.management.MalformedObjectNameException;
    37  import javax.management.Notification;
    38  import javax.management.NotificationListener;
    39  import javax.management.ObjectName;
    40  import javax.management.ReflectionException;
    41  import javax.management.RuntimeOperationsException;
    42  import java.lang.reflect.Constructor;
    43  import java.util.Enumeration;
    44  import java.util.Vector;
    45
    46  public class LoggerDynamicMBean extends AbstractDynamicMBean
    47                                    implements NotificationListener {
    48
    49    private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
    50    private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];
    51
    52    private Vector dAttributes = new Vector();
    53    private String dClassName = this.getClass().getName();
    54
    55    private String dDescription =
    56       "This MBean acts as a management facade for a org.apache.log4j.Logger instance.";
    57
    58    // This Logger instance is for logging.
    59    private static Logger cat = Logger.getLogger(LoggerDynamicMBean.class);
    60
    61    // We wrap this Logger instance.
    62    private Logger logger;
    63
    64    public LoggerDynamicMBean(Logger logger) {
    65      this.logger = logger;
    66      buildDynamicMBeanInfo();
    67    }
    68
    69    public
    70    void handleNotification(Notification notification, Object handback) {
    71      cat.debug("Received notification: "+notification.getType());
    72      registerAppenderMBean((Appender) notification.getUserData() );
    73
    74
    75    }
    76
    77    private
    78    void buildDynamicMBeanInfo() {
    79      Constructor[] constructors = this.getClass().getConstructors();
    80      dConstructors[0] = new MBeanConstructorInfo(
    81               "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance",
    82  	     constructors[0]);
    83
    84      dAttributes.add(new MBeanAttributeInfo("name",
    85  					   "java.lang.String",
    86  					   "The name of this Logger.",
    87  					   true,
    88  					   false,
    89  					   false));
    90
    91      dAttributes.add(new MBeanAttributeInfo("priority",
    92  					   "java.lang.String",
    93  					   "The priority of this logger.",
    94  					   true,
    95  					   true,
    96  					   false));
    97
    98
    99
    100
    101
    102     MBeanParameterInfo[] params = new MBeanParameterInfo[2];
    103     params[0] = new MBeanParameterInfo("class name", "java.lang.String",
    104 				       "add an appender to this logger");
    105     params[1] = new MBeanParameterInfo("appender name", "java.lang.String",
    106 				       "name of the appender");
    107
    108     dOperations[0] = new MBeanOperationInfo("addAppender",
    109 					    "addAppender(): add an appender",
    110 					    params,
    111 					    "void",
    112 					    MBeanOperationInfo.ACTION);
    113   }
    114
    115   protected
    116   Logger getLogger() {
    117     return logger;
    118   }
    119
    120
    121   public
    122   MBeanInfo getMBeanInfo() {
    123     //cat.debug("getMBeanInfo called.");
    124
    125     MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()];
    126     dAttributes.toArray(attribs);
    127
    128     MBeanInfo mb = new MBeanInfo(dClassName,
    129 			 dDescription,
    130 			 attribs,
    131 			 dConstructors,
    132 			 dOperations,
    133 			 new MBeanNotificationInfo[0]);
    134     //cat.debug("getMBeanInfo exit.");
    135     return mb;
    136   }
    137
    138   public
    139   Object invoke(String operationName, Object params[], String signature[])
    140     throws MBeanException,
    141     ReflectionException {
    142
    143     if(operationName.equals("addAppender")) {
    144       addAppender((String) params[0], (String) params[1]);
    145       return "Hello world.";
    146     }
    147
    148     return null;
    149   }
    150
    151
    152   public
    153   Object getAttribute(String attributeName) throws AttributeNotFoundException,
    154                                                    MBeanException,
    155                                                    ReflectionException {
    156
    157        // Check attributeName is not null to avoid NullPointerException later on
    158     if (attributeName == null) {
    159       throw new RuntimeOperationsException(new IllegalArgumentException(
    160 			"Attribute name cannot be null"),
    161        "Cannot invoke a getter of " + dClassName + " with null attribute name");
    162     }
    163
    164     // Check for a recognized attributeName and call the corresponding getter
    165     if (attributeName.equals("name")) {
    166       return logger.getName();
    167     }  else if(attributeName.equals("priority")) {
    168       Level l = logger.getLevel();
    169       if(l == null) {
    170 	return null;
    171       } else {
    172 	return l.toString();
    173       }
    174     } else if(attributeName.startsWith("appender=")) {
    175       try {
    176 	return new ObjectName("log4j:"+attributeName );
    177       } catch(MalformedObjectNameException e) {
    178 	    cat.error("Could not create ObjectName" + attributeName);
    179       } catch(RuntimeException e) {
    180 	    cat.error("Could not create ObjectName" + attributeName);
    181       }
    182     }
    183
    184
    185     // If attributeName has not been recognized throw an AttributeNotFoundException
    186     throw(new AttributeNotFoundException("Cannot find " + attributeName +
    187 					 " attribute in " + dClassName));
    188
    189   }
    190
    191
    192   void addAppender(String appenderClass, String appenderName) {
    193     cat.debug("addAppender called with "+appenderClass+", "+appenderName);
    194     Appender appender = (Appender)
    195        OptionConverter.instantiateByClassName(appenderClass,
    196 					      org.apache.log4j.Appender.class,
    197 					      null);
    198     appender.setName(appenderName);
    199     logger.addAppender(appender);
    200
    201     //appenderMBeanRegistration();
    202
    203   }
    204
    205
    206   public
    207   void setAttribute(Attribute attribute) throws AttributeNotFoundException,
    208                                                 InvalidAttributeValueException,
    209                                                 MBeanException,
    210                                                 ReflectionException {
    211
    212     // Check attribute is not null to avoid NullPointerException later on
    213     if (attribute == null) {
    214       throw new RuntimeOperationsException(
    215                   new IllegalArgumentException("Attribute cannot be null"),
    216 		  "Cannot invoke a setter of " + dClassName +
    217 		  " with null attribute");
    218     }
    219     String name = attribute.getName();
    220     Object value = attribute.getValue();
    221
    222     if (name == null) {
    223       throw new RuntimeOperationsException(
    224                     new IllegalArgumentException("Attribute name cannot be null"),
    225 		    "Cannot invoke the setter of "+dClassName+
    226 		    " with null attribute name");
    227     }
    228
    229
    230     if(name.equals("priority")) {
    231       if (value instanceof String) {
    232 	String s = (String) value;
    233 	Level p = logger.getLevel();
    234 	if(s.equalsIgnoreCase("NULL")) {
    235 	  p = null;
    236 	} else {
    237 	  p = OptionConverter.toLevel(s, p);
    238 	}
    239 	logger.setLevel(p);
    240       }
    241     } else {
    242       throw(new AttributeNotFoundException("Attribute " + name +
    243 					   " not found in " +
    244 					   this.getClass().getName()));
    245     }
    246   }
    247
    248   void appenderMBeanRegistration() {
    249     Enumeration enumeration = logger.getAllAppenders();
    250     while(enumeration.hasMoreElements()) {
    251       Appender appender = (Appender) enumeration.nextElement();
    252       registerAppenderMBean(appender);
    253     }
    254   }
    255
    256   void registerAppenderMBean(Appender appender) {
    257     String name = getAppenderName(appender);
    258     cat.debug("Adding AppenderMBean for appender named "+name);
    259     ObjectName objectName = null;
    260     try {
    261       AppenderDynamicMBean appenderMBean = new AppenderDynamicMBean(appender);
    262       objectName = new ObjectName("log4j", "appender", name);
    263       if (!server.isRegistered(objectName)) {
    264         registerMBean(appenderMBean, objectName);
    265         dAttributes.add(new MBeanAttributeInfo("appender=" + name, "javax.management.ObjectName",
    266                 "The " + name + " appender.", true, true, false));
    267       }
    268
    269     } catch(JMException e) {
    270       cat.error("Could not add appenderMBean for ["+name+"].", e);
    271     } catch(java.beans.IntrospectionException e) {
    272       cat.error("Could not add appenderMBean for ["+name+"].", e);
    273     } catch(RuntimeException e) {
    274       cat.error("Could not add appenderMBean for ["+name+"].", e);
    275     }
    276   }
    277
    278   public
    279   void postRegister(java.lang.Boolean registrationDone) {
    280     appenderMBeanRegistration();
    281   }
    282 }