/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// // Pair for the auto-generated RegistryData.cs, provides the helper ctors and methods. using System; using System.Collection.Generic; using System.Collections.Generic; using System.IO; using System.Reflection; using System.Xml.Schema; using JetBrains.Annotations; namespace JetBrains.Build.InstallationData { public partial class InstallationDataXml { #region Init public InstallationDataXml([NotNull] RegistryXml registry, [NotNull] params FolderXml[] folders) { if(registry == null) throw new ArgumentNullException("registry"); if(folders == null) throw new ArgumentNullException("folders"); Registry = registry; Files = folders; } public InstallationDataXml() : this(new RegistryXml(), new FolderXml[] {}) { } public InstallationDataXml(RegistryXml registry) : this(registry, new FolderXml[] {}) { } public InstallationDataXml(FolderXml folderxml) : this(new RegistryXml(), folderxml) { } #endregion #region Attributes /// /// Gets the XSD for the Registry Data XML files. /// public static XmlSchema RegistryDataXmlSchema { get { using(Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("JetBrains.Build.RegistryData.RegistryData.xsd")) return XmlSchema.Read(stream, null); } } #endregion #region Operations public void AssertValid() { if(Registry == null) throw new InvalidOperationException(string.Format("The Registry must not be Null.")); Registry.AssertValid(); if(Files == null) throw new InvalidOperationException(string.Format("The Files collection must not be Null.")); var hashFolderIds = new Dictionary(); foreach(FolderXml folderxml in Files) { folderxml.AssertValid(); if(hashFolderIds.ContainsKey(folderxml.Id)) throw new InvalidOperationException(string.Format("Duplicate folder ID “{0}”.", folderxml.Id)); hashFolderIds.Add(folderxml.Id, true); } } /// /// Makes sure all of the collections are non-Null (but may be empty). /// public void EnsureNotNull() { if(Registry == null) Registry = new RegistryXml(); Registry.EnsureNotNull(); if(Files == null) Files = new FolderXml[] {}; } /// /// Merges the installation data into the host's, and destroys the former. /// All of the collections are guaranteed to be non-Null /// public void MergeWith(InstallationDataXml addon) { EnsureNotNull(); Registry.MergeWith(addon.Registry); // Merge files var files = new List(Files); files.AddRange(addon.Files); Files = files.ToArray(); } /// /// Checks for duplicate keys and values, removes, if any. /// public void RemoveDuplicates() { EnsureNotNull(); if(Registry != null) Registry.RemoveDuplicates(); // Remove file duplicates (from the target point of view) var hashFiles = new Dictionary(); foreach(FolderXml folder in Files) { if(folder.Files == null) continue; foreach(FileXml file in folder.Files) { string sFileId = folder.TargetRoot + ":" + folder.TargetDir.Trim() + ":" + file.TargetName; if(hashFiles.ContainsKey(sFileId)) continue; hashFiles.Add(sFileId, true); } } } #endregion } public partial class RegistryXml { #region Init /// /// The default ctor, leaves the collections empty. /// public RegistryXml() : this(new RegistryKeyXml[] {}, new RegistryValueXml[] {}) { } /// /// Creates a object and fills it with data. /// /// Keys. /// Values. public RegistryXml([NotNull] ICollection keys, [NotNull] ICollection values) { if(keys == null) throw new ArgumentNullException("keys"); if(values == null) throw new ArgumentNullException("values"); Key = new RegistryKeyXml[keys.Count]; keys.CopyTo(Key, 0); Value = new RegistryValueXml[values.Count]; values.CopyTo(Value, 0); } #endregion #region Operations public void AssertValid() { if(Key == null) throw new InvalidOperationException(string.Format("The keys collection must not be Null.")); foreach(RegistryKeyXml keyxml in Key) keyxml.AssertValid(); if(Value == null) throw new InvalidOperationException(string.Format("The values collection must not be Null.")); foreach(RegistryValueXml valuexml in Value) valuexml.AssertValid(); // Note: the macros collection is fake and should not be validated. } /// /// Makes sure all of the collections are non-Null (but may be empty). /// public void EnsureNotNull() { if(Key == null) Key = new RegistryKeyXml[] {}; if(Value == null) Value = new RegistryValueXml[] {}; } /// /// Merges the keys and values into the host's, and destroys the former. /// The or colections may be Null on either parameter, but on return they're guaranteed to be non-Null in this object. /// public void MergeWith([NotNull] RegistryXml addon) { if(addon == null) throw new ArgumentNullException("addon"); var keys = new List(Key ?? new RegistryKeyXml[] {}); var values = new List(Value ?? new RegistryValueXml[] {}); foreach(RegistryKeyXml key in addon.Key ?? new RegistryKeyXml[] {}) keys.Add(key); foreach(RegistryValueXml value in addon.Value ?? new RegistryValueXml[] {}) values.Add(value); addon.Key = new RegistryKeyXml[] {}; addon.Value = new RegistryValueXml[] {}; Key = keys.ToArray(); Value = values.ToArray(); } /// /// Checks for duplicate keys and values, removes, if any. /// public void RemoveDuplicates() { IList keysOld = Key ?? new RegistryKeyXml[] {}; IList valuesOld = Value ?? new RegistryValueXml[] {}; var keysNew = new List(keysOld.Count); var valuesNew = new List(valuesOld.Count); var hashKeys = new HashSet(); var hashValues = new HashSet(); foreach(RegistryKeyXml keyxml in keysOld) { if(hashKeys.Contains(keyxml)) continue; keysNew.Add(keyxml); hashKeys.Add(keyxml); } foreach(RegistryValueXml valuexml in valuesOld) { if(hashValues.Contains(valuexml)) continue; valuesNew.Add(valuexml); hashValues.Add(valuexml); } Key = keysNew.ToArray(); Value = valuesNew.ToArray(); } /// /// Wraps into the installation data object. /// /// public InstallationDataXml ToInstallationData() { return new InstallationDataXml(this); } #endregion } public partial class RegistryKeyXml : IEquatable { #region Init public RegistryKeyXml() { } /// /// Creates a object. /// /// Hive. /// Path to the key under the hive. public RegistryKeyXml(RegistryHiveXml hive, [NotNull] string key) { if(key == null) throw new ArgumentNullException("key"); Hive = hive; Key = key; } #endregion #region Operations /// /// Creates a new Registry Value that derives its Hive and Key path from the current Registry key. /// /// Name of the value. /// Value of the value, must be either a or an . /// The new registry value. public RegistryValueXml CreateValue([NotNull] string name, [NotNull] object value) { return new RegistryValueXml(Hive, Key, name, value); } /// /// Creates a new array consisting of only this object. /// public RegistryKeyXml[] ToArray() { return new[] {this}; } #endregion #region Overrides public override bool Equals(object obj) { if(this == obj) return true; return Equals(obj as RegistryKeyXml); } #pragma warning disable RedundantOverridenMember public override int GetHashCode() { return base.GetHashCode(); } #pragma warning restore RedundantOverridenMember /// ///Returns a that represents the current . /// /// /// ///A that represents the current . /// ///2 public override string ToString() { return string.Format("", Hive, Key); } #endregion #region IEquatable Members public bool Equals(RegistryKeyXml registryKeyXml) { if(registryKeyXml == null) return false; if(!base.Equals(registryKeyXml)) return false; return true; } #endregion } public partial class RegistryBaseXml : IEquatable { #region Operations public virtual void AssertValid() { if(string.IsNullOrEmpty(Key)) throw new InvalidOperationException(string.Format("The key must not be empty.")); if(Key.IndexOf("/") >= 0) throw new InvalidOperationException(string.Format("The slashes in the key must be reverse.")); } #endregion #region Overrides public override bool Equals(object obj) { if(this == obj) return true; return Equals(obj as RegistryBaseXml); } public override int GetHashCode() { return hiveField.GetHashCode() + 29 * (keyField != null ? keyField.GetHashCode() : 0); } #endregion #region IEquatable Members public bool Equals(RegistryBaseXml registryBaseXml) { if(registryBaseXml == null) return false; return Equals(hiveField, registryBaseXml.hiveField) && Equals(keyField, registryBaseXml.keyField); } #endregion } public partial class FileXml { #region Init public FileXml(string name) : this(name, name) { } public FileXml(string sSourceName, string sTargetName) { SourceName = sSourceName; TargetName = sTargetName; } #endregion #region Operations public void AssertValid() { if(string.IsNullOrEmpty(SourceName)) throw new InvalidOperationException(string.Format("The source name must be specified.")); if(TargetName == null) // Target name is allowed to be empty throw new InvalidOperationException(string.Format("The target name must not be Null.")); } #endregion } public partial class FolderXml { #region Operations public void AssertValid() { Normalize(); if((Files == null) || (Files.Length == 0)) throw new InvalidOperationException(string.Format("The files collection of the folder must not be empty.")); if(string.IsNullOrEmpty(Id)) throw new InvalidOperationException(string.Format("The ID of a folder must not be empty.")); if(string.IsNullOrEmpty(MsiComponentGuid)) throw new InvalidOperationException(string.Format("The GUID must be specified.")); foreach(FileXml filexml in Files) filexml.AssertValid(); } public void Normalize() { TargetDir = TargetDir.Trim().Trim('/', '\\').Replace('/', '\\').Trim(); SourceDir = SourceDir.Trim().Trim('/', '\\').Replace('/', '\\').Trim(); } public InstallationDataXml ToInstallationData() { return new InstallationDataXml(this); } #endregion } public partial class MacroXml { } public partial class RegistryValueXml : IEquatable { #region Init /// /// Creates a object. /// /// Hive. /// Path to the key under the hive. /// Name of the value. /// Value of the value, must be either a or an . public RegistryValueXml(RegistryHiveXml hive, [NotNull] string key, [NotNull] string name, [NotNull] object value) { if(key == null) throw new ArgumentNullException("key"); if(name == null) throw new ArgumentNullException("name"); if(value == null) throw new ArgumentNullException("value"); Hive = hive; Key = key; Name = name; if(value is string) { Type = RegistryValueTypeXml.String; Value = (string)value; } else if(value is int) { Type = RegistryValueTypeXml.Dword; Value = value.ToString(); } else throw new InvalidOperationException(string.Format("The value type “{0}” is not supported.", value.GetType().AssemblyQualifiedName)); } #endregion #region Operations /// /// Creates a new array consisting of only this object. /// public RegistryValueXml[] ToArray() { return new[] {this}; } /// /// Creates a new Registry with just this value. /// public RegistryXml ToRegistry() { return new RegistryXml(new RegistryKeyXml[] {}, new[] {this}); } #endregion #region Overrides public override void AssertValid() { base.AssertValid(); if(Name == null) throw new InvalidOperationException(string.Format("The Name must not be Null, but it can be empty for the default value of the key.")); } public override bool Equals(object obj) { if(this == obj) return true; return Equals(obj as RegistryValueXml); } public override int GetHashCode() { int result = base.GetHashCode(); result = 29 * result + (nameField != null ? nameField.GetHashCode() : 0); result = 29 * result + (valueField != null ? valueField.GetHashCode() : 0); result = 29 * result + typeField.GetHashCode(); return result; } /// ///Returns a that represents the current . /// /// /// ///A that represents the current . /// ///2 public override string ToString() { return string.Format("", Hive, Key, Name, Value); } #endregion #region IEquatable Members public bool Equals(RegistryValueXml registryValueXml) { if(registryValueXml == null) return false; if(!base.Equals(registryValueXml)) return false; if(!Equals(nameField, registryValueXml.nameField)) return false; if(!Equals(valueField, registryValueXml.valueField)) return false; if(!Equals(typeField, registryValueXml.typeField)) return false; return true; } #endregion } }