JAL-3048 test updated for AlignExportSettings changes
[jalview.git] / srcjar2 / org / apache / log4j / jmx / AppenderDynamicMBean.java
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 org.apache.log4j.Appender;
21 import org.apache.log4j.Layout;
22 import org.apache.log4j.Level;
23 import org.apache.log4j.Logger;
24 import org.apache.log4j.Priority;
25 import org.apache.log4j.helpers.OptionConverter;
26 import org.apache.log4j.spi.OptionHandler;
27
28 import javax.management.Attribute;
29 import javax.management.AttributeNotFoundException;
30 import javax.management.InvalidAttributeValueException;
31 import javax.management.JMException;
32 import javax.management.MBeanAttributeInfo;
33 import javax.management.MBeanConstructorInfo;
34 import javax.management.MBeanException;
35 import javax.management.MBeanInfo;
36 import javax.management.MBeanNotificationInfo;
37 import javax.management.MBeanOperationInfo;
38 import javax.management.MBeanParameterInfo;
39 import javax.management.MBeanServer;
40 import javax.management.MalformedObjectNameException;
41 import javax.management.ObjectName;
42 import javax.management.ReflectionException;
43 import javax.management.RuntimeOperationsException;
44 import java.beans.BeanInfo;
45 import java.beans.IntrospectionException;
46 import java.beans.Introspector;
47 import java.beans.PropertyDescriptor;
48 import java.lang.reflect.Constructor;
49 import java.lang.reflect.InvocationTargetException;
50 import java.lang.reflect.Method;
51 import java.util.Hashtable;
52 import java.util.Vector;
53 import java.io.InterruptedIOException;
54
55 public class AppenderDynamicMBean extends AbstractDynamicMBean {
56
57   private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
58   private Vector dAttributes = new Vector();
59   private String dClassName = this.getClass().getName();
60
61   private Hashtable dynamicProps = new Hashtable(5);
62   private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[2];
63   private String dDescription =
64      "This MBean acts as a management facade for log4j appenders.";
65
66   // This category instance is for logging.
67   private static Logger cat = Logger.getLogger(AppenderDynamicMBean.class);
68
69   // We wrap this appender instance.
70   private Appender appender;
71
72   public  AppenderDynamicMBean(Appender appender) throws IntrospectionException {
73     this.appender = appender;
74     buildDynamicMBeanInfo();
75   }
76
77   private
78   void buildDynamicMBeanInfo() throws IntrospectionException {
79     Constructor[] constructors = this.getClass().getConstructors();
80     dConstructors[0] = new MBeanConstructorInfo(
81              "AppenderDynamicMBean(): Constructs a AppenderDynamicMBean instance",
82              constructors[0]);
83
84
85     BeanInfo bi = Introspector.getBeanInfo(appender.getClass());
86     PropertyDescriptor[] pd = bi.getPropertyDescriptors();
87
88     int size = pd.length;
89
90     for(int i = 0; i < size; i++) {
91       String name = pd[i].getName();
92       Method readMethod =  pd[i].getReadMethod();
93       Method writeMethod =  pd[i].getWriteMethod();
94       if(readMethod != null) {
95         Class returnClass = readMethod.getReturnType();
96         if(isSupportedType(returnClass)) {
97           String returnClassName;
98           if(returnClass.isAssignableFrom(Priority.class)) {
99             returnClassName = "java.lang.String";
100           } else {
101             returnClassName = returnClass.getName();
102           }
103
104           dAttributes.add(new MBeanAttributeInfo(name,
105                                                  returnClassName,
106                                                  "Dynamic",
107                                                  true,
108                                                  writeMethod != null,
109                                                  false));
110           dynamicProps.put(name, new MethodUnion(readMethod, writeMethod));
111         }
112       }
113     }
114
115     MBeanParameterInfo[] params = new MBeanParameterInfo[0];
116
117     dOperations[0] = new MBeanOperationInfo("activateOptions",
118                                             "activateOptions(): add an appender",
119                                             params,
120                                             "void",
121                                             MBeanOperationInfo.ACTION);
122
123     params = new MBeanParameterInfo[1];
124     params[0] = new MBeanParameterInfo("layout class", "java.lang.String",
125                                        "layout class");
126
127     dOperations[1] = new MBeanOperationInfo("setLayout",
128                                             "setLayout(): add a layout",
129                                             params,
130                                             "void",
131                                             MBeanOperationInfo.ACTION);
132   }
133
134   private
135   boolean isSupportedType(Class clazz) {
136     if(clazz.isPrimitive()) {
137       return true;
138     }
139
140     if(clazz == String.class) {
141       return true;
142     }
143
144
145     if(clazz.isAssignableFrom(Priority.class)) {
146       return true;
147     }
148
149     return false;
150
151
152   }
153
154
155
156   public
157   MBeanInfo getMBeanInfo() {
158     cat.debug("getMBeanInfo called.");
159
160     MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()];
161     dAttributes.toArray(attribs);
162
163     return new MBeanInfo(dClassName,
164                          dDescription,
165                          attribs,
166                          dConstructors,
167                          dOperations,
168                          new MBeanNotificationInfo[0]);
169   }
170
171   public
172   Object invoke(String operationName, Object params[], String signature[])
173     throws MBeanException,
174     ReflectionException {
175
176     if(operationName.equals("activateOptions") &&
177                      appender instanceof OptionHandler) {
178       OptionHandler oh = (OptionHandler) appender;
179       oh.activateOptions();
180       return "Options activated.";
181     } else if (operationName.equals("setLayout")) {
182       Layout layout = (Layout) OptionConverter.instantiateByClassName((String)
183                                                                       params[0],
184                                                                       Layout.class,
185                                                                       null);
186       appender.setLayout(layout);
187       registerLayoutMBean(layout);
188     }
189     return null;
190   }
191
192   void registerLayoutMBean(Layout layout) {
193     if(layout == null) {
194         return;
195     }
196
197     String name = getAppenderName(appender)+",layout="+layout.getClass().getName();
198     cat.debug("Adding LayoutMBean:"+name);
199     ObjectName objectName = null;
200     try {
201       LayoutDynamicMBean appenderMBean = new LayoutDynamicMBean(layout);
202       objectName = new ObjectName("log4j:appender="+name);
203       if (!server.isRegistered(objectName)) {
204         registerMBean(appenderMBean, objectName);
205         dAttributes.add(new MBeanAttributeInfo("appender=" + name, "javax.management.ObjectName",
206                 "The " + name + " layout.", true, true, false));
207       }
208
209     } catch(JMException e) {
210       cat.error("Could not add DynamicLayoutMBean for ["+name+"].", e);
211     } catch(java.beans.IntrospectionException e) {
212       cat.error("Could not add DynamicLayoutMBean for ["+name+"].", e);
213     } catch(RuntimeException e) {
214       cat.error("Could not add DynamicLayoutMBean for ["+name+"].", e);
215     }
216   }
217
218   protected
219   Logger getLogger() {
220     return cat;
221   }
222
223
224   public
225   Object getAttribute(String attributeName) throws AttributeNotFoundException,
226                                                    MBeanException,
227                                                    ReflectionException {
228
229        // Check attributeName is not null to avoid NullPointerException later on
230     if (attributeName == null) {
231       throw new RuntimeOperationsException(new IllegalArgumentException(
232                         "Attribute name cannot be null"),
233        "Cannot invoke a getter of " + dClassName + " with null attribute name");
234     }
235
236     cat.debug("getAttribute called with ["+attributeName+"].");
237     if(attributeName.startsWith("appender="+appender.getName()+",layout")) {
238       try {
239             return new ObjectName("log4j:"+attributeName );
240       } catch(MalformedObjectNameException e) {
241             cat.error("attributeName", e);
242       } catch(RuntimeException e) {
243             cat.error("attributeName", e);
244       }
245     }
246
247     MethodUnion mu = (MethodUnion) dynamicProps.get(attributeName);
248
249     //cat.debug("----name="+attributeName+", b="+b);
250
251     if(mu != null && mu.readMethod != null) {
252       try {
253         return mu.readMethod.invoke(appender, null);
254       } catch(IllegalAccessException e) {
255             return null;
256       } catch(InvocationTargetException e) {
257           if (e.getTargetException() instanceof InterruptedException
258                   || e.getTargetException() instanceof InterruptedIOException) {
259               Thread.currentThread().interrupt();
260           }
261             return null;
262       } catch(RuntimeException e) {
263             return null;
264       }
265     }
266
267
268
269     // If attributeName has not been recognized throw an AttributeNotFoundException
270     throw(new AttributeNotFoundException("Cannot find " + attributeName +
271                                          " attribute in " + dClassName));
272
273   }
274
275
276   public
277   void setAttribute(Attribute attribute) throws AttributeNotFoundException,
278                                                 InvalidAttributeValueException,
279                                                 MBeanException,
280                                                 ReflectionException {
281
282     // Check attribute is not null to avoid NullPointerException later on
283     if (attribute == null) {
284       throw new RuntimeOperationsException(
285                   new IllegalArgumentException("Attribute cannot be null"),
286                   "Cannot invoke a setter of " + dClassName +
287                   " with null attribute");
288     }
289     String name = attribute.getName();
290     Object value = attribute.getValue();
291
292     if (name == null) {
293       throw new RuntimeOperationsException(
294                     new IllegalArgumentException("Attribute name cannot be null"),
295                     "Cannot invoke the setter of "+dClassName+
296                     " with null attribute name");
297     }
298
299
300
301     MethodUnion mu = (MethodUnion) dynamicProps.get(name);
302
303     if(mu != null && mu.writeMethod != null) {
304       Object[] o = new Object[1];
305
306       Class[] params = mu.writeMethod.getParameterTypes();
307       if(params[0] == org.apache.log4j.Priority.class) {
308         value = OptionConverter.toLevel((String) value,
309                                         (Level) getAttribute(name));
310       }
311       o[0] = value;
312
313       try {
314         mu.writeMethod.invoke(appender,  o);
315
316       } catch(InvocationTargetException e) {
317         if (e.getTargetException() instanceof InterruptedException
318                 || e.getTargetException() instanceof InterruptedIOException) {
319             Thread.currentThread().interrupt();
320         }
321         cat.error("FIXME", e);
322       } catch(IllegalAccessException e) {
323             cat.error("FIXME", e);
324       } catch(RuntimeException e) {
325             cat.error("FIXME", e);
326       }
327     } else if(name.endsWith(".layout")) {
328
329     } else {
330       throw(new AttributeNotFoundException("Attribute " + name +
331                                            " not found in " +
332                                            this.getClass().getName()));
333     }
334   }
335
336   public
337   ObjectName preRegister(MBeanServer server, ObjectName name) {
338     cat.debug("preRegister called. Server="+server+ ", name="+name);
339     this.server = server;
340     registerLayoutMBean(appender.getLayout());
341
342     return name;
343   }
344
345
346 }
347