/**
*
*/
package vnet.sms.gateway.server.framework.internal.jmsbridge;
import static org.apache.commons.lang.Validate.notNull;
import java.util.concurrent.TimeUnit;
import javax.jms.DeliveryMode;
import javax.jms.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jms.JmsException;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jmx.export.annotation.ManagedAttribute;
import org.springframework.jmx.export.annotation.ManagedResource;
import vnet.sms.common.messages.GsmPdu;
import vnet.sms.common.wme.WindowedMessageEvent;
import vnet.sms.common.wme.receive.ReceivedLoginRequestAcknowledgementEvent;
import vnet.sms.common.wme.receive.ReceivedLoginRequestEvent;
import vnet.sms.common.wme.receive.ReceivedPingRequestAcknowledgementEvent;
import vnet.sms.common.wme.receive.ReceivedPingRequestEvent;
import vnet.sms.common.wme.receive.ReceivedSmsEvent;
import vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener;
import vnet.sms.gateway.server.framework.Jmx;
import com.yammer.metrics.Metrics;
import com.yammer.metrics.core.Histogram;
import com.yammer.metrics.core.Meter;
import com.yammer.metrics.core.MetricName;
import com.yammer.metrics.core.Timer;
/**
* @author obergner
*
*/
@ManagedResource(objectName = IncomingMessagesForwardingJmsBridge.OBJECT_NAME)
public class IncomingMessagesForwardingJmsBridge<ID extends java.io.Serializable>
implements IncomingMessagesListener<ID> {
private static final String TYPE = "JMSBridge";
private static final String NAME = "DEFAULT";
static final String OBJECT_NAME = Jmx.GROUP
+ ":type="
+ TYPE
+ ",name="
+ NAME;
private final Logger log = LoggerFactory
.getLogger(getClass());
private final Meter numberOfForwardedSms = Metrics
.newMeter(
new MetricName(
Jmx.GROUP,
TYPE,
"number-of-forwarded-sms"),
"sms-forwarded",
TimeUnit.SECONDS);
private final Meter numberOfForwardedLoginRequests = Metrics
.newMeter(
new MetricName(
Jmx.GROUP,
TYPE,
"number-of-forwarded-login-requests"),
"login-request-forwarded",
TimeUnit.SECONDS);
private final Meter numberOfForwardedLoginResponses = Metrics
.newMeter(
new MetricName(
Jmx.GROUP,
TYPE,
"number-of-forwarded-login-responses"),
"login-response-forwarded",
TimeUnit.SECONDS);
private final Histogram forwardedMessages = Metrics
.newHistogram(new MetricName(
Jmx.GROUP,
TYPE,
"forwarded-messages-distribution"));
private final Timer sendDuration = Metrics
.newTimer(
new MetricName(
Jmx.GROUP,
TYPE,
"message-send-duration"),
TimeUnit.MILLISECONDS,
TimeUnit.SECONDS);
private final JmsTemplate jmsTemplate;
// ------------------------------------------------------------------------
// Constructors
// ------------------------------------------------------------------------
/**
* @param jmsTemplate
*/
public IncomingMessagesForwardingJmsBridge(final JmsTemplate jmsTemplate) {
notNull(jmsTemplate, "Argument 'jmsTemplate' must not be null");
this.jmsTemplate = jmsTemplate;
}
// ------------------------------------------------------------------------
// IncomingMessagesListener
// ------------------------------------------------------------------------
/**
* @see vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener#smsReceived(vnet.sms.common.wme.receive.ReceivedSmsEvent)
*/
@Override
public void smsReceived(final ReceivedSmsEvent<ID> smsReceived) {
doForward(smsReceived);
this.numberOfForwardedSms.mark();
}
private void doForward(
final WindowedMessageEvent<ID, ? extends GsmPdu> windowedMessageEvent)
throws JmsException {
this.log.debug("Forwarding {} to [{}] ...", windowedMessageEvent,
this.jmsTemplate.getDefaultDestinationName());
final long before = System.currentTimeMillis();
this.jmsTemplate.convertAndSend(windowedMessageEvent);
this.sendDuration.update(System.currentTimeMillis() - before,
TimeUnit.MILLISECONDS);
this.forwardedMessages.update(1);
this.log.debug("Forwarded {} to [{}]", windowedMessageEvent,
this.jmsTemplate.getDefaultDestinationName());
}
/**
* @see vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener#loginRequestReceived(vnet.sms.common.wme.receive.ReceivedLoginRequestEvent)
*/
@Override
public void loginRequestReceived(
final ReceivedLoginRequestEvent<ID> loginRequestReceived) {
doForward(loginRequestReceived);
this.numberOfForwardedLoginRequests.mark();
}
/**
* @see vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener#loginResponseReceived(vnet.sms.common.wme.receive.ReceivedLoginRequestAcknowledgementEvent)
*/
@Override
public void loginResponseReceived(
final ReceivedLoginRequestAcknowledgementEvent<ID> loginResponseReceived) {
doForward(loginResponseReceived);
this.numberOfForwardedLoginResponses.mark();
}
/**
* @see vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener#pingRequestReceived(vnet.sms.common.wme.receive.ReceivedPingRequestEvent)
*/
@Override
public void pingRequestReceived(
final ReceivedPingRequestEvent<ID> pingRequestReceived) {
// Ignore
}
/**
* @see vnet.sms.gateway.nettysupport.publish.incoming.IncomingMessagesListener#pingResponseReceived(vnet.sms.common.wme.receive.ReceivedPingRequestAcknowledgementEvent)
*/
@Override
public void pingResponseReceived(
final ReceivedPingRequestAcknowledgementEvent<ID> pingResponseReceived) {
// Ignore
}
// ------------------------------------------------------------------------
// JMX API
// ------------------------------------------------------------------------
@ManagedAttribute(description = "The name of the JMS queue this JMS bridge will forward messages to by default")
public String getDefaultDestination() {
return this.jmsTemplate.getDefaultDestinationName();
}
@ManagedAttribute(description = "If this bridge uses the configured settings for delivery mode, "
+ "message priority and time-to-live, or if these are set administratively")
public boolean isExplicitQosEnabled() {
return this.jmsTemplate.isExplicitQosEnabled();
}
@ManagedAttribute(description = "The delivery mode to use for each forwarded message")
public String getDeliveryMode() {
final int deliveryMode = this.jmsTemplate.getDeliveryMode();
final String deliveryModeString;
switch (deliveryMode) {
case DeliveryMode.PERSISTENT:
deliveryModeString = "PERSISTENT";
break;
case DeliveryMode.NON_PERSISTENT:
deliveryModeString = "NON_PERSISTENT";
break;
default:
deliveryModeString = "ERROR:UNKNOWN";
}
return deliveryModeString;
}
@ManagedAttribute(description = "The priority this bridge uses for each message when forwarding it")
public int getMessagePriority() {
return this.jmsTemplate.getPriority();
}
@ManagedAttribute(description = "The time-to-live in milliseconds of each message sent")
public long getTimeToLive() {
return this.jmsTemplate.getTimeToLive();
}
@ManagedAttribute(description = "Are we forwarding messages transactionally?")
public boolean isSessionTransacted() {
return this.jmsTemplate.isSessionTransacted();
}
@ManagedAttribute(description = "The acknowledgement mode used when forwarding messages via JMS")
public String getSessionAcknowledgeMode() {
final int ackMode = this.jmsTemplate.getSessionAcknowledgeMode();
final String ackModeString;
switch (ackMode) {
case Session.AUTO_ACKNOWLEDGE:
ackModeString = "AUTO_ACKNOWLEDGE";
break;
case Session.CLIENT_ACKNOWLEDGE:
ackModeString = "CLIENT_ACKNOWLEDGE";
break;
case Session.DUPS_OK_ACKNOWLEDGE:
ackModeString = "DUPS_OK_ACKNOWLEDGE";
break;
case Session.SESSION_TRANSACTED:
ackModeString = "SESSION_TRANSACTED";
break;
default:
ackModeString = "ERROR:UNKNOWN";
}
return ackModeString;
}
@ManagedAttribute(description = "The time span in milliseconds after which this bridge will consider a receive failed")
public long getReceiveTimeoutMillis() {
return this.jmsTemplate.getReceiveTimeout();
}
}