org.opennms.systemreport.AbstractSystemReportPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.systemreport.AbstractSystemReportPlugin.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2010-2014 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2014 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.systemreport;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.io.StringReader;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

import org.apache.commons.exec.CommandLine;
import org.apache.commons.exec.DefaultExecutor;
import org.apache.commons.exec.ExecuteWatchdog;
import org.apache.commons.exec.PumpStreamHandler;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.builder.CompareToBuilder;
import org.opennms.systemreport.system.PsParser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;

public abstract class AbstractSystemReportPlugin implements SystemReportPlugin {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractSystemReportPlugin.class);
    protected static final long MAX_PROCESS_WAIT = 10000; // milliseconds
    private MBeanServerConnection m_connection = null;

    protected ResourceLocator m_resourceLocator = new SystemReportResourceLocator(MAX_PROCESS_WAIT);

    @Override
    public int getPriority() {
        return 99;
    }

    protected ResourceLocator getResourceLocator() {
        return m_resourceLocator;
    }

    protected void setResourceLocator(final ResourceLocator resourceLocator) {
        m_resourceLocator = resourceLocator;
    }

    @Override
    public Map<String, Resource> getEntries() {
        throw new UnsupportedOperationException("You must override getEntries()!");
    }

    @Override
    public String toString() {
        return String.format("%s[%d]", getName(), getPriority());
    }

    @Override
    public int compareTo(final SystemReportPlugin o) {
        return new CompareToBuilder().append(this.getPriority(), (o == null ? Integer.MIN_VALUE : o.getPriority()))
                .append(this.getName(), (o == null ? null : o.getName())).toComparison();
    }

    protected String slurp(final File lsb) {
        if (lsb != null && lsb.exists()) {
            FileInputStream stream = null;
            try {
                stream = new FileInputStream(lsb);
                FileChannel fc = stream.getChannel();
                MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
                return Charset.defaultCharset().decode(bb).toString().replace("[\\r\\n]*$", "");
            } catch (final Exception e) {
                LOG.debug("Unable to read from file '{}'", lsb.getPath(), e);
            } finally {
                IOUtils.closeQuietly(stream);
            }
        }
        return null;
    }

    protected String slurpCommand(final String[] command) {
        Process p = null;
        InputStream is = null;
        InputStreamReader isr = null;
        BufferedReader br = null;

        StringBuffer sb = new StringBuffer();
        try {
            p = Runtime.getRuntime().exec(command);
            is = p.getInputStream();
            isr = new InputStreamReader(is);
            br = new BufferedReader(isr);
            while (br.ready()) {
                final String line = br.readLine();
                if (line == null)
                    break;
                sb.append(line);
                if (br.ready())
                    sb.append("\n");
            }
        } catch (final Throwable e) {
            LOG.debug("Failure attempting to run command '{}'", Arrays.asList(command), e);
        } finally {
            IOUtils.closeQuietly(br);
            IOUtils.closeQuietly(isr);
            IOUtils.closeQuietly(is);
        }

        return sb.toString();
    }

    protected Map<String, String> splitMultilineString(final String regex, final String text) {
        final Map<String, String> map = new HashMap<String, String>();

        if (text != null) {
            final StringReader sr = new StringReader(text);
            final BufferedReader br = new BufferedReader(sr);
            try {
                while (br.ready()) {
                    final String line = br.readLine();
                    if (line == null)
                        break;
                    final String[] entry = line.split(regex, 2);
                    if (entry.length == 2) {
                        map.put(entry[0], entry[1]);
                    }
                }
            } catch (final IOException e) {
                LOG.debug("an error occurred parsing the text", e);
            } finally {
                IOUtils.closeQuietly(br);
                IOUtils.closeQuietly(sr);
            }
        }

        return map;
    }

    protected Resource getResourceFromProperty(final String propertyName) {
        return getResource(System.getProperty(propertyName));
    }

    protected Resource getResource(final String text) {
        if (text == null)
            return new ByteArrayResource(new byte[0]);
        return new ByteArrayResource(text.getBytes());
    }

    protected File createTemporaryFileFromString(final String text) {
        File tempFile = null;
        FileWriter fw = null;
        try {
            tempFile = File.createTempFile("topReportPlugin", null);
            tempFile.deleteOnExit();
            fw = new FileWriter(tempFile);
            fw.write(text);
            fw.close();
        } catch (final Exception e) {
            LOG.debug("Unable to write to temporary file.", e);
        } finally {
            IOUtils.closeQuietly(fw);
        }
        return tempFile;
    }

    protected Set<Integer> getOpenNMSProcesses() {
        LOG.trace("getOpenNMSProcesses()");
        final Set<Integer> processes = new HashSet<Integer>();

        final String jps = getResourceLocator().findBinary("jps");

        LOG.trace("jps = {}", jps);

        DataInputStream input = null;
        PsParser parser = null;
        PipedInputStream pis = null;
        PipedOutputStream output = new PipedOutputStream();
        DefaultExecutor executor = new DefaultExecutor();
        executor.setWatchdog(new ExecuteWatchdog(5000));

        if (jps != null) {
            CommandLine command = CommandLine.parse(jps + " -v");
            PumpStreamHandler streamHandler = new PumpStreamHandler(output, System.err);

            try {
                LOG.trace("executing '{}'", command);
                pis = new PipedInputStream(output);
                input = new DataInputStream(pis);
                parser = new PsParser(input, "opennms_bootstrap.jar", "status", 0);
                parser.start();
                executor.setStreamHandler(streamHandler);
                int exitValue = executor.execute(command);
                IOUtils.closeQuietly(output);
                parser.join();
                processes.addAll(parser.getProcesses());
                LOG.trace("finished '{}'", command);

                if (exitValue != 0) {
                    LOG.debug("error running '{}': exit value was {}", command, exitValue);
                }
            } catch (final Exception e) {
                LOG.debug("Failed to run '{}'", command, e);
            } finally {
                IOUtils.closeQuietly(input);
                IOUtils.closeQuietly(pis);
                IOUtils.closeQuietly(output);
            }
        }

        LOG.trace("looking for ps");
        final String ps = getResourceLocator().findBinary("ps");
        if (ps != null) {

            // try Linux/Mac style
            CommandLine command = CommandLine.parse(ps + " aww -o pid -o args");
            output = new PipedOutputStream();
            PumpStreamHandler streamHandler = new PumpStreamHandler(output, System.err);

            try {
                LOG.trace("executing '{}'", command);
                pis = new PipedInputStream(output);
                input = new DataInputStream(pis);
                parser = new PsParser(input, "opennms_bootstrap.jar", "status", 0);
                parser.start();
                executor.setStreamHandler(streamHandler);
                int exitValue = executor.execute(command);
                IOUtils.closeQuietly(output);
                parser.join(MAX_PROCESS_WAIT);
                processes.addAll(parser.getProcesses());
                LOG.trace("finished '{}'", command);

                if (exitValue != 0) {
                    LOG.debug("error running '{}': exit value was {}", command, exitValue);
                }
            } catch (final Exception e) {
                LOG.debug("error running '{}'", command, e);
            } finally {
                IOUtils.closeQuietly(input);
                IOUtils.closeQuietly(pis);
                IOUtils.closeQuietly(output);
            }

            if (processes.size() == 0) {
                // try Solaris style
                command = CommandLine.parse(ps + " -ea -o pid -o args");
                output = new PipedOutputStream();
                streamHandler = new PumpStreamHandler(output, System.err);

                try {
                    LOG.trace("executing '{}'", command);
                    pis = new PipedInputStream(output);
                    input = new DataInputStream(pis);
                    parser = new PsParser(input, "opennms_bootstrap.jar", "status", 0);
                    parser.start();
                    executor.setStreamHandler(streamHandler);
                    int exitValue = executor.execute(command);
                    IOUtils.closeQuietly(output);
                    parser.join(MAX_PROCESS_WAIT);
                    processes.addAll(parser.getProcesses());
                    LOG.trace("finished '{}'", command);

                    if (exitValue != 0) {
                        LOG.debug("error running '{}': exit value was {}", command, exitValue);
                    }
                } catch (final Exception e) {
                    LOG.debug("error running '{}'", command, e);
                } finally {
                    IOUtils.closeQuietly(input);
                    IOUtils.closeQuietly(pis);
                    IOUtils.closeQuietly(output);
                }
            }
        }

        if (processes.size() == 0) {
            LOG.warn("Unable to find any OpenNMS processes.");
        }

        return processes;
    }

    private MBeanServerConnection getConnection() {
        final List<Integer> ports = new ArrayList<Integer>();
        Integer p = Integer.getInteger("com.sun.management.jmxremote.port");
        if (p != null)
            ports.add(p);
        ports.add(18980);
        ports.add(1099);
        for (final Integer port : ports) {
            LOG.trace("Trying JMX at localhost:{}/jmxrmi", port);
            try {
                JMXServiceURL url = new JMXServiceURL(
                        String.format("service:jmx:rmi:///jndi/rmi://localhost:%d/jmxrmi", port));
                JMXConnector jmxc = JMXConnectorFactory.connect(url, null);
                return jmxc.getMBeanServerConnection();
            } catch (final Exception e) {
                LOG.debug("Unable to get JMX connection to OpenNMS on port {}.", port, e);
            }
        }
        return null;
    }

    protected void addGetters(final Object o, final Map<String, Resource> map) {
        if (o != null) {
            for (Method method : o.getClass().getDeclaredMethods()) {
                method.setAccessible(true);
                if (method.getName().startsWith("get") && Modifier.isPublic(method.getModifiers())) {
                    Object value;
                    try {
                        value = method.invoke(o);
                    } catch (Throwable e) {
                        value = e;
                    }
                    final String key = method.getName().replaceFirst("^get", "").replaceAll("([A-Z])", " $1")
                            .replaceFirst("^ ", "").replaceAll("\\bVm\\b", "VM");
                    map.put(key, getResource(value.toString()));
                }
            }
        }
    }

    protected <T> List<T> getBeans(final String mxBeanName, final Class<T> clazz) {
        initializeConnection();
        List<T> beans = new ArrayList<T>();
        if (m_connection == null)
            return beans;
        try {
            ObjectName o = new ObjectName(mxBeanName + ",*");
            for (final ObjectName name : (Set<ObjectName>) m_connection.queryNames(o, null)) {
                beans.add(getBean(name.getCanonicalName(), clazz));
            }
        } catch (final Exception e) {
            LOG.warn("Unable to get beans of type '{}'", mxBeanName, e);
        }
        return beans;
    }

    protected <T> T getBean(final String mxBeanName, final Class<T> clazz) {
        final List<Class<T>> classes = new ArrayList<Class<T>>();
        classes.add(clazz);
        return getBean(mxBeanName, classes);
    }

    protected <T> T getBean(final String mxBeanName, final List<? extends Class<T>> classes) {
        initializeConnection();
        if (m_connection == null || mxBeanName == null || classes == null || classes.size() == 0) {
            return null;
        }

        T bean = null;
        for (final Class<T> c : classes) {
            try {
                bean = ManagementFactory.newPlatformMXBeanProxy(m_connection, mxBeanName, c);
                break;
            } catch (final Exception e) {
                LOG.info("Unable to get management bean {} for class {}", mxBeanName, c.getName(), e);
            }
        }
        return bean;
    }

    private void initializeConnection() {
        if (m_connection == null) {
            m_connection = getConnection();
        }
    }
}