org.hyperic.hq.plugin.websphere.WebsphereUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.plugin.websphere.WebsphereUtil.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 *
 * Copyright (C) [2004, 2005, 2006], Hyperic, Inc.
 * This file is part of HQ.
 *
 * HQ is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program 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 General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */
package org.hyperic.hq.plugin.websphere;

import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.AdminClientFactory;
import com.ibm.websphere.management.exception.ConnectorException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Set;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.Metric;
import org.hyperic.hq.product.MetricInvalidException;
import org.hyperic.hq.product.MetricNotFoundException;
import org.hyperic.hq.product.MetricUnreachableException;
import org.hyperic.hq.product.PluginException;

/**
 * WebSphere JMX Utils for version 5.0 + These utils simply wrap
 * javax.management.* and WebSphere interfaces.
 */
public class WebsphereUtil {

    private static HashMap cache = new HashMap();
    private static Log log = LogFactory.getLog("WebSphereUtil");
    // WAS doesn't expose these anywhere we've found yet
    private static final String TRUST_STORE = "javax.net.ssl.trustStore";
    private static final String KEY_STORE = "javax.net.ssl.keyStore";
    private static final String TRUST_STORE_PWD = "javax.net.ssl.trustStorePassword";
    private static final String KEY_STORE_PWD = "javax.net.ssl.keyStorePassword";
    private static final HashMap beans = new HashMap();

    public static Object getRemoteMBeanValue(Metric metric)
            throws MetricNotFoundException, MetricUnreachableException, PluginException {

        return getRemoteMBeanValue(metric, metric.getAttributeName());
    }

    public static Object getRemoteMBeanValue(Metric metric, String attributeName)
            throws MetricNotFoundException, MetricUnreachableException, PluginException {

        AdminClient mServer = getMBeanServer(metric);

        ObjectName objName;

        try {
            objName = new ObjectName(metric.getObjectName());
        } catch (MalformedObjectNameException e) {
            throw new MetricInvalidException(e.getMessage(), e);
        }

        try {
            return mServer.getAttribute(objName, metric.getAttributeName());
        } catch (MBeanException e) {
            String msg = "MBeanException: " + e.getMessage();
            throw new PluginException(msg, e);
        } catch (AttributeNotFoundException e) {
            String msg = "Attribute '" + attributeName + "' " + "not found for '" + objName + "'";
            throw new MetricNotFoundException(msg, e);
        } catch (InstanceNotFoundException e) {
            String msg = "MBean '" + objName + "' not found";
            throw new MetricNotFoundException(msg, e);
        } catch (ReflectionException e) {
            String msg = "ReflectionException: " + e.getMessage();
            throw new PluginException(msg, e);
        } catch (ConnectorException e) {
            String msg = "ConnectorException: " + e.getMessage();
            throw new PluginException(msg, e);
        }
    }

    //XXX cache
    public static AdminClient getMBeanServer(Properties cfg) throws MetricUnreachableException {

        Properties props = getAdminProperties(cfg);

        if (log.isDebugEnabled()) {
            log.debug("Attempting to create admin client with props " + props + " from config " + cfg);
        }

        AdminClient mServer;
        WebsphereStopWatch timer = new WebsphereStopWatch();

        // http://blogs.sun.com/sunabl/entry/websphere_application_server_and_jvm ????
        // XXX test it with solaris version.
        try {
            mServer = AdminClientFactory.createAdminClient(props);
        } catch (LinkageError e) {
            log.error("Incorrect JVM ??? !!!", e);
            throw new MetricUnreachableException(e.getMessage(), e);
        } catch (ConnectorException ex) {
            Throwable e = ex;
            while ((e = (Throwable) e.getCause()) != null) {
                if (e instanceof LinkageError) {
                    throw new MetricUnreachableException("!!! Incorrect JVM !!!", e);
                }
            }
            throw new MetricUnreachableException(ex.getMessage(), ex);
        }

        if (log.isDebugEnabled() && timer.isTooLong()) {
            log.debug("createAdminClient took: " + timer.getElapsedSeconds() + " seconds");
        }

        return mServer;
    }

    public static Properties getAdminProperties(Properties cfg) {
        log.debug("[getAdminProperties] cfg=" + cfg);
        String host = cfg.getProperty(WebsphereProductPlugin.PROP_ADMIN_HOST, "localhost");
        String port = cfg.getProperty(WebsphereProductPlugin.PROP_ADMIN_PORT, "8880");

        Properties props = new Properties();

        props.setProperty(AdminClient.CONNECTOR_TYPE, AdminClient.CONNECTOR_TYPE_SOAP);

        props.setProperty(AdminClient.CONNECTOR_HOST, host);

        props.setProperty(AdminClient.CONNECTOR_PORT, port);

        String user = cfg.getProperty(AdminClient.USERNAME, "");
        String pass = cfg.getProperty(AdminClient.PASSWORD, "");

        // user and pass cannot be null because getProperty() is called
        // with default values
        if (!user.equals("") && !pass.equals("")) {
            props.setProperty(AdminClient.USERNAME, user);
            props.setProperty(AdminClient.PASSWORD, pass);
            props.setProperty(AdminClient.CONNECTOR_SECURITY_ENABLED, "true");

            // Set the ssl props, if they're available.  As of this writing, there are no
            // publicly-available constants for the prop keys, so they're kept in this source file.
            String trustStore = cfg.getProperty(TRUST_STORE);
            String keyStore = cfg.getProperty(KEY_STORE);
            String trustStorePwd = cfg.getProperty(TRUST_STORE_PWD);
            String keyStorePwd = cfg.getProperty(KEY_STORE_PWD);
            if (trustStore != null && keyStore != null && trustStorePwd != null && keyStorePwd != null) {
                props.setProperty(TRUST_STORE, trustStore);
                props.setProperty(KEY_STORE, keyStore);
                props.setProperty(TRUST_STORE_PWD, trustStorePwd);
                props.setProperty(KEY_STORE_PWD, keyStorePwd);
            }
        }

        log.debug("[getAdminProperties] props=" + props);
        return props;
    }

    public static AdminClient getMBeanServer(Metric metric) throws MetricUnreachableException {

        String key = metric.getPropString();
        AdminClient mServer = (AdminClient) cache.get(key);

        if (mServer != null) {
            try {
                mServer.getDomainName();
            } catch (ConnectorException e) {
                mServer = null;
                log.debug("getMBeanServer stale connection: " + key);
            }
        }

        if (mServer == null) {
            mServer = getMBeanServer(metric.getProperties());
            cache.put(key, mServer);
            log.debug("getMBeanServer caching: " + key);
        }

        return mServer;
    }

    //only use this for 1 metric at the moment, to
    //verify the admin server has been given proper
    //configuration.
    public static double getMBeanCount(AdminClient mServer, ObjectName query, String attr)
            throws MetricUnreachableException, MetricNotFoundException {

        double count = 0;

        try {
            Set beansSet = mServer.queryNames(query, null);
            for (Iterator it = beansSet.iterator(); it.hasNext();) {
                ObjectName name = (ObjectName) it.next();
                try {
                    if (attr != null) {
                        mServer.getAttribute(name, attr);
                    }
                    count++;
                } catch (AttributeNotFoundException e) {
                    throw new MetricNotFoundException(name.toString());
                } catch (InstanceNotFoundException e) {
                    throw new MetricNotFoundException(name.toString());
                } catch (Exception e) {
                    //e.g. unauthorized
                    throw new MetricUnreachableException(name + ": " + e.getMessage(), e);
                }
            }
        } catch (ConnectorException e) {
            throw new MetricUnreachableException(query.toString(), e);
        }

        if (count == 0) {
            throw new MetricNotFoundException(query + " (Invalid node name?)");
        }

        return count;
    }

    public static ObjectName resolve(AdminClient mServer, ObjectName name) throws PluginException {

        if (!name.isPattern()) {
            return name;
        }

        log.debug("[resolve] name: " + name);
        Set beansSet;
        try {
            beansSet = mServer.queryNames(name, null);
        } catch (ConnectorException e) {
            String msg = "[resolve] name:" + name + " error: " + e.getMessage();
            throw new PluginException(msg, e);
        }

        for (Object object : beansSet) {
            log.debug("[resolve] object found: " + object);
        }

        if (beansSet.size() != 1) {
            String msg = name + " query returned " + beansSet.size() + " results";
            throw new PluginException(msg);
        }

        ObjectName fullName = (ObjectName) beansSet.iterator().next();

        if (log.isDebugEnabled()) {
            log.debug(name + " resolved to: " + fullName);
        }

        return fullName;
    }

    public static boolean isRunning(Metric metric) {
        //for the moment avail == 1 MBean is registered.
        AdminClient mServer;
        String domain;

        try {
            mServer = getMBeanServer(metric);
            domain = mServer.getDomainName();
        } catch (MetricUnreachableException e) {
            log.debug(metric + ": " + e, e);
            return false;
        } catch (ConnectorException e) {
            log.debug(metric + ": " + e, e);
            return false;
        }

        String query = domain + ":" + metric.getObjectPropString() + ",*";

        ObjectName name = (ObjectName) beans.get(query);
        if (name == null) {
            try {
                name = new ObjectName(query);
            } catch (MalformedObjectNameException e) {
                throw new MetricInvalidException(metric.getObjectName());
            }
            try {
                name = resolve(mServer, name);
            } catch (PluginException e) {
                return false;
            }
            log.debug("isRunningCache " + query + "-->" + name);
            beans.put(query, name);
            return true;
        }

        try {
            mServer.getMBeanInfo(name);
            return true;
        } catch (Exception e) {
            beans.remove(query);
            return false;
        }
    }

    /**
     * Wrapper around javax.management.MBeanServer.invoke
     *
     * @param objectName Used to construct a javax.management.ObjectName which
     * is required by MBeanServer.invoke
     * @param props Properties for the AdminClient connection, defined by
     * WebsphereProductPlugin.getConfigSchema.
     * @param method Name of the method to invoke on the server.
     * @param args Arguments passed to MBeanServer.invoke
     * @param sig Argument signatures passed to MBeanServer.invoke
     * @throws PluginException on any error.
     */
    public static Object invoke(String objectName, Properties props, String method, Object[] args, String[] sig)
            throws PluginException {

        AdminClient mServer;
        try {
            mServer = getMBeanServer(props);
        } catch (MetricUnreachableException e) {
            throw new PluginException(e.getMessage(), e);
        }

        return invoke(mServer, objectName, method, args, sig);
    }

    public static Object invoke(AdminClient mServer, String objectName, String method, Object[] args, String[] sig)
            throws PluginException {

        ObjectName obj;
        try {
            obj = new ObjectName(objectName);
        } catch (MalformedObjectNameException e) {
            throw new PluginException(e);
        }

        try {
            if (obj.isPattern()) {
                obj = resolve(mServer, obj);
            }
            return mServer.invoke(obj, method, args, sig);
        } catch (InstanceNotFoundException e) {
            throw new PluginException(e.getMessage(), e);
        } catch (MBeanException e) {
            throw new PluginException(e.getMessage(), e);
        } catch (ReflectionException e) {
            throw new PluginException(e.getMessage(), e);
        } catch (ConnectorException e) {
            throw new PluginException(e.getMessage(), e);
        } catch (IllegalArgumentException e) {
            throw new PluginException(e.getMessage(), e);
        }
    }
}