Index: src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java =================================================================== --- src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java (revision 918) +++ src/test/java/quickfix/mina/acceptor/DynamicAcceptorSessionProviderTest.java (working copy) @@ -23,23 +23,15 @@ import java.util.ArrayList; import java.util.List; +import java.util.HashMap; import junit.framework.TestCase; import org.quickfixj.QFJException; -import quickfix.Application; -import quickfix.DefaultMessageFactory; -import quickfix.LogFactory; -import quickfix.MemoryStoreFactory; -import quickfix.MessageFactory; -import quickfix.MessageStoreFactory; -import quickfix.ScreenLogFactory; -import quickfix.Session; -import quickfix.SessionID; -import quickfix.SessionSettings; -import quickfix.UnitTestApplication; +import quickfix.*; import quickfix.mina.acceptor.DynamicAcceptorSessionProvider.TemplateMapping; +import quickfix.mina.SessionConnector; public class DynamicAcceptorSessionProviderTest extends TestCase { private DynamicAcceptorSessionProvider provider; @@ -79,7 +71,7 @@ public void testSessionCreation() throws Exception { Session session1 = provider.getSession(new SessionID("FIX.4.2", "SENDER", "SENDERSUB", - "SENDERLOC", "TARGET", "TARGETSUB", "TARGETLOC", null)); + "SENDERLOC", "TARGET", "TARGETSUB", "TARGETLOC", null), null); SessionID sessionID1 = session1.getSessionID(); assertEquals("wrong FIX version", "FIX.4.2", sessionID1.getBeginString()); assertEquals("wrong sender", "SENDER", sessionID1.getSenderCompID()); @@ -92,7 +84,7 @@ assertEquals("wrong setting", false, session1.getRefreshOnLogon()); assertEquals("wrong setting", false, session1.getCheckCompID()); - Session session2 = provider.getSession(new SessionID("FIX.4.4", "S1", "T")); + Session session2 = provider.getSession(new SessionID("FIX.4.4", "S1", "T"), null); SessionID sessionID2 = session2.getSessionID(); assertEquals("wrong FIX version", "FIX.4.4", sessionID2.getBeginString()); assertEquals("wrong sender", "S1", sessionID2.getSenderCompID()); @@ -101,7 +93,7 @@ assertEquals("wrong setting", false, session2.getRefreshOnLogon()); assertEquals("wrong setting", true, session2.getCheckCompID()); - Session session3 = provider.getSession(new SessionID("FIX.4.4", "X", "Y")); + Session session3 = provider.getSession(new SessionID("FIX.4.4", "X", "Y"), null); SessionID sessionID3 = session3.getSessionID(); assertEquals("wrong FIX version", "FIX.4.4", sessionID3.getBeginString()); assertEquals("wrong sender", "X", sessionID3.getSenderCompID()); @@ -120,7 +112,7 @@ public void testSessionTemplateNotFound() throws Exception { try { - provider.getSession(new SessionID("FIX.4.3", "S", "T")); + provider.getSession(new SessionID("FIX.4.3", "S", "T"), null); fail("No exception thrown"); } catch (QFJException e) { // Expected @@ -136,6 +128,41 @@ "ANY"), application, messageStoreFactory, logFactory, messageFactory); // Should actually throw an exception if it fails (see previous test) - assertNotNull(provider.getSession(new SessionID("FIX.4.2", "S", "T"))); + assertNotNull(provider.getSession(new SessionID("FIX.4.2", "S", "T"), null)); } + + /** Verify that if a new session comes in it gets added to the list in session connector */ + public void testDynamicSessionIsAddedToSessionConnector() throws Exception { + MySessionConnector connector = new MySessionConnector(settings, null); + + SessionID id1 = new SessionID("FIX.4.2", "me", "SENDERSUB", + "SENDERLOC", "you", "TARGETSUB", "TARGETLOC", null); + provider.getSession(id1, connector); + assertEquals(1, connector.sessions.size()); + // try again with same sesionID - should still be 1 + provider.getSession(id1, connector); + assertEquals(1, connector.sessions.size()); + + SessionID id2 = new SessionID("FIX.4.2", "SENDER2", "SENDERSUB", + "SENDERLOC", "TARGET2", "TARGETSUB", "TARGETLOC", null); + provider.getSession(id2, connector); + assertEquals(2, connector.sessions.size()); + } + private static class MySessionConnector extends SessionConnector { + private HashMap sessions = new HashMap(); + + public MySessionConnector(SessionSettings settings, SessionFactory sessionFactory) throws ConfigError { + super(settings, sessionFactory); + } + + @Override + public void addDynamicSession(Session inSession) { + sessions.put(inSession.getSessionID(), inSession); + } + + @Override + public void removeDynamicSession(SessionID inSessionID) { + sessions.remove(inSessionID); + } + } } Index: src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java =================================================================== --- src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java (revision 918) +++ src/test/java/quickfix/mina/ThreadPerSessionEventHandlingStrategyTest.java (working copy) @@ -127,6 +127,12 @@ strategy.getDispatcher(sessionID).run(); } + // verify the assumption that this always returns null + public void testVerifyGetConnectorAssumption() throws Exception { + ThreadPerSessionEventHandlingStrategyUnderTest strategy = new ThreadPerSessionEventHandlingStrategyUnderTest(); + assertNull(strategy.getSessionConnector()); + } + private Session setUpSession(SessionID sessionID) throws ConfigError { DefaultSessionFactory sessionFactory = new DefaultSessionFactory(new UnitTestApplication(), new MemoryStoreFactory(), new ScreenLogFactory(true, true, true)); Index: src/test/java/quickfix/mina/SessionConnectorTest.java =================================================================== --- src/test/java/quickfix/mina/SessionConnectorTest.java (revision 918) +++ src/test/java/quickfix/mina/SessionConnectorTest.java (working copy) @@ -22,6 +22,7 @@ import java.lang.reflect.Field; import java.util.Collections; import java.util.Map; +import java.util.HashMap; import junit.framework.TestCase; import quickfix.Acceptor; @@ -74,6 +75,46 @@ assertEquals(settings, connector.getSettings()); } + /** Test that adding/removing dynamic sessions works correctly */ + public void testAddingRemovingDymaicSessions() throws Exception { + SessionID sessionID = new SessionID(FixVersions.BEGINSTRING_FIX40, "TW", "ISLD"); + SessionID sessionID2 = new SessionID(FixVersions.BEGINSTRING_FIX40, "me", "you"); + SessionSettings settings = setUpSessionSettings(sessionID); + DefaultSessionFactory sessionFactory = new DefaultSessionFactory(new UnitTestApplication(), + new MemoryStoreFactory(), new ScreenLogFactory(true, true, true)); + + SessionConnector connector = new SessionConnectorUnderTest(settings, sessionFactory); + connector.setSessions(new HashMap()); + Session session = connector.createSession(sessionID); + + // one-time use connector to create a slightly different session + SessionSettings settings2 = setUpSessionSettings(sessionID2); + SessionConnector connector2 = new SessionConnectorUnderTest(settings2, sessionFactory); + connector.setSessions(new HashMap()); + Session session2 = connector2.createSession(sessionID2); + assertNotNull(session); + assertNotNull(session2); + + assertEquals(0, connector.getManagedSessions().size()); + connector.addDynamicSession(session); + assertEquals(1, connector.getManagedSessions().size()); + connector.addDynamicSession(session2); + assertEquals(2, connector.getManagedSessions().size()); + // the list can be in arbitrary order so let's make sure that we get both + HashMap map = new HashMap(); + for (Session s : connector.getManagedSessions()) { + map.put(s.getSessionID(), s); + } + assertEquals(session, map.get(session.getSessionID())); + assertEquals(session2, map.get(session2.getSessionID())); + + connector.removeDynamicSession(session.getSessionID()); + assertEquals(1, connector.getManagedSessions().size()); + assertEquals(session2, connector.getManagedSessions().get(0)); + connector.removeDynamicSession(session2.getSessionID()); + assertEquals(0, connector.getManagedSessions().size()); + } + private SessionSettings setUpSessionSettings(SessionID sessionID) { SessionSettings settings = new SessionSettings(); settings.setString(Session.SETTING_USE_DATA_DICTIONARY, "N"); Index: src/main/java/quickfix/mina/EventHandlingStrategy.java =================================================================== --- src/main/java/quickfix/mina/EventHandlingStrategy.java (revision 918) +++ src/main/java/quickfix/mina/EventHandlingStrategy.java (working copy) @@ -28,4 +28,7 @@ */ public interface EventHandlingStrategy { void onMessage(Session quickfixSession, Message message); + + /** Get the session connector associated with this strategy */ + SessionConnector getSessionConnector(); } Index: src/main/java/quickfix/mina/ThreadPerSessionEventHandlingStrategy.java =================================================================== --- src/main/java/quickfix/mina/ThreadPerSessionEventHandlingStrategy.java (revision 918) +++ src/main/java/quickfix/mina/ThreadPerSessionEventHandlingStrategy.java (working copy) @@ -47,6 +47,13 @@ dispatcher.enqueue(message); } + /** There is no such thing as a SesionConnector for thread-per-session handler - we don't multiplex + * between multiple sessions here so this is null + */ + public SessionConnector getSessionConnector() { + return null; + } + protected void startDispatcherThread(MessageDispatchingThread dispatcher) { dispatcher.start(); } Index: src/main/java/quickfix/mina/SingleThreadedEventHandlingStrategy.java =================================================================== --- src/main/java/quickfix/mina/SingleThreadedEventHandlingStrategy.java (revision 918) +++ src/main/java/quickfix/mina/SingleThreadedEventHandlingStrategy.java (working copy) @@ -50,6 +50,10 @@ } } + public SessionConnector getSessionConnector() { + return sessionConnector; + } + public void block() { while (true) { synchronized (this) { Index: src/main/java/quickfix/mina/acceptor/AcceptorSessionProvider.java =================================================================== --- src/main/java/quickfix/mina/acceptor/AcceptorSessionProvider.java (revision 918) +++ src/main/java/quickfix/mina/acceptor/AcceptorSessionProvider.java (working copy) @@ -21,6 +21,7 @@ import quickfix.Session; import quickfix.SessionID; +import quickfix.mina.SessionConnector; /** * Provides sessions to be served on an acceptor. This supports the @@ -35,5 +36,5 @@ * @return the associated session or null if no session can be * associated with the given ID. */ - Session getSession(SessionID sessionID); + Session getSession(SessionID sessionID, SessionConnector connector); } Index: src/main/java/quickfix/mina/acceptor/DynamicAcceptorSessionProvider.java =================================================================== --- src/main/java/quickfix/mina/acceptor/DynamicAcceptorSessionProvider.java (revision 918) +++ src/main/java/quickfix/mina/acceptor/DynamicAcceptorSessionProvider.java (working copy) @@ -38,6 +38,7 @@ import quickfix.SessionFactory; import quickfix.SessionID; import quickfix.SessionSettings; +import quickfix.mina.SessionConnector; /** * Dynamically defines sessions for an acceptor. This can be useful for @@ -49,7 +50,7 @@ */ public class DynamicAcceptorSessionProvider implements AcceptorSessionProvider { public static final String WILDCARD = "*"; - private static final SessionID ANY_SESSION = new SessionID(WILDCARD, WILDCARD, WILDCARD, + public static final SessionID ANY_SESSION = new SessionID(WILDCARD, WILDCARD, WILDCARD, WILDCARD, WILDCARD, WILDCARD, WILDCARD, null); private final List templateMappings; @@ -128,7 +129,7 @@ messageFactory); } - public synchronized Session getSession(SessionID sessionID) { + public synchronized Session getSession(SessionID sessionID, SessionConnector sessionConnector) { Session s = Session.lookupSession(sessionID); if (s == null) { try { @@ -147,6 +148,9 @@ optionallySetValue(dynamicSettings, TARGETSUBID, sessionID.getTargetSubID()); optionallySetValue(dynamicSettings, TARGETLOCID, sessionID.getTargetLocationID()); s = sessionFactory.create(sessionID, dynamicSettings); + if(sessionConnector != null) { + sessionConnector.addDynamicSession(s); + } } catch (ConfigError e) { throw new QFJException(e); } Index: src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java =================================================================== --- src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java (revision 918) +++ src/main/java/quickfix/mina/acceptor/AcceptorIoHandler.java (working copy) @@ -56,7 +56,7 @@ if (qfSession == null) { if (message.getHeader().getString(MsgType.FIELD).equals(MsgType.LOGON)) { SessionID sessionID = MessageUtils.getReverseSessionID(message); - qfSession = sessionProvider.getSession(sessionID); + qfSession = sessionProvider.getSession(sessionID, eventHandlingStrategy.getSessionConnector()); if (qfSession != null) { Log sessionLog = qfSession.getLog(); if (qfSession.hasResponder()) { @@ -101,7 +101,7 @@ protected Session findQFSession(IoSession protocolSession, SessionID sessionID) { Session s = super.findQFSession(protocolSession, sessionID); if (s == null) { - s = sessionProvider.getSession(sessionID); + s = sessionProvider.getSession(sessionID, eventHandlingStrategy.getSessionConnector()); } return s; } Index: src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java =================================================================== --- src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java (revision 918) +++ src/main/java/quickfix/mina/acceptor/AbstractSocketAcceptor.java (working copy) @@ -341,7 +341,7 @@ this.acceptorSessions = acceptorSessions; } - public Session getSession(SessionID sessionID) { + public Session getSession(SessionID sessionID, SessionConnector connector) { return acceptorSessions.get(sessionID); } } Index: src/main/java/quickfix/mina/SessionConnector.java =================================================================== --- src/main/java/quickfix/mina/SessionConnector.java (revision 918) +++ src/main/java/quickfix/mina/SessionConnector.java (working copy) @@ -106,6 +106,16 @@ return new ArrayList(sessions.keySet()); } + public void addDynamicSession(Session inSession) { + sessions.put(inSession.getSessionID(), inSession); + log.debug("adding session for "+inSession.getSessionID()); + } + + public void removeDynamicSession(SessionID inSessionID) { + sessions.remove(inSessionID); + log.debug("removing session for "+inSessionID); + } + public SessionSettings getSettings() { return settings; }