// 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()));
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);
}
}
}
}