/// <summary> /// Creates a new connect to feature. /// </summary> /// <param name="section">Section this connect belongs to.</param> /// <param name="childId">Id of the child.</param> /// <param name="primaryFeature">Sets the primary feature for the connection.</param> /// <param name="explicitPrimaryFeature">Sets if this is explicit primary.</param> public ConnectToFeature(Section section, string childId, string primaryFeature, bool explicitPrimaryFeature) { this.section = section; this.childId = childId; this.primaryFeature = primaryFeature; this.explicitPrimaryFeature = explicitPrimaryFeature; this.connectFeatures = new StringCollection(); }
/// <summary> /// Parse a table from the xml. /// </summary> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> /// <returns>The parsed table.</returns> internal static Table Parse(XmlReader reader, Section section, TableDefinitionCollection tableDefinitions) { Debug.Assert("table" == reader.LocalName); bool empty = reader.IsEmptyElement; TableOperation operation = TableOperation.None; string name = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; case "op": switch (reader.Value) { case "add": operation = TableOperation.Add; break; case "drop": operation = TableOperation.Drop; break; default: throw new WixException(WixErrors.IllegalAttributeValue(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name, reader.Value, "Add", "Drop")); } break; default: if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal)) { throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name)); } break; } } if (null == name) { throw new WixException(WixErrors.ExpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", "name")); } TableDefinition tableDefinition = tableDefinitions[name]; Table table = new Table(section, tableDefinition); table.Operation = operation; if (!empty) { bool done = false; // loop through all the rows in a table while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "row": Row.Parse(reader, table); break; default: throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "table", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "table")); } } return table; }
/// <summary> /// Creates a symbol without a row reference. /// </summary> /// <param name="section">Section to add symbol to.</param> /// <param name="tableName">Name of table for symbol.</param> /// <param name="rowId">Id of row for symbol.</param> public Symbol(Section section, string tableName, string rowId) { this.section = section; this.tableName = tableName; this.rowId = rowId; }
/// <summary> /// Creates a new section. /// </summary> /// <param name="id">Unique identifier for the section.</param> /// <param name="type">Type of section to create.</param> /// <param name="codepage">Codepage for the resulting database for this ection.</param> /// <returns>New section.</returns> internal Section CreateSection(string id, SectionType type, int codepage) { Section newSection = new Section(id, type, codepage); this.intermediate.Sections.Add(newSection); return newSection; }
/// <summary> /// Gets the symbol for a reference. /// </summary> /// <param name="section">Section that contains references to resolve.</param> /// <param name="reference">References to resolve.</param> /// <param name="allSymbols">Collection of all symbols from loaded intermediates.</param> /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param> /// <param name="unresolvedReferences">Unresolved references.</param> /// <param name="messageHandler">Message handler to report errors through.</param> /// <returns>Symbol it it was found or null if the symbol was not specified.</returns> internal static Symbol GetSymbolForReference( Section section, Reference reference, SymbolCollection allSymbols, StringCollection referencedSymbols, ArrayList unresolvedReferences, IMessageHandler messageHandler) { Symbol symbol = null; try { symbol = allSymbols[reference.SymbolicName]; if (null == symbol) { unresolvedReferences.Add(new ReferenceSection(section, reference)); } else { // components are indexed in ResolveComplexReferences if (null != symbol.TableName && "Component" != symbol.TableName && !referencedSymbols.Contains(symbol.Name)) { referencedSymbols.Add(symbol.Name); } } } catch (DuplicateSymbolsException e) { Symbol[] symbols = e.GetDuplicateSymbols(); Debug.Assert(1 < symbols.Length); messageHandler.OnMessage(WixErrors.DuplicateSymbol((null != symbols[0].Row ? symbols[0].Row.SourceLineNumbers : null), symbols[0].Name)); for (int i = 1; i < symbols.Length; ++i) { if (null != symbols[i].Row && null != symbols[i].Row.SourceLineNumbers) { messageHandler.OnMessage(WixErrors.DuplicateSymbol2(symbols[i].Row.SourceLineNumbers)); } } } return symbol; }
/// <summary> /// Create a row in a section. /// </summary> /// <param name="sourceLineNumbers">Line number information about the row.</param> /// <param name="section">Section in which a row is to be added.</param> /// <param name="tableDefinition">Table definition for the row being added.</param> /// <returns>The row added to the section.</returns> internal static Row CreateRowInSection(SourceLineNumberCollection sourceLineNumbers, Section section, TableDefinition tableDefinition) { Table table = section.Tables[tableDefinition.Name]; if (null == table) { table = new Table(section, tableDefinition); section.Tables.Add(table); } return table.CreateRow(sourceLineNumbers); }
/// <summary> /// Resolves all the simple references in a section. /// </summary> /// <param name="outputType">Active output type.</param> /// <param name="sections">Collection to add sections to.</param> /// <param name="section">Section with references to resolve.</param> /// <param name="allSymbols">Collection of all symbols from loaded intermediates.</param> /// <param name="referencedSymbols">Collection of all symbols referenced during linking.</param> /// <param name="unresolvedReferences">Unresolved references.</param> /// <param name="messageHandler">Message handler to report errors through.</param> /// <remarks>Note: recursive function.</remarks> internal static void ResolveReferences( OutputType outputType, SectionCollection sections, Section section, SymbolCollection allSymbols, StringCollection referencedSymbols, ArrayList unresolvedReferences, IMessageHandler messageHandler) { // if we already have this section bail if (sections.Contains(section)) { return; } // add the section to the output and loop through the rest of the references // in a simple depth-first search sections.Add(section); foreach (Reference reference in section.References) { // if we're building into an output, modules ignore all references to the Media table if (OutputType.Module == outputType && "Media" == reference.TableName) { continue; } Symbol symbol = Common.GetSymbolForReference(section, reference, allSymbols, referencedSymbols, unresolvedReferences, messageHandler); if (null != symbol) { Common.ResolveReferences(outputType, sections, symbol.Section, allSymbols, referencedSymbols, unresolvedReferences, messageHandler); } } }
/// <summary> /// Creates a new connect to feature. /// </summary> /// <param name="section">Section this connect belongs to.</param> /// <param name="childId">Id of the child.</param> public ConnectToFeature(Section section, string childId) : this(section, childId, null, false) { }
/// <summary> /// Parse a section from the xml. /// </summary> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> /// <returns>The parsed Section.</returns> internal static Section Parse(XmlReader reader, TableDefinitionCollection tableDefinitions) { Debug.Assert("section" == reader.LocalName); int codepage = 0; bool empty = reader.IsEmptyElement; string id = null; Section section = null; SectionType type = SectionType.Unknown; while (reader.MoveToNextAttribute()) { switch (reader.Name) { case "codepage": codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture); break; case "id": id = reader.Value; break; case "type": switch (reader.Value) { case "bundle": type = SectionType.Bundle; break; case "fragment": type = SectionType.Fragment; break; case "module": type = SectionType.Module; break; case "patchCreation": type = SectionType.PatchCreation; break; case "product": type = SectionType.Product; break; case "patch": type = SectionType.Patch; break; default: throw new WixException(WixErrors.IllegalAttributeValue(SourceLineNumberCollection.FromUri(reader.BaseURI), "section", reader.Name, reader.Value, "fragment", "module", "patchCreation", "product", "patch")); } break; default: if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal)) { throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "section", reader.Name)); } break; } } if (null == id && (SectionType.Unknown != type && SectionType.Fragment != type)) { throw new WixException(WixErrors.ExpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "section", "id", "type", type.ToString())); } if (SectionType.Unknown == type) { throw new WixException(WixErrors.ExpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "section", "type")); } section = new Section(id, type, codepage); section.sourceLineNumbers = SourceLineNumberCollection.FromUri(reader.BaseURI); if (!empty) { bool done = false; while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "table": section.Tables.Add(Table.Parse(reader, section, tableDefinitions)); break; default: throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "section", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "section")); } } return section; }
/// <summary> /// Gets the symbol for this action. /// </summary> /// <param name="section">Section the symbol should reference since actions don't belong to sections.</param> /// <returns>Symbol for this action.</returns> internal Symbol GetSymbol(Section section) { Symbol symbol = new Symbol(section, "Actions", String.Concat(Action.SequenceTypeToString(this.sequenceType), "/", this.id)); return symbol; }
/// <summary> /// Instantiate a new WixUnresolvedReferenceException. /// </summary> /// <param name="sourceLineNumbers">Source line information of the exception.</param> /// <param name="section">Section with a missing reference.</param> /// <param name="reference">The missing reference.</param> /// <param name="innerException">The exception that is the cause of the current exception.</param> internal WixUnresolvedReferenceException(SourceLineNumberCollection sourceLineNumbers, Section section, Reference reference, Exception innerException) : base(sourceLineNumbers, WixExceptionType.UnresolvedReference, innerException) { this.section = section; this.reference = reference; }
/// <summary> /// Instantiate a new WixUnresolvedReferenceException. /// </summary> /// <param name="sourceLineNumbers">Source line information of the exception.</param> /// <param name="section">Section with a missing reference.</param> /// <param name="reference">The missing reference.</param> internal WixUnresolvedReferenceException(SourceLineNumberCollection sourceLineNumbers, Section section, Reference reference) : this(sourceLineNumbers, section, reference, null) { }
/// <summary> /// Parse a tuple from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> /// <param name="tableDef">Table definition of the tuple to parse.</param> private static void ParseTuple(Intermediate intermediate, XmlReader reader, Section section, TableDefinition tableDef) { bool empty = reader.IsEmptyElement; SourceLineNumberCollection sourceLineNumbers = null; int field = 0; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "sourceLineNumber": sourceLineNumbers = new SourceLineNumberCollection(reader.Value); break; } } Row row = Common.CreateRowInSection(sourceLineNumbers, section, tableDef); if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "field": row[field] = Field.Parse(reader); ++field; break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'tuple': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'tuple'.")); } } }
/// <summary> /// Parse a table from the xml. /// </summary> /// <param name="intermediate">Intermediate to populate with persisted data.</param> /// <param name="reader">XmlReader where the intermediate is persisted.</param> /// <param name="section">Section to populate with persisted data.</param> /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param> private static void ParseTable(Intermediate intermediate, XmlReader reader, Section section, TableDefinitionCollection tableDefinitions) { bool empty = reader.IsEmptyElement; string name = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; } } if (null == name) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), "Table missing required attribute: 'name'"); } if (!empty) { bool done = false; // loop through all the rows (tuples) in a table while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "tuple": ParseTuple(intermediate, reader, section, tableDefinitions[name]); break; default: throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Unexpected element while processing 'table': '{0}'", reader.LocalName)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixInvalidIntermediateException(SourceLineNumberCollection.FromFileName(intermediate.Path), String.Format("Missing end element while processing 'table'.")); } } }
/// <summary> /// Finds the entry section and loads the symbols from an array of intermediates. /// </summary> /// <param name="allowIdenticalRows">Flag specifying whether identical rows are allowed or not.</param> /// <param name="messageHandler">Message handler object to route all errors through.</param> /// <param name="expectedOutputType">Expected entry output type, based on output file extension provided to the linker.</param> /// <param name="entrySection">Located entry section.</param> /// <param name="allSymbols">Collection of symbols loaded.</param> internal void FindEntrySectionAndLoadSymbols( bool allowIdenticalRows, IMessageHandler messageHandler, OutputType expectedOutputType, out Section entrySection, out SymbolCollection allSymbols) { entrySection = null; allSymbols = new SymbolCollection(); string outputExtension = Output.GetExtension(expectedOutputType); SectionType expectedEntrySectionType; try { expectedEntrySectionType = (SectionType)Enum.Parse(typeof(SectionType), expectedOutputType.ToString()); } catch (ArgumentException) { expectedEntrySectionType = SectionType.Unknown; } foreach (Section section in this.collection.Keys) { if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type || SectionType.Patch == section.Type || SectionType.Bundle == section.Type) { if (SectionType.Unknown != expectedEntrySectionType && section.Type != expectedEntrySectionType) { messageHandler.OnMessage(WixWarnings.UnexpectedEntrySection(section.SourceLineNumbers, section.Type.ToString(), expectedEntrySectionType.ToString(), outputExtension)); } if (null == entrySection) { entrySection = section; } else { messageHandler.OnMessage(WixErrors.MultipleEntrySections(entrySection.SourceLineNumbers, entrySection.Id, section.Id)); messageHandler.OnMessage(WixErrors.MultipleEntrySections2(section.SourceLineNumbers)); } } foreach (Symbol symbol in section.GetSymbols(messageHandler)) { try { Symbol existingSymbol = allSymbols[symbol.Name]; if (null == existingSymbol) { allSymbols.Add(symbol); } else if (allowIdenticalRows && existingSymbol.Row.IsIdentical(symbol.Row)) { messageHandler.OnMessage(WixWarnings.IdenticalRowWarning(symbol.Row.SourceLineNumbers, existingSymbol.Name)); messageHandler.OnMessage(WixWarnings.IdenticalRowWarning2(existingSymbol.Row.SourceLineNumbers)); } else { allSymbols.AddDuplicate(symbol); } } catch (DuplicateSymbolsException) { // if there is already a duplicate symbol, just // another to the list, don't bother trying to // see if there are any identical symbols allSymbols.AddDuplicate(symbol); } } } }
/// <summary> /// Checks if the collection contains a Section. /// </summary> /// <param name="section">The Section to check in the collection.</param> /// <returns>True if collection contains the Section.</returns> public bool Contains(Section section) { return this.collection.ContainsKey(section); }
/// <summary> /// Recursive helper function to resolve all references of passed in section. /// </summary> /// <param name="section">Section with references to resolve.</param> /// <param name="outputType">Parent output type that will get the resolved section collection.</param> /// <param name="allSymbols">All symbols that can be used to resolve section's references.</param> /// <param name="sections">Collection to add sections to during processing.</param> /// <param name="referencedSymbols">Collection populated during resolution of all symbols referenced during linking.</param> /// <param name="unresolvedReferences">Collection populated during resolution of all references that are left unresolved.</param> /// <param name="messageHandler">Message handler to report any duplicate symbols that may be tripped across.</param> /// <remarks>Note: recursive function.</remarks> private static void RecursivelyResolveReferences( Section section, OutputType outputType, SymbolCollection allSymbols, SectionCollection sections, StringCollection referencedSymbols, ArrayList unresolvedReferences, IMessageHandler messageHandler) { // if we already have this section bail if (sections.Contains(section)) { return; } // add the passed in section to the collection of sections sections.Add(section); // process all of the references contained in this section using the collection of // symbols provided. Then recursively call this method to process the // located symbol's section. All in all this is a very simple depth-first // search of the references per-section Table wixSimpleReferenceTable = section.Tables["WixSimpleReference"]; if (null != wixSimpleReferenceTable) { foreach (WixSimpleReferenceRow wixSimpleReferenceRow in wixSimpleReferenceTable.Rows) { // If we're building a Merge Module, ignore all references to the Media table // because Merge Modules don't have Media tables. if (OutputType.Module == outputType && "Media" == wixSimpleReferenceRow.TableName) { continue; } if ("WixAction" == wixSimpleReferenceRow.TableName) { Symbol[] symbols = allSymbols.GetSymbolsForSimpleReference(wixSimpleReferenceRow); if (0 == symbols.Length) { if (null != unresolvedReferences) { unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow)); } } else { foreach (Symbol symbol in symbols) { if (null != symbol.Section) { // components are indexed in ResolveComplexReferences if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name)) { referencedSymbols.Add(symbol.Name); } RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler); } } } } else { Symbol symbol = allSymbols.GetSymbolForSimpleReference(wixSimpleReferenceRow, messageHandler); if (null == symbol) { if (null != unresolvedReferences) { unresolvedReferences.Add(new SimpleReferenceSection(section, wixSimpleReferenceRow)); } } else { // components are indexed in ResolveComplexReferences if (null != referencedSymbols && null != symbol.Row.TableDefinition.Name && "Component" != symbol.Row.TableDefinition.Name && !referencedSymbols.Contains(symbol.Name)) { referencedSymbols.Add(symbol.Name); } RecursivelyResolveReferences(symbol.Section, outputType, allSymbols, sections, referencedSymbols, unresolvedReferences, messageHandler); } } } } }
/// <summary> /// Creates an object that ties simple references to their section. /// </summary> /// <param name="section">Section that owns the simple reference.</param> /// <param name="wixSimpleReferenceRow">The simple reference in the section.</param> public SimpleReferenceSection(Section section, WixSimpleReferenceRow wixSimpleReferenceRow) { this.Section = section; this.WixSimpleReferenceRow = wixSimpleReferenceRow; }
/// <summary> /// Creates an object that ties references to their section /// </summary> /// <param name="section">Section that owns the reference.</param> /// <param name="reference">Reference in the section.</param> public ReferenceSection(Section section, Reference reference) { this.section = section; this.reference = reference; }
/// <summary> /// Finds the entry section and loads the symbols from an array of intermediates. /// </summary> /// <param name="intermediates">Array of intermediates to load symbols for and find entry section.</param> /// <param name="allowIdenticalRows">Flag specifying whether identical rows are allowed or not.</param> /// <param name="messageHandler">Message handler object to route all errors through.</param> /// <param name="entrySection">Located entry section.</param> /// <param name="allSymbols">Collection of symbols loaded.</param> internal static void FindEntrySectionAndLoadSymbols( Intermediate[] intermediates, bool allowIdenticalRows, IMessageHandler messageHandler, out Section entrySection, out SymbolCollection allSymbols) { entrySection = null; allSymbols = new SymbolCollection(); for (int i = 0; i < intermediates.Length; ++i) { foreach (Section section in intermediates[i].Sections) { if (SectionType.Product == section.Type || SectionType.Module == section.Type || SectionType.PatchCreation == section.Type) { if (null == entrySection) { entrySection = section; } else { messageHandler.OnMessage(WixErrors.MultipleEntrySections(SourceLineNumberCollection.FromFileName(entrySection.Intermediate.SourcePath), entrySection.Id, section.Id)); messageHandler.OnMessage(WixErrors.MultipleEntrySections2(SourceLineNumberCollection.FromFileName(section.Intermediate.SourcePath))); } } foreach (Symbol symbol in section.GetSymbols(messageHandler)) { try { Symbol existingSymbol = allSymbols[symbol.Name]; if (null == existingSymbol) { allSymbols.Add(symbol); } else if (allowIdenticalRows && existingSymbol.Row.IsIdentical(symbol.Row)) { messageHandler.OnMessage(WixWarnings.IdenticalRowWarning(symbol.Row.SourceLineNumbers, existingSymbol.Name)); messageHandler.OnMessage(WixWarnings.IdenticalRowWarning2(existingSymbol.Row.SourceLineNumbers)); } else { allSymbols.AddDuplicate(symbol); } } catch (DuplicateSymbolsException) { // if there is already a duplicate symbol, just // another to the list, don't bother trying to // see if there are any identical symbols allSymbols.AddDuplicate(symbol); } } } } }
/// <summary> /// Creates a new section and makes it the active section in the core. /// </summary> /// <param name="id">Unique identifier for the section.</param> /// <param name="type">Type of section to create.</param> /// <param name="codepage">Codepage for the resulting database for this ection.</param> /// <returns>New section.</returns> internal Section CreateActiveSection(string id, SectionType type, int codepage) { Section newSection = this.CreateSection(id, type, codepage); this.activeSection = newSection; return newSection; }
/// <summary> /// Adds a section to the collection. /// </summary> /// <param name="section">Section to add to collection.</param> public void Add(Section section) { this.collection.Add(section, null); }
/// <summary> /// Creates a row in the active given <paramref name="section"/>. /// </summary> /// <param name="sourceLineNumbers">Source and line number of current row.</param> /// <param name="tableName">Name of table to create row in.</param> /// <param name="section">The section to which the row is added. If null, the row is added to the active section.</param> /// <returns>New row.</returns> internal Row CreateRow(SourceLineNumberCollection sourceLineNumbers, string tableName, Section section) { if (null == section) { throw new ArgumentNullException("section"); } TableDefinition tableDefinition = this.tableDefinitions[tableName]; Table table = section.Tables.EnsureTable(section, tableDefinition); return table.CreateRow(sourceLineNumbers); }
/// <summary> /// Checks if the collection contains a Section. /// </summary> /// <param name="section">The Section to check in the collection.</param> /// <returns>True if collection contains the Section.</returns> public bool Contains(Section section) { return(this.collection.ContainsKey(section)); }
/// <summary> /// Ensure this TableCollection contains a particular table. /// </summary> /// <param name="section">Section containing the new table.</param> /// <param name="tableDefinition">Definition of the table that should exist.</param> /// <returns>The table in this collection.</returns> public Table EnsureTable(Section section, TableDefinition tableDefinition) { Table table = this[tableDefinition.Name]; if (null == table) { table = new Table(section, tableDefinition); this.Add(table); } return table; }
/// <summary> /// Parse the root library element. /// </summary> /// <param name="reader">XmlReader with library persisted as Xml.</param> /// <param name="tableDefinitions">Collection containing TableDefinitions to use when reconstituting the intermediates.</param> /// <param name="suppressVersionCheck">Suppresses check for wix.dll version mismatch.</param> /// <returns>The parsed Library.</returns> private static Library Parse(XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) { Debug.Assert("wixLibrary" == reader.LocalName); bool empty = reader.IsEmptyElement; Library library = new Library(); Version version = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "version": version = new Version(reader.Value); break; default: if (!reader.NamespaceURI.StartsWith("http://www.w3.org/", StringComparison.Ordinal)) { throw new WixException(WixErrors.UnexpectedAttribute(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixLibrary", reader.Name)); } break; } } if (null != version && !suppressVersionCheck) { if (0 != currentVersion.CompareTo(version)) { throw new WixException(WixErrors.VersionMismatch(SourceLineNumberCollection.FromUri(reader.BaseURI), "library", version.ToString(), currentVersion.ToString())); } } if (!empty) { bool done = false; while (!done && (XmlNodeType.Element == reader.NodeType || reader.Read())) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "section": library.sections.Add(Section.Parse(reader, tableDefinitions)); break; case "WixLocalization": Localization localization = Localization.Parse(reader, tableDefinitions); library.localizations.Add(localization.Culture, localization); break; default: throw new WixException(WixErrors.UnexpectedElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixLibrary", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixException(WixErrors.ExpectedEndElement(SourceLineNumberCollection.FromUri(reader.BaseURI), "wixLibrary")); } } return(library); }
/// <summary> /// Creates a table in a section. /// </summary> /// <param name="section">Section to add table to.</param> /// <param name="tableDefinition">Definition of the table.</param> public Table(Section section, TableDefinition tableDefinition) { this.section = section; this.tableDefinition = tableDefinition; this.rows = new RowCollection(); }
/// <summary> /// Processes an XmlReader and builds up the output table object. /// </summary> /// <param name="reader">Reader to get data from.</param> /// <param name="section">Section to add loaded rows into.</param> /// <returns>Output table.</returns> internal static OutputTable Parse(XmlReader reader, Section section) { Debug.Assert("outputTable" == reader.LocalName); string name = null; bool empty = reader.IsEmptyElement; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "name": name = reader.Value; break; default: throw new WixParseException(String.Format("The outputTable element contains an unexpected attribute {0}.", reader.Name)); } } if (null == name) { throw new WixParseException("The outputTable/@name attribute was not found; it is required."); } OutputTable outputTable = null; if (!empty) { bool done = false; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "tableDefinition": outputTable = new OutputTable(TableDefinition.Parse(reader)); break; case "tuple": if (null == outputTable) { throw new WixParseException("The outputTable element is missing a tableDefinition child element."); } outputTable.outputRows.Add(new OutputRow(Row.Parse(reader, section, outputTable.tableDef))); break; default: throw new WixParseException(String.Format("The outputTable element contains an unexpected child element {0}.", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixParseException("Missing end element while processing the outputTable element."); } } return outputTable; }
/// <summary> /// Creates a Row from the XmlReader /// </summary> /// <param name="reader">Reader to get data from.</param> /// <param name="section">Section the row is added to.</param> /// <param name="tableDef">Table definition for this row.</param> /// <returns>New row object.</returns> internal static Row Parse(XmlReader reader, Section section, TableDefinition tableDef) { Debug.Assert("tuple" == reader.LocalName); bool empty = reader.IsEmptyElement; string sectionId = null; SourceLineNumberCollection sourceLineNumbers = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case "sectionId": sectionId = reader.Value; break; case "sourceLineNumber": sourceLineNumbers = new SourceLineNumberCollection(reader.Value); break; default: throw new WixParseException(String.Format("The tuple element contains an unexpected attribute {0}.", reader.Name)); } } Row row = Common.CreateRowInSection(sourceLineNumbers, section, tableDef); row.sectionId = sectionId; // loop through all the fields in a row if (!empty) { bool done = false; int field = 0; // loop through all the fields in a row while (!done && reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: switch (reader.LocalName) { case "field": if (row.Fields.Length <= field) { throw new WixParseException(String.Format("This tuple has more fields for table '{0}' than are defined. This is potentially because a standard table is being redefined as a custom table.", tableDef.Name)); } row[field] = Field.Parse(reader); ++field; break; default: throw new WixParseException(String.Format("The tuple element contains an unexpected child element {0}.", reader.Name)); } break; case XmlNodeType.EndElement: done = true; break; } } if (!done) { throw new WixParseException("Missing end element while processing the tuple element."); } } return row; }
/// <summary> /// Loads the standard actions' symbols into the entry section. /// </summary> /// <param name="allSymbols">Collection of symbols.</param> /// <param name="entrySection">Entry section.</param> /// <param name="actionTable">Table that contains the standard actions.</param> private void LoadStandardActionSymbols(SymbolCollection allSymbols, Section entrySection, ActionTable actionTable) { foreach (Action action in actionTable) { // if the action's symbol has not already been defined (i.e. overriden by the user), add it now Symbol symbol = action.GetSymbol(entrySection); if (!allSymbols.Contains(symbol.Name)) { allSymbols.Add(symbol); } } }
/// <summary> /// Creates a new complex reference. /// </summary> /// <param name="parentType">Parent type of complex reference.</param> /// <param name="parentId">Identifier for parent of complex reference.</param> /// <param name="parentLanguage">Language for parent of complex reference (only valid when parent is Module).</param> /// <param name="childType">Child type of complex reference.</param> /// <param name="childId">Identifier for child of complex reference.</param> /// <param name="primary">Flag if complex reference is the primary for advertised goop.</param> public ComplexReference(ComplexReferenceParentType parentType, string parentId, string parentLanguage, ComplexReferenceChildType childType, string childId, bool primary) { if (ComplexReferenceParentType.Module != this.parentType && null != this.parentLanguage) { throw new ArgumentException("ParentLanguage cannot be specified unless the parent is a Module."); } this.parentType = parentType; this.parentId = parentId; this.parentLanguage = parentLanguage; this.childType = childType; this.childId = childId; this.primary = primary; this.section = null; }
/// <summary> /// Create a row in a section. /// </summary> /// <param name="sourceLineNumbers">Line number information about the row.</param> /// <param name="section">Section in which a row is to be added.</param> /// <param name="tableName">Table of the row.</param> /// <param name="tableDefinitions">Table definitions containing the table's defition.</param> /// <returns>The row added to the section.</returns> internal static Row CreateRowInSection(SourceLineNumberCollection sourceLineNumbers, Section section, string tableName, TableDefinitionCollection tableDefinitions) { Table table = section.Tables[tableName]; if (null == table) { TableDefinition tableDef = tableDefinitions[tableName]; if (null == tableDef) { throw new ApplicationException(String.Format("Unknown table name: {0}", tableName)); } table = new Table(section, tableDef); section.Tables.Add(table); } return table.CreateRow(sourceLineNumbers); }