org.hyperic.hq.plugin.rabbitmq.core.HypericRabbitAdmin.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.plugin.rabbitmq.core.HypericRabbitAdmin.java

Source

/**
 * NOTE: This copyright does *not* cover user programs that use Hyperic
 * 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) [2010], VMware, Inc.
 *  This file is part of Hyperic.
 *
 *  Hyperic 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.rabbitmq.core;

import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Type;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.auth.AuthScope;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.client.AuthCache;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.protocol.ClientContext;
import org.apache.http.impl.auth.BasicScheme;
import org.apache.http.impl.client.BasicAuthCache;
import org.apache.http.protocol.BasicHttpContext;
import org.hyperic.hq.agent.AgentKeystoreConfig;
import org.hyperic.hq.product.PluginException;
import org.hyperic.util.config.ConfigResponse;
import org.hyperic.util.http.HQHttpClient;
import org.hyperic.util.http.HttpConfig;

/**
 * A HypericRabbitAdmin is created for each node/virtualHost.
 * HypericRabbitAdmin
 * @author Helena Edelson
 */
public final class HypericRabbitAdmin {

    private static final Log logger = LogFactory.getLog(HypericRabbitAdmin.class);
    private final DefaultHttpClient client;
    private String user;
    private String pass;
    private BasicHttpContext localcontext;
    private HttpHost targetHost;

    public HypericRabbitAdmin(Properties props) throws PluginException {
        int port = Integer.parseInt(props.getProperty(DetectorConstants.PORT));
        String addr = props.getProperty(DetectorConstants.ADDR);
        boolean https = "true".equals(props.getProperty(DetectorConstants.HTTPS));
        this.user = props.getProperty(DetectorConstants.USERNAME);
        this.pass = props.getProperty(DetectorConstants.PASSWORD);

        targetHost = new HttpHost(addr, port, https ? "https" : "http");
        AgentKeystoreConfig config = new AgentKeystoreConfig();
        client = new HQHttpClient(config, new HttpConfig(5000, 5000, null, 0), config.isAcceptUnverifiedCert());
        client.getCredentialsProvider().setCredentials(
                new AuthScope(targetHost.getHostName(), targetHost.getPort(), "Management: Web UI"),
                new UsernamePasswordCredentials(user, pass));
        List authPrefs = new ArrayList(1);
        authPrefs.add("Management: Web UI");

        AuthCache authCache = new BasicAuthCache();
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(targetHost, basicAuth);

        localcontext = new BasicHttpContext();
        localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);
    }

    public HypericRabbitAdmin(ConfigResponse props) throws PluginException {
        this(props.toProperties());
    }

    public RabbitOverview getOverview() throws PluginException {
        return get("/api/overview", RabbitOverview.class);
    }

    public List<RabbitVirtualHost> getVirtualHosts() throws PluginException {
        List<RabbitVirtualHost> res;
        try {
            res = Arrays.asList(get("/api/vhosts", RabbitVirtualHost[].class));
        } catch (PluginException ex) {
            logger.debug("[getVirtualHosts] " + ex.getLocalizedMessage(), ex);
            res = new ArrayList<RabbitVirtualHost>();
            List<String> names = Arrays.asList(get("/api/vhosts", String[].class));
            for (String name : names) {
                res.add(new RabbitVirtualHost(name));
            }
        }
        return res;
    }

    public List<RabbitQueue> getQueues(RabbitVirtualHost vh) throws PluginException {
        try {
            return Arrays
                    .asList(get("/api/queues/" + URLEncoder.encode(vh.getName(), "UTF-8"), RabbitQueue[].class));
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
    }

    public List<RabbitExchange> getExchanges(RabbitVirtualHost vh) throws PluginException {
        try {
            return Arrays.asList(
                    get("/api/exchanges/" + URLEncoder.encode(vh.getName(), "UTF-8"), RabbitExchange[].class));
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
    }

    public List<RabbitConnection> getConnections() throws PluginException {
        return Arrays.asList(get("/api/connections", RabbitConnection[].class));
    }

    public RabbitConnection getConnection(String cName) throws PluginException {
        try {
            cName = URLEncoder.encode(cName, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
        return get("/api/connections/" + cName, RabbitConnection.class);
    }

    public List<RabbitChannel> getChannels() throws PluginException {
        return Arrays.asList(get("/api/channels", RabbitChannel[].class));
    }

    public RabbitChannel getChannel(String chName) throws PluginException {
        try {
            chName = URLEncoder.encode(chName, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
        return get("/api/channels/" + chName, RabbitChannel.class);
    }

    public RabbitVirtualHost getVirtualHost(String vhName) throws PluginException {
        try {
            vhName = URLEncoder.encode(vhName, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }

        RabbitVirtualHost res;
        try {
            res = get("/api/vhosts/" + vhName, RabbitVirtualHost.class);
        } catch (PluginException ex) {
            logger.debug("[getVirtualHost] " + ex.getLocalizedMessage(), ex);
            String name = get("/api/vhosts/" + vhName, String.class);
            res = new RabbitVirtualHost(name);
        }
        return res;
    }

    public RabbitQueue getVirtualQueue(String vhName, String qName) throws PluginException {
        try {
            vhName = URLEncoder.encode(vhName, "UTF-8");
            qName = URLEncoder.encode(qName, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }

        return get("/api/queues/" + vhName + "/" + qName, RabbitQueue.class);
    }

    public RabbitExchange getExchange(String vhost, String exch) throws PluginException {
        try {
            vhost = URLEncoder.encode(vhost, "UTF-8");
            exch = URLEncoder.encode(exch, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }

        return get("/api/exchanges/" + vhost + "/" + exch, RabbitExchange.class);
    }

    public RabbitNode getNode(String node) throws PluginException {
        RabbitNode res;
        try {
            node = URLEncoder.encode(node, "UTF-8");
        } catch (UnsupportedEncodingException ex) {
            throw new RuntimeException(ex);
        }
        try {
            res = get("/api/nodes/" + node, RabbitNode.class);
        } catch (PluginException ex) {
            logger.debug("[getVirtualHost] " + ex.getLocalizedMessage(), ex);
            res = get("/api/overview/", RabbitNode.class);
            res.setName(node);
            res.setRunning(true);
        }
        return res;
    }

    private <T extends Object> T get(String api, Class<T> classOfT) throws PluginException {
        T res = null;
        try {
            HttpGet get = new HttpGet(targetHost.toURI() + api);
            HttpResponse response = client.execute(get, localcontext);
            int r = response.getStatusLine().getStatusCode();
            // response must be read in order to "close" the connection.
            // https://jira.hyperic.com/browse/HHQ-5063#comment-154101
            String responseBody = readInputString(response.getEntity().getContent());

            if (logger.isDebugEnabled()) {
                logger.debug("[" + api + "] -(" + r + ")-> " + responseBody);
            }

            if (r != 200) {
                throw new PluginException("[" + api + "] http error code: '" + r + "'");
            }

            GsonBuilder gsb = new GsonBuilder();
            gsb.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
            gsb.registerTypeAdapter(Integer.class, new IntegerDeserializer());
            gsb.registerTypeAdapter(int.class, new IntegerDeserializer());
            gsb.registerTypeAdapter(Date.class, new DateTimeDeserializer());
            gsb.registerTypeAdapter(MessageStats.class, new MessageStatsDeserializer());
            Gson gson = gsb.create();

            res = gson.fromJson(responseBody, classOfT);
            if (logger.isDebugEnabled()) {
                if (res.getClass().isArray()) {
                    logger.debug("[" + api + "] -(" + r + ")*> " + Arrays.asList((Object[]) res));
                } else {
                    logger.debug("[" + api + "] -(" + r + ")-> " + res);
                }
            }
        } catch (IOException ex) {
            logger.debug(ex.getMessage(), ex);
            throw new PluginException(ex.getMessage(), ex);
        }
        return res;
    }

    private class DateTimeDeserializer implements JsonDeserializer<Date> {

        public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
                throws JsonParseException {
            DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            try {
                return (Date) formatter.parse(json.getAsString());
            } catch (ParseException ex) {
                throw new JsonParseException(ex.getMessage(), ex);
            }
        }
    }

    private class IntegerDeserializer implements JsonDeserializer<Integer> {

        public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
            try {
                return json.getAsInt();
            } catch (NumberFormatException ex) {
                if (json.getAsString().equals("install_handle_from_sysinternals")) {
                    logger.debug(
                            "'Handle V3.42 (sysinternals)' is required by 'rabbitmq-management-agent' plugin on Windows Platforms. "
                                    + ex.getMessage());
                    return null;
                }
                throw new JsonParseException(ex.getMessage(), ex);
            }
        }
    }

    private class MessageStatsDeserializer implements JsonDeserializer<MessageStats> {

        public MessageStats deserialize(JsonElement je, Type Type, JsonDeserializationContext jdc)
                throws JsonParseException {
            MessageStats res = null;
            if (je.isJsonArray()) {
                res = new MessageStats();
            } else {
                GsonBuilder gsb = new GsonBuilder();
                gsb.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
                Gson gson = gsb.create();
                res = gson.fromJson(je, Type);
            }
            return res;
        }
    }

    public static String readInputString(InputStream in) throws IOException {
        StringBuilder out = new StringBuilder();
        byte[] b = new byte[4096];
        for (int n; (n = in.read(b)) != -1;) {
            out.append(new String(b, 0, n));
        }
        return out.toString();
    }
}