Index  Source Files  Annotated Class List  Alphabetical Class List  Class Hierarchy  Graphical Class Hierarchy 

SessionFactory.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) quickfixengine.org  All rights reserved.
00003 **
00004 ** This file is part of the QuickFIX FIX Engine
00005 **
00006 ** This file may be distributed under the terms of the quickfixengine.org
00007 ** license as defined by quickfixengine.org and appearing in the file
00008 ** LICENSE included in the packaging of this file.
00009 **
00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
00012 **
00013 ** See http://www.quickfixengine.org/LICENSE for licensing information.
00014 **
00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are
00016 ** not clear to you.
00017 **
00018 ****************************************************************************/
00019 
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026 
00027 #include "Utility.h"
00028 #include "Values.h"
00029 #include "DataDictionaryProvider.h"
00030 #include "SessionFactory.h"
00031 #include "SessionSettings.h"
00032 #include "Session.h"
00033 
00034 namespace FIX
00035 {
00036 SessionFactory::~SessionFactory()
00037 { QF_STACK_IGNORE_BEGIN
00038   Dictionaries::iterator i = m_dictionaries.begin();
00039   for ( ; i != m_dictionaries.end(); ++i )
00040     delete i->second;
00041   QF_STACK_IGNORE_END
00042 }
00043 
00044 Session* SessionFactory::create( const SessionID& sessionID,
00045                                  const Dictionary& settings ) throw( ConfigError )
00046 { QF_STACK_PUSH(SessionFactory::create)
00047 
00048   std::string connectionType = settings.getString( CONNECTION_TYPE );
00049   if ( connectionType != "acceptor" && connectionType != "initiator" )
00050     throw ConfigError( "Invalid ConnectionType" );
00051 
00052   if( connectionType == "acceptor" && settings.has(SESSION_QUALIFIER) )
00053     throw ConfigError( "SessionQualifier cannot be used with acceptor." );
00054 
00055   bool useDataDictionary = true;
00056   if ( settings.has( USE_DATA_DICTIONARY ) )
00057     useDataDictionary = settings.getBool( USE_DATA_DICTIONARY );
00058 
00059   std::string defaultApplVerID;
00060   if( sessionID.isFIXT() )
00061   {
00062     if( !settings.has(DEFAULT_APPLVERID) )
00063     {
00064       throw ConfigError("ApplVerID is required for FIXT transport");
00065     }
00066     defaultApplVerID = Message::toApplVerID( settings.getString(DEFAULT_APPLVERID) );
00067   }
00068 
00069   DataDictionaryProvider dataDictionaryProvider;
00070   if( useDataDictionary )
00071   {
00072     if( sessionID.isFIXT() )
00073     {
00074       processFixtDataDictionaries(sessionID, settings, dataDictionaryProvider);
00075     }
00076     else
00077     {
00078       processFixDataDictionary(sessionID, settings, dataDictionaryProvider);
00079     }
00080   }
00081 
00082   bool useLocalTime = false;
00083   if( settings.has(USE_LOCAL_TIME) )
00084     useLocalTime = settings.getBool( USE_LOCAL_TIME );
00085 
00086   int startDay = -1;
00087   int endDay = -1;
00088   try
00089   {
00090     startDay = settings.getDay( START_DAY );
00091     endDay = settings.getDay( END_DAY );
00092   }
00093   catch( ConfigError & ) {}
00094   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00095 
00096   UtcTimeOnly startTime;
00097   UtcTimeOnly endTime;
00098   try
00099   {
00100     startTime = UtcTimeOnlyConvertor::convert
00101                 ( settings.getString( START_TIME ) );
00102     endTime = UtcTimeOnlyConvertor::convert
00103               ( settings.getString( END_TIME ) );
00104   }
00105   catch ( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00106 
00107   TimeRange utcSessionTime
00108     ( startTime, endTime, startDay, endDay );
00109   TimeRange localSessionTime
00110     ( LocalTimeOnly(startTime.getHour(), startTime.getMinute(), startTime.getSecond()),
00111       LocalTimeOnly(endTime.getHour(), endTime.getMinute(), endTime.getSecond()),
00112       startDay, endDay );
00113   TimeRange sessionTimeRange = useLocalTime ? localSessionTime : utcSessionTime;
00114 
00115   if( startDay >= 0 && endDay < 0 )
00116     throw ConfigError( "StartDay used without EndDay" );
00117   if( endDay >= 0 && startDay < 0 )
00118     throw ConfigError( "EndDay used without StartDay" );
00119 
00120   HeartBtInt heartBtInt( 0 );
00121   if ( connectionType == "initiator" )
00122   {
00123     heartBtInt = HeartBtInt( settings.getLong( HEARTBTINT ) );
00124     if ( heartBtInt <= 0 ) throw ConfigError( "Heartbeat must be greater than zero" );
00125   }
00126 
00127   Session* pSession = 0;
00128   pSession = new Session( m_application, m_messageStoreFactory,
00129                           sessionID, dataDictionaryProvider, sessionTimeRange,
00130                           heartBtInt, m_pLogFactory );
00131 
00132   pSession->setSenderDefaultApplVerID(defaultApplVerID);
00133 
00134   int logonDay = startDay;
00135   int logoutDay = endDay;
00136   try
00137   {
00138     logonDay = settings.getDay( LOGON_DAY );
00139     logoutDay = settings.getDay( LOGOUT_DAY );
00140   }
00141   catch( ConfigError & ) {}
00142   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00143 
00144   UtcTimeOnly logonTime( startTime );
00145   UtcTimeOnly logoutTime( endTime );
00146   try
00147   {
00148     logonTime = UtcTimeOnlyConvertor::convert
00149                 ( settings.getString( LOGON_TIME ) );
00150   }
00151   catch( ConfigError & ) {}
00152   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00153   try
00154   {
00155     logoutTime = UtcTimeOnlyConvertor::convert
00156               ( settings.getString( LOGOUT_TIME ) );
00157   }
00158   catch( ConfigError & ) {}
00159   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00160 
00161   TimeRange utcLogonTime
00162     ( logonTime, logoutTime, logonDay, logoutDay );
00163   TimeRange localLogonTime
00164     ( LocalTimeOnly(logonTime.getHour(), logonTime.getMinute(), logonTime.getSecond()),
00165       LocalTimeOnly(logoutTime.getHour(), logoutTime.getMinute(), logoutTime.getSecond()),
00166       logonDay, logoutDay );
00167   TimeRange logonTimeRange = useLocalTime ? localLogonTime : utcLogonTime;
00168 
00169   if( !sessionTimeRange.isInRange(logonTime) )
00170     throw ConfigError( "LogonTime must be between StartTime and EndTime" );
00171   if( !sessionTimeRange.isInRange(logoutTime) )
00172     throw ConfigError( "LogoutTime must be between StartTime and EndTime" );
00173   pSession->setLogonTime( logonTimeRange );
00174 
00175   if ( settings.has( SEND_REDUNDANT_RESENDREQUESTS ) )
00176     pSession->setSendRedundantResendRequests( settings.getBool( SEND_REDUNDANT_RESENDREQUESTS ) );
00177   if ( settings.has( CHECK_COMPID ) )
00178     pSession->setCheckCompId( settings.getBool( CHECK_COMPID ) );
00179   if ( settings.has( CHECK_LATENCY ) )
00180     pSession->setCheckLatency( settings.getBool( CHECK_LATENCY ) );
00181   if ( settings.has( MAX_LATENCY ) )
00182     pSession->setMaxLatency( settings.getLong( MAX_LATENCY ) );
00183   if ( settings.has( LOGON_TIMEOUT ) )
00184     pSession->setLogonTimeout( settings.getLong( LOGON_TIMEOUT ) );
00185   if ( settings.has( LOGOUT_TIMEOUT ) )
00186     pSession->setLogoutTimeout( settings.getLong( LOGOUT_TIMEOUT ) );
00187   if ( settings.has( RESET_ON_LOGON ) )
00188     pSession->setResetOnLogon( settings.getBool( RESET_ON_LOGON ) );
00189   if ( settings.has( RESET_ON_LOGOUT ) )
00190     pSession->setResetOnLogout( settings.getBool( RESET_ON_LOGOUT ) );
00191   if ( settings.has( RESET_ON_DISCONNECT ) )
00192     pSession->setResetOnDisconnect( settings.getBool( RESET_ON_DISCONNECT ) );
00193   if ( settings.has( REFRESH_ON_LOGON ) )
00194     pSession->setRefreshOnLogon( settings.getBool( REFRESH_ON_LOGON ) );
00195   if ( settings.has( MILLISECONDS_IN_TIMESTAMP ) )
00196     pSession->setMillisecondsInTimeStamp( settings.getBool( MILLISECONDS_IN_TIMESTAMP ) );
00197   if ( settings.has( PERSIST_MESSAGES ) )
00198     pSession->setPersistMessages( settings.getBool( PERSIST_MESSAGES ) );
00199 
00200   return pSession;
00201 
00202   QF_STACK_POP
00203 }
00204 
00205 DataDictionary SessionFactory::createDataDictionary(const SessionID& sessionID, 
00206                                                      const Dictionary& settings, 
00207                                                      const std::string& settingsKey) throw(ConfigError)
00208 { QF_STACK_PUSH(SessionFactory::createDataDictionary)
00209 
00210   DataDictionary dataDictionary;
00211   std::string path = settings.getString( settingsKey );
00212   Dictionaries::iterator i = m_dictionaries.find( path );
00213   if ( i != m_dictionaries.end() )
00214     dataDictionary = *i->second;
00215   else
00216   {
00217     DataDictionary* p = new DataDictionary( path );
00218     dataDictionary = *p;
00219     m_dictionaries[ path ] = p;
00220   }
00221 
00222   if( settings.has( VALIDATE_FIELDS_OUT_OF_ORDER ) )
00223   {
00224     dataDictionary.checkFieldsOutOfOrder
00225     ( settings.getBool( VALIDATE_FIELDS_OUT_OF_ORDER ) );
00226   }
00227   if( settings.has( VALIDATE_FIELDS_HAVE_VALUES ) )
00228   {
00229     dataDictionary.checkFieldsHaveValues
00230     ( settings.getBool( VALIDATE_FIELDS_HAVE_VALUES ) );
00231   }
00232   if( settings.has( VALIDATE_USER_DEFINED_FIELDS ) )
00233   {
00234     dataDictionary.checkUserDefinedFields
00235     ( settings.getBool( VALIDATE_USER_DEFINED_FIELDS ) );
00236   }
00237 
00238   return dataDictionary;    
00239 
00240   QF_STACK_POP
00241 }
00242 
00243 void SessionFactory::processFixtDataDictionaries(const SessionID& sessionID, 
00244                                                  const Dictionary& settings, 
00245                                                  DataDictionaryProvider& provider) throw(ConfigError)
00246 { QF_STACK_PUSH(SessionFactory::processFixtDataDictionaries)
00247 
00248   DataDictionary dataDictionary = createDataDictionary(sessionID, settings, TRANSPORT_DATA_DICTIONARY);
00249   provider.addTransportDataDictionary(sessionID.getBeginString(), dataDictionary);
00250   
00251   for(Dictionary::const_iterator data = settings.begin(); data != settings.end(); ++data)
00252   {
00253     const std::string& key = data->first;
00254     const std::string frontKey = key.substr(0, strlen(APP_DATA_DICTIONARY));
00255     if( frontKey == string_toUpper(APP_DATA_DICTIONARY) )
00256     {
00257       if( key == string_toUpper(APP_DATA_DICTIONARY) )
00258       {
00259         DataDictionary dataDictionary = createDataDictionary(sessionID, settings, APP_DATA_DICTIONARY);
00260         provider.addApplicationDataDictionary(Message::toApplVerID(settings.getString(DEFAULT_APPLVERID)), dataDictionary);
00261       }
00262       else
00263       {
00264         std::string::size_type offset = key.find('.');
00265         if( offset == std::string::npos )
00266           throw ConfigError(std::string("Malformed ") + APP_DATA_DICTIONARY + ": " + key);
00267         std::string beginStringQualifier = key.substr(offset+1);
00268         DataDictionary dataDictionary = createDataDictionary(sessionID, settings, key);
00269         provider.addApplicationDataDictionary(Message::toApplVerID(beginStringQualifier), dataDictionary);
00270       }
00271     }
00272   }
00273 
00274   QF_STACK_POP
00275 }
00276 
00277 void SessionFactory::processFixDataDictionary(const SessionID& sessionID, 
00278                                               const Dictionary& settings, 
00279                                               DataDictionaryProvider& provider) throw(ConfigError)
00280 { QF_STACK_PUSH(SessionFactory::processFixDataDictionary)
00281 
00282   DataDictionary dataDictionary = createDataDictionary(sessionID, settings, DATA_DICTIONARY);
00283   provider.addTransportDataDictionary(sessionID.getBeginString(), dataDictionary);
00284   provider.addApplicationDataDictionary(Message::toApplVerID(sessionID.getBeginString()), dataDictionary);
00285 
00286   QF_STACK_POP
00287 }
00288 }

Generated on Mon Apr 5 20:59:51 2010 for QuickFIX by doxygen 1.6.1 written by Dimitri van Heesch, © 1997-2001