/* * JBoss, Home of Professional Open Source. * Copyright 2006, 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.ant; import java.beans.PropertyEditor; import java.beans.PropertyEditorManager; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.management.Attribute; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import javax.naming.Context; import javax.naming.InitialContext; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Task; import org.jboss.util.propertyeditor.PropertyEditors; /** * JMX.java. An ant plugin to call managed operations and set attributes * on mbeans in a jboss jmx mbean server. * To use this plugin with Ant, place the jbossjmx-ant.jar together with the * jboss jars jboss-j2ee.jar and jboss-common-client.jar, and the sun jnet.jar in the * ant/lib directory you wish to use. * * Here is an example from an ant build file. * * * * * * * * * * * * * * * * * Created: Tue Jun 11 20:17:44 2002 * * @author David Jencks * @author David Snyder * @version */ public class JMX extends Task { private String serverURL; private String adapterName = "jmx/invoker/RMIAdaptor"; private List ops = new ArrayList(); private List editors = new ArrayList(); /** * Creates a new JMX instance. * Provides a default adapterName for the current server, so you only need to set it to * talk to a remote server. * * @exception Exception if an error occurs */ public JMX() throws Exception { } /** * Use the setServerURL method to set the URL of the server * you wish to connect to. * * @param serverURL a String value */ public void setServerURL(String serverURL) { this.serverURL = serverURL; } /** * Use the setAdapterName method to set the name the * adapter mbean is bound under in jndi. * * @param adapterName a String value */ public void setAdapterName(String adapterName) { this.adapterName = adapterName; } /** * Use the addInvoke method to add an operation. * Include as attributes the target ObjectName and operation name. * Include as sub-elements parameters: see addParameter in the Invoke class. * * @param invoke an Invoke value */ public void addInvoke(Invoke invoke) { ops.add(invoke); } /** * Use the addSetAttribute method to add a set-attribute * operation. Include as attributes the target ObjectName and the * the attribute name. Include the value as a nested value tag * following the parameter syntax. * * @param setter a Setter value */ public void addSetAttribute(Setter setter) { ops.add(setter); } /** * Use the addGetAttribute method to add a get-attribute * operation. Include as attributes the target ObjectName, the * the attribute name, and a property name to hold the result of the * get-attribute operation. * * @param getter a Getter value */ public void addGetAttribute(Getter getter) { ops.add(getter); } /** * Use the addPropertyEditor method to make a PropertyEditor * available for values. Include attributes for the type and editor fully * qualified class name. * * @param peh a PropertyEditorHolder value */ public void addPropertyEditor(PropertyEditorHolder peh) { editors.add(peh); } /** * The execute method is called by ant to execute the task. * * @exception BuildException if an error occurs */ public void execute() throws BuildException { final ClassLoader origCL = Thread.currentThread().getContextClassLoader(); try { Thread.currentThread().setContextClassLoader(getClass().getClassLoader()); try { for (int i = 0; i < editors.size(); i++) { ((PropertyEditorHolder)editors.get(i)).execute(); } // end of for () } catch (Exception e) { e.printStackTrace(); throw new BuildException("Could not register property editors: " + e); } // end of try-catch try { Properties props = new Properties(); props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); props.put(Context.URL_PKG_PREFIXES, "org.jboss.naming:org.jnp.interfaces"); if (serverURL == null || "".equals(serverURL)) { props.put(Context.PROVIDER_URL, "jnp://localhost:1099"); } else { props.put(Context.PROVIDER_URL, serverURL); } InitialContext ctx = new InitialContext(props);; // if adapter is null, the use the default if (adapterName == null) { adapterName = "jmx/rmi/RMIAdaptor";//org.jboss.jmx.adaptor.rmi.RMIAdaptorService.DEFAULT_JNDI_NAME; } Object obj = ctx.lookup(adapterName); ctx.close(); if (!(obj instanceof MBeanServerConnection)) { throw new ClassCastException ("Object not of type: MBeanServerConnection, but: " + (obj == null ? "not found" : obj.getClass().getName())); } MBeanServerConnection server = (MBeanServerConnection) obj; for (int i = 0; i < ops.size(); i++) { Operation op = (Operation)ops.get(i); op.execute(server, this); } // end of for () } catch (Exception e) { e.printStackTrace(); throw new BuildException("problem: " + e); } // end of try-catch } finally { Thread.currentThread().setContextClassLoader(origCL); } } /** * The interface Operation provides a common interface * for the sub-tasks.. * */ public static interface Operation { void execute(MBeanServerConnection server, Task parent) throws Exception; } /** * The class Invoke specifies the invocation of a * managed operation. * */ public static class Invoke implements Operation { private ObjectName target; private String property; private String operation; private List params = new ArrayList(); /** * The setProperty method sets the name of the property * that will contain the result of the operation. * * @param property a String value */ public void setProperty(String property) { this.property = property; } /** * The setTarget method sets the ObjectName * of the target mbean. * * @param target an ObjectName value */ public void setTarget(ObjectName target) { this.target = target; } /** * The setOperation method specifies the operation to * be performed. * * @param operation a String value */ public void setOperation(String operation) { this.operation = operation; } /** * The addParameter method adds a parameter for * the operation. You must specify type and value. * * @param param a Param value */ public void addParameter(Param param) { params.add(param); } public void execute(MBeanServerConnection server, Task parent) throws Exception { int paramCount = params.size(); Object[] args = new Object[paramCount]; String[] types = new String[paramCount]; int pos = 0; for (int i = 0; i < params.size(); i++) { Param p = (Param)params.get(i); args[pos] = p.getValue(); types[pos] = p.getType(); pos++; } // end of for () Object result = server.invoke(target, operation, args, types); if( (property != null) && (result != null) ) { parent.getProject().setProperty(property,result.toString()); } } } /** * The class Setter specifies setting an attribute * value on an mbean. * */ public static class Setter implements Operation { private ObjectName target; private String attribute; private Param value; /** * The setTarget method sets the ObjectName * of the target mbean. * * @param target an ObjectName value */ public void setTarget(ObjectName target) { this.target = target; } /** * The setAttribute method specifies the attribute to be set. * * @param attribute a String value */ public void setAttribute(String attribute) { this.attribute = attribute; } /** * The setValue method specifies the value to be used. * The type is used to convert the value to the correct type. * * @param value a Param value */ public void setValue(Param value) { this.value = value; } public void execute(MBeanServerConnection server, Task parent) throws Exception { Attribute att = new Attribute(attribute, value.getValue()); server.setAttribute(target, att); } } /** * The class Getter specifies getting an attribute * value of an mbean. * */ public static class Getter implements Operation { private ObjectName target; private String attribute; private String property; /** * The setTarget method sets the ObjectName * of the target mbean. * * @param target an ObjectName value */ public void setTarget(ObjectName target) { this.target = target; } /** * The setAttribute method specifies the attribute to be * retrieved. * * @param attribute a String value */ public void setAttribute(String attribute) { this.attribute = attribute; } /** * The setProperty method specifies the name of the property * to be set with the attribute value. * * @param property a String value */ public void setProperty(String property) { this.property = property; } public void execute(MBeanServerConnection server, Task parent) throws Exception { Object result = server.getAttribute(target,attribute); if( (property != null) && (result != null) ) { parent.getProject().setProperty(property,result.toString()); } } } /** * The class Param is used to represent a object by * means of a string representation of its value and its type. * */ public static class Param { private String arg; private String type; /** * The setArg method sets the string representation * of the parameters value. * * @param arg a String value */ public void setArg(String arg) { this.arg = arg; } public String getArg() { return arg; } /** * The setType method sets the fully qualified class * name of the type represented by the param object. * * @param type a String value */ public void setType(String type) { this.type = type; } public String getType() { return type; } /** * The getValue method uses PropertyEditors to convert * the string representation of the value to an object, which it returns. * The PropertyEditor to use is determined by the type specified. * * @return an Object value * @exception Exception if an error occurs */ public Object getValue() throws Exception { PropertyEditor editor = PropertyEditors.getEditor(type); editor.setAsText(arg); return editor.getValue(); } } /** * The class PropertyEditorHolder allows you to add a * PropertyEditor to the default set. * */ public static class PropertyEditorHolder { private String type; private String editor; /** * The setType method specifies the return type from the * property editor. * * @param type a String value */ public void setType(final String type) { this.type = type; } public String getType() { return type; } private Class getTypeClass() throws ClassNotFoundException { //with a little luck, one of these will work with Ant's classloaders try { return Class.forName(type); } catch (ClassNotFoundException e) { } // end of try-catch try { return getClass().getClassLoader().loadClass(type); } catch (ClassNotFoundException e) { } // end of try-catch return Thread.currentThread().getContextClassLoader().loadClass(type); } /** * The setEditor method specifies the fully qualified * class name of the PropertyEditor for the type specified in the type field. * * @param editor a String value */ public void setEditor(final String editor) { this.editor = editor; } public String getEditor() { return editor; } private Class getEditorClass() throws ClassNotFoundException { //with a little luck, one of these will work with Ant's classloaders try { return Class.forName(editor); } catch (ClassNotFoundException e) { } // end of try-catch try { return getClass().getClassLoader().loadClass(editor); } catch (ClassNotFoundException e) { } // end of try-catch return Thread.currentThread().getContextClassLoader().loadClass(editor); } public void execute() throws ClassNotFoundException { PropertyEditorManager.registerEditor(getTypeClass(), getEditorClass()); } } }// JMX