be.fgov.kszbcss.rhq.websphere.component.server.WebSphereServerDiscoveryComponent.java Source code

Java tutorial

Introduction

Here is the source code for be.fgov.kszbcss.rhq.websphere.component.server.WebSphereServerDiscoveryComponent.java

Source

/*
 * RHQ WebSphere Plug-in
 * Copyright (C) 2012 Crossroads Bank for Social Security
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License, version 2, as
 * published by the Free Software Foundation, and/or the GNU Lesser
 * General Public License, version 2.1, also 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 and the GNU Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU General Public License
 * and the GNU Lesser General Public License along with this program;
 * if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package be.fgov.kszbcss.rhq.websphere.component.server;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javanet.staxutils.SimpleNamespaceContext;

import javax.management.ObjectName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.rhq.core.domain.configuration.Configuration;
import org.rhq.core.domain.configuration.PropertySimple;
import org.rhq.core.pluginapi.inventory.DiscoveredResourceDetails;
import org.rhq.core.pluginapi.inventory.InvalidPluginConfigurationException;
import org.rhq.core.pluginapi.inventory.ManualAddFacet;
import org.rhq.core.pluginapi.inventory.ProcessScanResult;
import org.rhq.core.pluginapi.inventory.ResourceComponent;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryComponent;
import org.rhq.core.pluginapi.inventory.ResourceDiscoveryContext;
import org.rhq.core.system.ProcessInfo;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

import be.fgov.kszbcss.rhq.websphere.connector.SecureAdminClientProvider;
import be.fgov.kszbcss.rhq.websphere.process.locator.ConfigurationBasedProcessLocator;

import com.ibm.websphere.management.AdminClient;
import com.ibm.websphere.management.exception.ConnectorException;

public class WebSphereServerDiscoveryComponent
        implements ResourceDiscoveryComponent<ResourceComponent<?>>, ManualAddFacet<ResourceComponent<?>> {
    private static class PortSpec {
        private final String endPointName;
        private final String protocol;

        public PortSpec(String endPointName, String protocol) {
            this.endPointName = endPointName;
            this.protocol = protocol;
        }

        public String getEndPointName() {
            return endPointName;
        }

        public String getProtocol() {
            return protocol;
        }
    }

    private static final Log log = LogFactory.getLog(WebSphereServerDiscoveryComponent.class);

    private static final List<PortSpec> portSpecs = new ArrayList<PortSpec>();

    static {
        portSpecs.add(new PortSpec("ORB_LISTENER_ADDRESS", "RMI"));
        portSpecs.add(new PortSpec("BOOTSTRAP_ADDRESS", "RMI"));
        portSpecs.add(new PortSpec("SOAP_CONNECTOR_ADDRESS", "SOAP"));
    }

    public Set<DiscoveredResourceDetails> discoverResources(ResourceDiscoveryContext<ResourceComponent<?>> context)
            throws InvalidPluginConfigurationException, Exception {
        Set<DiscoveredResourceDetails> result = new HashSet<DiscoveredResourceDetails>();
        for (ProcessScanResult process : context.getAutoDiscoveredProcesses()) {
            ProcessInfo processInfo = process.getProcessInfo();
            String[] commandLine = processInfo.getCommandLine();
            if (log.isDebugEnabled()) {
                log.debug("Examining process " + processInfo.getPid());
                log.debug("Command line: " + Arrays.asList(commandLine));
            }
            int appOptionIndex = -1; // The index of the -application option
            for (int i = 0; i < commandLine.length; i++) {
                if (commandLine[i].equals("-application")) {
                    appOptionIndex = i;
                    break;
                }
            }
            if (appOptionIndex == -1) {
                log.debug("No -application option found");
                continue;
            }
            if (commandLine.length - appOptionIndex != 7) {
                if (log.isDebugEnabled()) {
                    log.debug("Unexpected number of arguments (" + (commandLine.length - appOptionIndex)
                            + ") after -application");
                }
                continue;
            }
            if (!commandLine[appOptionIndex + 1].equals("com.ibm.ws.bootstrap.WSLauncher")) {
                log.debug("Expected com.ibm.ws.bootstrap.WSLauncher after -application");
                continue;
            }
            if (!commandLine[appOptionIndex + 2].equals("com.ibm.ws.runtime.WsServer")) {
                if (log.isDebugEnabled()) {
                    log.debug("Process doesn't appear to be a WebSphere server process; main class is "
                            + commandLine[appOptionIndex + 2]);
                }
                continue;
            }
            File repository = new File(commandLine[appOptionIndex + 3]);
            String cell = commandLine[appOptionIndex + 4];
            String node = commandLine[appOptionIndex + 5];
            String processName = commandLine[appOptionIndex + 6];
            if (processName.equals("nodeagent")) {
                log.debug("Process appears to be a node agent");
                continue;
            }
            if (processName.equals("dmgr")) {
                log.debug("Process appears to be a deployment manager");
                continue;
            }
            log.info("Discovered WebSphere application server process " + cell + "/" + node + "/" + processName);
            if (!repository.exists()) {
                log.error("Configuration repository " + repository + " doesn't exist");
                continue;
            }
            if (!repository.canRead()) {
                log.error("Configuration repository " + repository + " not readable");
                continue;
            }

            // Parse the serverindex.xml file for the node
            File serverIndexFile = new File(repository, "cells" + File.separator + cell + File.separator + "nodes"
                    + File.separator + node + File.separator + "serverindex.xml");
            if (log.isDebugEnabled()) {
                log.debug("Attempting to read " + serverIndexFile);
            }
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            DocumentBuilder builder = dbf.newDocumentBuilder();
            Document serverIndex;
            try {
                serverIndex = builder.parse(serverIndexFile);
            } catch (Exception ex) {
                log.error("Unable to parse " + serverIndexFile, ex);
                continue;
            }

            // Extract the port number
            XPathFactory xpathFactory = XPathFactory.newInstance();
            XPath xpath = xpathFactory.newXPath();
            SimpleNamespaceContext nsContext = new SimpleNamespaceContext();
            nsContext.setPrefix("serverindex",
                    "http://www.ibm.com/websphere/appserver/schemas/5.0/serverindex.xmi");
            xpath.setNamespaceContext(nsContext);
            int port = -1;
            String protocol = null;
            for (PortSpec portSpec : portSpecs) {
                if (log.isDebugEnabled()) {
                    log.debug("Attempting to extract " + portSpec.getEndPointName());
                }
                String portString = (String) xpath.evaluate("/serverindex:ServerIndex/serverEntries[@serverName='"
                        + processName + "']/specialEndpoints[@endPointName='" + portSpec.getEndPointName()
                        + "']/endPoint/@port", serverIndex, XPathConstants.STRING);
                if (portString == null || portString.length() == 0) {
                    log.debug(portSpec.getEndPointName() + " not found");
                    continue;
                }
                int candidatePort;
                try {
                    candidatePort = Integer.parseInt(portString);
                } catch (NumberFormatException ex) {
                    log.warn("Found non numerical port number in " + serverIndexFile);
                    continue;
                }
                if (log.isDebugEnabled()) {
                    log.debug("Port is " + candidatePort);
                }
                if (candidatePort != 0) {
                    if (log.isDebugEnabled()) {
                        log.debug("Using " + portSpec.getEndPointName() + "=" + candidatePort + ", protocol "
                                + portSpec.getProtocol());
                    }
                    port = candidatePort;
                    protocol = portSpec.getProtocol();
                    break;
                }
            }
            if (port == -1) {
                log.error("Unable to locate usable port in " + serverIndexFile);
                continue;
            }

            // Check if this is a managed server by looking for WebSphere instances of type NODE_AGENT
            boolean unmanaged = ((NodeList) xpath.evaluate(
                    "/serverindex:ServerIndex/serverEntries[@serverType='NODE_AGENT']", serverIndex,
                    XPathConstants.NODESET)).getLength() == 0;

            Configuration conf = new Configuration();
            conf.put(new PropertySimple("host", "localhost"));
            conf.put(new PropertySimple("port", port));
            conf.put(new PropertySimple("protocol", protocol));
            conf.put(new PropertySimple("loggingProvider", "none")); // TODO: autodetect XM4WAS
            conf.put(new PropertySimple("childJmxServerName", "JVM"));
            conf.put(new PropertySimple("unmanaged", unmanaged));
            result.add(new DiscoveredResourceDetails(context.getResourceType(),
                    cell + "/" + node + "/" + processName, processName, null,
                    processName + " (cell " + cell + ", node " + node + ")", conf, processInfo));
        }
        return result;
    }

    public DiscoveredResourceDetails discoverResource(Configuration pluginConfiguration,
            ResourceDiscoveryContext<ResourceComponent<?>> discoveryContext)
            throws InvalidPluginConfigurationException {
        ObjectName serverBeanName;
        try {
            AdminClient adminClient = new SecureAdminClientProvider(
                    new ConfigurationBasedProcessLocator(pluginConfiguration)).createAdminClient();
            serverBeanName = adminClient.getServerMBean();
        } catch (ConnectorException ex) {
            throw new InvalidPluginConfigurationException("Unable to connect to server", ex);
        }
        String cell = serverBeanName.getKeyProperty("cell");
        String node = serverBeanName.getKeyProperty("node");
        String process = serverBeanName.getKeyProperty("process");
        String processType = serverBeanName.getKeyProperty("processType");
        boolean unmanaged;
        if (processType.equals("ManagedProcess")) {
            unmanaged = false;
        } else if (processType.equals("UnManagedProcess")) {
            unmanaged = true;
        } else {
            throw new InvalidPluginConfigurationException("Unsupported process type " + processType);
        }
        pluginConfiguration.getSimple("unmanaged").setBooleanValue(unmanaged);
        return new DiscoveredResourceDetails(discoveryContext.getResourceType(), cell + "/" + node + "/" + process,
                process, null, process + " (cell " + cell + ", node " + node + ")", pluginConfiguration, null);
    }
}