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