package org.apache.tools.ant.taskdefs.optional.jmx;
/*
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 2000-2002 The Apache Software Foundation. All
* rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by the Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Ant" and "Apache Software Foundation" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache", nor may
* "Apache" appear in their name, without prior written permission of the
* Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <http://www.apache.org/>.
*
*/
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.optional.jmx.connector.JMXConnector;
import org.apache.tools.ant.types.optional.ContextType;
import org.apache.tools.ant.types.optional.MBeanType;
/**
* This is the abstract base class for Ant JMX mbean tasks.
* Implementations of AbstractMBean inherit its attributes (see below) for connecting to
* the JMX MBean server.</br></br>
*
* Refer to the user documentation for more information and examples on how to use
* this task.
*
* @author <a href="mailto:bdueck@yahoo.com">Brian Dueck</a>
* @version $Id: AbstractMBeanTask.java,v 1.5 2003/05/26 15:15:09 bdueck Exp $
*
*/
public abstract class AbstractMBeanTask extends AbstractManagementTask {
private ObjectName objectName = null;
private String name = null;
private String activeDomain = null;
private JMXConnector jmxServer = null;
public AbstractMBeanTask() {
super();
setContext(new MBeanType());
}
/**
* Execute the MBean task.
*
* @throws BuildException If an error occurs.
*/
public void execute() throws BuildException {
try {
MBeanServer server = login(getProviderUrl(), getJndiName(),
getUser(),getPassword());
execute(server);
} catch (Exception x) {
if (this.getFailOnError()) {
x.printStackTrace();
throw new BuildException("Error! " + x, x);
} else {
log("Warning! " + x,org.apache.tools.ant.Project.MSG_WARN);
}
}
}
/**
* Execute the JMX MBean task against the specified MBeanServer.
*
* @param mbserver The target MBeanServer.
* @throws BuildException If an error occurs.
*/
protected abstract void execute(MBeanServer mbserver) throws BuildException;
/**
* Return stringified version of the MBean.
*
* @return Stringified information about this object.
*/
public String toString() {
try {
return getObjectName().toString();
} catch (MalformedObjectNameException x) {
throw new BuildException(x);
}
}
/**
* Returns an ObjectName for this nested Ant MBean element.
* Lazily caches the result in a private instance.
*
* @return Returns the target ObjectName for this task.
* @throws MalformedObjectNameException If there is an error creating a valid ObjectName based on the parameters
* specified for this task (jndiName, server, name, type).
*/
protected ObjectName getObjectName() throws MalformedObjectNameException {
if (objectName == null) {
objectName = new ObjectName(getName());
if ((activeDomain != null) && ((objectName.getDomain() == null) || (objectName.getDomain().length() == 0)) ) {
objectName = new ObjectName(activeDomain + getName());
}
}
return objectName;
}
/**
* Sets the <code>name</code> attribute.
*
* @param name The name of the mbean.
*/
public void setName(String name) {
if ( (getContext() != null) && (getContext().getClass().isAssignableFrom(MBeanType.class)) ) {
((MBeanType)getContext()).setName(name);
} else {
this.name = name;
}
}
/**
* The name of the JMX MBean.
*
* @return The name of the MBean.
*/
protected String getName() {
if ( (getContext() != null) && (getContext().getClass().isAssignableFrom(MBeanType.class)) ) {
return ((MBeanType)getContext()).getName();
} else {
return name;
}
}
public String getActiveDomain() {
return activeDomain;
}
public JMXConnector getJMXServer() {
return jmxServer;
}
public void setMBeanRef(org.apache.tools.ant.types.Reference ref) {
Object obj = ref.getReferencedObject(this.getProject());
if (!(obj instanceof MBeanType)) {
String msg = "'" + ref.getRefId() + "' doesn't denote a " + MBeanType.DATA_TYPE_NAME + ". " + ref.getRefId() + " is a " + obj.getClass().getName();
throw new BuildException(msg);
}
setContext((ContextType) obj);
}
/**
* Helper function to find the MBeanAttributeInfo for the indicated attribute name.
*
* @returns The attribute info value or null if the named attribute cannot be
* found.
*
*/
protected MBeanAttributeInfo findAttributeInfo(javax.management.MBeanInfo beanInfo, String attributeName) {
MBeanAttributeInfo[] attributes = beanInfo.getAttributes();
for (int counter = 0; counter < attributes.length; counter++) {
if (attributes[counter].getName().equals(attributeName)) {
return attributes[counter];
}
}
return null;
}
/**
* Helper function to return MBeanAttributeInfo[] as a Map.
*
* @returns A map containing MBeanAttributeInfo's. Keyed by name, value is MBeanAttributeInfo.
*
*/
protected java.util.Map getAttributes(javax.management.MBeanInfo beanInfo) {
return getAttributes(beanInfo,null);
}
/**
* Helper function to return MBeanAttributeInfo[] as a Map.
* Returned attributes can be filtered by passing in a set of attribute names (ignored if null).
*
* @returns A map containing MBeanAttributeInfo's. Keyed by name, value is MBeanAttributeInfo.
*
*/
protected java.util.Map getAttributes(javax.management.MBeanInfo beanInfo, java.util.Set attributeNames) {
java.util.Map result = new java.util.TreeMap();
MBeanAttributeInfo[] attributes = beanInfo.getAttributes();
for (int counter = 0; counter < attributes.length; counter++) {
if ( (attributeNames == null) || (attributeNames.contains(attributes[counter].getName()) ) ) {
result.put(attributes[counter].getName(), attributes[counter]);
}
}
return result;
}
/**
* Helper function to extract attribute names from an MBeanFeatureInfo[]
* as a String[].
*
* @param features The feature information.
* @return An array of strings with the feature names.
*/
protected String[] getFeatureNames(javax.management.MBeanFeatureInfo[] features) {
String[] result = new String[features.length];
for (int counter = 0; counter < features.length; counter++) {
result[counter] = features[counter].getName();
}
return result;
}
/**
* Logs into a JMX server and returns the MBeanServer to
* use during task execution. The caller is responsible
* for invoking this method prior to executing any other
* methods on this interface.
*
* @param providerUrl The url of the JNDI provider.
* @param jndiName The JNDI name of the MBeanServer.
* @param user The user name to use for authentication.
* @param password The password to use for authentication.
* @return An MBeanServer.
* @raise BuildException if an error occurs attempting to login.
*/
private MBeanServer login(String providerUrl, String jndiName, String user, String password) throws javax.naming.NamingException {
try {
if (getContext().getServerType() == null) {
log("Warning! serverType not specified or unrecognized type. Defaulting to WebLogic.");
getContext().setServerType("weblogic");
}
jmxServer = org.apache.tools.ant.taskdefs.optional.jmx.connector.JMXConnectorFactory.createConnector(getContext().getServerType());
java.util.Hashtable properties = jmxServer.getInitialContextProperties(providerUrl,user,password);
MBeanServer mbserver = jmxServer.getMBeanServer(properties,jndiName);
activeDomain = jmxServer.getActiveDomain(mbserver);
return mbserver;
} catch (Exception e) {
e.printStackTrace();
throw new BuildException("JMX Error. " + e.getMessage(), e);
}
}
/**
* Removes a given mbean from an mbean server if required by the IfExists
* flag.
* If the mbean does not exist in the target mbean server, this is a null op.
* If the mbean exists, the action taken is determined by the ifExists
* paramter.</p>
* mbean exists && ifExists = skip : The mbean is left in place.</p>
* mbean exists && ifExists = warn : A warning is given and the mbean is left in place.</p>
* mbean exists && ifExists = fail : BuildException is thrown.</p>
* mbean exists && ifExists = replace : A warning is given and the mbean is removed.</p>
* mbean exists && ifExists = replaceAttributes : A warning is given but the mbean is left in place.</p>
*
* @param mbserver The MBeanServer that hosts the mbean.</p>
* @param mbean The mbean to remove.
* @param ifExists One of IfExists.getValues().
* @see IfExists
* @throws BuildException
*/
protected void removeMBeanIfExists(javax.management.MBeanServer mbserver,
javax.management.ObjectName mbean, String ifExists)
throws org.apache.tools.ant.BuildException {
if (mbserver.isRegistered(mbean)) {
String message = "Mbean " + mbean.getCanonicalName() + " already exists. ";
if (ifExists.equals(IfExists.FAIL)) {
throw new org.apache.tools.ant.BuildException(message);
} else if (ifExists.equals(IfExists.SKIP)) {
return;
} else if (ifExists.equals(IfExists.WARN)) {
log("Warning! " + message + "Skipping." + mbean);
return;
} else if (ifExists.equals(IfExists.REPLACE)) {
log("Warning! " + message + "It will be deleted and replaced. " + mbean);
try {
mbserver.unregisterMBean(mbean);
} catch (javax.management.InstanceNotFoundException eatMe) {
log("Warning! " + message + "However it cannot be properly removed.");
} catch (javax.management.MBeanRegistrationException eatMe) {
log("Warning! " + message + "However it cannot be properly removed.");
}
} else if (ifExists.equals(IfExists.REPLACE_ATTRIBUTES)) {
log("Warning! " + message + "Its attributes will be replaced. " + mbean);
}
}
}
}
/*
* $Log: AbstractMBeanTask.java,v $
* Revision 1.5 2003/05/26 15:15:09 bdueck
* Slight adjustment to log message.
*
* Revision 1.4 2003/05/26 10:13:05 bdueck
* *** empty log message ***
*
* Revision 1.3 2003/04/21 15:29:41 bdueck
* Various changes in preparation for version 1.2.
*
* Revision 1.2 2003/04/01 22:02:08 bdueck
* Factored out basic JNDI connectivity. Added support for mbeanref.
*
* Revision 1.1 2003/01/17 12:33:55 bdueck
* Initial check-in
*
*
*/