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