using System; using System.Collections.Generic; using System.Linq; using System.Text; using SuperSocket.SocketBase.Config; using SuperSocket.SocketBase.Logging; using SuperSocket.SocketBase.Provider; using SuperSocket.SocketEngine.Configuration; using SuperSocket.SocketBase.Metadata; namespace SuperSocket.SocketEngine { class WorkItemFactoryInfoLoader : IDisposable { private ProviderFactoryInfo m_DefaultLogFactory; private IConfigurationSource m_Config; public WorkItemFactoryInfoLoader(IConfigurationSource config, ILogFactory passedInLogFactory) : this(config) { if (passedInLogFactory != null) m_DefaultLogFactory = new ProviderFactoryInfo(ProviderKey.LogFactory, string.Empty, passedInLogFactory); } public WorkItemFactoryInfoLoader(IConfigurationSource config) { m_Config = config; } public ProviderFactoryInfo GetBootstrapLogFactory() { if (m_DefaultLogFactory != null) return m_DefaultLogFactory; if (string.IsNullOrEmpty(m_Config.LogFactory)) { m_DefaultLogFactory = new ProviderFactoryInfo(ProviderKey.LogFactory, string.Empty, typeof(Log4NetLogFactory)); return m_DefaultLogFactory; } ProviderFactoryInfo factory = null; if (m_Config.LogFactories != null && m_Config.LogFactories.Count() > 0) { var logConfig = m_Config.LogFactories.FirstOrDefault(f => f.Name.Equals(m_Config.LogFactory, StringComparison.OrdinalIgnoreCase)); if (logConfig != null) { factory = new ProviderFactoryInfo(ProviderKey.LogFactory, m_Config.LogFactory, ValidateProviderType(logConfig.Type)); } } if (factory == null) throw new Exception(string.Format("the specific log factory '{0}' cannot be found!", m_Config.LogFactory)); m_DefaultLogFactory = factory; return factory; } public List LoadResult(Func serverConfigResolver) { var workItemFactories = new List(m_Config.Servers.Count()); //var providerFactories = new List(); //Initialize server types var serverTypeFactories = InitializeProviderFactories(ProviderKey.ServerType, m_Config.ServerTypes); //Initialize connection filters var connectionFilterFactories = InitializeProviderFactories(ProviderKey.ConnectionFilter, m_Config.ConnectionFilters); //Initialize log factories var logFactoryFactories = InitializeProviderFactories(ProviderKey.LogFactory, m_Config.LogFactories, m_DefaultLogFactory); //Initialize Receive filter factories var receiveFilterFactories = InitializeProviderFactories(ProviderKey.ReceiveFilterFactory, m_Config.ReceiveFilterFactories); //Initialize command loader factories var commandLoaderFactories = InitializeProviderFactories(ProviderKey.CommandLoader, m_Config.CommandLoaders); //Initialize servers foreach (var c in m_Config.Servers.OrderBy(s => s.StartupOrder)) { var serverConfig = serverConfigResolver(c); if (string.IsNullOrEmpty(serverConfig.Name)) throw new Exception("The name attribute of server node is required!"); string serverType; if (string.IsNullOrEmpty(serverConfig.ServerTypeName)) { if (string.IsNullOrEmpty(serverConfig.ServerType)) throw new Exception("Either serverTypeName or serverType attribute of the server node is required!"); serverType = ValidateProviderType(serverConfig.ServerType); } else { var serviceFactory = serverTypeFactories.FirstOrDefault(p => p.Name.Equals(serverConfig.ServerTypeName, StringComparison.OrdinalIgnoreCase)); if (serviceFactory == null) throw new Exception(string.Format("Failed to find a service for server {0}!", serverConfig.Name)); serverType = serviceFactory.ExportFactory.TypeName; } var workItemFactory = new WorkItemFactoryInfo(); workItemFactory.Config = serverConfig; workItemFactory.ServerType = serverType; var serverTypeMeta = GetServerTypeMetadata(serverType); if (serverTypeMeta != null) { workItemFactory.StatusInfoMetadata = serverTypeMeta.StatusInfoMetadata; workItemFactory.IsServerManager = serverTypeMeta.IsServerManager; } var factories = new List(); workItemFactory.SocketServerFactory = new ProviderFactoryInfo(ProviderKey.SocketServerFactory, string.Empty, typeof(SocketServerFactory)); factories.Add(workItemFactory.SocketServerFactory); //Initialize connection filters if(!string.IsNullOrEmpty(serverConfig.ConnectionFilter)) { var currentFactories = GetSelectedFactories(connectionFilterFactories, serverConfig.ConnectionFilter); if (currentFactories.Any()) factories.AddRange(currentFactories); } //Initialize command loaders if (!string.IsNullOrEmpty(serverConfig.CommandLoader)) { var currentFactories = GetSelectedFactories(commandLoaderFactories, serverConfig.CommandLoader); if (currentFactories.Any()) factories.AddRange(currentFactories); } var logFactoryName = serverConfig.LogFactory; if (!string.IsNullOrEmpty(logFactoryName)) { logFactoryName = logFactoryName.Trim(); var logProviderFactory = logFactoryFactories.FirstOrDefault(p => p.Name.Equals(logFactoryName, StringComparison.OrdinalIgnoreCase)); if (logProviderFactory == null) throw new Exception(string.Format("the specific log factory '{0}' cannot be found!", logFactoryName)); workItemFactory.LogFactory = logProviderFactory; } else { if (m_DefaultLogFactory != null) workItemFactory.LogFactory = m_DefaultLogFactory; else workItemFactory.LogFactory = GetBootstrapLogFactory(); } if (workItemFactory.LogFactory != null) factories.Add(workItemFactory.LogFactory); //Initialize Receive filter factory if (!string.IsNullOrEmpty(serverConfig.ReceiveFilterFactory)) { var currentReceiveFilterFactory = receiveFilterFactories.FirstOrDefault(p => p.Name.Equals(serverConfig.ReceiveFilterFactory, StringComparison.OrdinalIgnoreCase)); if (currentReceiveFilterFactory == null) throw new Exception(string.Format("the specific Receive filter factory '{0}' cannot be found!", serverConfig.ReceiveFilterFactory)); factories.Add(currentReceiveFilterFactory); } workItemFactory.ProviderFactories = factories; workItemFactories.Add(workItemFactory); } return workItemFactories; } private IEnumerable GetSelectedFactories(List source, string selectedItems) { var items = selectedItems.Split(new char[] { ',', ';' }); if (items == null && !items.Any()) return null; items = items.Select(f => f.Trim()).ToArray(); return source.Where(p => items.Contains(p.Name, StringComparer.OrdinalIgnoreCase)); } private List InitializeProviderFactories(ProviderKey key, IEnumerable providerCollection) { return InitializeProviderFactories(key, providerCollection, null); } private List InitializeProviderFactories(ProviderKey key, IEnumerable providerCollection, ProviderFactoryInfo loadedFactory) { var loadedFactoryPassedIn = false; if(loadedFactory != null && !string.IsNullOrEmpty(loadedFactory.Name)) loadedFactoryPassedIn = true; var factories = new List(); if (providerCollection == null || !providerCollection.Any()) { return factories; } foreach (var provider in providerCollection) { if (loadedFactoryPassedIn) { if (loadedFactory.Name.Equals(provider.Name, StringComparison.OrdinalIgnoreCase)) { factories.Add(loadedFactory); continue; } } factories.Add(new ProviderFactoryInfo(key, provider.Name, ValidateProviderType(provider.Type))); } return factories; } /// /// Validates the type of the provider, needn't validate in default mode, because it will be validate later when initializing. /// /// Name of the type. /// protected virtual string ValidateProviderType(string typeName) { return typeName; } /// /// Gets the app server type's metadata, the return value is not required in this mode. /// /// Name of the type. /// protected virtual ServerTypeMetadata GetServerTypeMetadata(string typeName) { return null; } /// /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// public virtual void Dispose() { } } }