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