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

Generated on Mon Sep 15 2014 01:23:54 for QuickFIX by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2001