public async Task <InstallScript> ConvertManifestXml(XmlDocument doc, string name)
        {
            ExportProcessor.EnsureSystemData(_conn, ref _itemTypes);

            foreach (var elem in doc.ElementsByXPath("//Item[@action='add']").ToList())
            {
                elem.SetAttribute("action", "merge");
            }
            ItemType itemType;

            foreach (var elem in doc.ElementsByXPath("//Item[@type and @id]").ToList())
            {
                if (_itemTypes.TryGetValue(elem.Attribute("type", "").ToLowerInvariant(), out itemType) && itemType.IsVersionable)
                {
                    elem.SetAttribute(XmlFlags.Attr_ConfigId, elem.Attribute("id"));
                    elem.SetAttribute("where", string.Format("[{0}].[config_id] = '{1}'", itemType.Name.Replace(' ', '_'), elem.Attribute("id")));
                    elem.RemoveAttribute("id");
                }
            }

            var result = new InstallScript()
            {
                Title = name
            };
            await _exportTools.Export(result, doc).ConfigureAwait(false);

            return(result);
        }
Exemple #2
0
        public void Write(InstallScript script)
        {
            using (var xml = XmlTextWriter.Create(_path, _settings))
            {
                xml.WriteStartElement("imports");
                xml.WriteStartElement("package");
                xml.WriteAttributeString("name", script.Title);

                if (script.Title.StartsWith("com.aras.innovator"))
                {
                    if (script.Title.StartsWith("com.aras.innovator.solution."))
                    {
                        _baseFolderPath = Utils.CleanFileName(script.Title).Substring(28).Replace('.', '\\') + "\\Import";
                        xml.WriteAttributeString("path", _baseFolderPath);
                    }
                    else
                    {
                        _baseFolderPath = Utils.CleanFileName(script.Title).Replace('.', '\\');
                        xml.WriteAttributeString("path", ".\\");
                    }
                }
                else
                {
                    _baseFolderPath = Utils.CleanFileName(script.Title) + "\\Import";
                    xml.WriteAttributeString("path", _baseFolderPath);
                }

                xml.WriteEndElement();
                xml.WriteEndElement();
            }

            _baseFolderPath = Path.Combine(Path.GetDirectoryName(_path), _baseFolderPath);

            XmlWriter writer;
            var       existingPaths = new HashSet <string>();
            string    newPath;

            foreach (var line in script.Lines.Where(l => l.Type == InstallType.Create || l.Type == InstallType.Script))
            {
                newPath = line.FilePath(existingPaths);
                writer  = GetWriter(newPath);
                try
                {
                    writer.WriteStartElement("AML");
                    line.Script.WriteTo(writer);
                    writer.WriteEndElement();
                    writer.Flush();
                }
                finally
                {
                    writer.Close();
                }

                existingPaths.Add(newPath);
            }
        }
 public async Task Initialize(InstallScript script)
 {
     _script = script;
     _lines  = (_script.DependencySorted
 ? (_script.Lines ?? Enumerable.Empty <InstallItem>())
 : (await _sorter.SortByDependencies(script.Lines, _conn).ConfigureAwait(false))
                .Where(l => l.Type != InstallType.DependencyCheck)
                ).Where(l => l.Script != null && l.Type != InstallType.Warning).ToList();
     _currLine = -1;
 }
    public void Write(InstallScript script)
    {
      using (var xml = XmlTextWriter.Create(_path, _settings))
      {
        xml.WriteStartElement("imports");
        xml.WriteStartElement("package");
        xml.WriteAttributeString("name", script.Title);

        if (script.Title.StartsWith("com.aras.innovator"))
        {
          if (script.Title.StartsWith("com.aras.innovator.solution."))
          {
            _baseFolderPath = Utils.CleanFileName(script.Title).Substring(28).Replace('.', '\\') + "\\Import";
            xml.WriteAttributeString("path", _baseFolderPath);
          }
          else
          {
            _baseFolderPath = Utils.CleanFileName(script.Title).Replace('.', '\\');
            xml.WriteAttributeString("path", ".\\");
          }
        }
        else
        {
          _baseFolderPath = Utils.CleanFileName(script.Title) + "\\Import";
          xml.WriteAttributeString("path", _baseFolderPath);
        }

        xml.WriteEndElement();
        xml.WriteEndElement();
      }

      _baseFolderPath = Path.Combine(Path.GetDirectoryName(_path), _baseFolderPath);

      XmlWriter writer;
      var existingPaths = new HashSet<string>();
      string newPath;
      foreach (var line in script.Lines.Where(l => l.Type == InstallType.Create || l.Type == InstallType.Script))
      {
        newPath = line.FilePath(existingPaths);
        writer = GetWriter(newPath);
        try
        {
          writer.WriteStartElement("AML");
          line.Script.WriteTo(writer);
          writer.WriteEndElement();
          writer.Flush();
        }
        finally
        {
          writer.Close();
        }

        existingPaths.Add(newPath);
      }
    }
 public async Task Initialize(InstallScript script)
 {
   _log.Length = 0;
   _script = script;
   _lines = (_script.DependencySorted
     ? _script.Lines
     : (await ExportProcessor.SortByDependencies(script.Lines, _conn))
       .Where(l => l.Type != InstallType.DependencyCheck)
   ).Where(l => l.Script != null && l.Type != InstallType.Warning).ToList();
   _currLine = -1;
 }
    public override void Write(InstallScript script)
    {
      _package.PackageProperties.Created = script.Created;
      _package.PackageProperties.Creator = script.Creator;
      _package.PackageProperties.Description = script.Description;
      _package.PackageProperties.Modified = script.Modified;
      _package.PackageProperties.Revision = script.Version;
      _package.PackageProperties.Title = script.Title;
      if (script.Website != null)
        _package.PackageProperties.Identifier = script.Website.ToString();

      base.Write(script);
    }
Exemple #7
0
        public static PackageMetadataProvider FromScript(InstallScript script)
        {
            var metadata = new PackageMetadataProvider()
            {
                Title = script.Title
            };

            metadata.AddRange(script.Lines
                              .Where(l => l.Type != InstallType.DependencyCheck &&
                                     l.Type != InstallType.Warning)
                              .Select(l => ElementFactory.Local.FromXml(l.Script).AssertItem()));
            return(metadata);
        }
        public InstallScript Merge(IPackage baseDir, IPackage compareDir)
        {
            var docs     = new List <Tuple <XmlDocument, string> >();
            var metadata = baseDir.WriteAmlMergeScripts(compareDir, (path, prog) =>
            {
                ProgressChanged?.Invoke(this, new ProgressChangedEventArgs("Reading files", prog / 2));
                var doc = new XmlDocument();
                docs.Add(Tuple.Create(doc, path));
                return(doc.CreateNavigator().AppendChild());
            });

            ProgressChanged?.Invoke(this, new ProgressChangedEventArgs("Performing cleanup", 50));

            var allItems = docs
                           .Where(d => d.Item1.DocumentElement != null)
                           .SelectMany(d => d.Item1.DocumentElement
                                       .DescendantsAndSelf(el => el.LocalName == "Item"))
                           .ToArray();

            RemoveDeletesForItemsWithMultipleScripts(allItems);
            RemoveChangesToSystemProperties(allItems);

            var installScripts = docs
                                 .Where(d => d.Item1.DocumentElement != null)
                                 .SelectMany(d => XmlUtils.RootItems(d.Item1.DocumentElement)
                                             .Select(i => InstallItem.FromScript(i, d.Item2)))
                                 .ToArray();

            ProgressChanged?.Invoke(this, new ProgressChangedEventArgs("Processing dependencies", 75));

            var lines = (SortDependencies
        ? _sorter.SortByDependencies(installScripts, metadata)
        : installScripts).ToList();

            lines.RemoveWhere(i => i.Type == InstallType.DependencyCheck);

            var script = new InstallScript()
            {
                Created = DateTime.Now,
                Creator = Environment.UserName,
                Title   = "MergeScript",
                Lines   = lines
            };

            lines.InsertRange(0, FillInNullsOnRequiredProperties(allItems, metadata));

            ProgressChanged?.Invoke(this, new ProgressChangedEventArgs("Processing dependencies", 80));

            return(script);
        }
Exemple #9
0
        private static bool TryReadLegacyManifest(IPackageFile manifestFile, IPackage package, ILogger logger, out InstallScript installScript)
        {
            installScript = new InstallScript();
            var scripts  = new List <InstallItem>();
            var manifest = new XmlDocument();

            using (var manifestStream = manifestFile.Open())
                manifest.Load(manifestStream);

            foreach (var pkg in manifest.DocumentElement.Elements("package"))
            {
                if (string.IsNullOrEmpty(installScript.Title))
                {
                    installScript.Title = pkg.Attribute("name", "");
                }
                var folderPath = pkg.Attribute("path");
                if (folderPath == ".\\")
                {
                    folderPath = Utils.CleanFileName(pkg.Attribute("name", "")).Replace('.', '\\');
                }
                foreach (var file in package.Files()
                         .Where(f => f.Path.StartsWith(folderPath + "/", StringComparison.OrdinalIgnoreCase) &&
                                f.Path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)))
                {
                    try
                    {
                        var doc = new XmlDocument(manifest.NameTable);
                        using (var stream = file.Open())
                            doc.Load(stream);

                        var items = doc.DocumentElement.LocalName == "Item"
              ? new[] { doc.DocumentElement }
              : doc.DocumentElement.Elements("Item");
                        foreach (var item in items)
                        {
                            scripts.Add(InstallItem.FromScript(item, file.Path));
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.Data["path"] = file.Path;
                        throw;
                    }
                }
            }

            installScript.Lines = scripts;
            return(CleanKeyedNames(installScript.Lines, logger));
        }
        public override void Write(InstallScript script)
        {
            _package.PackageProperties.Created     = script.Created;
            _package.PackageProperties.Creator     = script.Creator;
            _package.PackageProperties.Description = script.Description;
            _package.PackageProperties.Modified    = script.Modified;
            _package.PackageProperties.Revision    = script.Version;
            _package.PackageProperties.Title       = script.Title;
            if (script.Website != null)
            {
                _package.PackageProperties.Identifier = script.Website.ToString();
            }

            base.Write(script);
        }
Exemple #11
0
 public static bool TryRead(this IPackage package, ILogger logger, out InstallScript installScript)
 {
     using (SharedUtils.StartActivity("Package.TryRead", "Read an Innovator Package from disk"))
     {
         var manifestFile = package.Manifest(false);
         if (manifestFile.Path.EndsWith(".mf", StringComparison.OrdinalIgnoreCase))
         {
             return(TryReadLegacyManifest(manifestFile, package, logger, out installScript));
         }
         else
         {
             return(TryReadPackage(manifestFile, package, logger, out installScript));
         }
     }
 }
    public InstallScript ConvertManifestXml(XmlDocument doc, string name)
    {
      ExportProcessor.EnsureSystemData(_conn, ref _itemTypes);

      foreach (var elem in doc.ElementsByXPath("//Item[@action='add']").ToList())
      {
        elem.SetAttribute("action", "merge");
      }
      ItemType itemType;
      foreach (var elem in doc.ElementsByXPath("//Item[@type and @id]").ToList())
      {
        if (_itemTypes.TryGetValue(elem.Attribute("type", "").ToLowerInvariant(), out itemType) && itemType.IsVersionable)
        {
          elem.SetAttribute(XmlFlags.Attr_ConfigId, elem.Attribute("id"));
          elem.SetAttribute("where", string.Format("[{0}].[config_id] = '{1}'", itemType.Name.Replace(' ', '_'), elem.Attribute("id")));
          elem.RemoveAttribute("id");
        }
      }

      var result = new InstallScript();
      result.Title = name;
      _exportTools.Export(result, doc);
      return result;
    }
Exemple #13
0
        public bool Write(InstallScript script,
                          Func <string, DatabasePackageAction> errorHandler = null,
                          Action <int, string> reportProgress = null)
        {
            var cont       = true;
            var typeGroups = from l in script.Lines
                             where l.Type == InstallType.Create
                             group l by l.Reference.Type into typeGroup
                             select typeGroup;
            var    cnt           = typeGroups.Count();
            var    idx           = 0;
            var    packageGroups = new HashSet <string>();
            string currPackageId = null;

            while (cont)
            {
                IEnumerable <IReadOnlyItem> elements;
                foreach (var typeGroup in typeGroups)
                {
                    if (reportProgress != null)
                    {
                        reportProgress((int)(idx * 50.0 / cnt), string.Format("Checking for existing package elements ({0} of {1}) ", idx + 1, cnt));
                    }

                    if (typeGroup.First().Reference.Unique.IsGuid())
                    {
                        elements = _conn.Apply("<Item type=\"PackageElement\" action=\"get\" select=\"element_id,name,source_id\"><element_type>"
                                               + typeGroup.Key
                                               + "</element_type><element_id condition=\"in\">'"
                                               + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + "','" + c)
                                               + "'</element_id></Item>").Items();
                    }
                    else
                    {
                        elements = _conn.Apply("<Item type=\"PackageElement\" action=\"get\" select=\"element_id,name,source_id\"><element_type>"
                                               + typeGroup.Key
                                               + "</element_type><element_id condition=\"in\">(select id from innovator.["
                                               + typeGroup.Key.Replace(' ', '_')
                                               + "] where "
                                               + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + " or " + c)
                                               + ")</element_id></Item>").Items();
                    }

                    packageGroups.UnionWith(elements.Select(e => e.SourceId().Value));
                    idx++;
                }

                var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"get\" select=\"name\"><id condition=\"in\">(select SOURCE_ID FROM innovator.PACKAGEGROUP where id in ('"
                                           + packageGroups.Aggregate((p, c) => p + "','" + c)
                                           + "'))</id></Item>").Items();
                currPackageId = packages.Where(p => p.Property("name").Value == script.Title).SingleOrDefault().Id();

                cont = false;
                if (packages.Any(p => p.Property("name").Value != script.Title))
                {
                    if (errorHandler != null)
                    {
                        var packageList = (from p in packages
                                           where p.Property("name").Value != script.Title
                                           select p.Property("name").Value)
                                          .Aggregate((p, c) => p + ", " + c);
                        switch (errorHandler("The package cannot be created because one or more elements exist in the packages: " + packageList))
                        {
                        case DatabasePackageAction.TryAgain:
                            cont = true;
                            break;

                        case DatabasePackageAction.RemoveElementsFromPackages:
                            foreach (var typeGroup in typeGroups)
                            {
                                if (reportProgress != null)
                                {
                                    reportProgress((int)(idx * 50.0 / cnt), string.Format("Removing package elements ({0} of {1}) ", idx + 1, cnt));
                                }

                                if (typeGroup.First().Reference.Unique.IsGuid())
                                {
                                    elements = _conn.Apply("<Item type=\"PackageElement\" action=\"purge\" where=\"[PackageElement].[element_type] = '"
                                                           + typeGroup.Key
                                                           + "' and [PackageElement].[element_id] in ('"
                                                           + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + "','" + c)
                                                           + "')\" />").Items();
                                }
                                else
                                {
                                    elements = _conn.Apply("<Item type=\"PackageElement\" action=\"purge\" where=\"[PackageElement].[element_type] = '"
                                                           + typeGroup.Key
                                                           + "' and [PackageElement].[element_id] in (select id from innovator.["
                                                           + typeGroup.Key.Replace(' ', '_')
                                                           + "] where "
                                                           + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + " or " + c)
                                                           + ")\" />").Items();
                                }

                                idx++;
                            }


                            break;

                        default:
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            // Try one more time to get the package
            if (string.IsNullOrEmpty(currPackageId))
            {
                var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"get\" select=\"name\"><name>" + script.Title + "</name></Item>");
                currPackageId = packages.AssertItem().Id();
            }

            // Add the package
            if (string.IsNullOrEmpty(currPackageId))
            {
                var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"add\" ><name>" + script.Title + "</name></Item>", true);
                currPackageId = packages.AssertItem().Id();
            }

            string groupId;

            foreach (var typeGroup in typeGroups)
            {
                if (reportProgress != null)
                {
                    reportProgress((int)(50 + idx * 50.0 / cnt), string.Format("Adding package elements of type ({0} of {1}) ", idx + 1, cnt));
                }

                groupId = _conn.Apply("<Item type=\"PackageGroup\" action=\"merge\" where=\"[PackageGroup].[source_id] = '"
                                      + currPackageId
                                      + "' and [PackageGroup].[name] = '"
                                      + typeGroup.Key
                                      + "'\"><name>"
                                      + typeGroup.Key
                                      + "</name></Item>", true).AssertItem().Id();

                foreach (var elem in typeGroup)
                {
                    _conn.Apply("<Item type=\"PackageElement\" action=\"merge\" where=\"[PackageElement].[source_id] = '"
                                + groupId
                                + "' and [PackageElement].[element_id] = '"
                                + (elem.InstalledId ?? elem.Reference.Unique)
                                + "'\">"
                                + "<element_type>" + typeGroup.Key + "</element_type>"
                                + "<element_id>" + (elem.InstalledId ?? elem.Reference.Unique) + "</element_id>"
                                + "<source_id>" + groupId + "</source_id>"
                                + "<name>" + elem.Reference.KeyedName + "</name></Item>").AssertNoError();
                }

                idx++;
            }

            return(true);
        }
        public virtual InstallScript Read()
        {
            var result = new InstallScript();

            XmlDocument          doc;
            var                  scripts  = new List <InstallItem>();
            var                  manifest = new XmlDocument();
            string               currPath;
            IEnumerable <string> paths;

            manifest.Load(GetExistingStream(null));

            if (manifest.DocumentElement.HasAttribute("created"))
            {
                result.Created = DateTime.Parse(manifest.DocumentElement.GetAttribute("created"));
            }
            result.Creator     = manifest.DocumentElement.GetAttribute("creator");
            result.Description = manifest.DocumentElement.GetAttribute("description");
            if (manifest.DocumentElement.HasAttribute("modified"))
            {
                result.Modified = DateTime.Parse(manifest.DocumentElement.GetAttribute("modified"));
            }
            result.Version = manifest.DocumentElement.GetAttribute("revision");
            result.Title   = manifest.DocumentElement.GetAttribute("title");
            if (manifest.DocumentElement.HasAttribute("website"))
            {
                result.Website = new Uri(manifest.DocumentElement.GetAttribute("website"));
            }

            foreach (var child in manifest.DocumentElement.ChildNodes.OfType <XmlElement>())
            {
                if (child.LocalName == "Item")
                {
                    scripts.Add(InstallItem.FromScript(child));
                }
                else
                {
                    currPath = child.GetAttribute("path");
                    paths    = string.IsNullOrEmpty(currPath)
            ? Enumerable.Empty <string>()
            : (currPath == "*"
              ? GetPaths()
              : Enumerable.Repeat(currPath, 1));

                    if (currPath == "*")
                    {
                        result.DependencySorted = false;
                    }
                    var reportXmlPaths = new HashSet <string>(paths
                                                              .Where(p => p.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
                                                              .Select(p => p + ".xml"), StringComparer.OrdinalIgnoreCase);

                    foreach (var path in paths
                             .Where(p => !reportXmlPaths.Contains(p)))
                    {
                        if (path.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
                        {
                            doc = ReadReport(path);
                        }
                        else
                        {
                            try
                            {
                                doc = new XmlDocument(manifest.NameTable);
                                var stream = GetExistingStream(path);
                                if (stream == null)
                                {
                                    throw new FileNotFoundException("A referenced file was not found in the package", path);
                                }
                                using (stream)
                                    using (var reader = new StreamReader(stream))
                                    {
                                        var text = reader.ReadToEnd();
                                        doc.LoadXml(text);
                                    }
                            }
                            catch (Exception ex) when(ex is XmlException || ex is IOException)
                            {
                                throw new InvalidOperationException($"Error reading the file {path}: {ex.Message}", ex);
                            }
                        }

                        var items = doc.DocumentElement.LocalName == "Item"
              ? new[] { doc.DocumentElement }
              : doc.DocumentElement.Elements("Item");
                        foreach (var item in items)
                        {
                            scripts.Add(InstallItem.FromScript(item, path));
                        }
                    }
                }
            }

            result.Lines = scripts;
            result.Lines.CleanKeyedNames();

            return(result);
        }
        public virtual void Write(InstallScript script)
        {
            string newPath;
            var    existingPaths = new HashSet <string>();

            // Record the import order
            var settings = new XmlWriterSettings()
            {
                OmitXmlDeclaration = true,
                Indent             = true,
                IndentChars        = "  "
            };

            using (var manifestStream = GetNewStream(null))
            {
                using (var manifestWriter = XmlWriter.Create(manifestStream, settings))
                {
                    manifestWriter.WriteStartElement("Import");

                    if (script.Created.HasValue)
                    {
                        manifestWriter.WriteAttributeString("created", script.Created.Value.ToString("s"));
                    }
                    manifestWriter.WriteAttributeString("creator", script.Creator);
                    manifestWriter.WriteAttributeString("description", script.Description);
                    if (script.Modified.HasValue)
                    {
                        manifestWriter.WriteAttributeString("modified", script.Modified.Value.ToString("s"));
                    }
                    manifestWriter.WriteAttributeString("revision", script.Version);
                    manifestWriter.WriteAttributeString("title", script.Title);
                    if (script.Website != null)
                    {
                        manifestWriter.WriteAttributeString("website", script.Website.ToString());
                    }

                    foreach (var line in script.Lines)
                    {
                        if (line.Type == InstallType.Warning)
                        {
                            // Do nothing
                        }
                        else if (line.Type == InstallType.DependencyCheck)
                        {
                            line.Script.WriteTo(manifestWriter);
                        }
                        else
                        {
                            if (line.Reference.Type == "Report" && line.Type != InstallType.Script)
                            {
                                newPath = line.FilePath(existingPaths, ".xslt");
                                WriteReport(line, newPath);
                            }
                            else
                            {
                                newPath = line.FilePath(existingPaths);

                                using (var stream = GetNewStream(newPath))
                                {
                                    using (var writer = GetWriter(stream))
                                    {
                                        writer.WriteStartElement("AML");
                                        line.Script.WriteTo(writer);
                                        writer.WriteEndElement();
                                    }
                                }
                            }

                            existingPaths.Add(newPath);
                            manifestWriter.WriteStartElement("Path");
                            manifestWriter.WriteAttributeString("path", newPath);
                            manifestWriter.WriteEndElement();
                        }
                    }
                    manifestWriter.WriteEndElement();
                }
            }
        }
    public bool Write(InstallScript script,
      Func<string, DatabasePackageAction> errorHandler = null,
      Action<int, string> reportProgress = null)
    {
      var cont = true;
      var typeGroups = from l in script.Lines
                       where l.Type == InstallType.Create
                       group l by l.Reference.Type into typeGroup
                       select typeGroup;
      var cnt = typeGroups.Count();
      var idx = 0;
      var packageGroups = new HashSet<string>();
      string currPackageId = null;

      while (cont)
      {
        IEnumerable<IReadOnlyItem> elements;
        foreach (var typeGroup in typeGroups)
        {
          if (reportProgress != null) reportProgress((int)(idx * 50.0 / cnt), string.Format("Checking for existing package elements ({0} of {1}) ", idx + 1, cnt));

          if (typeGroup.First().Reference.Unique.IsGuid())
          {
            elements = _conn.Apply("<Item type=\"PackageElement\" action=\"get\" select=\"element_id,name,source_id\"><element_type>"
              + typeGroup.Key
              + "</element_type><element_id condition=\"in\">'"
              + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + "','" + c)
              + "'</element_id></Item>").Items();
          }
          else
          {
            elements = _conn.Apply("<Item type=\"PackageElement\" action=\"get\" select=\"element_id,name,source_id\"><element_type>"
              + typeGroup.Key
              + "</element_type><element_id condition=\"in\">(select id from innovator.["
              + typeGroup.Key.Replace(' ', '_')
              + "] where "
              + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + " or " + c)
              + ")</element_id></Item>").Items();
          }

          packageGroups.UnionWith(elements.Select(e => e.SourceId().Value));
          idx++;
        }

        var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"get\" select=\"name\"><id condition=\"in\">(select SOURCE_ID FROM innovator.PACKAGEGROUP where id in ('"
          + packageGroups.Aggregate((p, c) => p + "','" + c)
          + "'))</id></Item>").Items();
        currPackageId = packages.Where(p => p.Property("name").Value == script.Title).SingleOrDefault().Id();

        cont = false;
        if (packages.Any(p => p.Property("name").Value != script.Title))
        {
          if (errorHandler != null)
          {
            var packageList = (from p in packages
                               where p.Property("name").Value != script.Title
                               select p.Property("name").Value)
                              .Aggregate((p, c) => p + ", " + c);
            switch (errorHandler("The package cannot be created because one or more elements exist in the packages: " + packageList))
            {
              case DatabasePackageAction.TryAgain:
                cont = true;
                break;
              case DatabasePackageAction.RemoveElementsFromPackages:
                foreach (var typeGroup in typeGroups)
                {
                  if (reportProgress != null) reportProgress((int)(idx * 50.0 / cnt), string.Format("Removing package elements ({0} of {1}) ", idx + 1, cnt));

                  if (typeGroup.First().Reference.Unique.IsGuid())
                  {
                    elements = _conn.Apply("<Item type=\"PackageElement\" action=\"purge\" where=\"[PackageElement].[element_type] = '"
                      + typeGroup.Key
                      + "' and [PackageElement].[element_id] in ('"
                      + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + "','" + c)
                      + "')\" />").Items();
                  }
                  else
                  {
                    elements = _conn.Apply("<Item type=\"PackageElement\" action=\"purge\" where=\"[PackageElement].[element_type] = '"
                      + typeGroup.Key
                      + "' and [PackageElement].[element_id] in (select id from innovator.["
                      + typeGroup.Key.Replace(' ', '_')
                      + "] where "
                      + typeGroup.Select(i => i.Reference.Unique).Aggregate((p, c) => p + " or " + c)
                      + ")\" />").Items();
                  }

                  idx++;
                }


                break;
              default:
                return false;
            }
          }
          else
          {
            return false;
          }
        }
      }

      // Try one more time to get the package
      if (string.IsNullOrEmpty(currPackageId))
      {
        var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"get\" select=\"name\"><name>" + script.Title + "</name></Item>");
        currPackageId = packages.AssertItem().Id();
      }

      // Add the package
      if (string.IsNullOrEmpty(currPackageId))
      {
        var packages = _conn.Apply("<Item type=\"PackageDefinition\" action=\"add\" ><name>" + script.Title + "</name></Item>", true);
        currPackageId = packages.AssertItem().Id();
      }

      string groupId;
      foreach (var typeGroup in typeGroups)
      {
        if (reportProgress != null) reportProgress((int)(50 + idx * 50.0 / cnt), string.Format("Adding package elements of type ({0} of {1}) ", idx + 1, cnt));

        groupId = _conn.Apply("<Item type=\"PackageGroup\" action=\"merge\" where=\"[PackageGroup].[source_id] = '"
          +  currPackageId
          + "' and [PackageGroup].[name] = '"
          + typeGroup.Key
          + "'\"><name>"
          + typeGroup.Key
          + "</name></Item>", true).AssertItem().Id();

        foreach (var elem in typeGroup)
        {
          _conn.Apply("<Item type=\"PackageElement\" action=\"merge\" where=\"[PackageElement].[source_id] = '"
            + groupId
            + "' and [PackageElement].[element_id] = '"
            + (elem.InstalledId ?? elem.Reference.Unique)
            + "'\">"
            + "<element_type>" + typeGroup.Key + "</element_type>"
            + "<element_id>" + (elem.InstalledId ?? elem.Reference.Unique) + "</element_id>"
            + "<source_id>" + groupId + "</source_id>"
            + "<name>" + elem.Reference.KeyedName + "</name></Item>").AssertNoError();
        }

        idx++;
      }

      return true;
    }
    /// <summary>
    /// Fill an install script with exports of the items in the XmlDocument
    /// </summary>
    public void Export(InstallScript script, XmlDocument doc
      , HashSet<ItemReference> warnings = null, bool checkDependencies = true)
    {
      try
      {
        _metadata.Wait();
        FixPolyItemReferences(doc);
        FixPolyItemListReferences(doc);
        FixForeignProperties(doc);
        FixCyclicalWorkflowLifeCycleRefs(doc);
        FixCyclicalWorkflowItemTypeRefs(doc);

        RemoveEmptyRelationshipTags(doc);
        RemoveVersionableRelIds(doc);
        SortRelationshipTags(doc);

        MoveFormRefsInline(doc, (script.Lines ?? Enumerable.Empty<InstallItem>()).Where(l => l.Type == InstallType.Create || l.Type == InstallType.Script));

        // Sort the resulting nodes as appropriate
        ReportProgress(98, "Sorting the results");
        XmlNode itemNode = doc.DocumentElement;
        while (itemNode != null && itemNode.LocalName != "Item") itemNode = itemNode.Elements().FirstOrDefault();
        if (itemNode == null) throw new InvalidOperationException(); //TODO: Give better error information here (e.g. interpret an error item if present)

        IEnumerable<InstallItem> results = null;
        if (checkDependencies)
        {
          int loops = 0;
          CycleState state = CycleState.ResolvedCycle;
          while (loops < 10 && state == CycleState.ResolvedCycle)
          {
            // Only reset if this is not a rescan
            if (script.Lines != null)
            {
              _dependAnalyzer.Reset(from l in script.Lines where l.Type == InstallType.Create || l.Type == InstallType.Script select l.Reference);
            }
            else
            {
              _dependAnalyzer.Reset();
            }
            var newInstallItems = (from e in itemNode.ParentNode.Elements()
                                   where e.LocalName == "Item" && e.HasAttribute("type")
                                   select InstallItem.FromScript(e)).ToList();

            foreach (var newInstallItem in newInstallItems)
            {
              _dependAnalyzer.GatherDependencies(newInstallItem.Script, newInstallItem.Reference, newInstallItem.CoreDependencies);
            }
            _dependAnalyzer.CleanDependencies();

            results = GetDependencyList(_dependAnalyzer
              , (script.Lines ?? Enumerable.Empty<InstallItem>()).Concat(newInstallItems)
              , out state).ToList();
            loops++;
          }
        }
        else
        {
          var newInstallItems = (from e in itemNode.ParentNode.Elements()
                                 where e.LocalName == "Item" && e.HasAttribute("type")
                                 select InstallItem.FromScript(e)).ToList();
          //foreach (var item in newInstallItems)
          //{
          //  item.Script.SetAttribute(XmlFlags.Attr_DependenciesAnalyzed, "1");
          //}

          results = (script.Lines ?? Enumerable.Empty<InstallItem>())
            .Concat(newInstallItems).ToList();
        }


        if (warnings == null) warnings = new HashSet<ItemReference>();
        warnings.ExceptWith(results.Select(r => r.Reference));

        script.Lines = warnings.Select(w => InstallItem.FromWarning(w, w.KeyedName))
          .Concat(results.Where(r => r.Type == InstallType.DependencyCheck || r.Type == InstallType.Warning))
          .OrderBy(r => r.Name)
          .ToList()
          .Concat(results.Where(r => r.Type != InstallType.DependencyCheck && r.Type != InstallType.Warning))
          .ToList();

        RemoveInjectedDependencies(doc);

        this.OnActionComplete(new ActionCompleteEventArgs());
      }
      catch (Exception ex)
      {
        this.OnActionComplete(new ActionCompleteEventArgs() { Exception = ex });
      }
    }
    public virtual void Write(InstallScript script)
    {
      string newPath;
      var existingPaths = new HashSet<string>();

      // Record the import order
      var settings = new XmlWriterSettings();
      settings.OmitXmlDeclaration = true;
      settings.Indent = true;
      settings.IndentChars = "  ";
      using (var manifestStream = GetNewStream(null))
      {
        using (var manifestWriter = XmlWriter.Create(manifestStream, settings))
        {
          manifestWriter.WriteStartElement("Import");

          if (script.Created.HasValue) manifestWriter.WriteAttributeString("created", script.Created.Value.ToString("s"));
          manifestWriter.WriteAttributeString("creator", script.Creator);
          manifestWriter.WriteAttributeString("description", script.Description);
          if (script.Modified.HasValue) manifestWriter.WriteAttributeString("modified", script.Modified.Value.ToString("s"));
          manifestWriter.WriteAttributeString("revision", script.Version);
          manifestWriter.WriteAttributeString("title", script.Title);
          if (script.Website != null)
            manifestWriter.WriteAttributeString("website", script.Website.ToString());

          foreach (var line in script.Lines)
          {
            if (line.Type == InstallType.Warning)
            {
              // Do nothing
            }
            else if (line.Type == InstallType.DependencyCheck)
            {
              line.Script.WriteTo(manifestWriter);
            }
            else
            {
              if (line.Reference.Type == "Report" && line.Type != InstallType.Script)
              {
                newPath = line.FilePath(existingPaths, ".xslt");
                WriteReport(line, newPath);
              }
              else
              {
                newPath = line.FilePath(existingPaths);

                using (var stream = GetNewStream(newPath))
                {
                  using (var writer = GetWriter(stream))
                  {
                    writer.WriteStartElement("AML");
                    line.Script.WriteTo(writer);
                    writer.WriteEndElement();
                  }
                }
              }

              existingPaths.Add(newPath);
              manifestWriter.WriteStartElement("Path");
              manifestWriter.WriteAttributeString("path", newPath);
              manifestWriter.WriteEndElement();
            }
          }
          manifestWriter.WriteEndElement();
        }
      }
    }
 /// <summary>
 /// Removes all the properties that reference the given item
 /// </summary>
 public void RemoveReferences(InstallScript script, ItemReference itemRef)
 {
   var nodes = _dependAnalyzer.RemoveDependencyReferences(itemRef);
   script.Lines = script.Lines.Where(l => !(l.Type == InstallType.Create || l.Type == InstallType.Script) || !nodes.Contains(l.Script)).ToList();
 }
 public static IEnumerable<InstallItemDiff> GetDiffs(InstallScript left, InstallScript right)
 {
   return GetDiffs(left.Lines, right.Lines);
 }
        public virtual InstallScript Read()
        {
            var result = new InstallScript();

            XmlDocument          doc;
            var                  scripts  = new List <InstallItem>();
            var                  manifest = new XmlDocument();
            string               currPath;
            IEnumerable <string> paths;

            manifest.Load(GetExistingStream(null));

            if (manifest.DocumentElement.HasAttribute("created"))
            {
                result.Created = DateTime.Parse(manifest.DocumentElement.GetAttribute("created"));
            }
            result.Creator     = manifest.DocumentElement.GetAttribute("creator");
            result.Description = manifest.DocumentElement.GetAttribute("description");
            if (manifest.DocumentElement.HasAttribute("modified"))
            {
                result.Modified = DateTime.Parse(manifest.DocumentElement.GetAttribute("modified"));
            }
            result.Version = manifest.DocumentElement.GetAttribute("revision");
            result.Title   = manifest.DocumentElement.GetAttribute("title");
            if (manifest.DocumentElement.HasAttribute("website"))
            {
                result.Website = new Uri(manifest.DocumentElement.GetAttribute("website"));
            }

            foreach (var child in manifest.DocumentElement.ChildNodes.OfType <XmlElement>())
            {
                if (child.LocalName == "Item")
                {
                    scripts.Add(InstallItem.FromScript(child));
                }
                else
                {
                    currPath = child.GetAttribute("path");
                    paths    = string.IsNullOrEmpty(currPath)
            ? Enumerable.Empty <string>()
            : (currPath == "*"
              ? GetPaths()
              : Enumerable.Repeat(currPath, 1));

                    if (currPath == "*")
                    {
                        result.DependencySorted = false;
                    }

                    foreach (var path in paths)
                    {
                        if (path.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
                        {
                            doc = ReadReport(path);
                        }
                        else
                        {
                            doc = new XmlDocument(manifest.NameTable);
                            var stream = GetExistingStream(path);
                            if (stream == null)
                            {
                                throw new FileNotFoundException("A referenced file was not found in the package", path);
                            }
                            doc.Load(stream);
                        }

                        foreach (var item in doc.DocumentElement.Elements("Item"))
                        {
                            scripts.Add(InstallItem.FromScript(item, path));
                        }
                    }
                }
            }

            result.Lines = scripts;
            result.Lines.CleanKeyedNames();

            return(result);
        }
    /// <summary>
    /// Fill an install script with exports of the specified items
    /// </summary>
    public void Export(InstallScript script, IEnumerable<ItemReference> items
      , bool checkDependencies = true)
    {
      ReportProgress(0, "Loading system data");
      _metadata.Wait();

      var uniqueItems = new HashSet<ItemReference>(items);
      if (script.Lines != null) uniqueItems.ExceptWith(script.Lines.Select(l => l.Reference));
      var itemList = uniqueItems.ToList();

      ItemType metaData;
      var outputDoc = new XmlDocument();
      outputDoc.AppendChild(outputDoc.CreateElement("AML"));
      XmlElement queryElem;
      var whereClause = new StringBuilder();

      ConvertPolyItemReferencesToActualType(itemList);
      string itemType;

      var groups = itemList.PagedGroupBy(i => new { Type = i.Type, Levels = i.Levels }, 25);
      foreach (var typeItems in groups)
      {
        whereClause.Length = 0;
        itemType = typeItems.Key.Type;

        // For versionable item types, get the latest generation
        if (_metadata.ItemTypeByName(typeItems.Key.Type.ToLowerInvariant(), out metaData) && metaData.IsVersionable)
        {
          queryElem = outputDoc.CreateElement("Item")
            .Attr("action", "get")
            .Attr("type", typeItems.Key.Type);

          if (typeItems.Any(i => i.Unique.IsGuid()))
          {
            whereClause.Append("[")
              .Append(typeItems.Key.Type.Replace(' ', '_'))
              .Append("].[config_id] in (select config_id from innovator.[")
              .Append(typeItems.Key.Type.Replace(' ', '_'))
              .Append("] where id in ('")
              .Append(typeItems.Where(i => i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + "','" + c))
              .Append("'))");
          }
          if (typeItems.Any(i => !i.Unique.IsGuid()))
          {
            whereClause.AppendSeparator(" or ",
              typeItems.Where(i => !i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + " or " + c));
          }
          queryElem.SetAttribute("where", whereClause.ToString());
        }
        else if (typeItems.Key.Type == "ItemType")
        {
          // Make sure relationship item types aren't accidentally added
          queryElem = outputDoc.CreateElement("Item").Attr("action", "get").Attr("type", typeItems.Key.Type);

          if (typeItems.Any(i => i.Unique.IsGuid()))
          {
            whereClause.Append("[ItemType].[id] in ('")
              .Append(typeItems.Where(i => i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + "','" + c))
              .Append("')");
          }
          if (typeItems.Any(i => !i.Unique.IsGuid()))
          {
            whereClause.AppendSeparator(" or ",
              typeItems.Where(i => !i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + " or " + c));
          }
          queryElem.SetAttribute("where", "(" + whereClause.ToString() + ") and [ItemType].[is_relationship] = '0'");

          SetQueryAttributes(queryElem, typeItems.Key.Type, typeItems.Key.Levels, typeItems);
          outputDoc.DocumentElement.AppendChild(queryElem);

          queryElem = outputDoc.CreateElement("Item")
            .Attr("action", "get")
            .Attr("type", "RelationshipType")
            .Attr("where", "[RelationshipType].[relationship_id] in (select id from innovator.[ItemType] where " + whereClause.ToString() + ")");
          itemType = "RelationshipType";
        }
        else if (typeItems.Key.Type == "List")
        {
          // Filter out auto-generated lists for polymorphic item types
          queryElem = outputDoc.CreateElement("Item")
            .Attr("action", "get")
            .Attr("type", typeItems.Key.Type);

          if (typeItems.Any(i => i.Unique.IsGuid()))
          {
            whereClause.Append("[List].[id] in ('")
              .Append(typeItems.Where(i => i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + "','" + c))
              .Append("')");
          }
          if (typeItems.Any(i => !i.Unique.IsGuid()))
          {
            whereClause.AppendSeparator(" or ",
              typeItems.Where(i => !i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + " or " + c));
          }

          queryElem.SetAttribute("where", "(" + whereClause.ToString() + @") and not [List].[id] in (
            select l.id
            from innovator.LIST l
            inner join innovator.PROPERTY p
            on l.id = p.DATA_SOURCE
            and p.name = 'itemtype'
            inner join innovator.ITEMTYPE it
            on it.id = p.SOURCE_ID
            and it.IMPLEMENTATION_TYPE = 'polymorphic'
            )");
        }
        else
        {
          queryElem = outputDoc.CreateElement("Item")
            .Attr("action", "get")
            .Attr("type", typeItems.Key.Type);

          if (typeItems.Any(i => i.Unique.IsGuid()))
          {
            whereClause.Append("[")
              .Append(typeItems.Key.Type.Replace(' ', '_'))
              .Append("].[id] in ('")
              .Append(typeItems.Where(i => i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + "','" + c))
              .Append("')");
          }
          if (typeItems.Any(i => !i.Unique.IsGuid()))
          {
            whereClause.AppendSeparator(" or ",
              typeItems.Where(i => !i.Unique.IsGuid()).Select(i => i.Unique).Aggregate((p, c) => p + " or " + c));
          }

          queryElem.SetAttribute("where", whereClause.ToString());
        }

        SetQueryAttributes(queryElem, itemType, typeItems.Key.Levels, typeItems);
        outputDoc.DocumentElement.AppendChild(queryElem);
      }

      try
      {
        ReportProgress(0, "Loading system data");

        FixFederatedRelationships(outputDoc.DocumentElement);
        var result = ExecuteExportQuery(ref outputDoc, items);

        // Add warnings for embedded relationships
        var warnings = new HashSet<ItemReference>();
        ItemReference warning;
        foreach (var relType in result.ElementsByXPath("/Result/Item[@type='ItemType']/Relationships/Item[@type='RelationshipType']"))
        {
          warning = ItemReference.FromFullItem(relType as XmlElement, true);
          warning.KeyedName = "* Possible missing relationship: " + warning.KeyedName;
          warnings.Add(warning);
        }

        //RemoveRelatedItems(result, items);
        //CleanUpSystemProps(result.DocumentElement.Elements(), items, false);
        FixPolyItemReferences(result);
        FloatVersionableRefs(result);
        var doc = TransformResults(ref result);
        NormalizeClassStructure(doc);
        FixFormFieldsPointingToSystemProperties(doc);
        ExpandSystemIdentities(doc);
        RemoveVersionableRelIds(doc);
        //TODO: Replace references to poly item lists

        Export(script, doc, warnings, checkDependencies);
        CleanUpSystemProps(doc.DocumentElement.Elements(), items.ToDictionary(i => i), true);
        ConvertFloatProps(doc);
        RemoveKeyedNameAttributes(doc.DocumentElement);

        if (string.IsNullOrWhiteSpace(script.Title))
        {
          if (script.Lines.Count(l => l.Type == InstallType.Create) == 1)
          {
            script.Title = script.Lines.Single(l => l.Type == InstallType.Create).Reference.ToString();
          }
          else if (items.Count() == 1)
          {
            script.Title = items.First().ToString();
          }
        }

        // Rename the FileTypes and identities to make comparing easier
        ItemReference newRef;
        foreach (var line in script.Lines.Where(l => l.Reference.Type == "FileType" || l.Reference.Type == "Identity"))
        {
          newRef = ItemReference.FromFullItem(line.Script.DescendantsAndSelf(e => e.LocalName == "Item").First(), true);
          if (newRef.Type == line.Reference.Type && !String.Equals(newRef.KeyedName, line.Reference.KeyedName))
          {
            line.Reference.KeyedName = newRef.KeyedName;
          }
        }
      }
      catch (Exception ex)
      {
        this.OnActionComplete(new ActionCompleteEventArgs() { Exception = ex });
      }
    }
        public virtual void Write(InstallScript script)
        {
            var existingPaths = new HashSet <string>();

            // Record the import order
            var settings = new XmlWriterSettings()
            {
                OmitXmlDeclaration = true,
                Indent             = true,
                IndentChars        = "  "
            };

            using (var manifestStream = GetNewStream(null))
            {
                using (var manifestWriter = XmlWriter.Create(manifestStream, settings))
                {
                    manifestWriter.WriteStartElement("Import");

                    if (script.Created.HasValue)
                    {
                        manifestWriter.WriteAttributeString("created", script.Created.Value.ToString("s"));
                    }
                    manifestWriter.WriteAttributeString("creator", script.Creator);
                    manifestWriter.WriteAttributeString("description", script.Description);
                    if (script.Modified.HasValue)
                    {
                        manifestWriter.WriteAttributeString("modified", script.Modified.Value.ToString("s"));
                    }
                    manifestWriter.WriteAttributeString("revision", script.Version);
                    manifestWriter.WriteAttributeString("title", script.Title);
                    if (script.Website != null)
                    {
                        manifestWriter.WriteAttributeString("website", script.Website.ToString());
                    }

                    // Achieve consistent file names regardless of the ordering.
                    foreach (var line in script.Lines)
                    {
                        line.Path = GetPath(line, existingPaths);
                    }
                    existingPaths.UnionWith(script.Lines.Select(l => l.Path));

                    foreach (var group in script.Lines.GroupBy(l => l.Path).Where(g => g.Skip(1).Any()))
                    {
                        foreach (var line in group.OrderBy(l => l.Reference.Unique).Skip(1))
                        {
                            line.Path = GetPath(line, existingPaths);
                        }
                    }


                    foreach (var line in script.Lines)
                    {
                        if (line.Type == InstallType.Warning)
                        {
                            // Do nothing
                        }
                        else if (line.Type == InstallType.DependencyCheck)
                        {
                            line.Script.WriteTo(manifestWriter);
                        }
                        else
                        {
                            manifestWriter.WriteStartElement("Path");
                            manifestWriter.WriteAttributeString("path", line.Path);
                            manifestWriter.WriteEndElement();
                        }
                    }
                    manifestWriter.WriteEndElement();

                    Action <InstallItem> writeFunc = line =>
                    {
                        if (line.Reference.Type == "Report" && line.Type != InstallType.Script)
                        {
                            WriteReport(line, line.Path);
                        }
                        else
                        {
                            using (var stream = GetNewStream(line.Path))
                            {
                                using (var writer = GetWriter(stream))
                                {
                                    writer.WriteStartElement("AML");
                                    line.Script.WriteTo(writer);
                                    writer.WriteEndElement();
                                }
                            }
                        }
                    };

                    var scriptLines = script.Lines.Where(l => l.Type != InstallType.Warning && l.Type != InstallType.DependencyCheck);
                    if (_parallel)
                    {
                        Parallel.ForEach(scriptLines, writeFunc);
                    }
                    else
                    {
                        foreach (var line in scriptLines)
                        {
                            writeFunc(line);
                        }
                    }
                }
            }
        }
    public virtual InstallScript Read()
    {
      var result = new InstallScript();

      XmlDocument doc;
      var scripts = new List<InstallItem>();
      var manifest = new XmlDocument();
      string currPath;
      IEnumerable<string> paths;
      manifest.Load(GetExistingStream(null));

      if (manifest.DocumentElement.HasAttribute("created"))
        result.Created = DateTime.Parse(manifest.DocumentElement.GetAttribute("created"));
      result.Creator = manifest.DocumentElement.GetAttribute("creator");
      result.Description = manifest.DocumentElement.GetAttribute("description");
      if (manifest.DocumentElement.HasAttribute("modified"))
        result.Modified = DateTime.Parse(manifest.DocumentElement.GetAttribute("modified"));
      result.Version = manifest.DocumentElement.GetAttribute("revision");
      result.Title = manifest.DocumentElement.GetAttribute("title");
      if (manifest.DocumentElement.HasAttribute("website"))
        result.Website = new Uri(manifest.DocumentElement.GetAttribute("website"));

      foreach (var child in manifest.DocumentElement.ChildNodes.OfType<XmlElement>())
      {
        if (child.LocalName == "Item")
        {
          scripts.Add(InstallItem.FromScript(child));
        }
        else
        {
          currPath = child.GetAttribute("path");
          paths = string.IsNullOrEmpty(currPath)
            ? Enumerable.Empty<string>()
            : (currPath == "*"
              ? GetPaths()
              : Enumerable.Repeat(currPath, 1));

          if (currPath == "*") result.DependencySorted = false;

          foreach (var path in paths)
          {
            if (path.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
            {
              doc = ReadReport(path);
            }
            else
            {
              doc = new XmlDocument(manifest.NameTable);
              doc.Load(GetExistingStream(path));
            }

            foreach (var item in doc.DocumentElement.Elements("Item"))
            {
              scripts.Add(InstallItem.FromScript(item));
            }
          }
        }
      }
      result.Lines = scripts;
      result.Lines.CleanKeyedNames();

      return result;
    }
 public static IEnumerable <InstallItemDiff> GetDiffs(InstallScript left, InstallScript right)
 {
     return(GetDiffs(left.Lines, right.Lines));
 }
Exemple #26
0
        private static bool TryReadPackage(IPackageFile manifestFile, IPackage package, ILogger logger, out InstallScript installScript)
        {
            installScript = new InstallScript();
            var result   = true;
            var scripts  = new List <InstallItem>();
            var manifest = new XmlDocument();

            using (var manifestStream = manifestFile.Open())
                manifest.Load(manifestStream);

            if (manifest.DocumentElement.HasAttribute("created"))
            {
                installScript.Created = DateTime.Parse(manifest.DocumentElement.GetAttribute("created"));
            }
            installScript.Creator     = manifest.DocumentElement.GetAttribute("creator");
            installScript.Description = manifest.DocumentElement.GetAttribute("description");
            if (manifest.DocumentElement.HasAttribute("modified"))
            {
                installScript.Modified = DateTime.Parse(manifest.DocumentElement.GetAttribute("modified"));
            }
            installScript.Version = manifest.DocumentElement.GetAttribute("revision");
            installScript.Title   = manifest.DocumentElement.GetAttribute("title");
            if (manifest.DocumentElement.HasAttribute("website"))
            {
                installScript.Website = new Uri(manifest.DocumentElement.GetAttribute("website"));
            }

            foreach (var child in manifest.DocumentElement.ChildNodes.OfType <XmlElement>())
            {
                if (child.LocalName == "Item")
                {
                    scripts.Add(InstallItem.FromScript(child));
                }
                else
                {
                    var currPath = child.GetAttribute("path");
                    var files    = Enumerable.Empty <IPackageFile>();
                    if (currPath == "*")
                    {
                        files = package.Files();
                        installScript.DependencySorted = false;
                    }
                    else if (!string.IsNullOrEmpty(currPath))
                    {
                        if (package.TryAccessFile(currPath, false, out var file))
                        {
                            files = new[] { file };
                        }
                        else
                        {
                            result = false;
                            logger.LogError("The file {Path} is referenced in the manifest, but not found in the package.", currPath);
                            continue;
                        }
                    }

                    var reportXmlPaths = new HashSet <string>(files
                                                              .Where(f => f.Path.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
                                                              .Select(f => f.Path + ".xml"), StringComparer.OrdinalIgnoreCase);

                    foreach (var file in files
                             .Where(f => !reportXmlPaths.Contains(f.Path)))
                    {
                        try
                        {
                            var doc = new XmlDocument(manifest.NameTable);
                            using (var writer = doc.CreateNavigator().AppendChild())
                                file.WriteAml(package, writer);
                            var items = doc.DocumentElement.LocalName == "Item"
                ? new[] { doc.DocumentElement }
                : doc.DocumentElement.Elements("Item");
                            foreach (var item in items)
                            {
                                scripts.Add(InstallItem.FromScript(item, file.Path));
                            }
                        }
                        catch (XmlException ex)
                        {
                            result = false;
                            logger.LogError(ex, "The AML script at {Path} is malformed", file.Path);
                        }
                        catch (Exception ex)
                        {
                            ex.Data["path"] = file.Path;
                            throw;
                        }
                    }
                }
            }

            installScript.Lines = scripts;
            result = CleanKeyedNames(installScript.Lines, logger) || result;
            return(result);
        }