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

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.plugin.websphere.WebsphereProductPlugin.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 java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.product.ProductPlugin;
import org.hyperic.hq.product.ProductPluginManager;
import org.hyperic.sigar.OperatingSystem;
import org.hyperic.sigar.win32.RegistryKey;
import org.hyperic.sigar.win32.Win32Exception;

public class WebsphereProductPlugin extends ProductPlugin {

    public static boolean VALID_JVM = true;
    public static final String NAME = "websphere";
    public static final String SERVER_NAME = "WebSphere";
    public static final String SERVER_DESC = "Application Server";
    public static final String ADMIN_NAME = "Admin";
    public static final String THRPOOL_NAME = "Thread Pool";
    public static final String CONNPOOL_NAME = "Connection Pool";
    public static final String APP_NAME = "Application";
    public static final String WEBAPP_NAME = "Webapp";
    public static final String EJB_NAME = "EJB";
    public static final String SERVER_ADMIN_NAME = SERVER_NAME + " " + ADMIN_NAME;
    public static final String VERSION_50 = "5.0";
    public static final String PROP_INSTALL_ROOT = "was.install.root";
    public static final String PROP_ADMIN_HOST = "admin.host";
    public static final String PROP_ADMIN_PORT = "admin.port";
    public static final String PROP_USERNAME = "username";
    public static final String PROP_PASSWORD = "password";
    public static final String PROP_SERVER_NODE = "server.node";
    public static final String PROP_SERVER_NAME = "server.name";
    public static final String PROP_SERVER_PORT = "server.port";
    public static final String PROP_SERVER_CELL = "server.cell";
    public static final String PROP_THRPOOL_NAME = "thrpool";
    public static final String PROP_CONNPOOL_NAME = "connpool";
    public static final String PROP_APP_NAME = "app";
    public static final String PROP_WEBAPP_NAME = "webapp";
    public static final String PROP_EJB_NAME = "ejb";
    public static final String PROP_WEBAPP_DISPLAY_NAME = PROP_WEBAPP_NAME + ".display";
    public static final String PROP_WEBAPP_CONTEXT = PROP_WEBAPP_NAME + ".context";
    public static final String PROP_EJB_JNDI_NAME = PROP_EJB_NAME + ".jndi";
    //XXX rid need to configure this in agent.properties
    public static final String PROP_INSTALLPATH = "websphere." + ProductPlugin.PROP_INSTALLPATH;
    private static final String[] REG_VERSIONS = { "5.1.0.0", "5.0.0.0", "6.0.0.0", "6.1.0.0", "7.0.0.0", "8.0.0.0",
            "8.5.0.0" };
    private static Log log = LogFactory.getLog("WebsphereProductPlugin");
    private static String REG_KEY;
    private static boolean hasSoapConfig = false;
    private static boolean isOSGi = false;
    private static boolean useExt = false;
    static boolean useJMX = true;
    private static String tmpdir;

    //if we are running with the ibm jdk we can configure
    //websphere.installpath ourselves.
    private static String getInstallPathFromJDK() {
        String res = null;
        if (VALID_JVM) {
            String javaHome = System.getProperty("java.home");
            File dir = new File(javaHome);
            do {
                if (!new File(dir, "profiles").exists()) {
                    dir = dir.getParentFile();
                } else {
                    res = dir.getAbsolutePath();
                }
            } while ((res == null) && (dir.getParentFile() != null));
        }
        return res;
    }

    /**
     * guess WebSphere installpath using the registry. returns most recent
     * version found.
     */
    public static File getRegistryInstallPath() {
        List<File> dirs = getRegistryInstallPaths();

        if (dirs.size() == 0) {
            return null;
        }

        return dirs.get(0);
    }

    public static List<File> getRegistryInstallPaths() {
        List<File> dirs = new ArrayList<File>();

        try {
            RegistryKey key = RegistryKey.LocalMachine.openSubKey(REG_KEY);

            for (int i = 0; i < REG_VERSIONS.length; i++) {
                String name = REG_VERSIONS[i];

                try {
                    RegistryKey ver = key.openSubKey(name);
                    String val = ver.getStringValue("InstallLocation");
                    if (val != null) {
                        dirs.add(new File(val.trim()));
                    }
                } catch (Win32Exception e) {
                    log.debug(e, e);
                }
            }
        } catch (Win32Exception e) {
            log.debug(e, e);
        } catch (UnsatisfiedLinkError e) {
            log.debug(e, e);
        } //dll is not on server-side

        return dirs;
    }

    private static String findInstallDir() {
        String dir = null;
        String where = "unknown";

        if (isWin32()) {
            File path = getRegistryInstallPath();
            if (path != null) {
                dir = path.getAbsolutePath();
                where = "registry";
            }
        }

        if (dir == null) {
            dir = WebsphereDetector.getRunningInstallPath();
            if (dir != null) {
                where = "process table";
            } else {
                dir = getInstallPathFromJDK();
                if (dir != null) {
                    where = "JRE";
                }
            }

            if (dir == null) {
                String root;
                if (isWin32()) {
                    root = "C:/Program Files";
                } else {
                    root = "/opt";
                }
                //default WebSphere installpath(s)
                dir = root + "/IBM/WebSphere/AppServer";
                if (!new File(dir).isDirectory()) {
                    dir = root + "/WebSphere/AppServer";
                    if (!new File(dir).isDirectory()) {
                        dir = null;
                    }
                }
                where = "default location";
            }
        }

        if (dir == null) {
            log.debug("Unable to determine " + PROP_INSTALLPATH);
            return null;
        } else {
            log.debug(PROP_INSTALLPATH + " configured using " + where + " (" + dir + ")");
            return dir;
        }
    }

    public static boolean hasSoapConfig() {
        return hasSoapConfig;
    }

    public static boolean isOSGi() {
        return isOSGi;
    }

    private void addClassPath(List<String> path, String dir, String[] jars) {

        if (jars == null) {
            return;
        }

        for (int j = 0; j < jars.length; j++) {
            if (!jars[j].endsWith(".jar")) {
                continue;
            }

            File f = new File(dir, jars[j]);
            log.debug("- Classpath += " + f);
            try {
                path.add(f.getCanonicalPath());
            } catch (IOException ex) {
                path.add(f.getAbsolutePath());
            }
        }
    }

    //jar names minus version "_6.1.0.jar"
    private void addClassPathOSGi(List<String> path, String dir, String[] jars) {
        log.debug("Adding OSGi packages from " + dir);
        final HashMap<String, Boolean> wantedJars = new HashMap<String, Boolean>();
        for (int i = 0; i < jars.length; i++) {
            wantedJars.put(jars[i], Boolean.TRUE);
        }

        String[] files = new File(dir).list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                int ix = name.indexOf('_');
                if (ix != -1) {
                    name = name.substring(0, ix);
                }
                return wantedJars.get(name) != null;
            }
        });

        addClassPath(path, dir, files);
    }

    private void copyToTmpAndAddClassPath(List<String> path, String dir, String[] jars) {
        final HashMap<String, Boolean> wantedJars = new HashMap<String, Boolean>();
        for (int i = 0; i < jars.length; i++) {
            wantedJars.put(jars[i], Boolean.TRUE);
        }

        String[] files = new File(dir).list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                int ix = name.indexOf('_');
                if (ix != -1) {
                    name = name.substring(0, ix);
                }
                return wantedJars.get(name) != null;
            }
        });

        String tmp = dir;
        if (tmp.contains(" ")) {
            tmp = tmpdir;
            if (tmp.contains(" ")) {
                tmp = isWin32() ? "c:\\tmp" : "/tmp";
            }
            log.info("Websphere install path (" + dir + ") contains a ' ', copying necesary jars to '" + tmp
                    + "' (websphere.tmpdir)");

            for (String jar : files) {
                try {
                    copyFile(new File(dir, jar), new File(tmp, jar));
                } catch (IOException ex) {
                    log.debug(ex, ex);
                }
            }
        }

        addClassPathOSGi(path, tmp, jars);
    }

    public static void copyFile(File sourceFile, File destFile) throws IOException {
        log.info("[copyFile] " + sourceFile.getCanonicalPath() + " => " + destFile.getCanonicalPath());

        if (!destFile.exists()) {
            destFile.createNewFile();
        }

        InputStream in = new FileInputStream(sourceFile);
        OutputStream out = new FileOutputStream(destFile);
        byte[] buf = new byte[1024];
        int len;
        while ((len = in.read(buf)) > 0) {
            out.write(buf, 0, len);
        }
        in.close();
        out.close();
    }

    //XXX bigmac hackattack
    //org.apache.commons.logging is embedded in this .jar
    //conflicts with our pdk/lib/commons-logging.jar
    //rewrite the .jar and remove the conflicting package
    private File runtimeJarHack(File file) throws Exception {
        String tmp = System.getProperty("java.io.tmpdir"); //agent/tmp
        File newJar = new File(tmp, file.getName());
        if (newJar.exists()) {
            return newJar;
        }
        log.debug("Creating " + newJar);
        JarFile jar = new JarFile(file);
        JarOutputStream os = new JarOutputStream(new FileOutputStream(newJar));
        byte[] buffer = new byte[1024];
        try {
            for (Enumeration<JarEntry> e = jar.entries(); e.hasMoreElements();) {
                int n;
                JarEntry entry = e.nextElement();

                if (entry.getName().startsWith("org/apache/commons/logging/")) {
                    continue;
                }
                InputStream entryStream = jar.getInputStream(entry);

                os.putNextEntry(entry);
                while ((n = entryStream.read(buffer)) != -1) {
                    os.write(buffer, 0, n);
                }
                entryStream.close();
            }
        } finally {
            jar.close();
            os.close();
        }
        return newJar;
    }

    //XXX HHQ-2044 emulate -Djava.ext.dirs
    private void setExtDirs(String installDir) throws Exception {
        ClassLoader parent = getClass().getClassLoader().getParent();
        URLClassLoader loader = null;

        //rewind to top most parent, which should (must) be ExtClassLoader
        while (parent != null) {
            if (parent instanceof URLClassLoader) {
                loader = (URLClassLoader) parent;
            }
            parent = parent.getParent();
        }

        log.debug("Using java.ext.dirs loader=" + loader);

        //bypass protected access.
        Method addURL = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });

        addURL.setAccessible(true);

        String[] dirs = { "lib", "plugins", "runtimes" };

        for (int i = 0; i < dirs.length; i++) {
            File dir = new File(installDir, dirs[i]);
            String[] jars = dir.list();
            if (jars != null) {
                for (int j = 0; j < jars.length; j++) {
                    File jar = new File(dir, jars[j]);
                    if (isValidJar(jar)) {
                        log.debug("classpath += " + jar);
                        if (jar.getName().startsWith("com.ibm.ws.runtime_")) {
                            jar = runtimeJarHack(jar);
                        }
                        URL url = sun.net.www.ParseUtil.fileToEncodedURL(jar);
                        addURL.invoke(loader, new Object[] { url });
                    } else {
                        log.debug("jar '" + jars[j] + "' skipped");
                        continue;
                    }
                }
            }
        }
    }

    private boolean isValidJar(File jar) {
        return jar.getName().startsWith("com.ibm") && jar.getName().endsWith(".jar")
                && !jar.getName().contains("thinclient") && jar.isFile();
    }

    private String[] getClassPathOSGi(String installDir) {
        ArrayList<String> path = new ArrayList<String>();

        String v = WebsphereDetector.getComponentVersion(new File(installDir, "properties/version/WAS.product"));
        if (v.startsWith("6")) {

            final String[] lib = { "bootstrap.jar", "j2ee.jar", "launchclient.jar", "mail-impl.jar" };
            addClassPathOSGi(path, installDir + "/lib/", lib);

            final String[] plugins = { "com.ibm.ws.bootstrap", "com.ibm.ws.emf", "com.ibm.ws.security.crypto",
                    "com.ibm.ws.wccm", "org.eclipse.core.runtime", "org.eclipse.osgi", "com.ibm.ws.runtime", };
            addClassPathOSGi(path, installDir + "/plugins/", plugins);

            final String[] runtimes = { "com.ibm.ws.admin.client", };
            addClassPathOSGi(path, installDir + "/runtimes/", runtimes);

        } else if (v.startsWith("7") || v.startsWith("8")) {
            final String[] lib = { "bootstrap.jar", };
            addClassPathOSGi(path, installDir + "/lib/", lib);

            final String[] plugins = { "com.ibm.ffdc.jar", "com.ibm.ws.admin.core.jar", "com.ibm.ws.runtime.jar",
                    "com.ibm.ws.emf.jar", "com.ibm.hpel.logging.jar", "org.eclipse.emf.ecore.jar",
                    "org.eclipse.emf.common.jar", "com.ibm.ws.prereq.soap.jar", "com.ibm.ws.prereq.javamail.jar",
                    "com.ibm.wsfp.main.jar", "javax.j2ee.management.jar", };
            addClassPathOSGi(path, installDir + "/plugins/", plugins);

            final String[] jarToCopy = { "com.ibm.ws.security.crypto.jar" };
            copyToTmpAndAddClassPath(path, installDir + "/plugins/", jarToCopy);
        } else {
            if (log.isDebugEnabled()) {
                log.error("Unknown version '" + v + "'");
            }
        }

        path.add("pdk/lib/mx4j/hq-jmx.jar");
        String[] cp = new String[path.size()];
        path.toArray(cp);
        return cp;
    }

    @Override
    public String[] getClassPath(ProductPluginManager manager) {
        OperatingSystem os = OperatingSystem.getInstance();
        boolean testIBMJDK = (os.getName().equals(OperatingSystem.NAME_LINUX)
                || os.getName().equals(OperatingSystem.NAME_WIN32));
        //assert testIBMJDK : os.getName();
        if (testIBMJDK) {
            VALID_JVM = System.getProperty("java.vm.vendor").toUpperCase().indexOf("IBM") != -1;
            if (!VALID_JVM) {
                log.debug("The WebSphere plugin needs a IBM JVM !!! " + "(agent jvm="
                        + System.getProperty("java.vm.vendor") + ")");
            }
            assert VALID_JVM;
        }

        if (isWin32()) {
            String prop = "websphere.regkey";
            REG_KEY = getPluginProperty(prop);
            if (REG_KEY == null) {
                log.error("Prop " + prop + "undefined");
                return new String[] {};
            }
        }

        Properties managerProps = manager.getProperties();

        tmpdir = managerProps.getProperty("websphere.tmpdir", System.getProperty("java.io.tmpdir"));
        useJMX = Boolean.valueOf(managerProps.getProperty("websphere.usejmx", "true"));
        useExt = Boolean.valueOf(managerProps.getProperty("websphere.useext", "false"));
        String installDir = managerProps.getProperty(PROP_INSTALLPATH, findInstallDir());

        log.debug("websphere.tmpdir = " + tmpdir);
        log.debug("websphere.usejmx = " + useJMX);
        log.debug("websphere.useext = " + useExt);
        log.debug(PROP_INSTALLPATH + " = " + installDir);

        if (installDir == null) {
            return new String[] { "pdk/lib/mx4j/hq-jmx.jar" };
        }

        //required for authentication
        String defaultCorbaConfig = installDir + File.separator + "properties" + File.separator
                + "sas.client.props";

        String corbaConfig = managerProps.getProperty("websphere.CORBA.ConfigURL", defaultCorbaConfig);

        System.setProperty("com.ibm.CORBA.ConfigURL", "file:" + corbaConfig);

        String defaultSoapProps = "properties" + File.separator + "soap.client.props";

        File installPropertiesDir = getInstallPropertiesDir(installDir, defaultSoapProps);
        String soapConfig = null;
        File soapConfigFile = null;
        if (installPropertiesDir != null && installPropertiesDir.exists()) {
            String defaultSoapConfig = installPropertiesDir.getPath();
            log.debug("default soap config is " + defaultSoapConfig);

            soapConfig = managerProps.getProperty("websphere.SOAP.ConfigURL", defaultSoapConfig);

            soapConfigFile = new File(soapConfig);
            hasSoapConfig = soapConfigFile.exists();
        }

        if (hasSoapConfig) {
            log.debug("Using soap properties: " + soapConfig);
            System.setProperty("com.ibm.SOAP.ConfigURL", "file:" + soapConfig);
        } else {
            log.debug("Unable to find soap.client.props in " + soapConfig);
        }

        isOSGi = new File(installDir, "/plugins").isDirectory();
        log.debug("isOSGi=" + isOSGi);

        //required for 6.1
        File sslConfigFile = null;
        if (hasSoapConfig && soapConfigFile != null) {
            sslConfigFile = new File(soapConfigFile.getParent(), "ssl.client.props");
        }

        if (sslConfigFile != null && sslConfigFile.exists()) {
            log.debug("Using ssl properties: " + sslConfigFile);
            System.setProperty("com.ibm.SSL.ConfigURL", "file:" + sslConfigFile);
        } else if (isOSGi) {
            log.debug("Unable to find ssl.client.props");
        }

        //required for 6.x
        System.setProperty(PROP_INSTALL_ROOT, installDir);

        if (isOSGi) {
            if (useExt) {
                try {
                    setExtDirs(installDir);
                    return new String[] { "pdk/lib/mx4j/hq-jmx.jar" };
                } catch (Exception e) {
                    log.error("setExtDirs: " + e, e);
                }
            }
            return getClassPathOSGi(installDir);
        }

        return new String[] {
                //5.0 + 5.1
                installDir + "/java/jre/lib/core.jar", installDir + "/java/jre/lib/ext/log.jar",
                installDir + "/lib/bootstrap.jar", installDir + "/lib/wssec.jar", installDir + "/lib/pmiclient.jar",
                installDir + "/lib/wasjmx.jar", installDir + "/lib/soap.jar", installDir + "/lib/sas.jar",
                installDir + "/lib/pmi.jar", installDir + "/lib/wsexception.jar", installDir + "/lib/jmxc.jar",
                installDir + "/lib/jmxx.jar", installDir + "/lib/jmxext.jar", installDir + "/lib/jflt.jar",
                installDir + "/lib/nls.jar", installDir + "/lib/ffdc.jar", installDir + "/lib/idl.jar",
                //5.0
                installDir + "/java/jre/lib/ext/ibmjsse.jar", installDir + "/java/jre/lib/ext/ibmjssefips-ob.jar",
                //5.1
                installDir + "/java/jre/lib/security.jar",
                //5.1.1
                installDir + "/java/jre/lib/ibmjsseprovider.jar",
                //4.0
                installDir + "/lib/perf.jar", installDir + "/lib/websphere.jar", installDir + "/lib/ujc.jar",
                installDir + "/lib/ns.jar", installDir + "/lib/iwsorb.jar",
                //4.0 AE
                installDir + "/lib/ejbcontainer.jar", installDir + "/lib/jts.jar", installDir + "/lib/csicpi.jar",
                installDir + "/lib/repository.jar",
                //both 4.0 + 5.0
                installDir + "/lib/admin.jar", installDir + "/lib/xerces.jar", installDir + "/lib/j2ee.jar",
                installDir + "/lib/ras.jar", installDir + "/lib/utils.jar",
                installDir + "/java/jre/lib/ext/mail.jar",
                //6.0
                installDir + "/lib/management.jar", installDir + "/lib/mail-impl.jar", installDir + "/lib/emf.jar",
                installDir + "/lib/utils.jar", installDir + "/lib/runtime.jar", installDir + "/lib/classloader.jar",
                installDir + "/lib/security.jar", installDir + "/lib/wasproduct.jar",
                installDir + "/lib/pmij2ee.jar", installDir + "/java/jre/lib/ibmcertpathprovider.jar",
                installDir + "/java/jre/lib/ext/ibmjceprovider.jar",
                installDir + "/java/jre/lib/ext/ibmjcefips.jar", installDir + "/etc/tmx4jTransform.jar",
                "pdk/lib/mx4j/hq-jmx.jar" };
    }

    File getInstallPropertiesDir(String installDir, String lookFor) {
        File result = getInstallPropertiesDirForWAS61(lookFor);

        if (result == null) {
            result = getInstallPropertiesDirForWAS60(installDir, lookFor);
        }

        return result;
    }

    File getInstallPropertiesDirForWAS61(String lookFor) {

        File result = null;

        List servers = getServerProcessList();
        if (servers.size() != 0) {
            for (Iterator it = servers.iterator(); it.hasNext();) {
                WebSphereProcess process = (WebSphereProcess) it.next();

                if (process.getServerRoot() != null) {
                    File candidate = new File(process.getServerRoot(), lookFor);
                    if (candidate.exists()) {
                        log.debug("Getting WAS properties from profile under server.root: " + candidate);
                        result = candidate;
                        break;
                    }
                }
            }
        }

        return result;
    }

    List getServerProcessList() {
        return WebsphereDetector.getServerProcessList();
    }

    File getInstallPropertiesDirForWAS60(String installDir, String lookFor) {

        File result = null;

        File profileDir = new File(installDir + File.separator + "profiles");
        if (profileDir.exists()) {
            File candidateDir = new File(profileDir + File.separator + "default");
            if (candidateDir.exists()) {
                File candidate = new File(candidateDir, lookFor);
                if (candidate.exists()) {
                    log.debug("Getting WAS properties from default profile location: " + candidate);
                    result = candidate;
                }
            }

            if (result == null) {
                // Look under non-default profiles.
                if (profileDir.isDirectory()) {
                    String[] profiles = profileDir.list();
                    if (profiles != null) {
                        for (int i = 0; i < profiles.length; i++) {
                            candidateDir = new File(profileDir, profiles[i]);
                            if (candidateDir.exists()) {
                                File candidate = new File(candidateDir, lookFor);
                                if (candidate.exists()) {
                                    log.debug("Getting WAS properties from profile non-default location: "
                                            + candidate);
                                    result = candidate;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
        }

        return result;
    }
}