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
    21  import java.lang.reflect.Constructor;
    22  import org.apache.log4j.*;
    23
    24  import org.apache.log4j.spi.HierarchyEventListener;
    25  import org.apache.log4j.spi.LoggerRepository;
    26  import org.apache.log4j.helpers.OptionConverter;
    27
    28  import java.util.Vector;
    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
    35  import javax.management.ObjectName;
    36  import javax.management.MBeanInfo;
    37  import javax.management.Attribute;
    38
    39  import javax.management.MBeanException;
    40  import javax.management.AttributeNotFoundException;
    41  import javax.management.RuntimeOperationsException;
    42  import javax.management.ReflectionException;
    43  import javax.management.InvalidAttributeValueException;
    44  import javax.management.NotificationBroadcasterSupport;
    45  import javax.management.NotificationBroadcaster;
    46  import javax.management.Notification;
    47  import javax.management.NotificationListener;
    48  import javax.management.NotificationFilter;
    49  import javax.management.NotificationFilterSupport;
    50  import javax.management.ListenerNotFoundException;
    51
    52  public class HierarchyDynamicMBean extends AbstractDynamicMBean
    53                                     implements HierarchyEventListener,
    54                                                NotificationBroadcaster {
    55
    56    static final String ADD_APPENDER = "addAppender.";
    57    static final String THRESHOLD = "threshold";
    58
    59    private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
    60    private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];
    61
    62    private Vector vAttributes = new Vector();
    63    private String dClassName = this.getClass().getName();
    64    private String dDescription =
    65       "This MBean acts as a management facade for org.apache.log4j.Hierarchy.";
    66
    67    private NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport();
    68
    69
    70    private LoggerRepository hierarchy;
    71
    72    private static Logger log = Logger.getLogger(HierarchyDynamicMBean.class);
    73
    74    public HierarchyDynamicMBean() {
    75      hierarchy = LogManager.getLoggerRepository();
    76      buildDynamicMBeanInfo();
    77    }
    78
    79    private
    80    void buildDynamicMBeanInfo() {
    81      Constructor[] constructors = this.getClass().getConstructors();
    82      dConstructors[0] = new MBeanConstructorInfo(
    83           "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance",
    84  	 constructors[0]);
    85
    86      vAttributes.add(new MBeanAttributeInfo(THRESHOLD,
    87  					   "java.lang.String",
    88  					   "The \"threshold\" state of the hiearchy.",
    89  					   true,
    90  					   true,
    91  					   false));
    92
    93      MBeanParameterInfo[] params = new MBeanParameterInfo[1];
    94      params[0] = new MBeanParameterInfo("name", "java.lang.String",
    95  				       "Create a logger MBean" );
    96      dOperations[0] = new MBeanOperationInfo("addLoggerMBean",
    97  				    "addLoggerMBean(): add a loggerMBean",
    98  				    params ,
    99  				    "javax.management.ObjectName",
    100 				    MBeanOperationInfo.ACTION);
    101   }
    102
    103
    104   public
    105   ObjectName addLoggerMBean(String name) {
    106     Logger cat = LogManager.exists(name);
    107
    108     if(cat != null) {
    109       return addLoggerMBean(cat);
    110     } else {
    111       return null;
    112     }
    113   }
    114
    115   ObjectName addLoggerMBean(Logger logger) {
    116     String name = logger.getName();
    117     ObjectName objectName = null;
    118     try {
    119       LoggerDynamicMBean loggerMBean = new LoggerDynamicMBean(logger);
    120       objectName = new ObjectName("log4j", "logger", name);
    121
    122       if (!server.isRegistered(objectName)) {
    123         server.registerMBean(loggerMBean, objectName);
    124         NotificationFilterSupport nfs = new NotificationFilterSupport();
    125         nfs.enableType(ADD_APPENDER + logger.getName());
    126         log.debug("---Adding logger [" + name + "] as listener.");
    127         nbs.addNotificationListener(loggerMBean, nfs, null);
    128         vAttributes.add(new MBeanAttributeInfo("logger=" + name, "javax.management.ObjectName",
    129                 "The " + name + " logger.", true, true, // this makes the object
    130                 // clickable
    131                 false));
    132
    133       }
    134
    135     } catch(Exception e) {
    136       log.error("Could not add loggerMBean for ["+name+"].", e);
    137     }
    138     return objectName;
    139   }
    140
    141   public
    142   void addNotificationListener(NotificationListener listener,
    143 			       NotificationFilter filter,
    144 			       java.lang.Object handback) {
    145     nbs.addNotificationListener(listener, filter, handback);
    146   }
    147
    148   protected
    149   Logger getLogger() {
    150     return log;
    151   }
    152
    153   public
    154   MBeanInfo getMBeanInfo() {
    155     //cat.debug("getMBeanInfo called.");
    156
    157     MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[vAttributes.size()];
    158     vAttributes.toArray(attribs);
    159
    160     return new MBeanInfo(dClassName,
    161 			 dDescription,
    162 			 attribs,
    163 			 dConstructors,
    164 			 dOperations,
    165 			 new MBeanNotificationInfo[0]);
    166   }
    167
    168   public
    169   MBeanNotificationInfo[] getNotificationInfo(){
    170     return nbs.getNotificationInfo();
    171   }
    172
    173   public
    174   Object invoke(String operationName,
    175 		Object params[],
    176 		String signature[]) throws MBeanException,
    177                                            ReflectionException {
    178
    179     if (operationName == null) {
    180       throw new RuntimeOperationsException(
    181         new IllegalArgumentException("Operation name cannot be null"),
    182 	"Cannot invoke a null operation in " + dClassName);
    183     }
    184     // Check for a recognized operation name and call the corresponding operation
    185
    186     if(operationName.equals("addLoggerMBean")) {
    187       return addLoggerMBean((String)params[0]);
    188     } else {
    189       throw new ReflectionException(
    190 	    new NoSuchMethodException(operationName),
    191 	    "Cannot find the operation " + operationName + " in " + dClassName);
    192     }
    193
    194   }
    195
    196
    197   public
    198   Object getAttribute(String attributeName) throws AttributeNotFoundException,
    199                                                     MBeanException,
    200                                                     ReflectionException {
    201
    202     // Check attributeName is not null to avoid NullPointerException later on
    203     if (attributeName == null) {
    204       throw new RuntimeOperationsException(new IllegalArgumentException(
    205 			"Attribute name cannot be null"),
    206        "Cannot invoke a getter of " + dClassName + " with null attribute name");
    207     }
    208
    209     log.debug("Called getAttribute with ["+attributeName+"].");
    210
    211     // Check for a recognized attributeName and call the corresponding getter
    212     if (attributeName.equals(THRESHOLD)) {
    213       return hierarchy.getThreshold();
    214     } else if(attributeName.startsWith("logger")) {
    215       int k = attributeName.indexOf("%3D");
    216       String val = attributeName;
    217       if(k > 0) {
    218 	val = attributeName.substring(0, k)+'='+ attributeName.substring(k+3);
    219       }
    220       try {
    221 	return new ObjectName("log4j:"+val);
    222       } catch(Exception e) {
    223 	log.error("Could not create ObjectName" + val);
    224       }
    225     }
    226
    227
    228
    229     // If attributeName has not been recognized throw an AttributeNotFoundException
    230     throw(new AttributeNotFoundException("Cannot find " + attributeName +
    231 					 " attribute in " + dClassName));
    232
    233   }
    234
    235
    236   public
    237   void addAppenderEvent(Category logger, Appender appender) {
    238     log.debug("addAppenderEvent called: logger="+logger.getName()+
    239 	      ", appender="+appender.getName());
    240     Notification n = new Notification(ADD_APPENDER+logger.getName(), this, 0);
    241     n.setUserData(appender);
    242     log.debug("sending notification.");
    243     nbs.sendNotification(n);
    244   }
    245
    246  public
    247   void removeAppenderEvent(Category cat, Appender appender) {
    248     log.debug("removeAppenderCalled: logger="+cat.getName()+
    249 	      ", appender="+appender.getName());
    250   }
    251
    252   public
    253   void postRegister(java.lang.Boolean registrationDone) {
    254     log.debug("postRegister is called.");
    255     hierarchy.addHierarchyEventListener(this);
    256     Logger root = hierarchy.getRootLogger();
    257     addLoggerMBean(root);
    258   }
    259
    260   public
    261   void removeNotificationListener(NotificationListener listener)
    262                                          throws ListenerNotFoundException {
    263     nbs.removeNotificationListener(listener);
    264   }
    265
    266   public
    267   void setAttribute(Attribute attribute) throws AttributeNotFoundException,
    268                                                 InvalidAttributeValueException,
    269                                                 MBeanException,
    270                                                 ReflectionException {
    271
    272     // Check attribute is not null to avoid NullPointerException later on
    273     if (attribute == null) {
    274       throw new RuntimeOperationsException(
    275                   new IllegalArgumentException("Attribute cannot be null"),
    276 	  "Cannot invoke a setter of "+dClassName+" with null attribute");
    277     }
    278     String name = attribute.getName();
    279     Object value = attribute.getValue();
    280
    281     if (name == null) {
    282       throw new RuntimeOperationsException(
    283                new IllegalArgumentException("Attribute name cannot be null"),
    284 	       "Cannot invoke the setter of "+dClassName+
    285 	       " with null attribute name");
    286     }
    287
    288     if(name.equals(THRESHOLD)) {
    289       Level l = OptionConverter.toLevel((String) value,
    290 					   hierarchy.getThreshold());
    291       hierarchy.setThreshold(l);
    292     }
    293
    294
    295   }
    296 }