1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.jmx;
19
20
21 import java.lang.reflect.Constructor;
22 import org.apache.log4j.*;
23
24 import org.apache.log4j.spi.HierarchyEventListener;
25 import org.apache.log4j.spi.LoggerRepository;
26 import org.apache.log4j.helpers.OptionConverter;
27
28 import java.util.Vector;
29 import javax.management.MBeanAttributeInfo;
30 import javax.management.MBeanConstructorInfo;
31 import javax.management.MBeanNotificationInfo;
32 import javax.management.MBeanOperationInfo;
33 import javax.management.MBeanParameterInfo;
34
35 import javax.management.ObjectName;
36 import javax.management.MBeanInfo;
37 import javax.management.Attribute;
38
39 import javax.management.MBeanException;
40 import javax.management.AttributeNotFoundException;
41 import javax.management.RuntimeOperationsException;
42 import javax.management.ReflectionException;
43 import javax.management.InvalidAttributeValueException;
44 import javax.management.NotificationBroadcasterSupport;
45 import javax.management.NotificationBroadcaster;
46 import javax.management.Notification;
47 import javax.management.NotificationListener;
48 import javax.management.NotificationFilter;
49 import javax.management.NotificationFilterSupport;
50 import javax.management.ListenerNotFoundException;
51
52 public class HierarchyDynamicMBean extends AbstractDynamicMBean
53 implements HierarchyEventListener,
54 NotificationBroadcaster {
55
56 static final String ADD_APPENDER = "addAppender.";
57 static final String THRESHOLD = "threshold";
58
59 private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
60 private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1];
61
62 private Vector vAttributes = new Vector();
63 private String dClassName = this.getClass().getName();
64 private String dDescription =
65 "This MBean acts as a management facade for org.apache.log4j.Hierarchy.";
66
67 private NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport();
68
69
70 private LoggerRepository hierarchy;
71
72 private static Logger log = Logger.getLogger(HierarchyDynamicMBean.class);
73
74 public HierarchyDynamicMBean() {
75 hierarchy = LogManager.getLoggerRepository();
76 buildDynamicMBeanInfo();
77 }
78
79 private
80 void buildDynamicMBeanInfo() {
81 Constructor[] constructors = this.getClass().getConstructors();
82 dConstructors[0] = new MBeanConstructorInfo(
83 "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance",
84 constructors[0]);
85
86 vAttributes.add(new MBeanAttributeInfo(THRESHOLD,
87 "java.lang.String",
88 "The \"threshold\" state of the hiearchy.",
89 true,
90 true,
91 false));
92
93 MBeanParameterInfo[] params = new MBeanParameterInfo[1];
94 params[0] = new MBeanParameterInfo("name", "java.lang.String",
95 "Create a logger MBean" );
96 dOperations[0] = new MBeanOperationInfo("addLoggerMBean",
97 "addLoggerMBean(): add a loggerMBean",
98 params ,
99 "javax.management.ObjectName",
100 MBeanOperationInfo.ACTION);
101 }
102
103
104 public
105 ObjectName addLoggerMBean(String name) {
106 Logger cat = LogManager.exists(name);
107
108 if(cat != null) {
109 return addLoggerMBean(cat);
110 } else {
111 return null;
112 }
113 }
114
115 ObjectName addLoggerMBean(Logger logger) {
116 String name = logger.getName();
117 ObjectName objectName = null;
118 try {
119 LoggerDynamicMBean loggerMBean = new LoggerDynamicMBean(logger);
120 objectName = new ObjectName("log4j", "logger", name);
121
122 if (!server.isRegistered(objectName)) {
123 server.registerMBean(loggerMBean, objectName);
124 NotificationFilterSupport nfs = new NotificationFilterSupport();
125 nfs.enableType(ADD_APPENDER + logger.getName());
126 log.debug("---Adding logger [" + name + "] as listener.");
127 nbs.addNotificationListener(loggerMBean, nfs, null);
128 vAttributes.add(new MBeanAttributeInfo("logger=" + name, "javax.management.ObjectName",
129 "The " + name + " logger.", true, true,
130
131 false));
132
133 }
134
135 } catch(Exception e) {
136 log.error("Could not add loggerMBean for ["+name+"].", e);
137 }
138 return objectName;
139 }
140
141 public
142 void addNotificationListener(NotificationListener listener,
143 NotificationFilter filter,
144 java.lang.Object handback) {
145 nbs.addNotificationListener(listener, filter, handback);
146 }
147
148 protected
149 Logger getLogger() {
150 return log;
151 }
152
153 public
154 MBeanInfo getMBeanInfo() {
155
156
157 MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[vAttributes.size()];
158 vAttributes.toArray(attribs);
159
160 return new MBeanInfo(dClassName,
161 dDescription,
162 attribs,
163 dConstructors,
164 dOperations,
165 new MBeanNotificationInfo[0]);
166 }
167
168 public
169 MBeanNotificationInfo[] getNotificationInfo(){
170 return nbs.getNotificationInfo();
171 }
172
173 public
174 Object invoke(String operationName,
175 Object params[],
176 String signature[]) throws MBeanException,
177 ReflectionException {
178
179 if (operationName == null) {
180 throw new RuntimeOperationsException(
181 new IllegalArgumentException("Operation name cannot be null"),
182 "Cannot invoke a null operation in " + dClassName);
183 }
184
185
186 if(operationName.equals("addLoggerMBean")) {
187 return addLoggerMBean((String)params[0]);
188 } else {
189 throw new ReflectionException(
190 new NoSuchMethodException(operationName),
191 "Cannot find the operation " + operationName + " in " + dClassName);
192 }
193
194 }
195
196
197 public
198 Object getAttribute(String attributeName) throws AttributeNotFoundException,
199 MBeanException,
200 ReflectionException {
201
202
203 if (attributeName == null) {
204 throw new RuntimeOperationsException(new IllegalArgumentException(
205 "Attribute name cannot be null"),
206 "Cannot invoke a getter of " + dClassName + " with null attribute name");
207 }
208
209 log.debug("Called getAttribute with ["+attributeName+"].");
210
211
212 if (attributeName.equals(THRESHOLD)) {
213 return hierarchy.getThreshold();
214 } else if(attributeName.startsWith("logger")) {
215 int k = attributeName.indexOf("%3D");
216 String val = attributeName;
217 if(k > 0) {
218 val = attributeName.substring(0, k)+'='+ attributeName.substring(k+3);
219 }
220 try {
221 return new ObjectName("log4j:"+val);
222 } catch(Exception e) {
223 log.error("Could not create ObjectName" + val);
224 }
225 }
226
227
228
229
230 throw(new AttributeNotFoundException("Cannot find " + attributeName +
231 " attribute in " + dClassName));
232
233 }
234
235
236 public
237 void addAppenderEvent(Category logger, Appender appender) {
238 log.debug("addAppenderEvent called: logger="+logger.getName()+
239 ", appender="+appender.getName());
240 Notification n = new Notification(ADD_APPENDER+logger.getName(), this, 0);
241 n.setUserData(appender);
242 log.debug("sending notification.");
243 nbs.sendNotification(n);
244 }
245
246 public
247 void removeAppenderEvent(Category cat, Appender appender) {
248 log.debug("removeAppenderCalled: logger="+cat.getName()+
249 ", appender="+appender.getName());
250 }
251
252 public
253 void postRegister(java.lang.Boolean registrationDone) {
254 log.debug("postRegister is called.");
255 hierarchy.addHierarchyEventListener(this);
256 Logger root = hierarchy.getRootLogger();
257 addLoggerMBean(root);
258 }
259
260 public
261 void removeNotificationListener(NotificationListener listener)
262 throws ListenerNotFoundException {
263 nbs.removeNotificationListener(listener);
264 }
265
266 public
267 void setAttribute(Attribute attribute) throws AttributeNotFoundException,
268 InvalidAttributeValueException,
269 MBeanException,
270 ReflectionException {
271
272
273 if (attribute == null) {
274 throw new RuntimeOperationsException(
275 new IllegalArgumentException("Attribute cannot be null"),
276 "Cannot invoke a setter of "+dClassName+" with null attribute");
277 }
278 String name = attribute.getName();
279 Object value = attribute.getValue();
280
281 if (name == null) {
282 throw new RuntimeOperationsException(
283 new IllegalArgumentException("Attribute name cannot be null"),
284 "Cannot invoke the setter of "+dClassName+
285 " with null attribute name");
286 }
287
288 if(name.equals(THRESHOLD)) {
289 Level l = OptionConverter.toLevel((String) value,
290 hierarchy.getThreshold());
291 hierarchy.setThreshold(l);
292 }
293
294
295 }
296 }