/******************************************************************************* * Copyright (c) quickfixj.org All rights reserved. * * This file is part of the QuickFIX/J FIX Engine * * This file may be distributed under the terms of the quickfixj.org * license as defined by quickfixj.org and appearing in the file * LICENSE included in the packaging of this file. * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING * THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE. * * See http://www.quickfixj.org/LICENSE for licensing information. * ******************************************************************************/ package org.quickfixj.jmx.mbean.session; import org.quickfixj.QFJException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import quickfix.Message; import quickfix.Session; import quickfix.SessionID; import quickfix.SessionNotFound; import quickfix.SessionStateListener; import quickfix.field.MsgType; import quickfix.field.NewSeqNo; import quickfix.field.converter.UtcTimestampConverter; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.ObjectName; import java.io.IOException; import java.util.ArrayList; public class SessionAdmin extends NotificationBroadcasterSupport implements SessionAdminMBean, MBeanRegistration, SessionStateListener { private static final String NOTIFICATION_TYPE = "quickfix.Session"; private final Session session; private final Logger log = LoggerFactory.getLogger(getClass()); private final ObjectName connectorName; private MBeanServer mbeanServer; private final ObjectName settingsName; public SessionAdmin(Session session, ObjectName connnectorName, ObjectName settingsName) { this.session = session; this.connectorName = connnectorName; this.settingsName = settingsName; } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getID() */ public String getID() { return session.getSessionID().toString(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getTargetCompID() */ public String getTargetCompID() { return session.getSessionID().getTargetCompID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getTargetSubID() */ public String getTargetSubID() { return session.getSessionID().getTargetSubID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getTargetLocationID() */ public String getTargetLocationID() { return session.getSessionID().getTargetLocationID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getSenderCompID() */ public String getSenderCompID() { return session.getSessionID().getSenderCompID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getSenderSubID() */ public String getSenderSubID() { return session.getSessionID().getSenderSubID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getSenderLocationID() */ public String getSenderLocationID() { return session.getSessionID().getSenderLocationID(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getBeginString() */ public String getBeginString() { return session.getSessionID().getBeginString(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#isLoggedOn() */ public boolean isLoggedOn() { return session.isLoggedOn(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getRemoteIPAddress() */ public String getRemoteIPAddress() { if (session.getResponder() != null) { return session.getResponder().getRemoteIPAddress(); } else { return ""; } } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#reset() */ public void reset() throws IOException { logInvocation("reset"); session.reset(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getNextSenderMsgSeqNum() */ public int getNextSenderMsgSeqNum() throws IOException { return session.getExpectedSenderNum(); } /* (non-Javadoc) * @see quickfix.jmx.QFJSessionMBean#setNextSenderMsgSeqNum(int) */ public void setNextSenderMsgSeqNum(int next) throws IOException { logAttributeChange("NextSenderMsgSeqNum", next); session.setNextSenderMsgSeqNum(next); } /* (non-Javadoc) * @see quickfix.jmx.QFJSessionMBean#setNextTargetMsgSeqNum(int) */ public void setNextTargetMsgSeqNum(int next) throws IOException { logAttributeChange("NextTargetMsgSeqNum", next); session.setNextTargetMsgSeqNum(next); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getNextTargetMsgSeqNum() */ public int getNextTargetMsgSeqNum() throws IOException { return session.getExpectedTargetNum(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getMessages(int, int) */ public String[] getMessages(int startSequence, int endSequence) throws IOException { ArrayList<String> messages = new ArrayList<String>(); session.getStore().get(startSequence, endSequence, messages); return messages.toArray(new String[messages.size()]); } /* (non-Javadoc) * @see quickfix.jmx.QFJSessionMBean#disconnect() */ public void disconnect() throws IOException { logInvocation("disconnect"); session.disconnect("JMX admin", false); } public void resetSequence(int nextSeqNum) throws SessionNotFound { logInvocation("resetSequence to: "+nextSeqNum); Message sequenceReset = new Message(); sequenceReset.getHeader().setField(new MsgType(MsgType.SEQUENCE_RESET)); sequenceReset.setField(new NewSeqNo(nextSeqNum)); doSend(sequenceReset, session.getSessionID()); } /** Helper method to be overridden by tests that handles sending out the message */ protected void doSend(Message message, SessionID sessionID) throws SessionNotFound { session.getContext().sendToTarget(message, sessionID); } /* (non-Javadoc) * @see quickfix.jmx.QFJSessionMBean#logon() */ public void logon() { logInvocation("logon"); session.logon(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#logoff() */ public void logoff() { logInvocation("logout"); session.logout(); } /* (non-Javadoc) * @see quickfix.jmx.QFJSessionMBean#isReconnectEnabled() */ public boolean isReconnectEnabled() { return session.isEnabled(); } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getHost() */ public String getHost() { try { return java.net.InetAddress.getLocalHost().getHostName(); } catch (java.net.UnknownHostException uhe) { log.error(uhe.getMessage(), uhe); return "N/A"; } } /* (non-Javadoc) * @see quickfix.jmx.SessionMBean#getProcessID() */ public String getProcessID() { return System.getProperty("java.pid"); } public ObjectName getConnectorName() { return connectorName; } public boolean getCheckCompID() { return session.getCheckCompID(); } public String getLogClassName() { return session.getLog().getClass().getName(); } public int getLogonTimeout() { return session.getLogonTimeout(); } public int getLogoutTimeout() { return session.getLogoutTimeout(); } public String getMessageFactoryClassName() { return session.getMessageFactory().getClass().getName(); } public String getMessageStoreClassName() { return session.getStore().getClass().getName(); } public boolean getRedundantResendRequestsAllowed() { return session.getRedundantResentRequestsAllowed(); } public boolean getRefreshOnLogon() { return session.getRefreshOnLogon(); } public boolean getResetOnDisconnect() { return session.getResetOnDisconnect(); } public boolean getResetOnLogout() { return session.getResetOnLogout(); } public boolean isLogonAlreadySent() { return session.isLogonAlreadySent(); } public boolean isLogonReceived() { return session.isLogonReceived(); } public boolean isLogonSendNeeded() { return session.isLogonSendNeeded(); } public boolean isLogonSent() { return session.isLogonSent(); } public boolean isLogonTimedOut() { return session.isLogonTimedOut(); } public boolean isLogoutReceived() { return session.isLogoutReceived(); } public boolean isLogoutSent() { return session.isLogoutSent(); } public boolean isLogoutTimedOut() { return session.isLogoutTimedOut(); } public void setLogonTimeout(int seconds) { logAttributeChange("LogonTimeout", seconds); session.setLogonTimeout(seconds); } public void setLogoutTimeout(int seconds) { logAttributeChange("LogoutTimeout", seconds); session.setLogoutTimeout(seconds); } public boolean isUsingDataDictionary() { return session.isUsingDataDictionary(); } public String getSessionID() { return session.getSessionID().toString(); } public boolean getEnabled() { return session.isEnabled(); } public String getStartTime() { try { return UtcTimestampConverter.convert(session.getStartTime(), true); } catch (IOException e) { return "[ERROR]"; } } public String getConnectionRole() { try { return mbeanServer.getAttribute(connectorName, "Role").toString(); } catch (Exception e) { return "[ERROR: " + e.getMessage() + "]"; } } private void logAttributeChange(String attributeName, int value) { session.getLog().onEvent("JMX: setting " + attributeName + " to " + value); } private void logInvocation(String operation) { session.getLog().onEvent("JMX: "+operation+" invoked"); } public void postDeregister() { try { mbeanServer.unregisterMBean(settingsName); } catch (RuntimeException e) { throw e; } catch (Exception e) { throw new QFJException("Connector MBean postregistration failed", e); } } public void postRegister(Boolean registrationDone) { } public void preDeregister() throws Exception { } public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { mbeanServer = server; return name; } // // Session State Notifications // public void onConnect() { sendNotification("connect"); } public void onDisconnect() { sendNotification("disconnect"); } public void onLogon() { sendNotification("logon"); } public void onLogout() { sendNotification("logout"); } public void onHeartBeatTimeout() { sendNotification("heartBeatTimeout"); } public void onMissedHeartBeat() { sendNotification("missedHeartBeat"); } public void onRefresh() { sendNotification("refresh"); } public void onReset() { sendNotification("reset"); } private void sendNotification(String eventName) { Notification notification = new Notification(NOTIFICATION_TYPE, this, -1, System.currentTimeMillis(), eventName); sendNotification(notification); } public void sendTestRequest() { session.generateTestRequest(System.currentTimeMillis()+""); } public void sendHeartBeat() { session.generateHeartbeat(); } public void sendLogoutMessage() { session.generateLogout(); } }