// Copyright (c) 2012, Outercurve Foundation. // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, // are permitted provided that the following conditions are met: // // - Redistributions of source code must retain the above copyright notice, this // list of conditions and the following disclaimer. // // - Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // // - Neither the name of the Outercurve Foundation nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR // ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON // ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using System; using System.IO; using System.Collections; using System.Collections.Generic; using System.Data; using System.Configuration; using System.Globalization; using System.Web; using System.Web.Caching; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Xml; namespace WebsitePanel.WebPortal { /// /// Summary description for ModuleDefinitions /// public class PortalConfiguration { private const string ROLES_DELIMITERS = ";,"; private const string APP_DATA_FOLDER = "~/App_Data"; private const string THEMES_FOLDER = "~/App_Themes"; private const string MODULES_PATTERN = "*_Modules.config"; private const string PAGES_PATTERN = "*_Pages.config"; private const string SITE_SETTINGS_FILE = "SiteSettings.config"; private const string MODULE_DEFINITIONS_KEY = "PortalModuleDefinitionsCacheKey"; private const string SITE_STRUCTURE_KEY = "SiteStructureCacheKey"; private const string SITE_SETTINGS_KEY = "SiteSettingsCacheKey"; public static Dictionary ModuleDefinitions { get { Dictionary modules = (Dictionary)HttpContext.Current.Cache[MODULE_DEFINITIONS_KEY]; if (modules == null) { // create list modules = new Dictionary(); // load modules string appData = HttpContext.Current.Server.MapPath(APP_DATA_FOLDER); FileInfo[] files = new DirectoryInfo(appData).GetFiles(MODULES_PATTERN); foreach (FileInfo file in files) LoadModulesFromXml(modules, file.FullName); // place to cache HttpContext.Current.Cache.Insert(MODULE_DEFINITIONS_KEY, modules, new System.Web.Caching.CacheDependency(appData)); } return modules; } } public static SiteStructure Site { get { SiteStructure site = (SiteStructure)HttpContext.Current.Cache[SITE_STRUCTURE_KEY]; if (site == null) { // create list site = new SiteStructure(); // load pages string appData = HttpContext.Current.Server.MapPath(APP_DATA_FOLDER); FileInfo[] files = new DirectoryInfo(appData).GetFiles(PAGES_PATTERN); foreach (FileInfo file in files) LoadPagesFromXml(site, file.FullName); // place to cache HttpContext.Current.Cache.Insert(SITE_STRUCTURE_KEY, site, new System.Web.Caching.CacheDependency(appData)); } return site; } } public static SiteSettings SiteSettings { get { SiteSettings settings = (SiteSettings)HttpContext.Current.Cache[SITE_SETTINGS_KEY]; if (settings == null) { // create list settings = new SiteSettings(); // load pages string appData = HttpContext.Current.Server.MapPath(APP_DATA_FOLDER); string path = Path.Combine(appData, SITE_SETTINGS_FILE); // load site settings XmlDocument xml = new XmlDocument(); xml.Load(path); XmlNodeList nodes = xml.SelectNodes("SiteSettings/*"); foreach(XmlNode node in nodes) { settings[node.LocalName] = node.InnerText; } // place to cache HttpContext.Current.Cache.Insert(SITE_SETTINGS_KEY, settings, new System.Web.Caching.CacheDependency(path)); } return settings; } } public static bool SaveSiteSettings() { // load pages string appData = HttpContext.Current.Server.MapPath(APP_DATA_FOLDER); string path = Path.Combine(appData, SITE_SETTINGS_FILE); try { // build and save site settings XmlDocument xml = new XmlDocument(); XmlElement root = xml.CreateElement("SiteSettings"); xml.AppendChild(root); foreach (string keyName in SiteSettings.AllKeys) { XmlElement elem = xml.CreateElement(keyName); elem.InnerText = SiteSettings[keyName]; root.AppendChild(elem); } xml.Save(path); } catch { return false; } return true; } private static void LoadModulesFromXml(Dictionary modules, string path) { // open xml document XmlDocument xml = new XmlDocument(); xml.Load(path); // select nodes XmlNodeList xmlModules = xml.SelectNodes("ModuleDefinitions/ModuleDefinition"); foreach (XmlNode xmlModule in xmlModules) { ModuleDefinition module = new ModuleDefinition(); if (xmlModule.Attributes["id"] == null) throw new Exception(String.Format("Module ID is not specified. File: {0}, Node: {1}", path, xmlModule.OuterXml)); module.Id = xmlModule.Attributes["id"].Value.ToLower(CultureInfo.InvariantCulture); modules.Add(module.Id, module); // controls XmlNodeList xmlControls = xmlModule.SelectNodes("Controls/Control"); foreach (XmlNode xmlControl in xmlControls) { ModuleControl control = new ModuleControl(); if (xmlControl.Attributes["icon"] != null) control.IconFile = xmlControl.Attributes["icon"].Value; if(xmlControl.Attributes["key"] != null) control.Key = xmlControl.Attributes["key"].Value.ToLower(CultureInfo.InvariantCulture); if (xmlControl.Attributes["src"] == null) throw new Exception(String.Format("Control 'src' is not specified. File: {0}, Node: {1}", path, xmlControl.ParentNode.OuterXml)); control.Src = xmlControl.Attributes["src"].Value; if (xmlControl.Attributes["title"] == null) throw new Exception(String.Format("Control 'title' is not specified. File: {0}, Node: {1}", path, xmlControl.ParentNode.OuterXml)); control.Title = xmlControl.Attributes["title"].Value; if (xmlControl.Attributes["type"] != null) control.ControlType = (ModuleControlType)Enum.Parse(typeof(ModuleControlType), xmlControl.Attributes["type"].Value, true); else control.ControlType = ModuleControlType.View; if (String.IsNullOrEmpty(control.Key)) module.DefaultControl = control; module.Controls.Add(control.Key, control); } } } private static void LoadPagesFromXml(SiteStructure site, string path) { // open xml document XmlDocument xml = new XmlDocument(); xml.Load(path); // select nodes XmlNodeList xmlPages = xml.SelectNodes("Pages/Page"); // process includes ProcessXmlIncludes(xml, path); // parse root nodes ParsePagesRecursively(path, site, xmlPages, null); } private static void ProcessXmlIncludes(XmlDocument xml, string parentPath) { // working dir string path = Path.GetDirectoryName(parentPath); // get all XmlNodeList nodes = xml.SelectNodes("//include"); foreach (XmlNode node in nodes) { if (node.Attributes["file"] == null) continue; string incPath = Path.Combine(path, node.Attributes["file"].Value); XmlDocument inc = new XmlDocument(); inc.Load(incPath); XmlElement incNode = xml.CreateElement(inc.DocumentElement.Name); incNode.InnerXml = inc.DocumentElement.InnerXml; // replace original node node.ParentNode.ReplaceChild(incNode, node); } } private static void ParsePagesRecursively(string path, SiteStructure site, XmlNodeList xmlPages, PortalPage parentPage) { foreach (XmlNode xmlPage in xmlPages) { PortalPage page = new PortalPage(); page.ParentPage = parentPage; // page properties if (xmlPage.Attributes["name"] == null) throw new Exception(String.Format("Page name is not specified. File: {0}, Node: {1}", path, xmlPage.OuterXml)); page.Name = xmlPage.Attributes["name"].Value; if (xmlPage.Attributes["roles"] == null) page.Roles.Add("*"); else page.Roles.AddRange(xmlPage.Attributes["roles"].Value.Split(ROLES_DELIMITERS.ToCharArray())); if (xmlPage.Attributes["selectedUserContext"] != null) page.Roles.AddRange(xmlPage.Attributes["selectedUserContext"].Value.Split(ROLES_DELIMITERS.ToCharArray())); page.Enabled = (xmlPage.Attributes["enabled"] != null) ? Boolean.Parse(xmlPage.Attributes["enabled"].Value) : true; page.Hidden = (xmlPage.Attributes["hidden"] != null) ? Boolean.Parse(xmlPage.Attributes["hidden"].Value) : false; page.SkinSrc = (xmlPage.Attributes["skin"] != null) ? xmlPage.Attributes["skin"].Value : null; page.AdminSkinSrc = (xmlPage.Attributes["adminskin"] != null) ? xmlPage.Attributes["adminskin"].Value : null; if (xmlPage.Attributes["url"] != null) page.Url = xmlPage.Attributes["url"].Value; if (xmlPage.Attributes["target"] != null) page.Target = xmlPage.Attributes["target"].Value; // content panes XmlNodeList xmlContentPanes = xmlPage.SelectNodes("Content"); foreach (XmlNode xmlContentPane in xmlContentPanes) { ContentPane pane = new ContentPane(); if (xmlContentPane.Attributes["id"] == null) throw new Exception(String.Format("ContentPane ID is not specified. File: {0}, Node: {1}", path, xmlContentPane.ParentNode.OuterXml)); pane.Id = xmlContentPane.Attributes["id"].Value; page.ContentPanes.Add(pane.Id, pane); // page modules XmlNodeList xmlModules = xmlContentPane.SelectNodes("Module"); foreach (XmlNode xmlModule in xmlModules) { PageModule module = new PageModule(); module.ModuleId = site.Modules.Count + 1; module.Page = page; site.Modules.Add(module.ModuleId, module); if (xmlModule.Attributes["moduleDefinitionID"] == null) throw new Exception(String.Format("ModuleDefinition ID is not specified. File: {0}, Node: {1}", path, xmlModule.ParentNode.OuterXml)); module.ModuleDefinitionID = xmlModule.Attributes["moduleDefinitionID"].Value.ToLower(CultureInfo.InvariantCulture); if (xmlModule.Attributes["title"] != null) module.Title = xmlModule.Attributes["title"].Value; if (xmlModule.Attributes["icon"] != null) module.IconFile = xmlModule.Attributes["icon"].Value; if (xmlModule.Attributes["container"] != null) module.ContainerSrc = xmlModule.Attributes["container"].Value; if (xmlModule.Attributes["admincontainer"] != null) module.AdminContainerSrc = xmlModule.Attributes["admincontainer"].Value; if (xmlModule.Attributes["viewRoles"] == null) module.ViewRoles.Add("*"); else module.ViewRoles.AddRange(xmlModule.Attributes["viewRoles"].Value.Split(ROLES_DELIMITERS.ToCharArray())); if (xmlModule.Attributes["readOnlyRoles"] != null) module.ReadOnlyRoles.AddRange(xmlModule.Attributes["readOnlyRoles"].Value.Split(ROLES_DELIMITERS.ToCharArray())); if (xmlModule.Attributes["editRoles"] == null) module.EditRoles.Add("*"); else module.EditRoles.AddRange(xmlModule.Attributes["editRoles"].Value.Split(ROLES_DELIMITERS.ToCharArray())); // settings XmlNodeList xmlSettings = xmlModule.SelectNodes("Settings/Add"); foreach (XmlNode xmlSetting in xmlSettings) { module.Settings[xmlSetting.Attributes["name"].Value] = xmlSetting.Attributes["value"].Value; } XmlNode xmlModuleData = xmlModule.SelectSingleNode("ModuleData"); if (xmlModuleData != null) { // check reference if (xmlModuleData.Attributes["ref"] != null) { // load referenced module data xmlModuleData = xmlModule.OwnerDocument.SelectSingleNode( "Pages/ModulesData/ModuleData[@id='" + xmlModuleData.Attributes["ref"].Value + "']"); } module.LoadXmlModuleData(xmlModuleData.OuterXml); } pane.Modules.Add(module); } } // add page to te array if (parentPage != null) parentPage.Pages.Add(page); site.Pages.Add(page); // process children XmlNodeList xmlChildPages = xmlPage.SelectNodes("Pages/Page"); ParsePagesRecursively(path, site, xmlChildPages, page); } } } }