SessionFactory.cpp
Go to the documentation of this file.
00001 /****************************************************************************
00002 ** Copyright (c) 2001-2014
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 
00026 #include "Utility.h"
00027 #include "Values.h"
00028 #include "DataDictionaryProvider.h"
00029 #include "SessionFactory.h"
00030 #include "SessionSettings.h"
00031 #include "Session.h"
00032 
00033 #include <memory>
00034 
00035 namespace FIX
00036 {
00037 SessionFactory::~SessionFactory()
00038 {
00039   Dictionaries::iterator i = m_dictionaries.begin();
00040   for ( ; i != m_dictionaries.end(); ++i )
00041     delete i->second;
00042 }
00043 
00044 Session* SessionFactory::create( const SessionID& sessionID,
00045                                  const Dictionary& settings ) throw( ConfigError )
00046 {
00047   std::string connectionType = settings.getString( CONNECTION_TYPE );
00048   if ( connectionType != "acceptor" && connectionType != "initiator" )
00049     throw ConfigError( "Invalid ConnectionType" );
00050 
00051   if( connectionType == "acceptor" && settings.has(SESSION_QUALIFIER) )
00052     throw ConfigError( "SessionQualifier cannot be used with acceptor." );
00053 
00054   bool useDataDictionary = true;
00055   if ( settings.has( USE_DATA_DICTIONARY ) )
00056     useDataDictionary = settings.getBool( USE_DATA_DICTIONARY );
00057 
00058   std::string defaultApplVerID;
00059   if( sessionID.isFIXT() )
00060   {
00061     if( !settings.has(DEFAULT_APPLVERID) )
00062     {
00063       throw ConfigError("ApplVerID is required for FIXT transport");
00064     }
00065     defaultApplVerID = Message::toApplVerID( settings.getString(DEFAULT_APPLVERID) );
00066   }
00067 
00068   DataDictionaryProvider dataDictionaryProvider;
00069   if( useDataDictionary )
00070   {
00071     if( sessionID.isFIXT() )
00072     {
00073       processFixtDataDictionaries(sessionID, settings, dataDictionaryProvider);
00074     }
00075     else
00076     {
00077       processFixDataDictionary(sessionID, settings, dataDictionaryProvider);
00078     }
00079   }
00080 
00081   bool useLocalTime = false;
00082   if( settings.has(USE_LOCAL_TIME) )
00083     useLocalTime = settings.getBool( USE_LOCAL_TIME );
00084 
00085   int startDay = -1;
00086   int endDay = -1;
00087   try
00088   {
00089     startDay = settings.getDay( START_DAY );
00090     endDay = settings.getDay( END_DAY );
00091   }
00092   catch( ConfigError & ) {}
00093   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00094 
00095   UtcTimeOnly startTime;
00096   UtcTimeOnly endTime;
00097   try
00098   {
00099     startTime = UtcTimeOnlyConvertor::convert
00100                 ( settings.getString( START_TIME ) );
00101     endTime = UtcTimeOnlyConvertor::convert
00102               ( settings.getString( END_TIME ) );
00103   }
00104   catch ( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00105 
00106   TimeRange utcSessionTime
00107     ( startTime, endTime, startDay, endDay );
00108   TimeRange localSessionTime
00109     ( LocalTimeOnly(startTime.getHour(), startTime.getMinute(), startTime.getSecond()),
00110       LocalTimeOnly(endTime.getHour(), endTime.getMinute(), endTime.getSecond()),
00111       startDay, endDay );
00112   TimeRange sessionTimeRange = useLocalTime ? localSessionTime : utcSessionTime;
00113 
00114   if( startDay >= 0 && endDay < 0 )
00115     throw ConfigError( "StartDay used without EndDay" );
00116   if( endDay >= 0 && startDay < 0 )
00117     throw ConfigError( "EndDay used without StartDay" );
00118 
00119   HeartBtInt heartBtInt( 0 );
00120   if ( connectionType == "initiator" )
00121   {
00122     heartBtInt = HeartBtInt( settings.getInt( HEARTBTINT ) );
00123     if ( heartBtInt <= 0 ) throw ConfigError( "Heartbeat must be greater than zero" );
00124   }
00125 
00126   std::auto_ptr<Session> pSession;
00127   pSession.reset( new Session( m_application, m_messageStoreFactory,
00128     sessionID, dataDictionaryProvider, sessionTimeRange,
00129     heartBtInt, m_pLogFactory ) );
00130 
00131   pSession->setSenderDefaultApplVerID(defaultApplVerID);
00132 
00133   int logonDay = startDay;
00134   int logoutDay = endDay;
00135   try
00136   {
00137     logonDay = settings.getDay( LOGON_DAY );
00138     logoutDay = settings.getDay( LOGOUT_DAY );
00139   }
00140   catch( ConfigError & ) {}
00141   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00142 
00143   UtcTimeOnly logonTime( startTime );
00144   UtcTimeOnly logoutTime( endTime );
00145   try
00146   {
00147     logonTime = UtcTimeOnlyConvertor::convert
00148                 ( settings.getString( LOGON_TIME ) );
00149   }
00150   catch( ConfigError & ) {}
00151   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00152   try
00153   {
00154     logoutTime = UtcTimeOnlyConvertor::convert
00155               ( settings.getString( LOGOUT_TIME ) );
00156   }
00157   catch( ConfigError & ) {}
00158   catch( FieldConvertError & e ) { throw ConfigError( e.what() ); }
00159 
00160   TimeRange utcLogonTime
00161     ( logonTime, logoutTime, logonDay, logoutDay );
00162   TimeRange localLogonTime
00163     ( LocalTimeOnly(logonTime.getHour(), logonTime.getMinute(), logonTime.getSecond()),
00164       LocalTimeOnly(logoutTime.getHour(), logoutTime.getMinute(), logoutTime.getSecond()),
00165       logonDay, logoutDay );
00166   TimeRange logonTimeRange = useLocalTime ? localLogonTime : utcLogonTime;
00167 
00168   if( !sessionTimeRange.isInRange(logonTime, logonDay) )
00169     throw ConfigError( "LogonTime must be between StartTime and EndTime" );
00170   if( !sessionTimeRange.isInRange(logoutTime, logoutDay) )
00171     throw ConfigError( "LogoutTime must be between StartTime and EndTime" );
00172   pSession->setLogonTime( logonTimeRange );
00173 
00174   if ( settings.has( SEND_REDUNDANT_RESENDREQUESTS ) )
00175     pSession->setSendRedundantResendRequests( settings.getBool( SEND_REDUNDANT_RESENDREQUESTS ) );
00176   if ( settings.has( CHECK_COMPID ) )
00177     pSession->setCheckCompId( settings.getBool( CHECK_COMPID ) );
00178   if ( settings.has( CHECK_LATENCY ) )
00179     pSession->setCheckLatency( settings.getBool( CHECK_LATENCY ) );
00180   if ( settings.has( MAX_LATENCY ) )
00181     pSession->setMaxLatency( settings.getInt( MAX_LATENCY ) );
00182   if ( settings.has( LOGON_TIMEOUT ) )
00183     pSession->setLogonTimeout( settings.getInt( LOGON_TIMEOUT ) );
00184   if ( settings.has( LOGOUT_TIMEOUT ) )
00185     pSession->setLogoutTimeout( settings.getInt( LOGOUT_TIMEOUT ) );
00186   if ( settings.has( RESET_ON_LOGON ) )
00187     pSession->setResetOnLogon( settings.getBool( RESET_ON_LOGON ) );
00188   if ( settings.has( RESET_ON_LOGOUT ) )
00189     pSession->setResetOnLogout( settings.getBool( RESET_ON_LOGOUT ) );
00190   if ( settings.has( RESET_ON_DISCONNECT ) )
00191     pSession->setResetOnDisconnect( settings.getBool( RESET_ON_DISCONNECT ) );
00192   if ( settings.has( REFRESH_ON_LOGON ) )
00193     pSession->setRefreshOnLogon( settings.getBool( REFRESH_ON_LOGON ) );
00194   if ( settings.has( MILLISECONDS_IN_TIMESTAMP ) )
00195     pSession->setMillisecondsInTimeStamp( settings.getBool( MILLISECONDS_IN_TIMESTAMP ) );
00196   if ( settings.has( PERSIST_MESSAGES ) )
00197     pSession->setPersistMessages( settings.getBool( PERSIST_MESSAGES ) );
00198   if ( settings.has( VALIDATE_LENGTH_AND_CHECKSUM ) )
00199     pSession->setValidateLengthAndChecksum( settings.getBool( VALIDATE_LENGTH_AND_CHECKSUM ) );
00200    
00201   return pSession.release();
00202 }
00203 
00204 void SessionFactory::destroy( Session* pSession )
00205 {
00206   delete pSession;
00207 }
00208 
00209 const DataDictionary * SessionFactory::createDataDictionary(const SessionID& sessionID, 
00210                                                     const Dictionary& settings, 
00211                                                     const std::string& settingsKey) throw(ConfigError)
00212 {
00213   DataDictionary * pDD = 0;
00214   std::string path = settings.getString( settingsKey );
00215   Dictionaries::iterator i = m_dictionaries.find( path );
00216   if ( i != m_dictionaries.end() )
00217   {
00218     pDD = i->second;
00219   }
00220   else
00221   {
00222     pDD = new DataDictionary( path );
00223     m_dictionaries[ path ] = pDD;
00224   }
00225 
00226   DataDictionary * pCopyOfDD = new DataDictionary(*pDD);
00227 
00228   if( settings.has( VALIDATE_FIELDS_OUT_OF_ORDER ) )
00229     pCopyOfDD->checkFieldsOutOfOrder( settings.getBool( VALIDATE_FIELDS_OUT_OF_ORDER ) );
00230   if( settings.has( VALIDATE_FIELDS_HAVE_VALUES ) )
00231     pCopyOfDD->checkFieldsHaveValues( settings.getBool( VALIDATE_FIELDS_HAVE_VALUES ) );
00232   if( settings.has( VALIDATE_USER_DEFINED_FIELDS ) )
00233     pCopyOfDD->checkUserDefinedFields( settings.getBool( VALIDATE_USER_DEFINED_FIELDS ) );
00234 
00235   return pCopyOfDD;
00236 }
00237 
00238 void SessionFactory::processFixtDataDictionaries(const SessionID& sessionID, 
00239                                                  const Dictionary& settings, 
00240                                                  DataDictionaryProvider& provider) throw(ConfigError)
00241 {
00242   const DataDictionary * pDataDictionary = createDataDictionary(sessionID, settings, TRANSPORT_DATA_DICTIONARY);
00243   provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
00244   
00245   for(Dictionary::const_iterator data = settings.begin(); data != settings.end(); ++data)
00246   {
00247     const std::string& key = data->first;
00248     const std::string frontKey = key.substr(0, strlen(APP_DATA_DICTIONARY));
00249     if( frontKey == string_toUpper(APP_DATA_DICTIONARY) )
00250     {
00251       if( key == string_toUpper(APP_DATA_DICTIONARY) )
00252       {
00253         provider.addApplicationDataDictionary(Message::toApplVerID(settings.getString(DEFAULT_APPLVERID)),
00254             createDataDictionary(sessionID, settings, APP_DATA_DICTIONARY));
00255       }
00256       else
00257       {
00258         std::string::size_type offset = key.find('.');
00259         if( offset == std::string::npos )
00260           throw ConfigError(std::string("Malformed ") + APP_DATA_DICTIONARY + ": " + key);
00261         std::string beginStringQualifier = key.substr(offset+1);
00262         provider.addApplicationDataDictionary(Message::toApplVerID(beginStringQualifier), 
00263             createDataDictionary(sessionID, settings, key));
00264       }
00265     }
00266   }
00267 }
00268 
00269 void SessionFactory::processFixDataDictionary(const SessionID& sessionID, 
00270                                               const Dictionary& settings, 
00271                                               DataDictionaryProvider& provider) throw(ConfigError)
00272 {
00273   const DataDictionary * pDataDictionary = createDataDictionary(sessionID, settings, DATA_DICTIONARY);
00274   provider.addTransportDataDictionary(sessionID.getBeginString(), pDataDictionary);
00275   provider.addApplicationDataDictionary(Message::toApplVerID(sessionID.getBeginString()), pDataDictionary);
00276 }
00277 }

Generated on Mon Jun 23 2014 23:49:38 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001