387 lines
No EOL
16 KiB
C#
387 lines
No EOL
16 KiB
C#
// Copyright (c) 2011, 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>
|
|
/// Summary description for ModuleDefinitions
|
|
/// </summary>
|
|
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<string, ModuleDefinition> ModuleDefinitions
|
|
{
|
|
get
|
|
{
|
|
Dictionary<string, ModuleDefinition> modules =
|
|
(Dictionary<string, ModuleDefinition>)HttpContext.Current.Cache[MODULE_DEFINITIONS_KEY];
|
|
if (modules == null)
|
|
{
|
|
// create list
|
|
modules = new Dictionary<string, ModuleDefinition>();
|
|
|
|
// 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<string, ModuleDefinition> 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 <includes>
|
|
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["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);
|
|
}
|
|
}
|
|
}
|
|
} |