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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 package org.apache.log4j.jmx;
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;
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;
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;
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;
51 public class LayoutDynamicMBean extends AbstractDynamicMBean {
53 private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
54 private Vector dAttributes = new Vector();
55 private String dClassName = this.getClass().getName();
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.";
62 // This category instance is for logging.
63 private static Logger cat = Logger.getLogger(LayoutDynamicMBean.class);
65 // We wrap this layout instance.
66 private Layout layout;
68 public LayoutDynamicMBean(Layout layout) throws IntrospectionException {
70 buildDynamicMBeanInfo();
74 void buildDynamicMBeanInfo() throws IntrospectionException {
75 Constructor[] constructors = this.getClass().getConstructors();
76 dConstructors[0] = new MBeanConstructorInfo(
77 "LayoutDynamicMBean(): Constructs a LayoutDynamicMBean instance",
81 BeanInfo bi = Introspector.getBeanInfo(layout.getClass());
82 PropertyDescriptor[] pd = bi.getPropertyDescriptors();
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";
97 returnClassName = returnClass.getName();
100 dAttributes.add(new MBeanAttributeInfo(name,
106 dynamicProps.put(name, new MethodUnion(readMethod, writeMethod));
111 MBeanParameterInfo[] params = new MBeanParameterInfo[0];
113 dOperations[0] = new MBeanOperationInfo("activateOptions",
114 "activateOptions(): add an layout",
117 MBeanOperationInfo.ACTION);
121 boolean isSupportedType(Class clazz) {
122 if(clazz.isPrimitive()) {
126 if(clazz == String.class) {
129 if(clazz.isAssignableFrom(Level.class)) {
139 MBeanInfo getMBeanInfo() {
140 cat.debug("getMBeanInfo called.");
142 MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()];
143 dAttributes.toArray(attribs);
145 return new MBeanInfo(dClassName,
150 new MBeanNotificationInfo[0]);
154 Object invoke(String operationName, Object params[], String signature[])
155 throws MBeanException,
156 ReflectionException {
158 if(operationName.equals("activateOptions") &&
159 layout instanceof OptionHandler) {
160 OptionHandler oh = layout;
161 oh.activateOptions();
162 return "Options activated.";
174 Object getAttribute(String attributeName) throws AttributeNotFoundException,
176 ReflectionException {
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");
186 MethodUnion mu = (MethodUnion) dynamicProps.get(attributeName);
188 cat.debug("----name="+attributeName+", mu="+mu);
190 if(mu != null && mu.readMethod != null) {
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();
199 } catch(IllegalAccessException e) {
201 } catch(RuntimeException e) {
208 // If attributeName has not been recognized throw an AttributeNotFoundException
209 throw(new AttributeNotFoundException("Cannot find " + attributeName +
210 " attribute in " + dClassName));
216 void setAttribute(Attribute attribute) throws AttributeNotFoundException,
217 InvalidAttributeValueException,
219 ReflectionException {
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");
228 String name = attribute.getName();
229 Object value = attribute.getValue();
232 throw new RuntimeOperationsException(
233 new IllegalArgumentException("Attribute name cannot be null"),
234 "Cannot invoke the setter of "+dClassName+
235 " with null attribute name");
240 MethodUnion mu = (MethodUnion) dynamicProps.get(name);
242 if(mu != null && mu.writeMethod != null) {
243 Object[] o = new Object[1];
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));
253 mu.writeMethod.invoke(layout, o);
255 } catch(InvocationTargetException e) {
256 if (e.getTargetException() instanceof InterruptedException
257 || e.getTargetException() instanceof InterruptedIOException) {
258 Thread.currentThread().interrupt();
260 cat.error("FIXME", e);
261 } catch(IllegalAccessException e) {
262 cat.error("FIXME", e);
263 } catch(RuntimeException e) {
264 cat.error("FIXME", e);
267 throw(new AttributeNotFoundException("Attribute " + name +
269 this.getClass().getName()));