- package org.apache.commons.modeler.modules;
-
- import java.io.FileNotFoundException;
- import java.io.FileOutputStream;
- import java.io.InputStream;
- import java.net.URL;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
-
- import javax.management.Attribute;
- import javax.management.MBeanServer;
- import javax.management.ObjectName;
- import javax.management.loading.MLet;
- import javax.xml.transform.TransformerException;
-
- import org.apache.commons.logging.Log;
- import org.apache.commons.logging.LogFactory;
- import org.apache.commons.modeler.AttributeInfo;
- import org.apache.commons.modeler.BaseModelMBean;
- import org.apache.commons.modeler.ManagedBean;
- import org.apache.commons.modeler.Registry;
- import org.apache.commons.modeler.util.DomUtil;
- import org.w3c.dom.Document;
- import org.w3c.dom.Node;
-
-
- /** This will create mbeans based on a config file.
- * The format is an extended version of MLET.
- *
- * Classloading. We don't support any explicit classloader tag.
- * A ClassLoader is just an mbean ( it can be the standard MLetMBean or
- * a custom one ).
- *
- * XXX add a special attribute to reference the loader mbean,
- * XXX figure out how to deal with private loaders
- */
- public class MbeansSource extends ModelerSource implements MbeansSourceMBean
- {
- private static Log log = LogFactory.getLog(MbeansSource.class);
- Registry registry;
- String type;
-
- // true if we are during the original loading
- boolean loading=true;
- List mbeans=new ArrayList();
- static boolean loaderLoaded=false;
- private Document document;
- private HashMap object2Node = new HashMap();
-
- long lastUpdate;
- long updateInterval=10000; // 10s
-
- public void setRegistry(Registry reg) {
- this.registry=reg;
- }
-
- public void setLocation( String loc ) {
- this.location=loc;
- }
-
- /** Used if a single component is loaded
- *
- * @param type
- */
- public void setType( String type ) {
- this.type=type;
- }
-
- public void setSource( Object source ) {
- this.source=source;
- }
-
- public Object getSource() {
- return source;
- }
-
- public String getLocation() {
- return location;
- }
-
- /** Return the list of mbeans created by this source.
- * It can be used to implement runtime services.
- */
- public List getMBeans() {
- return mbeans;
- }
-
- public List loadDescriptors( Registry registry, String location,
- String type, Object source)
- throws Exception
- {
- setRegistry(registry);
- setLocation(location);
- setType(type);
- setSource(source);
- execute();
- return mbeans;
- }
-
- public void start() throws Exception {
- registry.invoke(mbeans, "start", false);
- }
-
- public void stop() throws Exception {
- registry.invoke(mbeans, "stop", false);
- }
-
- public void init() throws Exception {
- if( mbeans==null) execute();
- if( registry==null ) registry=Registry.getRegistry();
-
- registry.invoke(mbeans, "init", false);
- }
-
- public void destroy() throws Exception {
- registry.invoke(mbeans, "destroy", false);
- }
-
- public void load() throws Exception {
- execute(); // backward compat
- }
-
- public void execute() throws Exception {
- if( registry==null ) registry=Registry.getRegistry();
- try {
- InputStream stream=getInputStream();
- long t1=System.currentTimeMillis();
- document = DomUtil.readXml(stream);
-
- // We don't care what the root node is.
- Node descriptorsN=document.getDocumentElement();
-
- if( descriptorsN == null ) {
- log.error("No descriptors found");
- return;
- }
-
- Node firstMbeanN=DomUtil.getChild(descriptorsN, null);
-
- if( firstMbeanN==null ) {
- // maybe we have a single mlet
- if( log.isDebugEnabled() )
- log.debug("No child " + descriptorsN);
- firstMbeanN=descriptorsN;
- }
-
- MBeanServer server=(MBeanServer)Registry.getServer();
-
- // XXX Not very clean... Just a workaround
- if( ! loaderLoaded ) {
- // Register a loader that will be find ant classes.
- ObjectName defaultLoader= new ObjectName("modeler",
- "loader", "modeler");
- MLet mlet=new MLet( new URL[0], this.getClass().getClassLoader());
- server.registerMBean(mlet, defaultLoader);
- loaderLoaded=true;
- }
-
- // Process nodes
- for (Node mbeanN = firstMbeanN; mbeanN != null;
- mbeanN= DomUtil.getNext(mbeanN, null, Node.ELEMENT_NODE))
- {
- String nodeName=mbeanN.getNodeName();
-
- // mbean is the "official" name
- if( "mbean".equals(nodeName) || "MLET".equals(nodeName) )
- {
- String code=DomUtil.getAttribute( mbeanN, "code" );
- String objectName=DomUtil.getAttribute( mbeanN, "objectName" );
- if( objectName==null ) {
- objectName=DomUtil.getAttribute( mbeanN, "name" );
- }
-
- if( log.isDebugEnabled())
- log.debug( "Processing mbean objectName=" + objectName +
- " code=" + code);
-
- // args can be grouped in constructor or direct childs
- Node constructorN=DomUtil.getChild(mbeanN, "constructor");
- if( constructorN == null ) constructorN=mbeanN;
-
- processArg(constructorN);
-
- try {
- ObjectName oname=new ObjectName(objectName);
- if( ! server.isRegistered( oname )) {
- // We wrap everything in a model mbean.
- // XXX need to support "StandardMBeanDescriptorsSource"
- String modelMBean=BaseModelMBean.class.getName();
- server.createMBean(modelMBean, oname,
- new Object[] { code, this},
- new String[] { String.class.getName(),
- ModelerSource.class.getName() }
- );
- mbeans.add(oname);
- }
- object2Node.put( oname, mbeanN );
- // XXX Arguments, loader !!!
- } catch( Exception ex ) {
- log.error( "Error creating mbean " + objectName, ex);
- }
-
- Node firstAttN=DomUtil.getChild(mbeanN, "attribute");
- for (Node descN = firstAttN; descN != null;
- descN = DomUtil.getNext( descN ))
- {
- processAttribute(server, descN, objectName);
- }
- } else if("jmx-operation".equals(nodeName) ) {
- String name=DomUtil.getAttribute(mbeanN, "objectName");
- if( name==null )
- name=DomUtil.getAttribute(mbeanN, "name");
-
- String operation=DomUtil.getAttribute(mbeanN, "operation");
-
- if( log.isDebugEnabled())
- log.debug( "Processing invoke objectName=" + name +
- " code=" + operation);
- try {
- ObjectName oname=new ObjectName(name);
-
- processArg( mbeanN );
- server.invoke( oname, operation, null, null);
- } catch (Exception e) {
- log.error( "Error in invoke " + name + " " + operation);
- }
- }
-
- ManagedBean managed=new ManagedBean();
- DomUtil.setAttributes(managed, mbeanN);
- Node firstN;
-
- // process attribute info
- firstN=DomUtil.getChild( mbeanN, "attribute");
- for (Node descN = firstN; descN != null;
- descN = DomUtil.getNext( descN ))
- {
- AttributeInfo ci=new AttributeInfo();
- DomUtil.setAttributes(ci, descN);
- managed.addAttribute( ci );
- }
-
- }
-
- long t2=System.currentTimeMillis();
- log.info( "Reading mbeans " + (t2-t1));
- loading=false;
- } catch( Exception ex ) {
- log.error( "Error reading mbeans ", ex);
- }
- }
-
- public void updateField( ObjectName oname, String name,
- Object value )
- {
- if( loading ) return;
- // nothing by default
- //log.info( "XXX UpdateField " + oname + " " + name + " " + value);
- Node n=(Node)object2Node.get( oname );
- if( n == null ) {
- log.info( "Node not found " + oname );
- return;
- }
- Node attNode=DomUtil.findChildWithAtt(n, "attribute", "name", name);
- if( attNode == null ) {
- // found no existing attribute with this name
- attNode=n.getOwnerDocument().createElement("attribute");
- DomUtil.setAttribute(attNode, "name", name);
- n.appendChild(attNode);
- }
- String oldValue=DomUtil.getAttribute(attNode, "value");
- if( oldValue != null ) {
- // we'll convert all values to text content
- DomUtil.removeAttribute( attNode, "value");
- }
- DomUtil.setText(attNode, value.toString());
-
- //store();
- }
-
- /** Store the mbeans.
- * XXX add a background thread to store it periodically
- */
- public void save() {
- // XXX customize no often than ( based on standard descriptor ), etc.
- // It doesn't work very well if we call this on each set att -
- // the triger will work for the first att, but all others will be delayed
- long time=System.currentTimeMillis();
- if( location!=null &&
- time - lastUpdate > updateInterval ) {
- lastUpdate=time;
- try {
- FileOutputStream fos=new FileOutputStream(location);
- DomUtil.writeXml(document, fos);
- } catch (TransformerException e) {
- log.error( "Error writing");
- } catch (FileNotFoundException e) {
- log.error( "Error writing" ,e );
- }
- }
- }
-
- private void processAttribute(MBeanServer server,
- Node descN, String objectName ) {
- String attName=DomUtil.getAttribute(descN, "name");
- String value=DomUtil.getAttribute(descN, "value");
- String type=null; // DomUtil.getAttribute(descN, "type");
- if( value==null ) {
- // The value may be specified as CDATA
- value=DomUtil.getContent(descN);
- }
- try {
- if( log.isDebugEnabled())
- log.debug("Set attribute " + objectName + " " + attName +
- " " + value);
- ObjectName oname=new ObjectName(objectName);
- // find the type
- if( type==null )
- type=registry.getType( oname, attName );
-
- if( type==null ) {
- log.info("Can't find attribute " + objectName + " " + attName );
-
- } else {
- Object valueO=registry.convertValue( type, value);
- server.setAttribute(oname, new Attribute(attName, valueO));
- }
- } catch( Exception ex) {
- log.error("Error processing attribute " + objectName + " " +
- attName + " " + value, ex);
- }
-
- }
-
- private void processArg(Node mbeanN) {
- Node firstArgN=DomUtil.getChild(mbeanN, "arg" );
- // process all args
- for (Node argN = firstArgN; argN != null;
- argN = DomUtil.getNext( argN ))
- {
- String type=DomUtil.getAttribute(argN, "type");
- String value=DomUtil.getAttribute(argN, "value");
- if( value==null ) {
- // The value may be specified as CDATA
- value=DomUtil.getContent(argN);
- }
- }
- }
- }