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.Layout;
    24  import org.apache.log4j.helpers.OptionConverter;
    25  import org.apache.log4j.spi.OptionHandler;
    26
    27  import java.util.Vector;
    28  import java.util.Hashtable;
    29  import java.lang.reflect.Method;
    30  import javax.management.MBeanAttributeInfo;
    31  import javax.management.MBeanConstructorInfo;
    32  import javax.management.MBeanNotificationInfo;
    33  import javax.management.MBeanInfo;
    34  import javax.management.Attribute;
    35
    36  import javax.management.MBeanException;
    37  import javax.management.AttributeNotFoundException;
    38  import javax.management.RuntimeOperationsException;
    39  import javax.management.ReflectionException;
    40  import javax.management.InvalidAttributeValueException;
    41  import javax.management.MBeanOperationInfo;
    42  import javax.management.MBeanParameterInfo;
    43
    44  import java.beans.Introspector;
    45  import java.beans.BeanInfo;
    46  import java.beans.PropertyDescriptor;
    47  import java.beans.IntrospectionException;
    48
    49  public class LayoutDynamicMBean extends AbstractDynamicMBean {
    50
    51    private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
    52    private Vector dAttributes = new Vector();
    53    private String dClassName = this.getClass().getName();
    54
    55    private Hashtable dynamicProps = new Hashtable(5);
    56    private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];
    57    private String dDescription =
    58       "This MBean acts as a management facade for log4j layouts.";
    59
    60    // This category instance is for logging.
    61    private static Logger cat = Logger.getLogger(LayoutDynamicMBean.class);
    62
    63    // We wrap this layout instance.
    64    private Layout layout;
    65
    66    public  LayoutDynamicMBean(Layout layout) throws IntrospectionException {
    67      this.layout = layout;
    68      buildDynamicMBeanInfo();
    69    }
    70
    71    private
    72    void buildDynamicMBeanInfo() throws IntrospectionException {
    73      Constructor[] constructors = this.getClass().getConstructors();
    74      dConstructors[0] = new MBeanConstructorInfo(
    75               "LayoutDynamicMBean(): Constructs a LayoutDynamicMBean instance",
    76  	     constructors[0]);
    77
    78
    79      BeanInfo bi = Introspector.getBeanInfo(layout.getClass());
    80      PropertyDescriptor[] pd = bi.getPropertyDescriptors();
    81
    82      int size = pd.length;
    83
    84      for(int i = 0; i < size; i++) {
    85        String name = pd[i].getName();
    86        Method readMethod =  pd[i].getReadMethod();
    87        Method writeMethod =  pd[i].getWriteMethod();
    88        if(readMethod != null) {
    89  	Class returnClass = readMethod.getReturnType();
    90  	if(isSupportedType(returnClass)) {
    91  	  String returnClassName;
    92  	  if(returnClass.isAssignableFrom(Level.class)) {
    93  	    returnClassName = "java.lang.String";
    94  	  } else {
    95  	    returnClassName = returnClass.getName();
    96  	  }
    97
    98  	  dAttributes.add(new MBeanAttributeInfo(name,
    99  						 returnClassName,
    100 						 "Dynamic",
    101 						 true,
    102 						 writeMethod != null,
    103 						 false));
    104 	  dynamicProps.put(name, new MethodUnion(readMethod, writeMethod));
    105 	}
    106       }
    107     }
    108
    109     MBeanParameterInfo[] params = new MBeanParameterInfo[0];
    110
    111     dOperations[0] = new MBeanOperationInfo("activateOptions",
    112 					    "activateOptions(): add an layout",
    113 					    params,
    114 					    "void",
    115 					    MBeanOperationInfo.ACTION);
    116   }
    117
    118   private
    119   boolean isSupportedType(Class clazz) {
    120     if(clazz.isPrimitive()) {
    121       return true;
    122     }
    123
    124     if(clazz == String.class) {
    125       return true;
    126     }
    127     if(clazz.isAssignableFrom(Level.class)) {
    128       return true;
    129     }
    130
    131     return false;
    132   }
    133
    134
    135
    136   public
    137   MBeanInfo getMBeanInfo() {
    138     cat.debug("getMBeanInfo called.");
    139
    140     MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()];
    141     dAttributes.toArray(attribs);
    142
    143     return new MBeanInfo(dClassName,
    144 			 dDescription,
    145 			 attribs,
    146 			 dConstructors,
    147 			 dOperations,
    148 			 new MBeanNotificationInfo[0]);
    149   }
    150
    151   public
    152   Object invoke(String operationName, Object params[], String signature[])
    153     throws MBeanException,
    154     ReflectionException {
    155
    156     if(operationName.equals("activateOptions") &&
    157                      layout instanceof OptionHandler) {
    158       OptionHandler oh = (OptionHandler) layout;
    159       oh.activateOptions();
    160       return "Options activated.";
    161     }
    162     return null;
    163   }
    164
    165   protected
    166   Logger  getLogger() {
    167     return cat;
    168   }
    169
    170
    171   public
    172   Object getAttribute(String attributeName) throws AttributeNotFoundException,
    173                                                    MBeanException,
    174                                                    ReflectionException {
    175
    176        // Check attributeName is not null to avoid NullPointerException later on
    177     if (attributeName == null) {
    178       throw new RuntimeOperationsException(new IllegalArgumentException(
    179 			"Attribute name cannot be null"),
    180        "Cannot invoke a getter of " + dClassName + " with null attribute name");
    181     }
    182
    183
    184     MethodUnion mu = (MethodUnion) dynamicProps.get(attributeName);
    185
    186     cat.debug("----name="+attributeName+", mu="+mu);
    187
    188     if(mu != null && mu.readMethod != null) {
    189       try {
    190 	return mu.readMethod.invoke(layout, null);
    191       } catch(Exception e) {
    192 	return null;
    193       }
    194     }
    195
    196
    197
    198     // If attributeName has not been recognized throw an AttributeNotFoundException
    199     throw(new AttributeNotFoundException("Cannot find " + attributeName +
    200 					 " attribute in " + dClassName));
    201
    202   }
    203
    204
    205   public
    206   void setAttribute(Attribute attribute) throws AttributeNotFoundException,
    207                                                 InvalidAttributeValueException,
    208                                                 MBeanException,
    209                                                 ReflectionException {
    210
    211     // Check attribute is not null to avoid NullPointerException later on
    212     if (attribute == null) {
    213       throw new RuntimeOperationsException(
    214                   new IllegalArgumentException("Attribute cannot be null"),
    215 		  "Cannot invoke a setter of " + dClassName +
    216 		  " with null attribute");
    217     }
    218     String name = attribute.getName();
    219     Object value = attribute.getValue();
    220
    221     if (name == null) {
    222       throw new RuntimeOperationsException(
    223                     new IllegalArgumentException("Attribute name cannot be null"),
    224 		    "Cannot invoke the setter of "+dClassName+
    225 		    " with null attribute name");
    226     }
    227
    228
    229
    230     MethodUnion mu = (MethodUnion) dynamicProps.get(name);
    231
    232     if(mu != null && mu.writeMethod != null) {
    233       Object[] o = new Object[1];
    234
    235       Class[] params = mu.writeMethod.getParameterTypes();
    236       if(params[0] == org.apache.log4j.Priority.class) {
    237 	value = OptionConverter.toLevel((String) value,
    238 					(Level) getAttribute(name));
    239       }
    240       o[0] = value;
    241
    242       try {
    243 	mu.writeMethod.invoke(layout,  o);
    244
    245       } catch(Exception e) {
    246 	cat.error("FIXME", e);
    247       }
    248     } else {
    249       throw(new AttributeNotFoundException("Attribute " + name +
    250 					   " not found in " +
    251 					   this.getClass().getName()));
    252     }
    253   }
    254 }
    255
    256