Package.cs :  » Build-Systems » CruiseControl.NET » ThoughtWorks » CruiseControl » WebDashboard » Plugins » Administration » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Build Systems » CruiseControl.NET 
CruiseControl.NET » ThoughtWorks » CruiseControl » WebDashboard » Plugins » Administration » Package.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;
using System.Xml.Serialization;
using System.Xml;
using System.Diagnostics;
using ThoughtWorks.CruiseControl.WebDashboard.Configuration;
using ThoughtWorks.CruiseControl.Core.Reporting.Dashboard.Navigation;
using ThoughtWorks.CruiseControl.WebDashboard.IO;

namespace ThoughtWorks.CruiseControl.WebDashboard.Plugins.Administration{
    /// <summary>
    /// Defines a plug-in package.
    /// </summary>
    /// <remarks>
    /// A plug-in package contains all the files and configuration to get a plug-in working
    /// in the web dashboard.
    /// </remarks>
    public class Package
        : IDisposable
    {
        #region Private constants
        private const int blockSize = 16384;
        #endregion

        #region Private fields
        private PackageManifest manifest;
        private List<string> files = new List<string>();
        private string tempFolder;
        #endregion

        #region Constructors
        /// <summary>
        /// Initialises a new package from a stream.
        /// </summary>
        /// <param name="packageStream">The stream that contains the package.</param>
        public Package(Stream packageStream)
        {
            // Extract all the files into a temporary location
            ExtractAllFiles(packageStream);

            // Attempt to load the manifest
            string manifestFile = Path.Combine(tempFolder, "Manifest.xml");
            if (File.Exists(manifestFile))
            {
                XmlSerializer serialiser = new XmlSerializer(typeof(PackageManifest));
                using (Stream inputStream = File.OpenRead(manifestFile))
                {
                    manifest = serialiser.Deserialize(inputStream) as PackageManifest;
                    inputStream.Close();
                }
            }
        }
        #endregion

        #region Public properties
        #region Manifest
        /// <summary>
        /// The manifest of the package.
        /// </summary>
        public PackageManifest Manifest
        {
            get { return manifest; }
            set { manifest = value; }
        }
        #endregion

        #region IsValid
        /// <summary>
        /// Returns true if this is a valid package.
        /// </summary>
        public bool IsValid
        {
            get { return (manifest != null); }
        }
        #endregion
        #endregion

        #region Public methods
        #region Install()
        /// <summary>
        /// Installs the package to the specified location.
        /// </summary>
        public void Install()
        {
            if (!IsValid) throw new ApplicationException("This is not a valid package");

            // Start the stopwatch
            FireMessage(TraceLevel.Info, "Starting installation");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            try
            {
                // Copy all the files
                FireMessage(TraceLevel.Verbose, "Installing files");
                foreach (FileLocation folder in manifest.FileLocations)
                {
                    CopyFiles(folder);
                }

                // Add all the configuration settings
                FireMessage(TraceLevel.Verbose, "Updating configuration");
                UpdateConfigurationFile(true);
            }
            catch (Exception error)
            {
                // Tell the calling app that an unexpected error occurred
                FireMessage(TraceLevel.Error,
                    "An unexpected error occurred during the installation: '{0}'",
                    error.Message);
            }
            finally
            {
                // Display the elapsed time
                stopwatch.Stop();
                double time = stopwatch.ElapsedMilliseconds;
                FireMessage(TraceLevel.Info,
                    "Installation has completed ({0:0.00}s)",
                    time / 1000);
            }
        }
        #endregion

        #region Uninstall()
        /// <summary>
        /// Uninstalls the package from the specified location.
        /// </summary>
        public void Uninstall()
        {
            if (!IsValid) throw new ApplicationException("This is not a valid package");

            // Start the stopwatch
            FireMessage(TraceLevel.Info, "Starting uninstallation");
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();

            try
            {
                // Delete all the files
                FireMessage(TraceLevel.Verbose, "Removing files");
                foreach (FileLocation folder in manifest.FileLocations)
                {
                    RemoveFiles(folder);
                }

                // Remove all the configuration settings
                FireMessage(TraceLevel.Verbose, "Updating configuration");
                UpdateConfigurationFile(false);
            }
            catch (Exception error)
            {
                // Tell the calling app that an unexpected error occurred
                FireMessage(TraceLevel.Error,
                    "An unexpected error occurred during the uninstallation: '{0}'",
                    error.Message);
            }
            finally
            {
                // Display the elapsed time
                stopwatch.Stop();
                double time = stopwatch.ElapsedMilliseconds;
                FireMessage(TraceLevel.Info,
                    "Uninstallation has completed ({0:0.00}s)",
                    time / 1000);
            }
        }
        #endregion

        #region Dispose()
        /// <summary>
        /// Removes all the temporary files.
        /// </summary>
        public void Dispose()
        {
            foreach (string fileName in files)
            {
                if (File.Exists(fileName)) File.Delete(fileName);
            }
        }
        #endregion
        #endregion

        #region Public events
        /// <summary>
        /// A message for the calling application.
        /// </summary>
        public event EventHandler<PackageImportEventArgs> Message;
        #endregion

        #region Private methods
        #region FireMessage()
        /// <summary>
        /// Fires the <see cref="Message"/> event.
        /// </summary>
        /// <param name="message">The message to pass.</param>
        /// <param name="level">The level of the message.</param>
        /// <param name="values">The values for the message.</param>
        private void FireMessage(TraceLevel level, string message, params object[] values)
        {
            if (message != null)
            {
                string fullMessage = string.Format(message, values);
                PackageImportEventArgs args = new PackageImportEventArgs(fullMessage, level);
                Message(this, args);
            }
        }
        #endregion

        #region ExtractAllFiles()
        /// <summary>
        /// Extracts all the files to a temporary location
        /// </summary>
        /// <param name="packageStream">The stream to load the files from.</param>
        private void ExtractAllFiles(Stream packageStream)
        {
            tempFolder = Path.GetTempPath();
            ZipInputStream zipIn = new ZipInputStream(packageStream);
            ZipEntry entry = zipIn.GetNextEntry();
            while (entry != null)
            {
                string fileName = Path.Combine(tempFolder, entry.Name);
                using (FileStream outputWriter = File.Create(fileName))
                {
                    byte[] data = new byte[blockSize];
                    int dataLength = zipIn.Read(data, 0, blockSize);
                    while (dataLength > 0)
                    {
                        outputWriter.Write(data, 0, dataLength);
                        dataLength = zipIn.Read(data, 0, blockSize);
                    }
                    outputWriter.Close();
                }
                files.Add(fileName);
                entry = zipIn.GetNextEntry();
            }
        }
        #endregion

        #region CopyFiles()
        /// <summary>
        /// Copies files to the install location.
        /// </summary>
        /// <param name="folder">The details of the files to copy.</param>
        private void CopyFiles(FileLocation folder)
        {
            // Make sure the target folder exists
            FireMessage(TraceLevel.Verbose, "Copying files to target '{0}'", folder.Location);
            string target = ProgramDataFolder.MapPath(folder.Location);
            if (!Directory.Exists(target))
            {
                FireMessage(TraceLevel.Info, "Adding target folder '{0}'", folder.Location);
                Directory.CreateDirectory(target);
            }
            foreach (string file in folder.Files)
            {
                // Make sure the source file exists
                string source = Path.Combine(tempFolder, file);
                if (File.Exists(source))
                {
                    // Set to overwrite in case there is an older version of the file
                    FireMessage(TraceLevel.Info, "Deploying file '{0}' to target '{1}'", file, folder.Location);
                    File.Copy(source, Path.Combine(target, file), true);
                }
                else
                {
                    FireMessage(TraceLevel.Warning, "Source file '{0}' does not exist in package", file);
                }
            }
        }
        #endregion

        #region RemoveFiles()
        /// <summary>
        /// Removes files to the install location.
        /// </summary>
        /// <param name="folder">The details of the files to remove.</param>
        private void RemoveFiles(FileLocation folder)
        {
            // Make sure the target folder exists
            FireMessage(TraceLevel.Verbose, "Removing files from target '{0}'", folder.Location);
            string target = ProgramDataFolder.MapPath(folder.Location);
            if (Directory.Exists(target))
            {
                foreach (string file in folder.Files)
                {
                    // Make sure the file exists
                    string targetFile = Path.Combine(target, file);
                    if (File.Exists(targetFile))
                    {
                        // Set to overwrite in case there is an older version of the file
                        FireMessage(TraceLevel.Info, "Removing file '{0}' from target '{1}'", file, folder.Location);
                        File.Delete(targetFile);
                    }
                }
            }
        }
        #endregion

        #region UpdateConfigurationSetting()
        /// <summary>
        /// Updates a setting in the config file.
        /// </summary>
        /// <param name="configXml">The XML document contains the configuration.</param>
        /// <param name="setting">The setting to add.</param>
        /// <param name="addSettings"></param>
        private void UpdateConfigurationSetting(XmlDocument configXml, ConfigurationSetting setting, bool addSettings)
        {
            // Attempt to find the parent element
            XmlElement element = configXml.SelectSingleNode(setting.Path) as XmlElement;
            if (element != null)
            {
                FireMessage(TraceLevel.Verbose, "Element found ('{0}'), updating", setting.Path);
                string xpath = string.IsNullOrEmpty(setting.Filter) ? 
                    setting.Name : 
                    string.Format("{0}[{1}]", setting.Name, setting.Filter);
                if (addSettings)
                {
                    // Otherwise see if there is an old element, if there is then overwrite it, otherwise
                    // a new element must be added
                    XmlNode oldElement = element.SelectSingleNode(xpath);
                    if (oldElement != null)
                    {
                        FireMessage(TraceLevel.Info,
                            "Setting element '{0}' on element '{1}' to value '{2}'",
                            setting.Name,
                            setting.Path,
                            setting.Value);
                        oldElement.InnerText = setting.Value;
                        element = oldElement as XmlElement;
                    }
                    else
                    {
                        FireMessage(TraceLevel.Info,
                            "Adding new element '{0}' to element '{1}' with value '{2}'",
                            setting.Name,
                            setting.Path,
                            setting.Value);
                        XmlElement newElement = configXml.CreateElement(setting.Name);
                        newElement.InnerText = setting.Value;
                        element.AppendChild(newElement);
                        element = newElement;
                    }

                    // Set the attributes
                    foreach (ConfigurationAttribute attribute in setting.Attributes ?? new ConfigurationAttribute[0])
                    {
                        FireMessage(TraceLevel.Info,
                            "Setting attribute '{0}' on element '{1}' to value '{2}'",
                            attribute.Name,
                            setting.Name,
                            attribute.Value);
                        element.SetAttribute(attribute.Name, attribute.Value);
                    }
                }
                else
                {
                    // See if the element is there
                    XmlNode oldElement = element.SelectSingleNode(xpath);
                    if (oldElement != null)
                    {
                        FireMessage(TraceLevel.Info,
                            "Removing element '{0}' on element '{1}'",
                            setting.Name,
                            setting.Path);
                        oldElement.ParentNode.RemoveChild(oldElement);
                    }
                }
            }
            else
            {
                if (addSettings) FireMessage(TraceLevel.Warning, "Unable to find element '{0}'", setting.Path);
            }
        }
        #endregion

        #region UpdateConfigurationFile()
        /// <summary>
        /// Updates the configuration file.
        /// </summary>
        /// <param name="addSettings"></param>
        private void UpdateConfigurationFile(bool addSettings)
        {
            // Load the existing configuration file
            string configFile = DashboardConfigurationLoader.CalculateDashboardConfigPath();
            XmlDocument configXml = new XmlDocument();
            if (File.Exists(configFile))
            {
                FireMessage(TraceLevel.Verbose, "Loading configuration file");
                configXml.Load(configFile);

                // Add or update each setting
                bool configChanged = false;
                foreach (ConfigurationSetting setting in manifest.ConfigurationSettings)
                {
                    UpdateConfigurationSetting(configXml, setting, addSettings);
                    configChanged = true;
                }

                if (configChanged)
                {
                    // Save the updated configuration file
                    FireMessage(TraceLevel.Verbose, "Saving configuration file");
                    XmlWriterSettings settings = new XmlWriterSettings();
                    settings.CloseOutput = true;
                    settings.ConformanceLevel = ConformanceLevel.Document;
                    settings.Indent = true;
                    using (XmlWriter writer = XmlWriter.Create(configFile, settings))
                    {
                        configXml.Save(writer);
                        writer.Close();
                    }
                }
            }
            else
            {
                FireMessage(TraceLevel.Warning, "Configuration file does not exist");
            }
        }
        #endregion
        #endregion
    }
}
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.