/*******************************************************************************
* This file is part of OpenNMS(R).
*
* Copyright (C) 2009-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.sms.ping.internal;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.log4j.Logger;
import org.opennms.core.utils.LogUtils;
import org.opennms.sms.reflector.smsservice.OnmsInboundMessageNotification;
import org.smslib.AGateway;
import org.smslib.GatewayException;
import org.smslib.InboundBinaryMessage;
import org.smslib.InboundMessage;
import org.smslib.OutboundMessage;
import org.smslib.TimeoutException;
import org.smslib.Message.MessageTypes;
/**
* SmsMessenger
*
* @author brozow
* @version $Id: $
*/
public class SmsPonger implements OnmsInboundMessageNotification {
Logger log = Logger.getLogger(getClass());
Map<String,String> s_tokenResponses = buildTokenResponses();
/** {@inheritDoc} */
public void process(AGateway gateway, MessageTypes msgType, InboundMessage msg) {
debugf("SmsPonger.processInboundMessage");
if (isPingRequest(msg)) {
debugf("Message is a ping request: %s", msg.getText());
sendPong(gateway, msg);
}
}
private boolean isPingRequest(InboundMessage msg) {
return (!(msg instanceof InboundBinaryMessage))
&& msg.getText() != null &&
(isPseudoPingRequest(msg)
|| isCanonicalPingRequest(msg));
}
private boolean isCanonicalPingRequest(InboundMessage msg) {
return (!(msg instanceof InboundBinaryMessage))
&& msg.getText() != null
&& msg.getText().length() >= 4
&& "ping".equalsIgnoreCase(msg.getText().substring(0, 4));
}
private boolean isPseudoPingRequest(InboundMessage msg) {
if (s_tokenResponses.size() == 0) {
debugf("No token responses found, not processing pseudo-pings");
return false;
}
if (msg instanceof InboundBinaryMessage || msg.getText() == null)
return false;
for (String token : s_tokenResponses.keySet()) {
if (msg.getText().matches(token))
return true;
}
return false;
}
private void sendPong(AGateway gateway, InboundMessage msg) {
String pongResponse = (isCanonicalPingRequest(msg)) ? "pong" : getPseudoPongResponse(msg);
debugf("SmsPonger.sendPong: sending string '%s'", pongResponse);
try {
OutboundMessage pong = new OutboundMessage(msg.getOriginator(), pongResponse);
pong.setGatewayId(gateway.getGatewayId());
if (!gateway.sendMessage(pong)) {
errorf("Failed to send pong request to %s", msg.getOriginator());
}
} catch (TimeoutException e) {
errorf(e, "Timeout sending pong request to %s", msg.getOriginator());
} catch (GatewayException e) {
errorf(e, "Gateway exception sending pong request to %s", msg.getOriginator());
} catch (IOException e) {
errorf(e, "IOException sending pong request to %s", msg.getOriginator());
} catch (InterruptedException e) {
errorf(e, "InterruptedException sending poing request to %s", msg.getOriginator());
}
}
private String getPseudoPongResponse(InboundMessage msg) {
for (Entry<String, String> tuple : s_tokenResponses.entrySet()) {
if (msg.getText().matches(tuple.getKey())) {
return tuple.getValue();
}
}
debugf("No pseudo-ping response found, defaulting to 'pong' (this should not happen)");
return "";
}
private static Map<String,String> buildTokenResponses() {
// Use a LinkedHashMap to preserve ordering
Map<String,String> tokenResponses = new LinkedHashMap<String,String>();
String pseudoPingTokensPsv = System.getProperty("sms.ping.tokens", "");
String pseudoPingResponsesPsv = System.getProperty("sms.ping.responses", "");
String[] tokens = pseudoPingTokensPsv.split(";");
String[] responses = pseudoPingResponsesPsv.split(";");
if (tokens.length == 0) {
LogUtils.debugf(SmsPonger.class, "No pseudo-ping tokens defined");
return tokenResponses;
}
if (tokens.length != responses.length) {
LogUtils.errorf(SmsPonger.class, "Length of sms.ping.tokens (%d) is mismatched with length of sms.ping.responses (%d)", tokens.length, responses.length);
return tokenResponses;
}
for (int i = 0; i < tokens.length; i++) {
tokenResponses.put(tokens[i], responses[i]);
LogUtils.debugf(SmsPonger.class, "Setting response '%s' for pseudo-ping token '%s'", responses[i], tokens[i]);
}
return tokenResponses;
}
private void debugf(String fmt, Object... args) {
if (log.isDebugEnabled()) {
log.debug(String.format(fmt, args));
}
}
private void errorf(Throwable t, String fmt, Object... args) {
log.error(String.format(fmt, args), t);
}
private void errorf(String fmt, Object... args) {
log.error(String.format(fmt, args));
}
}