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 java.lang.reflect.Constructor;
    21  import org.apache.log4j.Logger;
    22  import org.apache.log4j.Level;
    23  import org.apache.log4j.Appender;
    24  import org.apache.log4j.helpers.OptionConverter;
    25
    26  import java.util.Vector;
    27  import java.util.Enumeration;
    28
    29  import javax.management.MBeanAttributeInfo;
    30  import javax.management.MBeanConstructorInfo;
    31  import javax.management.MBeanNotificationInfo;
    32  import javax.management.MBeanOperationInfo;
    33  import javax.management.MBeanParameterInfo;
    34  import javax.management.ObjectName;
    35  import javax.management.MBeanInfo;
    36  import javax.management.Attribute;
    37
    38  import javax.management.MBeanException;
    39  import javax.management.AttributeNotFoundException;
    40  import javax.management.RuntimeOperationsException;
    41  import javax.management.ReflectionException;
    42  import javax.management.InvalidAttributeValueException;
    43  import javax.management.NotificationListener;
    44  import javax.management.Notification;
    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(Exception e) {
    178 	cat.error("Could not create ObjectName" + attributeName);
    179       }
    180     }
    181
    182
    183     // If attributeName has not been recognized throw an AttributeNotFoundException
    184     throw(new AttributeNotFoundException("Cannot find " + attributeName +
    185 					 " attribute in " + dClassName));
    186
    187   }
    188
    189
    190   void addAppender(String appenderClass, String appenderName) {
    191     cat.debug("addAppender called with "+appenderClass+", "+appenderName);
    192     Appender appender = (Appender)
    193        OptionConverter.instantiateByClassName(appenderClass,
    194 					      org.apache.log4j.Appender.class,
    195 					      null);
    196     appender.setName(appenderName);
    197     logger.addAppender(appender);
    198
    199     //appenderMBeanRegistration();
    200
    201   }
    202
    203
    204   public
    205   void setAttribute(Attribute attribute) throws AttributeNotFoundException,
    206                                                 InvalidAttributeValueException,
    207                                                 MBeanException,
    208                                                 ReflectionException {
    209
    210     // Check attribute is not null to avoid NullPointerException later on
    211     if (attribute == null) {
    212       throw new RuntimeOperationsException(
    213                   new IllegalArgumentException("Attribute cannot be null"),
    214 		  "Cannot invoke a setter of " + dClassName +
    215 		  " with null attribute");
    216     }
    217     String name = attribute.getName();
    218     Object value = attribute.getValue();
    219
    220     if (name == null) {
    221       throw new RuntimeOperationsException(
    222                     new IllegalArgumentException("Attribute name cannot be null"),
    223 		    "Cannot invoke the setter of "+dClassName+
    224 		    " with null attribute name");
    225     }
    226
    227
    228     if(name.equals("priority")) {
    229       if (value instanceof String) {
    230 	String s = (String) value;
    231 	Level p = logger.getLevel();
    232 	if(s.equalsIgnoreCase("NULL")) {
    233 	  p = null;
    234 	} else {
    235 	  p = OptionConverter.toLevel(s, p);
    236 	}
    237 	logger.setLevel(p);
    238       }
    239     } else {
    240       throw(new AttributeNotFoundException("Attribute " + name +
    241 					   " not found in " +
    242 					   this.getClass().getName()));
    243     }
    244   }
    245
    246   void appenderMBeanRegistration() {
    247     Enumeration enumeration = logger.getAllAppenders();
    248     while(enumeration.hasMoreElements()) {
    249       Appender appender = (Appender) enumeration.nextElement();
    250       registerAppenderMBean(appender);
    251     }
    252   }
    253
    254   void registerAppenderMBean(Appender appender) {
    255     String name = appender.getName();
    256     cat.debug("Adding AppenderMBean for appender named "+name);
    257     ObjectName objectName = null;
    258     try {
    259       AppenderDynamicMBean appenderMBean = new AppenderDynamicMBean(appender);
    260       objectName = new ObjectName("log4j", "appender", name);
    261       if (!server.isRegistered(objectName)) {
    262         server.registerMBean(appenderMBean, objectName);
    263         dAttributes.add(new MBeanAttributeInfo("appender=" + name, "javax.management.ObjectName",
    264                 "The " + name + " appender.", true, true, false));
    265       }
    266
    267     } catch(Exception e) {
    268       cat.error("Could not add appenderMBean for ["+name+"].", e);
    269     }
    270   }
    271
    272   public
    273   void postRegister(java.lang.Boolean registrationDone) {
    274     appenderMBeanRegistration();
    275   }
    276 }