MigrationEngine.cs :  » Build-Systems » CruiseControl.NET » ThoughtWorks » CruiseControl » MigrationWizard » 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 » MigrationWizard » MigrationEngine.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;

namespace ThoughtWorks.CruiseControl.MigrationWizard{
    /// <summary>
    /// The engine for performing the actual migration.
    /// </summary>
    public class MigrationEngine
    {
        #region Private fields
        private Stack<Action<string>> rollbackActions = new Stack<Action<string>>();
        private Version versionNumber;
        #endregion

        #region Version numbers
        private readonly Version version140 = new Version(1, 4, 0);
        private readonly Version version141 = new Version(1, 4, 1);
        private readonly Version version142 = new Version(1, 4, 2);
        private readonly Version version143 = new Version(1, 4, 3);
        private readonly Version version144 = new Version(1, 4, 4);
        private readonly Version version150 = new Version(1, 5, 0);
        #endregion

        #region Public properties
        #region MigrationOptions
        /// <summary>
        /// The current migration options.
        /// </summary>
        public MigrationOptions MigrationOptions { get; set; }
        #endregion
        #endregion

        #region Public methods
        #region Run()
        /// <summary>
        /// Performs a migration.
        /// </summary>
        public void Run()
        {
            FireMessage("Starting migration", MigrationEventType.Information);
            var isSuccessful = true;

            versionNumber = new Version(MigrationOptions.CurrentVersion);

            if (MigrationOptions.MigrateServer && isSuccessful)
            {
                isSuccessful = MigrateServerFiles();
            }
            if (MigrationOptions.MigrateConfiguration && isSuccessful)
            {
                isSuccessful = MigrateConfiguration();
            }
            if (MigrationOptions.MigrateWebDashboard && isSuccessful)
            {
                isSuccessful = MigrateWebDashboardFiles();
            }

            if (isSuccessful)
            {
                FireMessage("Migration has completed successfully", MigrationEventType.Information);
            }
            else
            {
                FireMessage("Migration has failed - rolling back changes", MigrationEventType.Warning);
                while (rollbackActions.Count > 0)
                {
                    var action = rollbackActions.Pop();
                    action(null);
                }
                FireMessage("Rollback completed", MigrationEventType.Information);
            }
        }
        #endregion
        #endregion

        #region Public events
        #region Message
        /// <summary>
        /// Logs a message.
        /// </summary>
        public event EventHandler<MigrationEventArgs> Message;
        #endregion
        #endregion

        #region Private methods
        #region FireMessage()
        /// <summary>
        /// Logs a message.
        /// </summary>
        /// <param name="message"></param>
        private void FireMessage(string message, MigrationEventType type)
        {
            if (Message != null)
            {
                Message(this, new MigrationEventArgs(message, type));
            }
        }
        #endregion

        #region MigrateServerFiles()
        private bool MigrateServerFiles()
        {
            var isSuccessful = false;
            try
            {
                FireMessage("Migrating server files", MigrationEventType.Information);

                if (versionNumber < version150)
                {
                    // Make sure the folder exists
                    EnsureFolderExists(MigrationOptions.NewServerLocation, "server");
                }

                // Load the configuration
                var document = new XmlDocument();
                document.Load(MigrationOptions.ConfigurationLocation);

                if (versionNumber < version150)
                {
                    // Find all the projects that don't have an artefacts or working folder and move them
                    var projectFoldersToMove = FindProjectFoldersToMove(document);
                    if (projectFoldersToMove.Count == 0)
                    {
                        FireMessage("No project folders found", MigrationEventType.Information);
                    }
                    else
                    {
                        FireMessage(string.Format("{0} project folder(s) found", projectFoldersToMove.Count), MigrationEventType.Information);
                        foreach (var projectName in projectFoldersToMove)
                        {
                            var oldProjectPath = Path.Combine(MigrationOptions.CurrentServerLocation, projectName);
                            var newProjectPath = Path.Combine(MigrationOptions.NewServerLocation, projectName);
                            MoveFolder(oldProjectPath,
                                newProjectPath,
                                string.Format("Project folder for '{0}' moved", projectName),
                                string.Format("Project folder for '{0}' restored", projectName));
                        }
                    }

                    // Move the project state files
                    var projectStatesToMove = FindProjectStatesToMove(document);
                    if (projectStatesToMove.Count == 0)
                    {
                        FireMessage("No project state files found", MigrationEventType.Information);
                    }
                    else
                    {
                        FireMessage(string.Format("{0} project state file(s) found", projectStatesToMove.Count), MigrationEventType.Information);
                        foreach (var projectName in projectStatesToMove)
                        {
                            var oldProjectPath = Path.Combine(MigrationOptions.CurrentServerLocation, projectName + ".state");
                            var newProjectPath = Path.Combine(MigrationOptions.NewServerLocation, projectName + ".state");
                            MoveFile(oldProjectPath,
                                newProjectPath,
                                string.Format("Project state file for '{0}' moved", projectName),
                                string.Format("Project state file for '{0}' restored", projectName));
                        }
                    }

                    // Move the project state file
                    var stateFile = Path.Combine(MigrationOptions.CurrentServerLocation, "ProjectsState.xml");
                    if (File.Exists(stateFile))
                    {
                        MoveFile(stateFile,
                            Path.Combine(MigrationOptions.NewServerLocation, "ProjectsState.xml"),
                            "Project state file moved",
                            "Project state file restored");
                    }
                }

                // Update the configuration files
                var logLocation = Path.Combine(MigrationOptions.NewServerLocation, "ccnet.log");
                UpdateServerConfigurationFile(logLocation, "ccnet.exe.config");
                UpdateServerConfigurationFile(logLocation, "ccservice.exe.config");

                // Update any statistics files
                if (versionNumber < version143)
                {
                    var statisticsFiles = FindStatisticsFiles(document);
                    if (statisticsFiles.Count == 0)
                    {
                        FireMessage("No statistics files found", MigrationEventType.Information);
                    }
                    else
                    {
                        FireMessage(string.Format("{0} statistics file(s) found", statisticsFiles.Count), MigrationEventType.Information);
                        foreach (var statisticsFile in statisticsFiles)
                        {
                            FireMessage(string.Format("Migrating {0}", statisticsFile), MigrationEventType.Information);
                            var lines = File.ReadAllLines(statisticsFile);
                            using (var output = File.CreateText(statisticsFile))
                            {
                                foreach (var line in lines)
                                {
                                    if (!string.Equals(line, "<statistics>") &&
                                        !string.Equals(line, "</statistics>"))
                                    {
                                        output.WriteLine(line);
                                    }
                                }
                                output.Flush();
                            }
                        }
                    }
                }

                FireMessage("Server files successfully migrated", MigrationEventType.Information);
                isSuccessful = true;
            }
            catch (Exception error)
            {
                FireMessage("An unexpected error has occurred while migrating server files: " + error.Message, MigrationEventType.Error);
            }
            FireMessage("Server migration completed " + (isSuccessful ? "without errors" : "with errors"), MigrationEventType.Status);
            return isSuccessful;
        }
        #endregion

        #region UpdateServerConfigurationFile()
        private void UpdateServerConfigurationFile(string logLocation, string configFileName)
        {
            FireMessage("Updating server configuration file: " + configFileName, MigrationEventType.Information);
            var changeCount = 0;

            var configFile = Path.Combine(MigrationOptions.CurrentServerLocation, configFileName);
            if (MigrationOptions.BackupServerConfiguration)
            {
                BackupFile(configFile);
            }
            var configDocument = new XmlDocument();
            configDocument.Load(configFile);

            if (versionNumber < version150)
            {
                changeCount += UpdateAttribute(configDocument, "/configuration/appSettings/add[@key='ServerLogFilePath']", "value", "ccnet.log", logLocation) ? 1 : 0;
                changeCount += UpdateAttribute(configDocument, "/configuration/log4net/appender[@name='RollingFileAppender']/file", "value", "ccnet.log", logLocation) ? 1 : 0;
            }
            if (changeCount > 0)
            {
                configDocument.Save(configFile);
                FireMessage("Server configuration file updated", MigrationEventType.Information);
            }
            else
            {
                FireMessage("Server configuration file not changed - up to date", MigrationEventType.Information);
            }
        }
        #endregion

        #region UpdateNode()
        private bool UpdateAttribute(XmlDocument configDocument, string xpath, string attribute, string oldValue, string newValue)
        {
            var updated = false;
            var node = configDocument.SelectSingleNode(xpath) as XmlElement;
            if (node != null)
            {
                var nodeValue = node.GetAttribute(attribute);
                if (string.Equals(oldValue, nodeValue))
                {
                    node.SetAttribute(attribute, newValue);
                    updated = true;
                }
            }

            return updated;
        }
        #endregion

        #region BackupFile()
        /// <summary>
        /// Backups a file.
        /// </summary>
        /// <param name="fileName"></param>
        private void BackupFile(string fileName)
        {
            FireMessage("Backing up " + fileName, MigrationEventType.Information);

            var loop = 0;
            var newFile = Path.Combine(Path.GetDirectoryName(fileName),
                Path.GetFileNameWithoutExtension(fileName) +
                "(Backup)" + 
                Path.GetExtension(fileName));
            while (File.Exists(newFile))
            {
                newFile = Path.Combine(Path.GetDirectoryName(fileName),
                    Path.GetFileNameWithoutExtension(fileName) +
                    string.Format(" (Backup {0})", ++loop) +
                    Path.GetExtension(fileName));
            }

            File.Copy(fileName, newFile);

            FireMessage(
                string.Format("{0} backed up to {1}", Path.GetFileName(fileName), newFile),
                MigrationEventType.Information);
        }
        #endregion

        #region FindProjectNode()
        /// <summary>
        /// Find the parent project node.
        /// </summary>
        /// <param name="itemNode"></param>
        /// <returns></returns>
        private XmlNode FindProjectNode(XmlNode itemNode)
        {
            var node = itemNode.ParentNode;
            while ((node != null) && (node.Name != "project"))
            {
                node = node.ParentNode;
            }
            return node;
        }
        #endregion

        #region FindStatisticsFiles()
        private List<string> FindStatisticsFiles(XmlDocument document)
        {
            FireMessage("Searching for statistics publishers", MigrationEventType.Information);
            var statisticsFiles = new List<string>();
            foreach (XmlElement statisticsEl in document.SelectNodes("//statistics"))
            {
                var projectEl = FindProjectNode(statisticsEl) as XmlElement;
                var artefactFolder = RetrievePropertyValue(projectEl, "artifactDirectory");

                string fileName;
                if (!string.IsNullOrEmpty(artefactFolder))
                {
                    fileName = Path.Combine(artefactFolder, "report.xml");
                }
                else
                {
                    var projectName = RetrievePropertyValue(projectEl, "name");
                    fileName = Path.Combine(
                            Path.Combine(MigrationOptions.NewServerLocation, projectName),
                            Path.Combine("Artifacts", "report.xml"));
                }
                if (File.Exists(fileName))
                {
                    statisticsFiles.Add(fileName);
                }
            }
            return statisticsFiles;
        }
        #endregion

        #region FindProjectFoldersToMove()
        private List<string> FindProjectFoldersToMove(XmlDocument document)
        {
            FireMessage("Searching for project folders to migrate", MigrationEventType.Information);
            var projectFoldersToMove = new List<string>();
            foreach (XmlElement projectEl in document.SelectNodes("/cruisecontrol/project"))
            {
                var hasWorking = !string.IsNullOrEmpty(projectEl.GetAttribute("workingDirectory")) ||
                    (projectEl.SelectSingleNode("workingDirectory") != null);
                var hasArtefact = !string.IsNullOrEmpty(projectEl.GetAttribute("artifactDirectory")) ||
                    (projectEl.SelectSingleNode("artifactDirectory") != null);

                if (!hasArtefact || !hasWorking)
                {
                    var projectName = RetrievePropertyValue(projectEl, "name");

                    // Since we are not validating the XML, there is the possibility of invalid XML (i.e. no name)
                    if (!string.IsNullOrEmpty(projectName))
                    {
                        var projectPath = Path.Combine(MigrationOptions.CurrentServerLocation, projectName);
                        if (Directory.Exists(projectPath)) projectFoldersToMove.Add(projectName);
                    }
                }
            }
            return projectFoldersToMove;
        }
        #endregion

        #region FindProjectStatesToMove()
        private List<string> FindProjectStatesToMove(XmlDocument document)
        {
            FireMessage("Searching for project state files to migrate", MigrationEventType.Information);
            var projectStatesToMove = new List<string>();
            foreach (XmlElement projectEl in document.SelectNodes("/cruisecontrol/project"))
            {
                var projectName = RetrievePropertyValue(projectEl, "name");

                // Since we are not validating the XML, there is the possibility of invalid XML (i.e. no name)
                if (!string.IsNullOrEmpty(projectName))
                {
                    var projectPath = Path.Combine(MigrationOptions.CurrentServerLocation, projectName + ".state");
                    if (File.Exists(projectPath)) projectStatesToMove.Add(projectName);
                }
            }
            return projectStatesToMove;
        }
        #endregion

        #region RetrievePropertyValue()
        private string RetrievePropertyValue(XmlElement parentEl, string property)
        {
            var value = parentEl.GetAttribute(property);
            if (string.IsNullOrEmpty(value))
            {
                var nameEl = parentEl.SelectSingleNode(property);
                if (nameEl != null) value = nameEl.InnerText;
            }
            return value;
        }
        #endregion

        #region MoveFolder()
        private void MoveFolder(string oldPath, string newPath, string completedMessage, string rollbackMessage)
        {
            FireMessage(
                string.Format("Moving folder '{0}' to '{1}'", oldPath, newPath),
                MigrationEventType.Information);
            if (Directory.Exists(newPath))
            {
                FireMessage(
                    string.Format("Folder '{0}' already exists - unable to move", newPath),
                    MigrationEventType.Warning);
            }
            else
            {
                Directory.Move(oldPath, newPath);
                FireMessage(completedMessage, MigrationEventType.Information);
                rollbackActions.Push(s =>
                {
                    FireMessage(
                        string.Format("Moving folder '{0}' to '{1}'", newPath, oldPath),
                        MigrationEventType.Information);
                    Directory.Move(newPath, oldPath);
                    FireMessage(rollbackMessage, MigrationEventType.Information);
                });
            }
        }
        #endregion

        #region MoveFile()
        private void MoveFile(string oldPath, string newPath, string completedMessage, string rollbackMessage)
        {
            FireMessage(
                string.Format("Moving file '{0}' to '{1}'", oldPath, newPath),
                MigrationEventType.Information);
            if (File.Exists(newPath))
            {
                FireMessage(
                    string.Format("File '{0}' already exists - unable to move", newPath),
                    MigrationEventType.Warning);
            }
            else
            {
                File.Move(oldPath, newPath);
                FireMessage(completedMessage, MigrationEventType.Information);
                rollbackActions.Push(s =>
                {
                    FireMessage(
                        string.Format("Moving file '{0}' to '{1}'", newPath, oldPath),
                        MigrationEventType.Information);
                    File.Move(newPath, oldPath);
                    FireMessage(rollbackMessage, MigrationEventType.Information);
                });
            }
        }
        #endregion

        #region EnsureFolderExists()
        private void EnsureFolderExists(string folderPath, string name)
        {
            if (!Directory.Exists(folderPath))
            {
                FireMessage("Creating " + name + " folder: " + folderPath, MigrationEventType.Information);
                Directory.CreateDirectory(folderPath);
                rollbackActions.Push(s =>
                {
                    FireMessage("Deleting " + name + " folder: " + folderPath, MigrationEventType.Information);
                    Directory.Delete(folderPath, true);
                    FireMessage("Server folder deleted", MigrationEventType.Information);
                });
                FireMessage(CapitialiseName(name) + " folder created", MigrationEventType.Information);
            }
            else
            {
                FireMessage(CapitialiseName(name) + " folder already exists: " + folderPath, MigrationEventType.Information);
            }
        }
        #endregion

        #region CapitialiseName()
        private string CapitialiseName(string name)
        {
            return name.Substring(0, 1).ToUpper() + name.Substring(1);
        }
        #endregion

        #region MigrateConfiguration()
        private bool MigrateConfiguration()
        {
            var isSuccessful = false;
            try
            {
                FireMessage("Migrating configuration", MigrationEventType.Information);

                // Backup the configuration
                if (MigrationOptions.BackupConfiguration)
                {
                    BackupFile(MigrationOptions.ConfigurationLocation);
                }

                // Open the configuration file
                var configDoc = new XmlDocument();
                configDoc.Load(MigrationOptions.ConfigurationLocation);

                if (versionNumber < version150)
                {
                    FireMessage("Updating e-mail group configuration", MigrationEventType.Information);
                    var groups = configDoc.SelectNodes("//email/groups/group");
                    if (groups.Count == 0)
                    {
                        FireMessage("No e-mail groups found", MigrationEventType.Information);
                    }
                    else
                    {
                        foreach (XmlElement groupEl in groups)
                        {
                            // Retrieve the property value
                            var notification = RetrievePropertyValue(groupEl, "notification");

                            // Remove the old value
                            var notificationEl = groupEl.SelectSingleNode("notification");
                            if (notificationEl != null)
                            {
                                groupEl.RemoveChild(notificationEl);
                            }
                            else 
                            {
                                groupEl.RemoveAttribute("notification");
                            }

                            // Add the new structure
                            var notificationsEl = configDoc.CreateElement("notifications");
                            groupEl.AppendChild(notificationsEl);
                            notificationEl = configDoc.CreateElement("notificationType");
                            notificationsEl.AppendChild(notificationEl);
                            if (!string.IsNullOrEmpty(notification))
                            {
                                notificationEl.InnerText = notification;
                            }
                            else
                            {
                                notificationEl.InnerText = "Always";
                            }
                        }
                        FireMessage(
                            string.Format("{0} e-mail groups found and converted", groups.Count),
                            MigrationEventType.Information);
                    }
                }

                // Save the configuration file
                configDoc.Save(MigrationOptions.ConfigurationLocation);

                FireMessage("Configuration files successfully migrated", MigrationEventType.Information);
                isSuccessful = true;
            }
            catch (Exception error)
            {
                FireMessage("An unexpected error has occurred while migrating configuration: " + error.Message, MigrationEventType.Error);
            }
            FireMessage("Configuration migration completed " + (isSuccessful ? "without errors" : "with errors"), MigrationEventType.Status);
            return isSuccessful;
        }
        #endregion

        #region MigrateWebDashboardFiles()
        private bool MigrateWebDashboardFiles()
        {
            var isSuccessful = false;
            try
            {
                FireMessage("Migrating web dashboard files", MigrationEventType.Information);

                if (versionNumber < version150)
                {
                    // Make sure the folder exists
                    EnsureFolderExists(MigrationOptions.NewWebDashboardLocation, "web dashboard");
                }

                if (versionNumber < version150)
                {
                    // Move the dashboard configuration
                    var stateFile = Path.Combine(MigrationOptions.CurrentWebDashboardLocation, "dashboard.config");
                    if (File.Exists(stateFile))
                    {
                        MoveFile(stateFile,
                            Path.Combine(MigrationOptions.NewWebDashboardLocation, "dashboard.config"),
                            "Dashboard configuration moved",
                            "Dashboard configuration restored");
                    }

                    // Move the packages folder
                    var packagesFolder = Path.Combine(MigrationOptions.CurrentWebDashboardLocation, "packages");
                    if (Directory.Exists(packagesFolder))
                    {
                        MoveFolder(packagesFolder,
                            Path.Combine(MigrationOptions.NewWebDashboardLocation, "packages"),
                            "Packages folder moved",
                            "Packages folder restored");
                    }
                }

                FireMessage("Web dashboard files successfully migrated", MigrationEventType.Information);
                isSuccessful = true;
            }
            catch (Exception error)
            {
                FireMessage("An unexpected error has occurred while migrating web dashboard files: " + error.Message, MigrationEventType.Error);
            }
            FireMessage("Web dashboard migration completed " + (isSuccessful ? "without errors" : "with errors"), MigrationEventType.Status);
            return isSuccessful;
        }
        #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.