/* * Copyright 1999-2005 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.log4j.jmx; import java.lang.reflect.Constructor; import org.apache.log4j.Logger; import org.apache.log4j.Level; import org.apache.log4j.Layout; import org.apache.log4j.helpers.OptionConverter; import org.apache.log4j.spi.OptionHandler; import java.util.Vector; import java.util.Hashtable; import java.lang.reflect.Method; import javax.management.MBeanAttributeInfo; import javax.management.MBeanConstructorInfo; import javax.management.MBeanNotificationInfo; import javax.management.MBeanInfo; import javax.management.Attribute; import javax.management.MBeanException; import javax.management.AttributeNotFoundException; import javax.management.RuntimeOperationsException; import javax.management.ReflectionException; import javax.management.InvalidAttributeValueException; import javax.management.MBeanOperationInfo; import javax.management.MBeanParameterInfo; import java.beans.Introspector; import java.beans.BeanInfo; import java.beans.PropertyDescriptor; import java.beans.IntrospectionException; public class LayoutDynamicMBean extends AbstractDynamicMBean { private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; private Vector dAttributes = new Vector(); private String dClassName = this.getClass().getName(); private Hashtable dynamicProps = new Hashtable(5); private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1]; private String dDescription = "This MBean acts as a management facade for log4j layouts."; // This category instance is for logging. private static Logger cat = Logger.getLogger(LayoutDynamicMBean.class); // We wrap this layout instance. private Layout layout; public LayoutDynamicMBean(Layout layout) throws IntrospectionException { this.layout = layout; buildDynamicMBeanInfo(); } private void buildDynamicMBeanInfo() throws IntrospectionException { Constructor[] constructors = this.getClass().getConstructors(); dConstructors[0] = new MBeanConstructorInfo( "LayoutDynamicMBean(): Constructs a LayoutDynamicMBean instance", constructors[0]); BeanInfo bi = Introspector.getBeanInfo(layout.getClass()); PropertyDescriptor[] pd = bi.getPropertyDescriptors(); int size = pd.length; for(int i = 0; i < size; i++) { String name = pd[i].getName(); Method readMethod = pd[i].getReadMethod(); Method writeMethod = pd[i].getWriteMethod(); if(readMethod != null) { Class returnClass = readMethod.getReturnType(); if(isSupportedType(returnClass)) { String returnClassName; if(returnClass.isAssignableFrom(Level.class)) { returnClassName = "java.lang.String"; } else { returnClassName = returnClass.getName(); } dAttributes.add(new MBeanAttributeInfo(name, returnClassName, "Dynamic", true, writeMethod != null, false)); dynamicProps.put(name, new MethodUnion(readMethod, writeMethod)); } } } MBeanParameterInfo[] params = new MBeanParameterInfo[0]; dOperations[0] = new MBeanOperationInfo("activateOptions", "activateOptions(): add an layout", params, "void", MBeanOperationInfo.ACTION); } private boolean isSupportedType(Class clazz) { if(clazz.isPrimitive()) { return true; } if(clazz == String.class) { return true; } if(clazz.isAssignableFrom(Level.class)) { return true; } return false; } public MBeanInfo getMBeanInfo() { cat.debug("getMBeanInfo called."); MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()]; dAttributes.toArray(attribs); return new MBeanInfo(dClassName, dDescription, attribs, dConstructors, dOperations, new MBeanNotificationInfo[0]); } public Object invoke(String operationName, Object params[], String signature[]) throws MBeanException, ReflectionException { if(operationName.equals("activateOptions") && layout instanceof OptionHandler) { OptionHandler oh = (OptionHandler) layout; oh.activateOptions(); return "Options activated."; } return null; } protected Logger getLogger() { return cat; } public Object getAttribute(String attributeName) throws AttributeNotFoundException, MBeanException, ReflectionException { // Check attributeName is not null to avoid NullPointerException later on if (attributeName == null) { throw new RuntimeOperationsException(new IllegalArgumentException( "Attribute name cannot be null"), "Cannot invoke a getter of " + dClassName + " with null attribute name"); } MethodUnion mu = (MethodUnion) dynamicProps.get(attributeName); cat.debug("----name="+attributeName+", mu="+mu); if(mu != null && mu.readMethod != null) { try { return mu.readMethod.invoke(layout, null); } catch(Exception e) { return null; } } // If attributeName has not been recognized throw an AttributeNotFoundException throw(new AttributeNotFoundException("Cannot find " + attributeName + " attribute in " + dClassName)); } public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException { // Check attribute is not null to avoid NullPointerException later on if (attribute == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute cannot be null"), "Cannot invoke a setter of " + dClassName + " with null attribute"); } String name = attribute.getName(); Object value = attribute.getValue(); if (name == null) { throw new RuntimeOperationsException( new IllegalArgumentException("Attribute name cannot be null"), "Cannot invoke the setter of "+dClassName+ " with null attribute name"); } MethodUnion mu = (MethodUnion) dynamicProps.get(name); if(mu != null && mu.writeMethod != null) { Object[] o = new Object[1]; Class[] params = mu.writeMethod.getParameterTypes(); if(params[0] == org.apache.log4j.Priority.class) { value = OptionConverter.toLevel((String) value, (Level) getAttribute(name)); } o[0] = value; try { mu.writeMethod.invoke(layout, o); } catch(Exception e) { cat.error("FIXME", e); } } else { throw(new AttributeNotFoundException("Attribute " + name + " not found in " + this.getClass().getName())); } } }