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 }