org.jboss.mx.metadata.JBossXMBean10 Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.mx.metadata;
import java.beans.IntrospectionException;
import java.beans.PropertyEditor;
import java.beans.PropertyEditorManager;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.management.Descriptor;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.NotCompliantMBeanException;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.modelmbean.ModelMBeanAttributeInfo;
import javax.management.modelmbean.ModelMBeanConstructorInfo;
import javax.management.modelmbean.ModelMBeanInfo;
import javax.management.modelmbean.ModelMBeanInfoSupport;
import javax.management.modelmbean.ModelMBeanNotificationInfo;
import javax.management.modelmbean.ModelMBeanOperationInfo;
import org.dom4j.Attribute;
import org.dom4j.Element;
import org.jboss.logging.Logger;
import org.jboss.mx.modelmbean.XMBeanConstants;
import org.jboss.mx.util.JBossNotCompliantMBeanException;
import org.jboss.util.Classes;
import org.jboss.util.StringPropertyReplacer;
import org.jboss.util.propertyeditor.PropertyEditors;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
/**
* The JBoss 1.0 model mbean descriptor parser class.
*
* @author Matt Munz
* @author [email protected]
* @author [email protected]
* @version $Revision: 81026 $
*/
public class JBossXMBean10 extends AbstractBuilder
implements XMBeanConstants
{
private static Logger log = Logger.getLogger(JBossXMBean10.class);
// Attributes ----------------------------------------------------
private Element element;
/**
* The class name of the Model MBean implementation class.
*/
private String mmbClassName = null;
/**
* The class name of the resource object represented by this Model MBean.
*/
private String resourceClassName = null;
// Constructors --------------------------------------------------
public JBossXMBean10(String mmbClassName, String resourceClassName, Element element, Map properties)
{
super();
this.mmbClassName = mmbClassName;
this.resourceClassName = resourceClassName;
this.element = element;
setProperties(properties);
}
// MetaDataBuilder implementation --------------------------------
public MBeanInfo build() throws NotCompliantMBeanException
{
try
{
if (element == null)
{
throw new JBossNotCompliantMBeanException("No xml configuration supplied!");
}
String description = element.elementTextTrim("description");
if (resourceClassName == null)
{
resourceClassName = element.elementTextTrim("class");
}
List constructors = element.elements("constructor");
List operations = element.elements("operation");
List attributes = element.elements("attribute");
List notifications = element.elements("notification");
Descriptor descr = getDescriptor(element, mmbClassName, MBEAN_DESCRIPTOR);
ModelMBeanInfo info = buildMBeanMetaData(
description, constructors, operations,
attributes, notifications, descr
);
return (MBeanInfo) info;
}
catch (Throwable t)
{
throw new JBossNotCompliantMBeanException("Error parsing the XML file: ", t);
}
}
// Protected -----------------------------------------------------
protected Descriptor getDescriptor(final Element parent, final String infoName, final String type)
throws NotCompliantMBeanException
{
Descriptor descr = new DescriptorSupport();
descr.setField(NAME, infoName);
descr.setField(DISPLAY_NAME, infoName);
descr.setField(DESCRIPTOR_TYPE, type);
Element descriptors = parent.element("descriptors");
if (descriptors == null)
{
return descr;
}
for (Iterator i = descriptors.elementIterator(); i.hasNext();)
{
Element descriptor = (Element)i.next();
String name = descriptor.getName();
if (name.equals("persistence"))
{
String persistPolicy = descriptor.attributeValue(PERSIST_POLICY);
String persistPeriod = descriptor.attributeValue(PERSIST_PERIOD);
String persistLocation = descriptor.attributeValue(PERSIST_LOCATION);
String persistName = descriptor.attributeValue(PERSIST_NAME);
if (persistPolicy != null)
{
validate(persistPolicy, PERSIST_POLICIES);
descr.setField(PERSIST_POLICY, persistPolicy);
}
if (persistPeriod != null)
{
descr.setField(PERSIST_PERIOD, persistPeriod);
}
if (persistLocation != null)
{
descr.setField(PERSIST_LOCATION, persistLocation);
}
if (persistName != null)
{
descr.setField(PERSIST_NAME, persistName);
}
}
else if (name.equals(CURRENCY_TIME_LIMIT))
{
descr.setField(CURRENCY_TIME_LIMIT, descriptor.attributeValue("value"));
}
else if (name.equals(DEFAULT))
{
String value = descriptor.attributeValue("value");
descr.setField(DEFAULT, value);
}
else if (name.equals("display-name"))//DISPLAY_NAME is displayname
{
String value = descriptor.attributeValue("value");
descr.setField(DISPLAY_NAME, value);
}
else if (name.equals(CACHED_VALUE))
{
String value = descriptor.attributeValue("value");
descr.setField(CACHED_VALUE, value);
}
else if (name.equals(PERSISTENCE_MANAGER))
{
descr.setField(PERSISTENCE_MANAGER, descriptor.attributeValue("value"));
}
else if (name.equals(DESCRIPTOR))
{
descr.setField(descriptor.attributeValue("name"), descriptor.attributeValue("value"));
}
else if (name.equals("injection"))
{
descr.setField(descriptor.attributeValue("id"), descriptor.attributeValue("setMethod"));
}
else if(name.equals(INTERCEPTORS))
{
Descriptor[] interceptorDescriptors = buildInterceptors(descriptor);
descr.setField(INTERCEPTORS, interceptorDescriptors);
}
} // end of for ()
return descr;
}
private void validate(String value, String[] valid) throws NotCompliantMBeanException
{
for (int i = 0; i< valid.length; i++)
{
if (valid[i].equalsIgnoreCase(value))
{
return;
} // end of if ()
} // end of for ()
throw new JBossNotCompliantMBeanException("Unknown descriptor value: " + value);
}
// builder methods
protected ModelMBeanInfo buildMBeanMetaData(String description,
List constructors, List operations, List attributes,
List notifications, Descriptor descr)
throws NotCompliantMBeanException
{
ModelMBeanOperationInfo[] operInfo =
buildOperationInfo(operations);
ModelMBeanAttributeInfo[] attrInfo =
buildAttributeInfo(attributes);
ModelMBeanConstructorInfo[] constrInfo =
buildConstructorInfo(constructors);
ModelMBeanNotificationInfo[] notifInfo =
buildNotificationInfo(notifications);
ModelMBeanInfo info = new ModelMBeanInfoSupport(
mmbClassName, description, attrInfo, constrInfo,
operInfo, notifInfo, descr
);
return info;
}
protected ModelMBeanConstructorInfo[] buildConstructorInfo(List constructors)
throws NotCompliantMBeanException
{
List infos = new ArrayList();
for (Iterator it = constructors.iterator(); it.hasNext();)
{
Element constr = (Element) it.next();
String name = constr.elementTextTrim("name");
String description = constr.elementTextTrim("description");
List params = constr.elements("parameter");
MBeanParameterInfo[] paramInfo =
buildParameterInfo(params);
Descriptor descr = getDescriptor(constr, name, OPERATION_DESCRIPTOR);
descr.setField(ROLE, ROLE_CONSTRUCTOR);
ModelMBeanConstructorInfo info =
new ModelMBeanConstructorInfo(name, description, paramInfo, descr);
infos.add(info);
}
return (ModelMBeanConstructorInfo[]) infos.toArray(
new ModelMBeanConstructorInfo[0]);
}
protected ModelMBeanOperationInfo[] buildOperationInfo(List operations)
throws NotCompliantMBeanException
{
List infos = new ArrayList();
for (Iterator it = operations.iterator(); it.hasNext(); )
{
Element oper = (Element) it.next();
String name = oper.elementTextTrim("name");
String description = oper.elementTextTrim("description");
String type = oper.elementTextTrim("return-type");
String impact = oper.attributeValue("impact");
List params = oper.elements("parameter");
MBeanParameterInfo[] paramInfo =
buildParameterInfo(params);
Descriptor descr = getDescriptor(oper, name, OPERATION_DESCRIPTOR);
descr.setField(ROLE, ROLE_OPERATION);
// defaults to ACTION_INFO
int operImpact = MBeanOperationInfo.ACTION_INFO;
if (impact != null)
{
if (impact.equals(INFO))
operImpact = MBeanOperationInfo.INFO;
else if (impact.equals(ACTION))
operImpact = MBeanOperationInfo.ACTION;
else if (impact.equals(ACTION_INFO))
operImpact = MBeanOperationInfo.ACTION_INFO;
}
// default return-type is void
if (type == null)
type = "void";
ModelMBeanOperationInfo info = new ModelMBeanOperationInfo(
name, description, paramInfo, type, operImpact, descr);
infos.add(info);
}
return (ModelMBeanOperationInfo[]) infos.toArray(
new ModelMBeanOperationInfo[0]);
}
protected ModelMBeanNotificationInfo[] buildNotificationInfo(List notifications)
throws NotCompliantMBeanException
{
List infos = new ArrayList();
for (Iterator it = notifications.iterator(); it.hasNext();)
{
Element notif = (Element) it.next();
String name = notif.elementTextTrim("name");
String description = notif.elementTextTrim("description");
List notifTypes = notif.elements("notification-type");
Descriptor descr = getDescriptor(notif, name, NOTIFICATION_DESCRIPTOR);
List types = new ArrayList();
for (Iterator iterator = notifTypes.iterator(); iterator.hasNext();)
{
Element type = (Element) iterator.next();
types.add(type.getTextTrim());
}
ModelMBeanNotificationInfo info = new ModelMBeanNotificationInfo(
(String[]) types.toArray(new String[types.size()]), name, description, descr);
infos.add(info);
}
return (ModelMBeanNotificationInfo[]) infos.toArray(
new ModelMBeanNotificationInfo[infos.size()]
);
}
protected ModelMBeanAttributeInfo[] buildAttributeInfo(List attributes)
throws NotCompliantMBeanException
{
List infos = new ArrayList();
for (Iterator it = attributes.iterator(); it.hasNext();)
{
Element attr = (Element) it.next();
String name = attr.elementTextTrim("name");
String description = attr.elementTextTrim("description");
String type = attr.elementTextTrim("type");
String access = attr.attributeValue("access");
String getMethod = attr.attributeValue("getMethod");
String setMethod = attr.attributeValue("setMethod");
Descriptor descr = getDescriptor(attr, name, ATTRIBUTE_DESCRIPTOR);
//Convert types here from string to specified type
String unconvertedValue = (String)descr.getFieldValue(CACHED_VALUE);
if (unconvertedValue != null && !"java.lang.String".equals(type))
{
descr.setField(CACHED_VALUE, convertValue(unconvertedValue, type));
}
else
{
// if is absent
// try new syntax for VALUE initialization
// e.g
Object value = getAttributeValue(attr, type, CACHED_VALUE);
if (value != null)
descr.setField(CACHED_VALUE, value);
}
String unconvertedDefault = (String)descr.getFieldValue(DEFAULT);
if (unconvertedDefault != null && !"java.lang.String".equals(type))
{
descr.setField(DEFAULT, convertValue(unconvertedDefault, type));
}
else
{
// if is absent
// try new syntax for DEFAULT initialization
// e.g
Object value = getAttributeValue(attr, type, DEFAULT);
if (value != null)
descr.setField(DEFAULT, value);
}
if (getMethod != null)
{
descr.setField(GET_METHOD, getMethod);
} // end of if ()
if (setMethod != null)
{
descr.setField(SET_METHOD, setMethod);
} // end of if ()
// defaults read-write
boolean isReadable = true;
boolean isWritable = true;
if (access.equalsIgnoreCase("read-only"))
isWritable = false;
else if (access.equalsIgnoreCase("write-only"))
isReadable = false;
ModelMBeanAttributeInfo info = new ModelMBeanAttributeInfo(
name, type, description, isReadable, isWritable, false, descr
);
infos.add(info);
}
return (ModelMBeanAttributeInfo[]) infos.toArray(
new ModelMBeanAttributeInfo[0]
);
}
/**
* Get the value for the attribute descriptor "value" or "default"
* the same way we would do for mbean attribute overrides
*/
protected Object getAttributeValue(Element attribute, String typeName, String which)
throws NotCompliantMBeanException
{
Object value = null;
Element descriptors = attribute.element("descriptors");
if (descriptors != null)
{
for (Iterator i = descriptors.elementIterator(); i.hasNext();)
{
// looking for 'which', i.e. "value" or "default"
Element descriptor = (Element)i.next();
String name = descriptor.getName();
if (name.equals(which) && descriptor.hasContent())
{
// at this point "value" attribute does not exist
// plus the descriptor has content so we know the
// new syntax is used.
//
// Convert to org.w3c.dom.Element so that the code
// from ServiceConfigurator can be applied, plus
// if attribute type is org.w3c.dom.Element we need
// to make the conversion anyway.
// descriptor(org.dom4j.Element) -> element (org.w3c.dom.Element)
try
{
org.w3c.dom.Element element = toW3CElement(descriptor);
boolean replace = true;
boolean trim = true;
String replaceAttr = element.getAttribute("replace");
if( replaceAttr.length() > 0 )
replace = Boolean.valueOf(replaceAttr).booleanValue();
String trimAttr = element.getAttribute("trim");
if( trimAttr.length() > 0 )
trim = Boolean.valueOf(trimAttr).booleanValue();
// Get the classloader for loading attribute classes.
ClassLoader cl = Thread.currentThread().getContextClassLoader();
// see if it is a primitive type first
Class typeClass = Classes.getPrimitiveTypeForName(typeName);
if (typeClass == null)
{
// nope try look up
try
{
typeClass = cl.loadClass(typeName);
}
catch (ClassNotFoundException e)
{
throw new JBossNotCompliantMBeanException
("Class not found '" + typeName + "'", e);
}
}
/* Attributes of type Element are passed as is after optionally
performing system property replacement
*/
if (typeClass.equals(org.w3c.dom.Element.class))
{
// Use the first child Element of this element as the value
NodeList nl = element.getChildNodes();
for (int j=0; j < nl.getLength(); j++)
{
Node n = nl.item(j);
if (n.getNodeType() == Node.ELEMENT_NODE)
{
value = n;
break;
}
}
// Replace any ${x} references in the element text
if( replace )
{
PropertyEditor editor = PropertyEditorManager.findEditor(typeClass);
if( editor == null )
{
log.warn("Cannot perform property replace on Element");
}
else
{
editor.setValue(value);
String text = editor.getAsText();
text = StringPropertyReplacer.replaceProperties(text);
editor.setAsText(text);
value = editor.getValue();
}
}
}
if (value == null)
{
PropertyEditor editor = PropertyEditorManager.findEditor(typeClass);
if (editor == null)
{
throw new JBossNotCompliantMBeanException
("No property editor for type '" + typeName + "'");
}
// Get the attribute value
String attributeText = getElementContent(element, trim, replace);
editor.setAsText(attributeText);
value = editor.getValue();
}
}
catch (org.dom4j.DocumentException e)
{
throw new JBossNotCompliantMBeanException(
"cannot convert '" + which + "' descriptor to org.w3c.dom.Element", e);
}
// stop processing
break;
}
}
}
return value;
}
/**
* Convert org.dom4j.Element->org.w3c.dom.Element
*/
private org.w3c.dom.Element toW3CElement(org.dom4j.Element d4element)
throws org.dom4j.DocumentException
{
// prepare
org.dom4j.Document d4doc = org.dom4j.DocumentFactory.getInstance().createDocument();
org.dom4j.io.DOMWriter d4Writer = new org.dom4j.io.DOMWriter();
// copy
d4doc.setRootElement(d4element.createCopy());
// convert
org.w3c.dom.Document doc = d4Writer.write(d4doc);
// return root Element - should I copy again?
return doc.getDocumentElement();
}
/**
* Copied from ServiceConfigurator
*/
private String getElementContent(org.w3c.dom.Element element, boolean trim, boolean replace)
{
NodeList nl = element.getChildNodes();
String attributeText = "";
for (int i = 0; i < nl.getLength(); i++)
{
Node n = nl.item(i);
if( n instanceof org.w3c.dom.Text )
{
attributeText += ((org.w3c.dom.Text)n).getData();
}
} // end of for ()
if( trim )
attributeText = attributeText.trim();
if (replace)
attributeText = StringPropertyReplacer.replaceProperties(attributeText);
return attributeText;
}
/**
* Describe convertType
method here.
* Copied from ServiceConfigurator, without Element support.
*
* @param unconverted a String
value
* @param typeName a String
value
* @return an Object
value
* @exception NotCompliantMBeanException if an error occurs
*/
protected Object convertValue(String unconverted, String typeName)
throws NotCompliantMBeanException
{
Object value = null;
try
{
value = PropertyEditors.convertValue(unconverted, typeName);
}
catch (ClassNotFoundException e)
{
log.debug("Failed to load type class", e);
throw new NotCompliantMBeanException
("Class not found for type: " + typeName);
}
catch(IntrospectionException e)
{
throw new NotCompliantMBeanException
("No property editor for type=" + typeName);
}
return value;
}
protected MBeanParameterInfo[] buildParameterInfo(List parameters)
{
Iterator it = parameters.iterator();
List infos = new ArrayList();
while (it.hasNext())
{
Element param = (Element) it.next();
String name = param.elementTextTrim("name");
String type = param.elementTextTrim("type");
String descr = param.elementTextTrim("description");
MBeanParameterInfo info = new MBeanParameterInfo(name, type, descr);
infos.add(info);
}
return (MBeanParameterInfo[]) infos.toArray(new MBeanParameterInfo[0]);
}
protected Descriptor[] buildInterceptors(Element descriptor)
{
List interceptors = descriptor.elements("interceptor");
ArrayList tmp = new ArrayList();
for(int i = 0; i < interceptors.size(); i ++)
{
Element interceptor = (Element) interceptors.get(i);
String code = interceptor.attributeValue("code");
DescriptorSupport interceptorDescr = new DescriptorSupport();
interceptorDescr.setField("code", code);
List attributes = interceptor.attributes();
for(int a = 0; a < attributes.size(); a ++)
{
Attribute attr = (Attribute) attributes.get(a);
String name = attr.getName();
String value = attr.getValue();
value = StringPropertyReplacer.replaceProperties(value);
interceptorDescr.setField(name, value);
}
tmp.add(interceptorDescr);
}
Descriptor[] descriptors = new Descriptor[tmp.size()];
tmp.toArray(descriptors);
return descriptors;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy