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}