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 java.util.Enumeration; 021import java.util.Iterator; 022import java.util.Vector; 023 024import javax.management.Attribute; 025import javax.management.AttributeList; 026import javax.management.DynamicMBean; 027import javax.management.InstanceAlreadyExistsException; 028import javax.management.InstanceNotFoundException; 029import javax.management.JMException; 030import javax.management.MBeanRegistration; 031import javax.management.MBeanRegistrationException; 032import javax.management.MBeanServer; 033import javax.management.NotCompliantMBeanException; 034import javax.management.ObjectName; 035import javax.management.RuntimeOperationsException; 036 037import org.apache.log4j.Logger; 038import org.apache.log4j.Appender; 039 040public abstract class AbstractDynamicMBean implements DynamicMBean, 041 MBeanRegistration { 042 043 String dClassName; 044 MBeanServer server; 045 private final Vector mbeanList = new Vector(); 046 047 /** 048 * Get MBean name. 049 * @param appender appender, may not be null. 050 * @return name. 051 * @since 1.2.16 052 */ 053 static protected String getAppenderName(final Appender appender){ 054 String name = appender.getName(); 055 if (name == null || name.trim().length() == 0) { 056 // try to get some form of a name, because null is not allowed (exception), and empty string certainly isn't useful in JMX.. 057 name = appender.toString(); 058 } 059 return name; 060 } 061 062 063 /** 064 * Enables the to get the values of several attributes of the Dynamic MBean. 065 */ 066 public 067 AttributeList getAttributes(String[] attributeNames) { 068 069 // Check attributeNames is not null to avoid NullPointerException later on 070 if (attributeNames == null) { 071 throw new RuntimeOperationsException( 072 new IllegalArgumentException("attributeNames[] cannot be null"), 073 "Cannot invoke a getter of " + dClassName); 074 } 075 076 AttributeList resultList = new AttributeList(); 077 078 // if attributeNames is empty, return an empty result list 079 if (attributeNames.length == 0) 080 return resultList; 081 082 // build the result attribute list 083 for (int i=0 ; i<attributeNames.length ; i++){ 084 try { 085 Object value = getAttribute((String) attributeNames[i]); 086 resultList.add(new Attribute(attributeNames[i],value)); 087 } catch (JMException e) { 088 e.printStackTrace(); 089 } catch (RuntimeException e) { 090 e.printStackTrace(); 091 } 092 } 093 return(resultList); 094 } 095 096 /** 097 * Sets the values of several attributes of the Dynamic MBean, and returns the 098 * list of attributes that have been set. 099 */ 100 public AttributeList setAttributes(AttributeList attributes) { 101 102 // Check attributes is not null to avoid NullPointerException later on 103 if (attributes == null) { 104 throw new RuntimeOperationsException( 105 new IllegalArgumentException("AttributeList attributes cannot be null"), 106 "Cannot invoke a setter of " + dClassName); 107 } 108 AttributeList resultList = new AttributeList(); 109 110 // if attributeNames is empty, nothing more to do 111 if (attributes.isEmpty()) 112 return resultList; 113 114 // for each attribute, try to set it and add to the result list if successfull 115 for (Iterator i = attributes.iterator(); i.hasNext();) { 116 Attribute attr = (Attribute) i.next(); 117 try { 118 setAttribute(attr); 119 String name = attr.getName(); 120 Object value = getAttribute(name); 121 resultList.add(new Attribute(name,value)); 122 } catch(JMException e) { 123 e.printStackTrace(); 124 } catch(RuntimeException e) { 125 e.printStackTrace(); 126 } 127 } 128 return(resultList); 129 } 130 131 protected 132 abstract 133 Logger getLogger(); 134 135 public 136 void postDeregister() { 137 getLogger().debug("postDeregister is called."); 138 } 139 140 public 141 void postRegister(java.lang.Boolean registrationDone) { 142 } 143 144 145 146 public 147 ObjectName preRegister(MBeanServer server, ObjectName name) { 148 getLogger().debug("preRegister called. Server="+server+ ", name="+name); 149 this.server = server; 150 return name; 151 } 152 /** 153 * Registers MBean instance in the attached server. Must <em>NOT</em> 154 * be called before registration of this instance. 155 */ 156 protected 157 void registerMBean(Object mbean, ObjectName objectName) 158 throws InstanceAlreadyExistsException, MBeanRegistrationException, 159 NotCompliantMBeanException { 160 server.registerMBean(mbean, objectName); 161 mbeanList.add(objectName); 162 } 163 164 /** 165 * Performs cleanup for deregistering this MBean. Default implementation 166 * unregisters MBean instances which are registered using 167 * {@link #registerMBean(Object mbean, ObjectName objectName)}. 168 */ 169 public 170 void preDeregister() { 171 getLogger().debug("preDeregister called."); 172 173 Enumeration iterator = mbeanList.elements(); 174 while (iterator.hasMoreElements()) { 175 ObjectName name = (ObjectName) iterator.nextElement(); 176 try { 177 server.unregisterMBean(name); 178 } catch (InstanceNotFoundException e) { 179 getLogger().warn("Missing MBean " + name.getCanonicalName()); 180 } catch (MBeanRegistrationException e) { 181 getLogger().warn("Failed unregistering " + name.getCanonicalName()); 182 } 183 } 184 } 185 186 187}