// Stephen Toub // stoub@microsoft.com using System; using System.Xml; using System.Collections; using System.Configuration; using Msdn.Outlook.Calendaring; namespace Msdn.Outlook.Calendaring { /// /// Configuration section handler for the Outlook Calendar Provider system. /// Expects a configuration section named "calendarProviders". Under that node /// is a node "providers". Each "provider" node under "providers" creates /// a single provider that can be used by the system. If the type of this /// provider is GroupCalendarProvider, then it can have subproviders as /// "provider" nodes underneath it, none of which need id attributes. /// public class CalendarProviderSettings : IConfigurationSectionHandler { /// Initialize the section handler. public CalendarProviderSettings(){} /// Gets instances of the registered providers from the configuration file. public static CalendarProvider [] Providers { get { // 12/26/12: M.Gerow; This statement was commented out because configuration // section caused error after converting to ASP.NET 3.5, so simply // hard-coded array of providers below to get things working again. //return (CalendarProvider[])ConfigurationSettings.GetConfig("outlookCalendar"); CalendarProvider[] providers = new CalendarProvider[4]; providers[0] = new RssCalendarProvider(); providers[0].Initialize("Recent Posts to Blogs on MSDN", new Guid("{5835AD45-BAA7-4766-8E23-C2F870824BAD}")); providers[0].Configure("http://blogs.msdn.com/MainFeed.aspx"); providers[1] = new EventLogCalendarProvider(); providers[1].Initialize("Application Event Log Calendar", new Guid("{2FC380F2-FD3F-46af-BDB4-40BD727813CE}")); providers[1].Configure("Application"); providers[2] = new SystemRestoreCalendarProvider(); providers[2].Initialize("System Restore Points", new Guid("{7CB4C0A5-D6EA-48e1-92DE-852148F64149}")); providers[2].Configure(""); providers[3] = new TaskListCalendarProvider(); providers[3].Initialize("SharePoint 2010 Task List", new Guid("{5996DB53-AE0C-45be-B4C1-86CCBF61B0A7}")); providers[3].Configure("http://[Your SharePoint Server];[Your Task List Name]"); return providers; } } /// Finds an instance of a registered provider based on its ID. /// The ID of the calendar provider for which to search. /// The instance with the matching ID if found; null, otherwise. public static CalendarProvider Lookup(Guid id) { // Loop through each provider to find the one with the specified ID. This is // fine for a small number of providers as it is an infrequent event and looping // through a small list is insignificant overhead. If a large number of providers // is used, it would be better to store Providers as a hashtable, or at least // as a sorted array. foreach(CalendarProvider prov in Providers) { if (prov.ID.Equals(id)) return prov; } // Oops return null; } /// Parses the configuratino section and returns an array of providers. /// Not used. /// Not used. /// The XML configuration section. /// An array of calendar provider instances based on the providers described in the configuration file. public object Create(object parent, object configContext, System.Xml.XmlNode section) { if (section != null) { // Get the providers section XmlNodeList nodes = section.SelectNodes("providers/provider"); if (nodes != null && nodes.Count > 0) { // Add each provider from list ArrayList providers = new ArrayList(nodes.Count); ParseProvidersFromList(nodes, providers, true); return providers.ToArray(typeof(CalendarProvider)); } } // No providers, so empty array return new CalendarProvider[0]; } /// Parses a list of provider nodes into instances of those providers, adding them to the result list. /// The provider node to be parsed. /// The output list of instantiated providers. /// /// Whether the providers should have IDs. This method is used recursively to parse GroupCalendarProviders. Top-level /// providers should all have IDs, but providers that are members of a group do not need IDs. It's not an error /// if they have them, but we ignore them if they do. /// private void ParseProvidersFromList(XmlNodeList nodes, ArrayList result, bool idRequired) { // Add each provider from the list foreach(XmlNode provNode in nodes) { // Get all attributes describing the provider XmlAttribute typeName = provNode.Attributes["type"]; XmlAttribute name = provNode.Attributes["name"]; XmlAttribute id = provNode.Attributes["id"]; XmlAttribute initData = provNode.Attributes["initData"]; // Make sure we have what we need if (typeName == null) throw new ConfigurationException("A configured provider is missing a type.", provNode); if (name == null) throw new ConfigurationException("A configured provider is missing a name.", provNode); if (idRequired && id == null) throw new ConfigurationException("A configured provider is missing an id.", provNode); // Instantiate the provider CalendarProvider provider; try { Type provType = Type.GetType(typeName.Value); if (!provType.IsSubclassOf(typeof(CalendarProvider))) throw new ConfigurationException("Providers must derive from CalendarProvider."); provider = (CalendarProvider)Activator.CreateInstance(provType); } catch(Exception exc) { throw new ConfigurationException("Unable to create provider " + name.Value, exc, provNode); } // Initialize the provider with the attribute data. Top-level providers use the provided ID. // Nested providers have an empty ID. provider.Initialize(name.Value, idRequired ? new Guid(id.Value) : Guid.Empty); if (initData != null) provider.Configure(initData.Value); // If it's a grouping provider, recur. GroupingCalendarProvider allows us to take from a bunch // of different sources and display on a single calendar to Outlook!! GroupingCalendarProvider can be // nested, though it's unclear why one would want to do that except for web.config organizational reasons. // Only top-level providers can be accessed by id currently. if (provider is GroupingCalendarProvider) { ArrayList childProviders = new ArrayList(); ParseProvidersFromList(provNode.SelectNodes("provider"), childProviders, false); ((GroupingCalendarProvider)provider).Providers = (CalendarProvider[])childProviders.ToArray(typeof(CalendarProvider)); } // Add the provider to the list result.Add(provider); } } } }