/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 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 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 General Public License for more details. * * You should have received a copy of the GNU 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.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.HashMap; import java.util.Properties; import org.apache.commons.io.IOUtils; import org.jivesoftware.smack.Chat; import org.jivesoftware.smack.ChatManager; import org.jivesoftware.smack.ConnectionConfiguration; import org.jivesoftware.smack.ConnectionListener; import org.jivesoftware.smack.MessageListener; import org.jivesoftware.smack.XMPPConnection; import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.ConnectionConfiguration.SecurityMode; import org.jivesoftware.smack.packet.Message; import org.jivesoftware.smackx.muc.MultiUserChat; import org.opennms.core.utils.ConfigFileConstants; import org.opennms.core.utils.ThreadCategory; /** * Singleton class used to send messages to an XMPP Server. Used by * XMPPNotificationStragetgy and XMPPGroupNotificationStrategy * * @author <a href="mailto:jonathan@opennms.org">Jonathan Sartin</a> * @author <a href="mailto:ranger@opennms.org">Benjamin Reed</a> * @author <a href="mailto:jonathan@opennms.org">Jonathan Sartin</a> * @author <a href="mailto:ranger@opennms.org">Benjamin Reed</a> * @version $Id: $ */ public class XMPPNotificationManager { private final Properties props = new Properties(); private static final String LOG4J_CATEGORY = "OpenNMS.Notifd"; private static final String XMPP_RESOURCE = "notifd"; private static final String TRUST_STORE_PASSWORD = "changeit"; private static final String XMPP_PORT = "5222"; private final XMPPConnection xmpp; private final ConnectionConfiguration xmppConfig; private final String xmppServer; private final String xmppServiceName; private final String xmppUser; private final String xmppPassword; private final int xmppPort; private final HashMap<String, MultiUserChat> rooms = new HashMap<String, MultiUserChat>(); private static XMPPNotificationManager instance = null; private ConnectionListener conlistener = new ConnectionListener() { public void connectionClosed() { log().debug("XMPP connection closed"); } public void connectionClosedOnError(Exception e) { log().warn("XMPP connection closed", e); } public void reconnectingIn(int seconds) { if (log().isDebugEnabled()) log().debug("XMPP reconnecting in " + seconds + " seconds"); } public void reconnectionFailed(Exception e) { log().warn("XMPP reconnection failed", e); xmpp.disconnect(); instance = null; } public void reconnectionSuccessful() { log().debug("XMPP reconnection succeeded"); } }; /** * <p>Constructor for XMPPNotificationManager.</p> */ protected XMPPNotificationManager() { // get the category logger String oldPrefix = ThreadCategory.getPrefix(); ThreadCategory.setPrefix(LOG4J_CATEGORY); try { // Load up some properties File config = null; try { config = ConfigFileConstants.getFile(ConfigFileConstants.XMPP_CONFIG_FILE_NAME); } catch (IOException e) { log().warn(ConfigFileConstants.XMPP_CONFIG_FILE_NAME + " not readable", e); } if (Boolean.getBoolean("useSystemXMPPConfig") || !config.canRead()) { this.props.putAll(System.getProperties()); } else { FileInputStream fis = null; try { fis = new FileInputStream(config); this.props.load(fis); } catch (FileNotFoundException e) { log().warn("unable to load " + config, e); } catch (IOException e) { log().warn("unable to load " + config, e); } finally { IOUtils.closeQuietly(fis); } } xmppServer = this.props.getProperty("xmpp.server"); xmppServiceName = this.props.getProperty("xmpp.servicename", xmppServer); xmppUser = this.props.getProperty("xmpp.user"); xmppPassword = this.props.getProperty("xmpp.pass"); xmppPort = Integer.valueOf(this.props.getProperty("xmpp.port", XMPP_PORT)); xmppConfig = new ConnectionConfiguration(xmppServer, xmppPort, xmppServiceName); boolean debuggerEnabled = Boolean.parseBoolean(props.getProperty("xmpp.debuggerEnabled")); xmppConfig.setDebuggerEnabled(debuggerEnabled); if (debuggerEnabled) { log().setLevel(ThreadCategory.Level.DEBUG); } xmppConfig.setSASLAuthenticationEnabled(Boolean.parseBoolean(props.getProperty("xmpp.SASLEnabled", "true"))); xmppConfig.setSelfSignedCertificateEnabled(Boolean.parseBoolean(props.getProperty("xmpp.selfSignedCertificateEnabled"))); if (Boolean.parseBoolean(props.getProperty("xmpp.TLSEnabled"))) { xmppConfig.setSecurityMode(SecurityMode.enabled); } else { xmppConfig.setSecurityMode(SecurityMode.disabled); } if (this.props.containsKey("xmpp.truststorePassword")) { xmppConfig.setTruststorePassword(this.props.getProperty("xmpp.truststorePassword")); } else { xmppConfig.setTruststorePassword(TRUST_STORE_PASSWORD); } if (log().isDebugEnabled()) { log().debug("XMPP Manager connection config: " + xmppConfig.toString()); } xmpp = new XMPPConnection(xmppConfig); // Connect to xmpp server connectToServer(); } finally { ThreadCategory.setPrefix(oldPrefix); } } private void connectToServer() { try { log().debug("Attempting vanilla XMPP Connection to " + xmppServer + ":" + xmppPort); xmpp.connect(); if (xmpp.isConnected()) { log().debug("XMPP Manager successfully connected"); // Following requires a later version of the library if (xmpp.isSecureConnection()) log().debug("XMPP Manager successfully nogotiated a secure connection"); if (xmpp.isUsingTLS()) log().debug("XMPP Manager successfully nogotiated a TLS connection"); log().debug("XMPP Manager Connected"); login(); // Add connection listener xmpp.addConnectionListener(conlistener); } else { log().debug("XMPP Manager Not Connected"); } } catch (Throwable e) { log().fatal("XMPP Manager unable to connect", e); } } /** * Check if manager is logged in to xmpp server. * * @return true if logged in, false otherwise */ private void login() { try { if (xmpp.isConnected()) { log().debug("XMPP Manager logging in"); xmpp.login(xmppUser, xmppPassword, XMPP_RESOURCE); rooms.clear(); } else { log().debug("XMPP Manager unable to login: Not connected to XMPP server"); } } catch (Throwable e) { log().fatal("XMPP Manager unable to login: ", e); } } /** * get an instance of the XMPPNotificationManager * * @return instance of XMPPNotificationManager */ public static synchronized XMPPNotificationManager getInstance() { if (instance == null) { instance = new XMPPNotificationManager(); } return instance; } /** * <p>isLoggedIn</p> * * @return a boolean. */ public boolean isLoggedIn() { return (xmpp.isAuthenticated()); } /** * send an xmpp message to a specified recipient. * * @param xmppTo * recipient of the xmpp message * @param xmppMessage * text to be sent in the body of the message * @return true if message is sent, false otherwise */ private static class NullMessageListener implements MessageListener { public void processMessage(Chat chat, Message message) { } } /** * <p>sendMessage</p> * * @param xmppTo a {@link java.lang.String} object. * @param xmppMessage a {@link java.lang.String} object. * @return a boolean. */ public boolean sendMessage(String xmppTo, String xmppMessage) { if (!isLoggedIn()) { connectToServer(); } try { ChatManager cm = xmpp.getChatManager(); cm.createChat(xmppTo, new NullMessageListener()).sendMessage(xmppMessage); log().debug("XMPP Manager sent message to: " + xmppTo); } catch (XMPPException e) { log().fatal("XMPP Exception Sending message ", e); return false; } return true; } /** * send an xmpp message to a specified Chat Room. * * @param xmppChatRoom * room to send message to. * @param xmppMessage * text to be sent in the body of the message * @return true if message is sent, false otherwise */ public boolean sendGroupChat(String xmppChatRoom, String xmppMessage) { MultiUserChat groupChat; if (rooms.containsKey(xmppChatRoom)) { groupChat = rooms.get(xmppChatRoom); } else { log().debug("Adding room: " + xmppChatRoom); groupChat = new MultiUserChat(xmpp, xmppChatRoom); rooms.put(xmppChatRoom, groupChat); } if (!groupChat.isJoined()) { log().debug("Joining room: " + xmppChatRoom); try { groupChat.join(xmppUser); } catch (XMPPException e) { log().fatal("XMPP Exception joining chat room ", e); return false; } } try { groupChat.sendMessage(xmppMessage); log().debug("XMPP Manager sent message to: " + xmppChatRoom); } catch (XMPPException e) { log().fatal("XMPP Exception sending message to Chat room", e); return false; } return true; } /** * <p>log</p> * * @return a {@link org.opennms.core.utils.ThreadCategory} object. */ protected ThreadCategory log() { return ThreadCategory.getInstance(this.getClass()); } }