org.opennms.netmgt.notifd.AbstractSlackCompatibleNotificationStrategy.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.netmgt.notifd.AbstractSlackCompatibleNotificationStrategy.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2015-2016 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2016 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.netmgt.notifd;

import java.io.IOException;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.io.IOUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.util.EntityUtils;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.opennms.core.web.HttpClientWrapper;
import org.opennms.netmgt.config.NotificationManager;
import org.opennms.netmgt.model.notifd.Argument;
import org.opennms.netmgt.model.notifd.NotificationStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractSlackCompatibleNotificationStrategy implements NotificationStrategy {

    protected abstract String getChannelPropertyName();

    protected abstract String getIconEmojiPropertyName();

    protected abstract String getIconUrlPropertyName();

    protected abstract String getUsernamePropertyName();

    protected abstract String getUrlPropertyName();

    protected abstract String decorateMessageBody(String body);

    protected abstract String decorateMessageSubject(String subject);

    protected abstract String formatWebhookErrorResponse(int statusCode, String contents);

    protected static final Logger LOG = LoggerFactory.getLogger(AbstractSlackCompatibleNotificationStrategy.class);
    private List<Argument> m_arguments;

    /** {@inheritDoc} */
    @SuppressWarnings("unchecked")
    public int send(List<Argument> arguments) {

        m_arguments = arguments;

        String url = getUrl();
        if (url == null) {
            LOG.error("send: url must not be null");
            return 1;
        }
        String iconUrl = getIconUrl();
        String iconEmoji = getIconEmoji();
        String channel = getChannel();
        String message = buildMessage(arguments);

        final HttpClientWrapper clientWrapper = HttpClientWrapper.create().setConnectionTimeout(3000)
                .setSocketTimeout(3000).useSystemProxySettings();

        HttpPost postMethod = new HttpPost(url);

        JSONObject jsonData = new JSONObject();
        jsonData.put("username", getUsername());
        if (iconUrl != null) {
            jsonData.put("icon_url", iconUrl);
        }
        if (iconEmoji != null) {
            jsonData.put("icon_emoji", iconEmoji);
        }
        if (channel != null) {
            jsonData.put("channel", channel);
        }
        jsonData.put("text", message);

        if (jsonData.containsKey("icon_url") && jsonData.containsKey("icon_emoji")) {
            LOG.warn("Both URL and emoji specified for icon. Sending both; behavior is undefined.");
        }

        LOG.debug("Prepared JSON POST data for webhook is: {}", jsonData.toJSONString());
        final HttpEntity entity = new StringEntity(jsonData.toJSONString(), ContentType.APPLICATION_JSON);
        postMethod.setEntity(entity);
        // Mattermost 1.1.0 does not like having charset specified alongside Content-Type
        postMethod.setHeader("Content-Type", "application/json");

        String contents = null;
        int statusCode = -1;
        try {
            CloseableHttpResponse response = clientWrapper.getClient().execute(postMethod);
            statusCode = response.getStatusLine().getStatusCode();
            contents = EntityUtils.toString(response.getEntity());
            LOG.debug("send: Contents is: {}", contents);
        } catch (IOException e) {
            LOG.error("send: I/O problem with webhook post/response: {}", e);
            throw new RuntimeException("Problem with webhook post: " + e.getMessage());
        } finally {
            IOUtils.closeQuietly(clientWrapper);
        }

        if ("ok".equals(contents)) {
            LOG.debug("Got 'ok' back from webhook, indicating success.");
            statusCode = 0;
        } else {
            LOG.info("Got a non-ok response from webhook, attempting to dissect response.");
            LOG.error("Webhook returned non-OK response to notification post: {}",
                    formatWebhookErrorResponse(statusCode, contents));
            statusCode = 1;
        }

        return statusCode;
    }

    protected String getUrl() {
        String url = getValueFromSwitchOrProp("Webhook URL", "url", getUrlPropertyName());

        if (url == null) {
            LOG.error(
                    "No webhook URL specified as a notification command switch or via system property {}. Cannot continue.",
                    getUrlPropertyName());
        }
        return url;
    }

    protected String getUsername() {
        String username = getValueFromSwitchOrProp("Bot username", "username", getUsernamePropertyName());

        if (username == null) {
            LOG.warn(
                    "No bot username specified as a notification command switch or via system property {}. Using default value opennms.",
                    getUsernamePropertyName());
            return "opennms";
        }
        return username;
    }

    protected String getIconUrl() {
        String iconurl = getValueFromSwitchOrProp("Icon URL", "iconurl", getIconUrlPropertyName());

        if (iconurl == null) {
            LOG.info(
                    "No icon URL specified as a notification command switch or via system property {}. Not setting one.",
                    getIconUrlPropertyName());
        }
        return iconurl;
    }

    protected String getIconEmoji() {
        String iconemoji = getValueFromSwitchOrProp("Icon Emoji", "iconemoji", getIconEmojiPropertyName());

        if (iconemoji == null) {
            LOG.info(
                    "No icon emoji specified as a notification command switch or via system property {}. Not setting one.",
                    getIconEmojiPropertyName());
        }
        if (iconemoji != null && !iconemoji.startsWith(":") && !iconemoji.endsWith(":")) {
            LOG.warn("Specified icon emoji '{}' is not colon-enclosed. Did you mean to do this?", iconemoji);
        }
        return iconemoji;
    }

    protected String getChannel() {
        String channel = getValueFromSwitchOrProp("Channel name", "channel", getChannelPropertyName());

        if (channel == null) {
            LOG.info(
                    "No channel specified as a notification command switch or via system property {}. Not setting one.",
                    getChannelPropertyName());
        }
        return channel;
    }

    protected String getValueFromSwitchOrProp(String what, String switchName, String propName) {
        LOG.debug("Trying to get {} from notification switch {}", what, switchName);
        String val = getSwitchValue(switchName);
        if (val != null) {
            LOG.info("Using {} value {} from notification switch {}", what, val, switchName);
            return val;
        }
        LOG.debug("Trying to get {} from system property {}", what, propName);
        val = System.getProperty(propName);
        if (val != null) {
            LOG.info("Using {} value {} from system property {}", what, val, propName);
            return val;
        }

        LOG.warn("Could not determine value for {} from notification command switch {} or system property {}", what,
                switchName, propName);
        return null;
    }

    /**
     * Helper method to look into the Argument list and return the associated value.
     * If the value is an empty String, this method returns null.
     * @param argSwitch
     * @return
     */
    private String getSwitchValue(String argSwitch) {
        String value = null;
        for (Iterator<Argument> it = m_arguments.iterator(); it.hasNext();) {
            Argument arg = it.next();
            if (arg.getSwitch().equals(argSwitch)) {
                if (!"".equals(arg.getValue())) {
                    value = arg.getValue();
                } else if (!"".equals(arg.getSubstitution())) {
                    value = arg.getSubstitution();
                }
            }
        }
        if (value != null && value.equals(""))
            value = null;

        return value;
    }

    protected String buildMessage(List<Argument> args) {
        String subject = null;
        String body = null;
        for (Argument arg : args) {
            if (NotificationManager.PARAM_SUBJECT.equals(arg.getSwitch())) {
                subject = arg.getValue();
            } else if (NotificationManager.PARAM_TEXT_MSG.equals(arg.getSwitch())) {
                body = arg.getValue();
            }
        }

        StringBuilder bldr = new StringBuilder();
        if ("".equals(subject) || "RESOLVED: ".equals(subject)) {
            subject = null;
        } else {
            bldr.append(decorateMessageSubject(subject));
        }

        if ("".equals(body) || "RESOLVED: ".equals(body)) {
            body = null;
        } else {
            bldr.append(decorateMessageBody(body));
        }

        return bldr.toString();
    }

}