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