package org.jconfig.jmx;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Hashtable;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
import org.jconfig.Configuration;
import org.jconfig.ConfigurationManager;
import org.jconfig.ConfigurationManagerException;
/**
* This MBean manages each Configuration that the ConfiguratorManager holds.<br><br>
* Atributes: <br>
* <ul><li>Its own name</li>
* <li>One attribute for each category</li></ul>
* <br>
* Operations: <br>
* <ul><li>Reload: It reloads the configuration using ConfigurationManager.reload()</li>
* <li>Save: Saves que configuration using ConfigurationMananager.save()</li></ul>
* <br>
* <br>
* Notes: <br>
* ConfigurationMbeans could be registered as FileChangeListeners
* If the configuration file changes, the method reloadConfiguration should be executed
* so as to sincronize the MBean with its managed configuration
*
*@author Eduardo Macarron emacarron@euskalnet.net
*/
public class ConfigurationDynamicMBean extends AbstractDynamicMBean {
private MBeanConstructorInfo[] dConstructors = new MBeanConstructorInfo[1];
// can reload, and save a configuration
private MBeanOperationInfo[] dOperations = new MBeanOperationInfo[3];
private ArrayList alBasicAttributes = new ArrayList();
private ArrayList alMbeanAttributes = new ArrayList();
private String dClassName = this.getClass().getName();
private String dDescription =
"This MBean acts as a management facade for a org.jconfig.Configuration instance.";
private ObjectName objectName;
// Configuration name
// Cannot hold a Configuration instance because it changes on reloads
private String configurationName;
public ConfigurationDynamicMBean(ObjectName objectName,String configurationName) {
// constructor, wraps configurator and builds MBean infor
this.configurationName = configurationName;
this.objectName = objectName;
buildDynamicMBeanInfo();
}
private void buildDynamicMBeanInfo() {
Constructor[] constructors = this.getClass().getConstructors();
dConstructors[0] =
new MBeanConstructorInfo(
"ConfigurationDynamicMBean(): Constructs a ConfigurationDynamicMBean instance",
constructors[0]);
alBasicAttributes.add(
new MBeanAttributeInfo(
"name",
"java.lang.String",
"The name of this Configuration.",
true,
false,
false));
// has no parameters
MBeanParameterInfo[] params = new MBeanParameterInfo[0];
MBeanParameterInfo[] params2 = new MBeanParameterInfo[1];
params2[0] = new MBeanParameterInfo(
"name",
"java.lang.String",
"The name");
dOperations[0] =
new MBeanOperationInfo(
"reloadConfiguration",
"reloadConfiguration(): reloads configuration",
params,
"void",
MBeanOperationInfo.ACTION);
dOperations[1] =
new MBeanOperationInfo(
"saveConfiguration",
"saveConfiguration(): saves configuration",
params,
"void",
MBeanOperationInfo.ACTION);
dOperations[2] =
new MBeanOperationInfo(
"addCategory",
"addCategory(String name): create new category",
params2,
"void",
MBeanOperationInfo.ACTION);
}
public MBeanInfo getMBeanInfo() {
System.out.println("getMBeanInfo called.");
MBeanAttributeInfo[] attribs =
new MBeanAttributeInfo[alBasicAttributes.size()
+ alMbeanAttributes.size()];
ArrayList al = new ArrayList();
al.addAll(alBasicAttributes);
al.addAll(alMbeanAttributes);
al.toArray(attribs);
al = null;
MBeanInfo mb =
new MBeanInfo(
dClassName,
dDescription,
attribs,
dConstructors,
dOperations,
new MBeanNotificationInfo[0]);
System.out.println("getMBeanInfo exit.");
return mb;
}
public Object invoke(
String operationName,
Object params[],
String signature[])
throws MBeanException, ReflectionException {
if (operationName.equals("reloadConfiguration")) {
reloadConfiguration();
} else if (operationName.equals("saveConfiguration")) {
saveConfiguration();
} else {
throw new ReflectionException(
new NoSuchMethodException(operationName),
"Cannot find the operation "
+ operationName
+ " in "
+ dClassName);
}
return null;
}
public void addCategory(String name) throws MBeanException {
}
public void reloadConfiguration() throws MBeanException {
System.out.println("reloadConfiguration called");
try {
// deregister categories
categoryMBeanDeregistration();
// reload configuration
ConfigurationManager.getInstance().reload(configurationName);
// register categories again
categoryMBeanRegistration();
} catch (ConfigurationManagerException cme) {
throw new MBeanException(cme);
}
}
public void saveConfiguration() throws MBeanException {
System.out.println("saveConfiguration called");
try {
ConfigurationManager.getInstance().save(configurationName);
} catch (ConfigurationManagerException cme) {
throw new MBeanException(cme);
}
}
public Object getAttribute(String attributeName)
throws AttributeNotFoundException, MBeanException, ReflectionException {
// Check attributeName is not null to avoid NullPointerException later on
if (attributeName == null) {
throw new RuntimeOperationsException(
new IllegalArgumentException("Attribute name cannot be null"),
"Cannot invoke a getter of "
+ dClassName
+ " with null attribute name");
}
// Check for a recognized attributeName and call the corresponding getter
if (attributeName.equals("name")) {
return configurationName;
} else if (attributeName.startsWith("category=")) {
Hashtable keys = new Hashtable();
keys.put("configuration", configurationName);
keys.put(
"category",
attributeName.substring(attributeName.indexOf("=") + 1));
try {
return new ObjectName(objectName.getDomain(), keys);
} catch (Exception e) {
System.out.println(
"Could not create ObjectName "
+ objectName.getDomain()
+ ":"
+ keys);
}
}
//If attributeName has not been recognized throw an AttributeNotFoundException
throw (
new AttributeNotFoundException(
"Cannot find "
+ attributeName
+ " attribute in "
+ dClassName));
}
public void setAttribute(Attribute attribute)
throws
AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException,
ReflectionException {
// Check attribute is not null to avoid NullPointerException later on
if (attribute == null) {
throw new RuntimeOperationsException(
new IllegalArgumentException("Attribute cannot be null"),
"Cannot invoke a setter of "
+ dClassName
+ " with null attribute");
}
String name = attribute.getName();
Object value = attribute.getValue();
if (name == null) {
throw new RuntimeOperationsException(
new IllegalArgumentException("Attribute name cannot be null"),
"Cannot invoke the setter of "
+ dClassName
+ " with null attribute name");
}
}
void categoryMBeanRegistration() {
// registers all categories
Configuration configuration =
ConfigurationManager.getConfiguration(configurationName);
String[] categoryNames = configuration.getCategoryNames();
for (int i = 0; i < categoryNames.length; i++) {
registerCategoryMBean(categoryNames[i]);
}
}
void registerCategoryMBean(String categoryName) {
System.out.println("Adding CategoryMBean for category named " + categoryName);
ObjectName categoryObjectName = null;
try {
Hashtable keys = new Hashtable();
keys.put("configuration", configurationName);
keys.put("category", categoryName);
categoryObjectName = new ObjectName(objectName.getDomain(), keys);
CategoryDynamicMBean categoryMBean =
new CategoryDynamicMBean(
categoryObjectName,
configurationName,
categoryName);
server.registerMBean(categoryMBean, categoryObjectName);
alMbeanAttributes.add(
new MBeanAttributeInfo(
"category=" + categoryName,
"javax.management.ObjectName",
"The " + categoryName + " category.",
true,
true,
false));
} catch (Exception e) {
System.out.println(
"Could not add CategoryMBean for [" + categoryName + "]."+e);
}
}
public void postRegister(java.lang.Boolean registrationDone) {
System.out.println("postRegister called");
// registers an MBean for every category found in this configuration
categoryMBeanRegistration();
}
void categoryMBeanDeregistration() {
// deregisters all categories
Configuration configuration =
ConfigurationManager.getConfiguration(configurationName);
String[] categoryNames = configuration.getCategoryNames();
for (int i = 0; i < categoryNames.length; i++) {
unregisterCategoryMBean(categoryNames[i]);
}
// categories are removed
alMbeanAttributes.clear();
}
void unregisterCategoryMBean(String categoryName) {
System.out.println("Removing CategoryMBean for category named " + categoryName);
ObjectName categoryObjectName = null;
try {
Hashtable keys = new Hashtable();
keys.put("configuration", configurationName);
keys.put("category", categoryName);
categoryObjectName = new ObjectName(objectName.getDomain(), keys);
server.unregisterMBean(categoryObjectName);
} catch (Exception e) {
System.out.println(
"Could not add CategoryMBean for [" + categoryName + "]."+e);
}
}
}