001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.log4j.jmx; 019 020import org.apache.log4j.Appender; 021import org.apache.log4j.Level; 022import org.apache.log4j.Logger; 023import org.apache.log4j.helpers.OptionConverter; 024 025import javax.management.Attribute; 026import javax.management.AttributeNotFoundException; 027import javax.management.InvalidAttributeValueException; 028import javax.management.JMException; 029import javax.management.MBeanAttributeInfo; 030import javax.management.MBeanConstructorInfo; 031import javax.management.MBeanException; 032import javax.management.MBeanInfo; 033import javax.management.MBeanNotificationInfo; 034import javax.management.MBeanOperationInfo; 035import javax.management.MBeanParameterInfo; 036import javax.management.MalformedObjectNameException; 037import javax.management.Notification; 038import javax.management.NotificationListener; 039import javax.management.ObjectName; 040import javax.management.ReflectionException; 041import javax.management.RuntimeOperationsException; 042import java.lang.reflect.Constructor; 043import java.util.Enumeration; 044import java.util.Vector; 045 046public class LoggerDynamicMBean extends AbstractDynamicMBean 047 implements NotificationListener { 048 049 private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1]; 050 private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[1]; 051 052 private Vector dAttributes = new Vector(); 053 private String dClassName = this.getClass().getName(); 054 055 private String dDescription = 056 "This MBean acts as a management facade for a org.apache.log4j.Logger instance."; 057 058 // This Logger instance is for logging. 059 private static Logger cat = Logger.getLogger(LoggerDynamicMBean.class); 060 061 // We wrap this Logger instance. 062 private Logger logger; 063 064 public LoggerDynamicMBean(Logger logger) { 065 this.logger = logger; 066 buildDynamicMBeanInfo(); 067 } 068 069 public 070 void handleNotification(Notification notification, Object handback) { 071 cat.debug("Received notification: "+notification.getType()); 072 registerAppenderMBean((Appender) notification.getUserData() ); 073 074 075 } 076 077 private 078 void buildDynamicMBeanInfo() { 079 Constructor[] constructors = this.getClass().getConstructors(); 080 dConstructors[0] = new MBeanConstructorInfo( 081 "HierarchyDynamicMBean(): Constructs a HierarchyDynamicMBean instance", 082 constructors[0]); 083 084 dAttributes.add(new MBeanAttributeInfo("name", 085 "java.lang.String", 086 "The name of this Logger.", 087 true, 088 false, 089 false)); 090 091 dAttributes.add(new MBeanAttributeInfo("priority", 092 "java.lang.String", 093 "The priority of this logger.", 094 true, 095 true, 096 false)); 097 098 099 100 101 102 MBeanParameterInfo[] params = new MBeanParameterInfo[2]; 103 params[0] = new MBeanParameterInfo("class name", "java.lang.String", 104 "add an appender to this logger"); 105 params[1] = new MBeanParameterInfo("appender name", "java.lang.String", 106 "name of the appender"); 107 108 dOperations[0] = new MBeanOperationInfo("addAppender", 109 "addAppender(): add an appender", 110 params, 111 "void", 112 MBeanOperationInfo.ACTION); 113 } 114 115 protected 116 Logger getLogger() { 117 return logger; 118 } 119 120 121 public 122 MBeanInfo getMBeanInfo() { 123 //cat.debug("getMBeanInfo called."); 124 125 MBeanAttributeInfo[] attribs = new MBeanAttributeInfo[dAttributes.size()]; 126 dAttributes.toArray(attribs); 127 128 MBeanInfo mb = new MBeanInfo(dClassName, 129 dDescription, 130 attribs, 131 dConstructors, 132 dOperations, 133 new MBeanNotificationInfo[0]); 134 //cat.debug("getMBeanInfo exit."); 135 return mb; 136 } 137 138 public 139 Object invoke(String operationName, Object params[], String signature[]) 140 throws MBeanException, 141 ReflectionException { 142 143 if(operationName.equals("addAppender")) { 144 addAppender((String) params[0], (String) params[1]); 145 return "Hello world."; 146 } 147 148 return null; 149 } 150 151 152 public 153 Object getAttribute(String attributeName) throws AttributeNotFoundException, 154 MBeanException, 155 ReflectionException { 156 157 // Check attributeName is not null to avoid NullPointerException later on 158 if (attributeName == null) { 159 throw new RuntimeOperationsException(new IllegalArgumentException( 160 "Attribute name cannot be null"), 161 "Cannot invoke a getter of " + dClassName + " with null attribute name"); 162 } 163 164 // Check for a recognized attributeName and call the corresponding getter 165 if (attributeName.equals("name")) { 166 return logger.getName(); 167 } else if(attributeName.equals("priority")) { 168 Level l = logger.getLevel(); 169 if(l == null) { 170 return null; 171 } else { 172 return l.toString(); 173 } 174 } else if(attributeName.startsWith("appender=")) { 175 try { 176 return new ObjectName("log4j:"+attributeName ); 177 } catch(MalformedObjectNameException e) { 178 cat.error("Could not create ObjectName" + attributeName); 179 } catch(RuntimeException e) { 180 cat.error("Could not create ObjectName" + attributeName); 181 } 182 } 183 184 185 // If attributeName has not been recognized throw an AttributeNotFoundException 186 throw(new AttributeNotFoundException("Cannot find " + attributeName + 187 " attribute in " + dClassName)); 188 189 } 190 191 192 void addAppender(String appenderClass, String appenderName) { 193 cat.debug("addAppender called with "+appenderClass+", "+appenderName); 194 Appender appender = (Appender) 195 OptionConverter.instantiateByClassName(appenderClass, 196 org.apache.log4j.Appender.class, 197 null); 198 appender.setName(appenderName); 199 logger.addAppender(appender); 200 201 //appenderMBeanRegistration(); 202 203 } 204 205 206 public 207 void setAttribute(Attribute attribute) throws AttributeNotFoundException, 208 InvalidAttributeValueException, 209 MBeanException, 210 ReflectionException { 211 212 // Check attribute is not null to avoid NullPointerException later on 213 if (attribute == null) { 214 throw new RuntimeOperationsException( 215 new IllegalArgumentException("Attribute cannot be null"), 216 "Cannot invoke a setter of " + dClassName + 217 " with null attribute"); 218 } 219 String name = attribute.getName(); 220 Object value = attribute.getValue(); 221 222 if (name == null) { 223 throw new RuntimeOperationsException( 224 new IllegalArgumentException("Attribute name cannot be null"), 225 "Cannot invoke the setter of "+dClassName+ 226 " with null attribute name"); 227 } 228 229 230 if(name.equals("priority")) { 231 if (value instanceof String) { 232 String s = (String) value; 233 Level p = logger.getLevel(); 234 if(s.equalsIgnoreCase("NULL")) { 235 p = null; 236 } else { 237 p = OptionConverter.toLevel(s, p); 238 } 239 logger.setLevel(p); 240 } 241 } else { 242 throw(new AttributeNotFoundException("Attribute " + name + 243 " not found in " + 244 this.getClass().getName())); 245 } 246 } 247 248 void appenderMBeanRegistration() { 249 Enumeration enumeration = logger.getAllAppenders(); 250 while(enumeration.hasMoreElements()) { 251 Appender appender = (Appender) enumeration.nextElement(); 252 registerAppenderMBean(appender); 253 } 254 } 255 256 void registerAppenderMBean(Appender appender) { 257 String name = getAppenderName(appender); 258 cat.debug("Adding AppenderMBean for appender named "+name); 259 ObjectName objectName = null; 260 try { 261 AppenderDynamicMBean appenderMBean = new AppenderDynamicMBean(appender); 262 objectName = new ObjectName("log4j", "appender", name); 263 if (!server.isRegistered(objectName)) { 264 registerMBean(appenderMBean, objectName); 265 dAttributes.add(new MBeanAttributeInfo("appender=" + name, "javax.management.ObjectName", 266 "The " + name + " appender.", true, true, false)); 267 } 268 269 } catch(JMException e) { 270 cat.error("Could not add appenderMBean for ["+name+"].", e); 271 } catch(java.beans.IntrospectionException e) { 272 cat.error("Could not add appenderMBean for ["+name+"].", e); 273 } catch(RuntimeException e) { 274 cat.error("Could not add appenderMBean for ["+name+"].", e); 275 } 276 } 277 278 public 279 void postRegister(java.lang.Boolean registrationDone) { 280 appenderMBeanRegistration(); 281 } 282}