aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs98
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs4
-rw-r--r--src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs2
-rw-r--r--src/WixToolset.Core/Compiler.cs566
-rw-r--r--src/WixToolset.Core/Compiler_Bundle.cs244
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs49
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs31
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs52
-rw-r--r--src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs13
9 files changed, 680 insertions, 379 deletions
diff --git a/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs b/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
index 20ecd157..7fd510c6 100644
--- a/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
+++ b/src/WixToolset.Core.Burn/Bind/GenerateManifestDataFromIRCommand.cs
@@ -2,6 +2,7 @@
2 2
3namespace WixToolset.Core.Burn.Bind 3namespace WixToolset.Core.Burn.Bind
4{ 4{
5 using System;
5 using System.Collections.Generic; 6 using System.Collections.Generic;
6 using System.Linq; 7 using System.Linq;
7 using System.Text; 8 using System.Text;
@@ -37,8 +38,8 @@ namespace WixToolset.Core.Burn.Bind
37 public void Execute() 38 public void Execute()
38 { 39 {
39 var tuples = this.Section.Tuples.ToList(); 40 var tuples = this.Section.Tuples.ToList();
40 var cellsByTableAndRowId = new Dictionary<string, List<WixCustomTableCellTuple>>(); 41 var cellsByCustomDataAndElementId = new Dictionary<string, List<WixBundleCustomDataCellTuple>>();
41 var customTablesById = new Dictionary<string, WixCustomTableTuple>(); 42 var customDataById = new Dictionary<string, WixBundleCustomDataTuple>();
42 43
43 foreach (var kvp in this.ExtensionSearchTuplesById) 44 foreach (var kvp in this.ExtensionSearchTuplesById)
44 { 45 {
@@ -63,6 +64,7 @@ namespace WixToolset.Core.Burn.Bind
63 case TupleDefinitionType.WixBundle: 64 case TupleDefinitionType.WixBundle:
64 case TupleDefinitionType.WixBundleCatalog: 65 case TupleDefinitionType.WixBundleCatalog:
65 case TupleDefinitionType.WixBundleContainer: 66 case TupleDefinitionType.WixBundleContainer:
67 case TupleDefinitionType.WixBundleCustomDataAttribute:
66 case TupleDefinitionType.WixBundleExePackage: 68 case TupleDefinitionType.WixBundleExePackage:
67 case TupleDefinitionType.WixBundleExtension: 69 case TupleDefinitionType.WixBundleExtension:
68 case TupleDefinitionType.WixBundleMsiFeature: 70 case TupleDefinitionType.WixBundleMsiFeature:
@@ -82,7 +84,6 @@ namespace WixToolset.Core.Burn.Bind
82 case TupleDefinitionType.WixBundleVariable: 84 case TupleDefinitionType.WixBundleVariable:
83 case TupleDefinitionType.WixChain: 85 case TupleDefinitionType.WixChain:
84 case TupleDefinitionType.WixComponentSearch: 86 case TupleDefinitionType.WixComponentSearch:
85 case TupleDefinitionType.WixCustomTableColumn:
86 case TupleDefinitionType.WixDependencyProvider: 87 case TupleDefinitionType.WixDependencyProvider:
87 case TupleDefinitionType.WixFileSearch: 88 case TupleDefinitionType.WixFileSearch:
88 case TupleDefinitionType.WixGroup: 89 case TupleDefinitionType.WixGroup:
@@ -95,12 +96,12 @@ namespace WixToolset.Core.Burn.Bind
95 case TupleDefinitionType.WixUpdateRegistration: 96 case TupleDefinitionType.WixUpdateRegistration:
96 break; 97 break;
97 98
98 case TupleDefinitionType.WixCustomTable: 99 case TupleDefinitionType.WixBundleCustomData:
99 unknownTuple = !this.IndexCustomTableTuple((WixCustomTableTuple)tuple, customTablesById); 100 unknownTuple = !this.IndexBundleCustomDataTuple((WixBundleCustomDataTuple)tuple, customDataById);
100 break; 101 break;
101 102
102 case TupleDefinitionType.WixCustomTableCell: 103 case TupleDefinitionType.WixBundleCustomDataCell:
103 this.IndexCustomTableCellTuple((WixCustomTableCellTuple)tuple, cellsByTableAndRowId); 104 this.IndexBundleCustomDataCellTuple((WixBundleCustomDataCellTuple)tuple, cellsByCustomDataAndElementId);
104 break; 105 break;
105 106
106 case TupleDefinitionType.MustBeFromAnExtension: 107 case TupleDefinitionType.MustBeFromAnExtension:
@@ -118,68 +119,87 @@ namespace WixToolset.Core.Burn.Bind
118 } 119 }
119 } 120 }
120 121
121 this.AddIndexedCellTuples(customTablesById, cellsByTableAndRowId); 122 this.AddIndexedCellTuples(customDataById, cellsByCustomDataAndElementId);
122 } 123 }
123 124
124 private bool IndexCustomTableTuple(WixCustomTableTuple wixCustomTableTuple, Dictionary<string, WixCustomTableTuple> customTablesById) 125 private bool IndexBundleCustomDataTuple(WixBundleCustomDataTuple wixBundleCustomDataTuple, Dictionary<string, WixBundleCustomDataTuple> customDataById)
125 { 126 {
126 if (!wixCustomTableTuple.Unreal) 127 switch (wixBundleCustomDataTuple.Type)
127 { 128 {
128 return false; 129 case WixBundleCustomDataType.BootstrapperApplication:
130 case WixBundleCustomDataType.BundleExtension:
131 break;
132 default:
133 return false;
129 } 134 }
130 135
131 var tableId = wixCustomTableTuple.Id.Id; 136 var customDataId = wixBundleCustomDataTuple.Id.Id;
132 customTablesById.Add(tableId, wixCustomTableTuple); 137 customDataById.Add(customDataId, wixBundleCustomDataTuple);
133 return true; 138 return true;
134 } 139 }
135 140
136 private void IndexCustomTableCellTuple(WixCustomTableCellTuple wixCustomTableCellTuple, Dictionary<string, List<WixCustomTableCellTuple>> cellsByTableAndRowId) 141 private void IndexBundleCustomDataCellTuple(WixBundleCustomDataCellTuple wixBundleCustomDataCellTuple, Dictionary<string, List<WixBundleCustomDataCellTuple>> cellsByCustomDataAndElementId)
137 { 142 {
138 var tableAndRowId = wixCustomTableCellTuple.TableRef + "/" + wixCustomTableCellTuple.RowId; 143 var tableAndRowId = wixBundleCustomDataCellTuple.CustomDataRef + "/" + wixBundleCustomDataCellTuple.ElementId;
139 if (!cellsByTableAndRowId.TryGetValue(tableAndRowId, out var cells)) 144 if (!cellsByCustomDataAndElementId.TryGetValue(tableAndRowId, out var cells))
140 { 145 {
141 cells = new List<WixCustomTableCellTuple>(); 146 cells = new List<WixBundleCustomDataCellTuple>();
142 cellsByTableAndRowId.Add(tableAndRowId, cells); 147 cellsByCustomDataAndElementId.Add(tableAndRowId, cells);
143 } 148 }
144 149
145 cells.Add(wixCustomTableCellTuple); 150 cells.Add(wixBundleCustomDataCellTuple);
146 } 151 }
147 152
148 private void AddIndexedCellTuples(Dictionary<string, WixCustomTableTuple> customTablesById, Dictionary<string, List<WixCustomTableCellTuple>> cellsByTableAndRowId) 153 private void AddIndexedCellTuples(Dictionary<string, WixBundleCustomDataTuple> customDataById, Dictionary<string, List<WixBundleCustomDataCellTuple>> cellsByCustomDataAndElementId)
149 { 154 {
150 var sb = new StringBuilder(); 155 foreach (var elementValues in cellsByCustomDataAndElementId.Values)
151 using (var writer = XmlWriter.Create(sb, BurnBackendHelper.WriterSettings))
152 { 156 {
153 foreach (var rowOfCells in cellsByTableAndRowId.Values) 157 var elementName = elementValues[0].CustomDataRef;
154 { 158 var customDataTuple = customDataById[elementName];
155 var tableId = rowOfCells[0].TableRef;
156 var tableTuple = customTablesById[tableId];
157
158 if (!tableTuple.Unreal)
159 {
160 return;
161 }
162 159
163 var columnNames = tableTuple.ColumnNamesSeparated; 160 var attributeNames = customDataTuple.AttributeNamesSeparated;
164 161
165 var rowDataByColumn = rowOfCells.ToDictionary(t => t.ColumnRef, t => t.Data); 162 var elementValuesByAttribute = elementValues.ToDictionary(t => t.AttributeRef, t => t.Value);
166 163
167 writer.WriteStartElement(tableId, BurnCommon.BADataNamespace); 164 var sb = new StringBuilder();
165 using (var writer = XmlWriter.Create(sb, BurnBackendHelper.WriterSettings))
166 {
167 switch (customDataTuple.Type)
168 {
169 case WixBundleCustomDataType.BootstrapperApplication:
170 writer.WriteStartElement(elementName, BurnCommon.BADataNamespace);
171 break;
172 case WixBundleCustomDataType.BundleExtension:
173 writer.WriteStartElement(elementName, BurnCommon.BundleExtensionDataNamespace);
174 break;
175 default:
176 throw new NotImplementedException();
177 }
168 178
169 // Write all row data as attributes in table column order. 179 // Write all row data as attributes in table column order.
170 foreach (var column in columnNames) 180 foreach (var attributeName in attributeNames)
171 { 181 {
172 if (rowDataByColumn.TryGetValue(column, out var data)) 182 if (elementValuesByAttribute.TryGetValue(attributeName, out var value))
173 { 183 {
174 writer.WriteAttributeString(column, data); 184 writer.WriteAttributeString(attributeName, value);
175 } 185 }
176 } 186 }
177 187
178 writer.WriteEndElement(); 188 writer.WriteEndElement();
179 } 189 }
180 }
181 190
182 this.BackendHelper.AddBootstrapperApplicationData(sb.ToString()); 191 switch (customDataTuple.Type)
192 {
193 case WixBundleCustomDataType.BootstrapperApplication:
194 this.BackendHelper.AddBootstrapperApplicationData(sb.ToString());
195 break;
196 case WixBundleCustomDataType.BundleExtension:
197 this.BackendHelper.AddBundleExtensionData(customDataTuple.BundleExtensionRef, sb.ToString());
198 break;
199 default:
200 throw new NotImplementedException();
201 }
202 }
183 } 203 }
184 204
185 private bool AddTupleFromExtension(IntermediateTuple tuple) 205 private bool AddTupleFromExtension(IntermediateTuple tuple)
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
index daf4c96e..553b470b 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/CreateOutputFromIRCommand.cs
@@ -4,6 +4,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
4{ 4{
5 using System; 5 using System;
6 using System.Collections.Generic; 6 using System.Collections.Generic;
7 using System.Diagnostics;
7 using System.Globalization; 8 using System.Globalization;
8 using System.Linq; 9 using System.Linq;
9 using WixToolset.Data; 10 using WixToolset.Data;
@@ -978,7 +979,8 @@ namespace WixToolset.Core.WindowsInstaller.Bind
978 979
979 if (customTableDefinition.Unreal) 980 if (customTableDefinition.Unreal)
980 { 981 {
981 return; 982 Debug.Assert(false, "CustomTableDefinition should never be unreal.");
983 continue;
982 } 984 }
983 985
984 var customRow = this.CreateRow(firstCellTuple, customTableDefinition); 986 var customRow = this.CreateRow(firstCellTuple, customTableDefinition);
diff --git a/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs b/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs
index 0312ab44..cfb46ff9 100644
--- a/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs
+++ b/src/WixToolset.Core.WindowsInstaller/Bind/LoadTableDefinitionsCommand.cs
@@ -208,7 +208,7 @@ namespace WixToolset.Core.WindowsInstaller.Bind
208 columns.Add(columnDefinition); 208 columns.Add(columnDefinition);
209 } 209 }
210 210
211 var customTable = new TableDefinition(tuple.Id.Id, null, columns, tuple.Unreal); 211 var customTable = new TableDefinition(tuple.Id.Id, null, columns);
212 return customTable; 212 return customTable;
213 } 213 }
214 } 214 }
diff --git a/src/WixToolset.Core/Compiler.cs b/src/WixToolset.Core/Compiler.cs
index da0806fb..bbd6b292 100644
--- a/src/WixToolset.Core/Compiler.cs
+++ b/src/WixToolset.Core/Compiler.cs
@@ -3668,7 +3668,6 @@ namespace WixToolset.Core
3668 { 3668 {
3669 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node); 3669 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
3670 string tableId = null; 3670 string tableId = null;
3671 var unreal = false;
3672 var columns = new List<WixCustomTableColumnTuple>(); 3671 var columns = new List<WixCustomTableColumnTuple>();
3673 3672
3674 foreach (var attrib in node.Attributes()) 3673 foreach (var attrib in node.Attributes())
@@ -3680,9 +3679,6 @@ namespace WixToolset.Core
3680 case "Id": 3679 case "Id":
3681 tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib); 3680 tableId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
3682 break; 3681 break;
3683 case "Unreal":
3684 unreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(sourceLineNumbers, attrib);
3685 break;
3686 default: 3682 default:
3687 this.Core.UnexpectedAttribute(node, attrib); 3683 this.Core.UnexpectedAttribute(node, attrib);
3688 break; 3684 break;
@@ -3710,315 +3706,336 @@ namespace WixToolset.Core
3710 var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child); 3706 var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
3711 switch (child.Name.LocalName) 3707 switch (child.Name.LocalName)
3712 { 3708 {
3713 case "Column": 3709 case "Column":
3714 string columnName = null; 3710 var column = this.ParseColumnElement(child, childSourceLineNumbers, tableId);
3715 IntermediateFieldType? columnType = null; 3711 if (column != null)
3716 var description = String.Empty;
3717 int? keyColumn = null;
3718 var keyTable = String.Empty;
3719 var localizable = false;
3720 long? maxValue = null;
3721 long? minValue = null;
3722 WixCustomTableColumnCategoryType? category = null;
3723 var modularization = WixCustomTableColumnModularizeType.None;
3724 var nullable = false;
3725 var primaryKey = false;
3726 var setValues = String.Empty;
3727 var columnUnreal = false;
3728 var width = 0;
3729
3730 foreach (var childAttrib in child.Attributes())
3731 {
3732 switch (childAttrib.Name.LocalName)
3733 { 3712 {
3734 case "Id": 3713 columns.Add(column);
3735 columnName = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, childAttrib); 3714 }
3715 break;
3716 case "Row":
3717 this.ParseRowElement(child, childSourceLineNumbers, tableId);
3718 break;
3719 default:
3720 this.Core.UnexpectedElement(node, child);
3721 break;
3722 }
3723 }
3724 else
3725 {
3726 this.Core.ParseExtensionElement(node, child);
3727 }
3728 }
3729
3730 if (columns.Count > 0)
3731 {
3732 if (!columns.Where(c => c.PrimaryKey).Any())
3733 {
3734 this.Core.Write(ErrorMessages.CustomTableMissingPrimaryKey(sourceLineNumbers));
3735 }
3736
3737 if (!this.Core.EncounteredError)
3738 {
3739 var columnNames = String.Join(new string(WixCustomTableTuple.ColumnNamesSeparator, 1), columns.Select(c => c.Name));
3740
3741 this.Core.AddTuple(new WixCustomTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, tableId))
3742 {
3743 ColumnNames = columnNames,
3744 });
3745 }
3746 }
3747 }
3748
3749 /// <summary>
3750 /// Parses a Column element.
3751 /// </summary>
3752 /// <param name="child">Element to parse.</param>
3753 /// <param name="childSourceLineNumbers">Element's SourceLineNumbers.</param>
3754 /// <param name="tableId">Table Id.</param>
3755 private WixCustomTableColumnTuple ParseColumnElement(XElement child, SourceLineNumber childSourceLineNumbers, string tableId)
3756 {
3757 string columnName = null;
3758 IntermediateFieldType? columnType = null;
3759 var description = String.Empty;
3760 int? keyColumn = null;
3761 var keyTable = String.Empty;
3762 var localizable = false;
3763 long? maxValue = null;
3764 long? minValue = null;
3765 WixCustomTableColumnCategoryType? category = null;
3766 var modularization = WixCustomTableColumnModularizeType.None;
3767 var nullable = false;
3768 var primaryKey = false;
3769 var setValues = String.Empty;
3770 var columnUnreal = false;
3771 var width = 0;
3772
3773 foreach (var childAttrib in child.Attributes())
3774 {
3775 switch (childAttrib.Name.LocalName)
3776 {
3777 case "Id":
3778 columnName = this.Core.GetAttributeIdentifierValue(childSourceLineNumbers, childAttrib);
3779 break;
3780 case "Category":
3781 var categoryValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3782 switch (categoryValue)
3783 {
3784 case "text":
3785 category = WixCustomTableColumnCategoryType.Text;
3736 break; 3786 break;
3737 case "Category": 3787 case "upperCase":
3738 var categoryValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3788 category = WixCustomTableColumnCategoryType.UpperCase;
3739 switch (categoryValue)
3740 {
3741 case "text":
3742 category = WixCustomTableColumnCategoryType.Text;
3743 break;
3744 case "upperCase":
3745 category = WixCustomTableColumnCategoryType.UpperCase;
3746 break;
3747 case "lowerCase":
3748 category = WixCustomTableColumnCategoryType.LowerCase;
3749 break;
3750 case "integer":
3751 category = WixCustomTableColumnCategoryType.Integer;
3752 break;
3753 case "doubleInteger":
3754 category = WixCustomTableColumnCategoryType.DoubleInteger;
3755 break;
3756 case "timeDate":
3757 category = WixCustomTableColumnCategoryType.TimeDate;
3758 break;
3759 case "identifier":
3760 category = WixCustomTableColumnCategoryType.Identifier;
3761 break;
3762 case "property":
3763 category = WixCustomTableColumnCategoryType.Property;
3764 break;
3765 case "filename":
3766 category = WixCustomTableColumnCategoryType.Filename;
3767 break;
3768 case "wildCardFilename":
3769 category = WixCustomTableColumnCategoryType.WildCardFilename;
3770 break;
3771 case "path":
3772 category = WixCustomTableColumnCategoryType.Path;
3773 break;
3774 case "paths":
3775 category = WixCustomTableColumnCategoryType.Paths;
3776 break;
3777 case "anyPath":
3778 category = WixCustomTableColumnCategoryType.AnyPath;
3779 break;
3780 case "defaultDir":
3781 category = WixCustomTableColumnCategoryType.DefaultDir;
3782 break;
3783 case "regPath":
3784 category = WixCustomTableColumnCategoryType.RegPath;
3785 break;
3786 case "formatted":
3787 category = WixCustomTableColumnCategoryType.Formatted;
3788 break;
3789 case "formattedSddl":
3790 category = WixCustomTableColumnCategoryType.FormattedSddl;
3791 break;
3792 case "template":
3793 category = WixCustomTableColumnCategoryType.Template;
3794 break;
3795 case "condition":
3796 category = WixCustomTableColumnCategoryType.Condition;
3797 break;
3798 case "guid":
3799 category = WixCustomTableColumnCategoryType.Guid;
3800 break;
3801 case "version":
3802 category = WixCustomTableColumnCategoryType.Version;
3803 break;
3804 case "language":
3805 category = WixCustomTableColumnCategoryType.Language;
3806 break;
3807 case "binary":
3808 category = WixCustomTableColumnCategoryType.Binary;
3809 break;
3810 case "customSource":
3811 category = WixCustomTableColumnCategoryType.CustomSource;
3812 break;
3813 case "cabinet":
3814 category = WixCustomTableColumnCategoryType.Cabinet;
3815 break;
3816 case "shortcut":
3817 category = WixCustomTableColumnCategoryType.Shortcut;
3818 break;
3819 case "":
3820 break;
3821 default:
3822 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Category", categoryValue,
3823 "text", "upperCase", "lowerCase", "integer", "doubleInteger", "timeDate", "identifier", "property", "filename",
3824 "wildCardFilename", "path", "paths", "anyPath", "defaultDir", "regPath", "formatted", "formattedSddl", "template",
3825 "condition", "guid", "version", "language", "binary", "customSource", "cabinet", "shortcut"));
3826 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below.
3827 break;
3828 }
3829 break; 3789 break;
3830 case "Description": 3790 case "lowerCase":
3831 description = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3791 category = WixCustomTableColumnCategoryType.LowerCase;
3832 break; 3792 break;
3833 case "KeyColumn": 3793 case "integer":
3834 keyColumn = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 1, 32); 3794 category = WixCustomTableColumnCategoryType.Integer;
3835 break; 3795 break;
3836 case "KeyTable": 3796 case "doubleInteger":
3837 keyTable = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3797 category = WixCustomTableColumnCategoryType.DoubleInteger;
3838 break; 3798 break;
3839 case "Localizable": 3799 case "timeDate":
3840 localizable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); 3800 category = WixCustomTableColumnCategoryType.TimeDate;
3841 break; 3801 break;
3842 case "MaxValue": 3802 case "identifier":
3843 maxValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); 3803 category = WixCustomTableColumnCategoryType.Identifier;
3844 break; 3804 break;
3845 case "MinValue": 3805 case "property":
3846 minValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue); 3806 category = WixCustomTableColumnCategoryType.Property;
3847 break; 3807 break;
3848 case "Modularize": 3808 case "filename":
3849 var modularizeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3809 category = WixCustomTableColumnCategoryType.Filename;
3850 switch (modularizeValue)
3851 {
3852 case "column":
3853 modularization = WixCustomTableColumnModularizeType.Column;
3854 break;
3855 case "companionFile":
3856 modularization = WixCustomTableColumnModularizeType.CompanionFile;
3857 break;
3858 case "condition":
3859 modularization = WixCustomTableColumnModularizeType.Condition;
3860 break;
3861 case "controlEventArgument":
3862 modularization = WixCustomTableColumnModularizeType.ControlEventArgument;
3863 break;
3864 case "controlText":
3865 modularization = WixCustomTableColumnModularizeType.ControlText;
3866 break;
3867 case "icon":
3868 modularization = WixCustomTableColumnModularizeType.Icon;
3869 break;
3870 case "none":
3871 modularization = WixCustomTableColumnModularizeType.None;
3872 break;
3873 case "property":
3874 modularization = WixCustomTableColumnModularizeType.Property;
3875 break;
3876 case "semicolonDelimited":
3877 modularization = WixCustomTableColumnModularizeType.SemicolonDelimited;
3878 break;
3879 case "":
3880 break;
3881 default:
3882 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Modularize", modularizeValue, "column", "companionFile", "condition", "controlEventArgument", "controlText", "icon", "property", "semicolonDelimited"));
3883 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below.
3884 break;
3885 }
3886 break; 3810 break;
3887 case "Nullable": 3811 case "wildCardFilename":
3888 nullable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); 3812 category = WixCustomTableColumnCategoryType.WildCardFilename;
3889 break; 3813 break;
3890 case "PrimaryKey": 3814 case "path":
3891 primaryKey = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); 3815 category = WixCustomTableColumnCategoryType.Path;
3892 break; 3816 break;
3893 case "Set": 3817 case "paths":
3894 setValues = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3818 category = WixCustomTableColumnCategoryType.Paths;
3895 break; 3819 break;
3896 case "Type": 3820 case "anyPath":
3897 var typeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib); 3821 category = WixCustomTableColumnCategoryType.AnyPath;
3898 switch (typeValue) 3822 break;
3899 { 3823 case "defaultDir":
3900 case "binary": 3824 category = WixCustomTableColumnCategoryType.DefaultDir;
3901 columnType = IntermediateFieldType.Path; 3825 break;
3902 break; 3826 case "regPath":
3903 case "int": 3827 category = WixCustomTableColumnCategoryType.RegPath;
3904 columnType = IntermediateFieldType.Number; 3828 break;
3905 break; 3829 case "formatted":
3906 case "string": 3830 category = WixCustomTableColumnCategoryType.Formatted;
3907 columnType = IntermediateFieldType.String; 3831 break;
3908 break; 3832 case "formattedSddl":
3909 case "": 3833 category = WixCustomTableColumnCategoryType.FormattedSddl;
3910 break; 3834 break;
3911 default: 3835 case "template":
3912 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Type", typeValue, "binary", "int", "string")); 3836 category = WixCustomTableColumnCategoryType.Template;
3913 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below. 3837 break;
3914 break; 3838 case "condition":
3915 } 3839 category = WixCustomTableColumnCategoryType.Condition;
3840 break;
3841 case "guid":
3842 category = WixCustomTableColumnCategoryType.Guid;
3916 break; 3843 break;
3917 case "Width": 3844 case "version":
3918 width = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 0, Int32.MaxValue); 3845 category = WixCustomTableColumnCategoryType.Version;
3919 break; 3846 break;
3920 case "Unreal": 3847 case "language":
3921 columnUnreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib); 3848 category = WixCustomTableColumnCategoryType.Language;
3849 break;
3850 case "binary":
3851 category = WixCustomTableColumnCategoryType.Binary;
3852 break;
3853 case "customSource":
3854 category = WixCustomTableColumnCategoryType.CustomSource;
3855 break;
3856 case "cabinet":
3857 category = WixCustomTableColumnCategoryType.Cabinet;
3858 break;
3859 case "shortcut":
3860 category = WixCustomTableColumnCategoryType.Shortcut;
3861 break;
3862 case "":
3922 break; 3863 break;
3923 default: 3864 default:
3924 this.Core.UnexpectedAttribute(child, childAttrib); 3865 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Category", categoryValue,
3866 "text", "upperCase", "lowerCase", "integer", "doubleInteger", "timeDate", "identifier", "property", "filename",
3867 "wildCardFilename", "path", "paths", "anyPath", "defaultDir", "regPath", "formatted", "formattedSddl", "template",
3868 "condition", "guid", "version", "language", "binary", "customSource", "cabinet", "shortcut"));
3869 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below.
3925 break; 3870 break;
3926 }
3927 }
3928
3929 if (null == columnName)
3930 {
3931 this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Id"));
3932 }
3933
3934 if (!columnType.HasValue)
3935 {
3936 this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Type"));
3937 } 3871 }
3938 else if (columnType == IntermediateFieldType.Number) 3872 break;
3939 { 3873 case "Description":
3940 if (2 != width && 4 != width) 3874 description = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3941 { 3875 break;
3942 this.Core.Write(ErrorMessages.CustomTableIllegalColumnWidth(childSourceLineNumbers, child.Name.LocalName, "Width", width)); 3876 case "KeyColumn":
3943 } 3877 keyColumn = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 1, 32);
3944 } 3878 break;
3945 else if (columnType == IntermediateFieldType.Path) 3879 case "KeyTable":
3880 keyTable = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3881 break;
3882 case "Localizable":
3883 localizable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib);
3884 break;
3885 case "MaxValue":
3886 maxValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue);
3887 break;
3888 case "MinValue":
3889 minValue = this.Core.GetAttributeLongValue(childSourceLineNumbers, childAttrib, Int32.MinValue + 1, Int32.MaxValue);
3890 break;
3891 case "Modularize":
3892 var modularizeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3893 switch (modularizeValue)
3946 { 3894 {
3947 if (!category.HasValue) 3895 case "column":
3948 { 3896 modularization = WixCustomTableColumnModularizeType.Column;
3949 category = WixCustomTableColumnCategoryType.Binary; 3897 break;
3950 } 3898 case "companionFile":
3951 else if (category != WixCustomTableColumnCategoryType.Binary) 3899 modularization = WixCustomTableColumnModularizeType.CompanionFile;
3952 { 3900 break;
3953 this.Core.Write(ErrorMessages.ExpectedBinaryCategory(childSourceLineNumbers)); 3901 case "condition":
3954 } 3902 modularization = WixCustomTableColumnModularizeType.Condition;
3903 break;
3904 case "controlEventArgument":
3905 modularization = WixCustomTableColumnModularizeType.ControlEventArgument;
3906 break;
3907 case "controlText":
3908 modularization = WixCustomTableColumnModularizeType.ControlText;
3909 break;
3910 case "icon":
3911 modularization = WixCustomTableColumnModularizeType.Icon;
3912 break;
3913 case "none":
3914 modularization = WixCustomTableColumnModularizeType.None;
3915 break;
3916 case "property":
3917 modularization = WixCustomTableColumnModularizeType.Property;
3918 break;
3919 case "semicolonDelimited":
3920 modularization = WixCustomTableColumnModularizeType.SemicolonDelimited;
3921 break;
3922 case "":
3923 break;
3924 default:
3925 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Modularize", modularizeValue, "column", "companionFile", "condition", "controlEventArgument", "controlText", "icon", "property", "semicolonDelimited"));
3926 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below.
3927 break;
3955 } 3928 }
3956 3929 break;
3957 this.Core.ParseForExtensionElements(child); 3930 case "Nullable":
3958 3931 nullable = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib);
3959 if (!this.Core.EncounteredError) 3932 break;
3933 case "PrimaryKey":
3934 primaryKey = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib);
3935 break;
3936 case "Set":
3937 setValues = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3938 break;
3939 case "Type":
3940 var typeValue = this.Core.GetAttributeValue(childSourceLineNumbers, childAttrib);
3941 switch (typeValue)
3960 { 3942 {
3961 var attributes = primaryKey ? WixCustomTableColumnTupleAttributes.PrimaryKey : WixCustomTableColumnTupleAttributes.None; 3943 case "binary":
3962 attributes |= localizable ? WixCustomTableColumnTupleAttributes.Localizable : WixCustomTableColumnTupleAttributes.None; 3944 columnType = IntermediateFieldType.Path;
3963 attributes |= nullable ? WixCustomTableColumnTupleAttributes.Nullable : WixCustomTableColumnTupleAttributes.None; 3945 break;
3964 attributes |= columnUnreal ? WixCustomTableColumnTupleAttributes.Unreal : WixCustomTableColumnTupleAttributes.None; 3946 case "int":
3965 3947 columnType = IntermediateFieldType.Number;
3966 var column = this.Core.AddTuple(new WixCustomTableColumnTuple(childSourceLineNumbers, new Identifier(AccessModifier.Private, tableId, columnName)) 3948 break;
3967 { 3949 case "string":
3968 TableRef = tableId, 3950 columnType = IntermediateFieldType.String;
3969 Name = columnName, 3951 break;
3970 Type = columnType.Value, 3952 case "":
3971 Attributes = attributes, 3953 break;
3972 Width = width, 3954 default:
3973 Category = category, 3955 this.Core.Write(ErrorMessages.IllegalAttributeValue(childSourceLineNumbers, child.Name.LocalName, "Type", typeValue, "binary", "int", "string"));
3974 Description = description, 3956 columnType = IntermediateFieldType.String; // set a value to prevent expected attribute error below.
3975 KeyColumn = keyColumn, 3957 break;
3976 KeyTable = keyTable,
3977 MaxValue = maxValue,
3978 MinValue = minValue,
3979 Modularize = modularization,
3980 Set = setValues,
3981 });
3982 columns.Add(column);
3983 } 3958 }
3984 break; 3959 break;
3985 case "Row": 3960 case "Width":
3986 this.ParseRow(child, tableId); 3961 width = this.Core.GetAttributeIntegerValue(childSourceLineNumbers, childAttrib, 0, Int32.MaxValue);
3962 break;
3963 case "Unreal":
3964 columnUnreal = YesNoType.Yes == this.Core.GetAttributeYesNoValue(childSourceLineNumbers, childAttrib);
3987 break; 3965 break;
3988 default: 3966 default:
3989 this.Core.UnexpectedElement(node, child); 3967 this.Core.UnexpectedAttribute(child, childAttrib);
3990 break; 3968 break;
3991 }
3992 } 3969 }
3993 else 3970 }
3971
3972 if (null == columnName)
3973 {
3974 this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Id"));
3975 }
3976
3977 if (!columnType.HasValue)
3978 {
3979 this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Type"));
3980 }
3981 else if (columnType == IntermediateFieldType.Number)
3982 {
3983 if (2 != width && 4 != width)
3994 { 3984 {
3995 this.Core.ParseExtensionElement(node, child); 3985 this.Core.Write(ErrorMessages.CustomTableIllegalColumnWidth(childSourceLineNumbers, child.Name.LocalName, "Width", width));
3996 } 3986 }
3997 } 3987 }
3998 3988 else if (columnType == IntermediateFieldType.Path)
3999 if (columns.Count > 0)
4000 { 3989 {
4001 if (!columns.Where(c => c.PrimaryKey).Any()) 3990 if (!category.HasValue)
4002 { 3991 {
4003 this.Core.Write(ErrorMessages.CustomTableMissingPrimaryKey(sourceLineNumbers)); 3992 category = WixCustomTableColumnCategoryType.Binary;
4004 } 3993 }
4005 3994 else if (category != WixCustomTableColumnCategoryType.Binary)
4006 if (!this.Core.EncounteredError)
4007 { 3995 {
4008 var columnNames = String.Join(new string(WixCustomTableTuple.ColumnNamesSeparator, 1), columns.Select(c => c.Name)); 3996 this.Core.Write(ErrorMessages.ExpectedBinaryCategory(childSourceLineNumbers));
4009
4010 this.Core.AddTuple(new WixCustomTableTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, tableId))
4011 {
4012 ColumnNames = columnNames,
4013 Unreal = unreal,
4014 });
4015 } 3997 }
4016 } 3998 }
3999
4000 this.Core.ParseForExtensionElements(child);
4001
4002 if (this.Core.EncounteredError)
4003 {
4004 return null;
4005 }
4006
4007 var attributes = primaryKey ? WixCustomTableColumnTupleAttributes.PrimaryKey : WixCustomTableColumnTupleAttributes.None;
4008 attributes |= localizable ? WixCustomTableColumnTupleAttributes.Localizable : WixCustomTableColumnTupleAttributes.None;
4009 attributes |= nullable ? WixCustomTableColumnTupleAttributes.Nullable : WixCustomTableColumnTupleAttributes.None;
4010 attributes |= columnUnreal ? WixCustomTableColumnTupleAttributes.Unreal : WixCustomTableColumnTupleAttributes.None;
4011
4012 var column = this.Core.AddTuple(new WixCustomTableColumnTuple(childSourceLineNumbers, new Identifier(AccessModifier.Private, tableId, columnName))
4013 {
4014 TableRef = tableId,
4015 Name = columnName,
4016 Type = columnType.Value,
4017 Attributes = attributes,
4018 Width = width,
4019 Category = category,
4020 Description = description,
4021 KeyColumn = keyColumn,
4022 KeyTable = keyTable,
4023 MaxValue = maxValue,
4024 MinValue = minValue,
4025 Modularize = modularization,
4026 Set = setValues,
4027 });
4028 return column;
4017 } 4029 }
4018 4030
4019 private void ParseRow(XElement node, string tableId) 4031 /// <summary>
4032 /// Parses a Row element.
4033 /// </summary>
4034 /// <param name="node">Element to parse.</param>
4035 /// <param name="sourceLineNumbers">Element's SourceLineNumbers.</param>
4036 /// <param name="tableId">Table Id.</param>
4037 private void ParseRowElement(XElement node, SourceLineNumber sourceLineNumbers, string tableId)
4020 { 4038 {
4021 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
4022 var rowId = Guid.NewGuid().ToString("N").ToUpperInvariant(); 4039 var rowId = Guid.NewGuid().ToString("N").ToUpperInvariant();
4023 4040
4024 foreach (var attrib in node.Attributes()) 4041 foreach (var attrib in node.Attributes())
@@ -6204,6 +6221,9 @@ namespace WixToolset.Core
6204 case "BootstrapperApplicationRef": 6221 case "BootstrapperApplicationRef":
6205 this.ParseBootstrapperApplicationRefElement(child); 6222 this.ParseBootstrapperApplicationRefElement(child);
6206 break; 6223 break;
6224 case "BundleCustomData":
6225 this.ParseBundleCustomDataElement(child);
6226 break;
6207 case "BundleExtension": 6227 case "BundleExtension":
6208 this.ParseBundleExtensionElement(child); 6228 this.ParseBundleExtensionElement(child);
6209 break; 6229 break;
diff --git a/src/WixToolset.Core/Compiler_Bundle.cs b/src/WixToolset.Core/Compiler_Bundle.cs
index 31896a42..5154a72f 100644
--- a/src/WixToolset.Core/Compiler_Bundle.cs
+++ b/src/WixToolset.Core/Compiler_Bundle.cs
@@ -7,6 +7,7 @@ namespace WixToolset.Core
7 using System.Diagnostics; 7 using System.Diagnostics;
8 using System.Globalization; 8 using System.Globalization;
9 using System.IO; 9 using System.IO;
10 using System.Linq;
10 using System.Xml.Linq; 11 using System.Xml.Linq;
11 using WixToolset.Data; 12 using WixToolset.Data;
12 using WixToolset.Data.Burn; 13 using WixToolset.Data.Burn;
@@ -276,6 +277,9 @@ namespace WixToolset.Core
276 case "BootstrapperApplicationRef": 277 case "BootstrapperApplicationRef":
277 this.ParseBootstrapperApplicationRefElement(child); 278 this.ParseBootstrapperApplicationRefElement(child);
278 break; 279 break;
280 case "BundleCustomData":
281 this.ParseBundleCustomDataElement(child);
282 break;
279 case "BundleExtension": 283 case "BundleExtension":
280 this.ParseBundleExtensionElement(child); 284 this.ParseBundleExtensionElement(child);
281 break; 285 break;
@@ -767,6 +771,246 @@ namespace WixToolset.Core
767 } 771 }
768 } 772 }
769 773
774
775
776 /// <summary>
777 /// Parses a BundleCustomData element.
778 /// </summary>
779 /// <param name="node">Element to parse.</param>
780 private void ParseBundleCustomDataElement(XElement node)
781 {
782 var sourceLineNumbers = Preprocessor.GetSourceLineNumbers(node);
783 string customDataId = null;
784 WixBundleCustomDataType? customDataType = null;
785 string extensionId = null;
786 var attributeDefinitions = new List<WixBundleCustomDataAttributeTuple>();
787
788 foreach (var attrib in node.Attributes())
789 {
790 if (String.IsNullOrEmpty(attrib.Name.NamespaceName) || CompilerCore.WixNamespace == attrib.Name.Namespace)
791 {
792 switch (attrib.Name.LocalName)
793 {
794 case "Id":
795 customDataId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
796 break;
797 case "Type":
798 var typeValue = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
799 switch (typeValue)
800 {
801 case "bootstrapperApplication":
802 customDataType = WixBundleCustomDataType.BootstrapperApplication;
803 break;
804 case "bundleExtension":
805 customDataType = WixBundleCustomDataType.BundleExtension;
806 break;
807 default:
808 this.Core.Write(ErrorMessages.IllegalAttributeValue(sourceLineNumbers, node.Name.LocalName, "Type", typeValue, "bootstrapperApplication", "bundleExtension"));
809 customDataType = WixBundleCustomDataType.Unknown; // set a value to prevent expected attribute error below.
810 break;
811 }
812 break;
813 case "ExtensionId":
814 extensionId = this.Core.GetAttributeIdentifierValue(sourceLineNumbers, attrib);
815 this.Core.CreateSimpleReference(sourceLineNumbers, TupleDefinitions.WixBundleExtension, extensionId);
816 break;
817 default:
818 this.Core.UnexpectedAttribute(node, attrib);
819 break;
820 }
821 }
822 else
823 {
824 this.Core.ParseExtensionAttribute(node, attrib);
825 }
826 }
827
828 if (null == customDataId)
829 {
830 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
831 }
832
833 var hasExtensionId = null != extensionId;
834 if (hasExtensionId && !customDataType.HasValue)
835 {
836 customDataType = WixBundleCustomDataType.BundleExtension;
837 }
838
839 if (!customDataType.HasValue)
840 {
841 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Type"));
842 }
843 else if (hasExtensionId)
844 {
845 if (customDataType.Value == WixBundleCustomDataType.BootstrapperApplication)
846 {
847 this.Core.Write(ErrorMessages.IllegalAttributeWithOtherAttribute(sourceLineNumbers, node.Name.LocalName, "ExtensonId", "Type", "bootstrapperApplication"));
848 }
849 }
850 else if (customDataType.Value == WixBundleCustomDataType.BundleExtension)
851 {
852 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "ExtensionId", "Type", "bundleExtension"));
853 }
854
855 foreach (var child in node.Elements())
856 {
857 if (CompilerCore.WixNamespace == child.Name.Namespace)
858 {
859 var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
860 switch (child.Name.LocalName)
861 {
862 case "BundleAttributeDefinition":
863 var attributeDefinition = this.ParseBundleAttributeDefinitionElement(child, childSourceLineNumbers, customDataId);
864 if (attributeDefinition != null)
865 {
866 attributeDefinitions.Add(attributeDefinition);
867 }
868 break;
869 case "BundleElement":
870 this.ParseBundleElementElement(child, childSourceLineNumbers, customDataId);
871 break;
872 default:
873 this.Core.UnexpectedElement(node, child);
874 break;
875 }
876 }
877 else
878 {
879 this.Core.ParseExtensionElement(node, child);
880 }
881 }
882
883 if (attributeDefinitions.Count > 0)
884 {
885 if (!this.Core.EncounteredError)
886 {
887 var attributeNames = String.Join(new string(WixBundleCustomDataTuple.AttributeNamesSeparator, 1), attributeDefinitions.Select(c => c.Name));
888
889 this.Core.AddTuple(new WixBundleCustomDataTuple(sourceLineNumbers, new Identifier(AccessModifier.Public, customDataId))
890 {
891 AttributeNames = attributeNames,
892 Type = customDataType.Value,
893 BundleExtensionRef = extensionId,
894 });
895 }
896 }
897 }
898
899 /// <summary>
900 /// Parses a BundleAttributeDefinition element.
901 /// </summary>
902 /// <param name="node">Element to parse.</param>
903 /// <param name="sourceLineNumbers">Element's SourceLineNumbers.</param>
904 /// <param name="customDataId">BundleCustomData Id.</param>
905 private WixBundleCustomDataAttributeTuple ParseBundleAttributeDefinitionElement(XElement node, SourceLineNumber sourceLineNumbers, string customDataId)
906 {
907 string attributeName = null;
908
909 foreach (var attrib in node.Attributes())
910 {
911 switch (attrib.Name.LocalName)
912 {
913 case "Id":
914 attributeName = this.Core.GetAttributeValue(sourceLineNumbers, attrib);
915 break;
916 default:
917 this.Core.UnexpectedAttribute(node, attrib);
918 break;
919 }
920 }
921
922 if (null == attributeName)
923 {
924 this.Core.Write(ErrorMessages.ExpectedAttribute(sourceLineNumbers, node.Name.LocalName, "Id"));
925 }
926
927 this.Core.ParseForExtensionElements(node);
928
929 if (this.Core.EncounteredError)
930 {
931 return null;
932 }
933
934 var customDataAttribute = this.Core.AddTuple(new WixBundleCustomDataAttributeTuple(sourceLineNumbers, new Identifier(AccessModifier.Private, customDataId, attributeName))
935 {
936 CustomDataRef = customDataId,
937 Name = attributeName,
938 });
939 return customDataAttribute;
940 }
941
942 /// <summary>
943 /// Parses a BundleElement element.
944 /// </summary>
945 /// <param name="node">Element to parse.</param>
946 /// <param name="sourceLineNumbers">Element's SourceLineNumbers.</param>
947 /// <param name="customDataId">BundleCustomData Id.</param>
948 private void ParseBundleElementElement(XElement node, SourceLineNumber sourceLineNumbers, string customDataId)
949 {
950 var elementId = Guid.NewGuid().ToString("N").ToUpperInvariant();
951
952 foreach (var attrib in node.Attributes())
953 {
954 this.Core.ParseExtensionAttribute(node, attrib);
955 }
956
957 foreach (var child in node.Elements())
958 {
959 var childSourceLineNumbers = Preprocessor.GetSourceLineNumbers(child);
960 switch (child.Name.LocalName)
961 {
962 case "BundleAttribute":
963 string attributeName = null;
964 string value = null;
965 foreach (var attrib in child.Attributes())
966 {
967 switch (attrib.Name.LocalName)
968 {
969 case "Id":
970 attributeName = this.Core.GetAttributeValue(childSourceLineNumbers, attrib);
971 break;
972 case "Value":
973 value = this.Core.GetAttributeValue(childSourceLineNumbers, attrib);
974 break;
975 default:
976 this.Core.ParseExtensionAttribute(child, attrib);
977 break;
978 }
979 }
980
981 if (null == attributeName)
982 {
983 this.Core.Write(ErrorMessages.ExpectedAttribute(childSourceLineNumbers, child.Name.LocalName, "Id"));
984 }
985
986 if (String.IsNullOrEmpty(value))
987 {
988 value = Common.GetInnerText(child);
989 }
990
991 if (!this.Core.EncounteredError)
992 {
993 this.Core.AddTuple(new WixBundleCustomDataCellTuple(childSourceLineNumbers, new Identifier(AccessModifier.Private, customDataId, elementId, attributeName))
994 {
995 ElementId = elementId,
996 AttributeRef = attributeName,
997 CustomDataRef = customDataId,
998 Value = value,
999 });
1000 }
1001 break;
1002 default:
1003 this.Core.UnexpectedElement(node, child);
1004 break;
1005 }
1006 }
1007
1008 if (!this.Core.EncounteredError)
1009 {
1010 this.Core.CreateSimpleReference(sourceLineNumbers, TupleDefinitions.WixBundleCustomData, customDataId);
1011 }
1012 }
1013
770 /// <summary> 1014 /// <summary>
771 /// Parse the BundleExtension element. 1015 /// Parse the BundleExtension element.
772 /// </summary> 1016 /// </summary>
diff --git a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
index 4b1ec718..ae83150a 100644
--- a/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/BundleManifestFixture.cs
@@ -13,7 +13,7 @@ namespace WixToolsetTest.CoreIntegration
13 public class BundleManifestFixture 13 public class BundleManifestFixture
14 { 14 {
15 [Fact] 15 [Fact]
16 public void PopulatesBAManifestWithUnrealCustomTable() 16 public void PopulatesBAManifestWithBootstrapperApplicationBundleCustomData()
17 { 17 {
18 var folder = TestData.Get(@"TestData"); 18 var folder = TestData.Get(@"TestData");
19 19
@@ -43,11 +43,50 @@ namespace WixToolsetTest.CoreIntegration
43 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath); 43 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
44 extractResult.AssertSuccess(); 44 extractResult.AssertSuccess();
45 45
46 var customElements = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:BundleCustomTable"); 46 var customElements = extractResult.SelectBADataNodes("/ba:BootstrapperApplicationData/ba:BundleCustomTableBA");
47 Assert.Equal(3, customElements.Count); 47 Assert.Equal(3, customElements.Count);
48 Assert.Equal("<BundleCustomTable Id='one' Column2='two' />", customElements[0].GetTestXml()); 48 Assert.Equal("<BundleCustomTableBA Id='one' Column2='two' />", customElements[0].GetTestXml());
49 Assert.Equal("<BundleCustomTable Id='&gt;' Column2='&lt;' />", customElements[1].GetTestXml()); 49 Assert.Equal("<BundleCustomTableBA Id='&gt;' Column2='&lt;' />", customElements[1].GetTestXml());
50 Assert.Equal("<BundleCustomTable Id='1' Column2='2' />", customElements[2].GetTestXml()); 50 Assert.Equal("<BundleCustomTableBA Id='1' Column2='2' />", customElements[2].GetTestXml());
51 }
52 }
53
54 [Fact]
55 public void PopulatesBEManifestWithBundleExtensionBundleCustomData()
56 {
57 var folder = TestData.Get(@"TestData");
58
59 using (var fs = new DisposableFileSystem())
60 {
61 var baseFolder = fs.GetFolder();
62 var intermediateFolder = Path.Combine(baseFolder, "obj");
63 var bundlePath = Path.Combine(baseFolder, @"bin\test.exe");
64 var baFolderPath = Path.Combine(baseFolder, "ba");
65 var extractFolderPath = Path.Combine(baseFolder, "extract");
66
67 var result = WixRunner.Execute(new[]
68 {
69 "build",
70 Path.Combine(folder, "BundleCustomTable", "BundleCustomTable.wxs"),
71 Path.Combine(folder, "BundleWithPackageGroupRef", "MinimalPackageGroup.wxs"),
72 Path.Combine(folder, "BundleWithPackageGroupRef", "Bundle.wxs"),
73 "-bindpath", Path.Combine(folder, "SimpleBundle", "data"),
74 "-intermediateFolder", intermediateFolder,
75 "-o", bundlePath
76 });
77
78 result.AssertSuccess();
79
80 Assert.True(File.Exists(bundlePath));
81
82 var extractResult = BundleExtractor.ExtractBAContainer(null, bundlePath, baFolderPath, extractFolderPath);
83 extractResult.AssertSuccess();
84
85 var customElements = extractResult.SelectBundleExtensionDataNodes("/be:BundleExtensionData/be:BundleExtension[@Id='CustomTableExtension']/be:BundleCustomTableBE");
86 Assert.Equal(3, customElements.Count);
87 Assert.Equal("<BundleCustomTableBE Id='one' Column2='two' />", customElements[0].GetTestXml());
88 Assert.Equal("<BundleCustomTableBE Id='&gt;' Column2='&lt;' />", customElements[1].GetTestXml());
89 Assert.Equal("<BundleCustomTableBE Id='1' Column2='2' />", customElements[2].GetTestXml());
51 } 90 }
52 } 91 }
53 92
diff --git a/src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs b/src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs
index 85a0ffae..afba1cbc 100644
--- a/src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs
+++ b/src/test/WixToolsetTest.CoreIntegration/CustomTableFixture.cs
@@ -3,7 +3,6 @@
3namespace WixToolsetTest.CoreIntegration 3namespace WixToolsetTest.CoreIntegration
4{ 4{
5 using System.IO; 5 using System.IO;
6 using Microsoft.Build.Tasks;
7 using WixBuildTools.TestSupport; 6 using WixBuildTools.TestSupport;
8 using WixToolset.Core.TestPackage; 7 using WixToolset.Core.TestPackage;
9 using Xunit; 8 using Xunit;
@@ -160,36 +159,6 @@ namespace WixToolsetTest.CoreIntegration
160 } 159 }
161 160
162 [Fact] 161 [Fact]
163 public void UnrealCustomTableIsNotPresentInMsi()
164 {
165 var folder = TestData.Get(@"TestData");
166
167 using (var fs = new DisposableFileSystem())
168 {
169 var baseFolder = fs.GetFolder();
170 var intermediateFolder = Path.Combine(baseFolder, "obj");
171 var msiPath = Path.Combine(baseFolder, @"bin\test.msi");
172
173 var result = WixRunner.Execute(new[]
174 {
175 "build",
176 Path.Combine(folder, "CustomTable", "CustomTable.wxs"),
177 Path.Combine(folder, "ProductWithComponentGroupRef", "MinimalComponentGroup.wxs"),
178 Path.Combine(folder, "ProductWithComponentGroupRef", "Product.wxs"),
179 "-bindpath", Path.Combine(folder, "SingleFile", "data"),
180 "-intermediateFolder", intermediateFolder,
181 "-o", msiPath
182 });
183
184 result.AssertSuccess();
185
186 Assert.True(File.Exists(msiPath));
187 var results = Query.QueryDatabase(msiPath, new[] { "CustomTable2" });
188 Assert.Empty(results);
189 }
190 }
191
192 [Fact]
193 public void CanCompileAndDecompile() 162 public void CanCompileAndDecompile()
194 { 163 {
195 var folder = TestData.Get(@"TestData"); 164 var folder = TestData.Get(@"TestData");
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
index dacbc014..38d207ca 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/BundleCustomTable/BundleCustomTable.wxs
@@ -5,22 +5,42 @@
5 <PackageGroupRef Id="MinimalPackageGroup" /> 5 <PackageGroupRef Id="MinimalPackageGroup" />
6 </PackageGroup> 6 </PackageGroup>
7 7
8 <CustomTable Id="BundleCustomTable" Unreal="yes"> 8 <BundleCustomData Id="BundleCustomTableBA" Type="bootstrapperApplication">
9 <Column Id="Id" Type="string" PrimaryKey="yes" /> 9 <BundleAttributeDefinition Id="Id" />
10 <Column Id="Column2" Type="string" PrimaryKey="yes" /> 10 <BundleAttributeDefinition Id="Column2" />
11 11
12 <Row> 12 <BundleElement>
13 <Data Column="Id">one</Data> 13 <BundleAttribute Id="Id">one</BundleAttribute>
14 <Data Column="Column2">two</Data> 14 <BundleAttribute Id="Column2">two</BundleAttribute>
15 </Row> 15 </BundleElement>
16 <Row> 16 <BundleElement>
17 <Data Column="Column2">&lt;</Data> 17 <BundleAttribute Id="Column2">&lt;</BundleAttribute>
18 <Data Column="Id">&gt;</Data> 18 <BundleAttribute Id="Id">&gt;</BundleAttribute>
19 </Row> 19 </BundleElement>
20 <Row> 20 <BundleElement>
21 <Data Column="Id">1</Data> 21 <BundleAttribute Id="Id">1</BundleAttribute>
22 <Data Column="Column2">2</Data> 22 <BundleAttribute Id="Column2">2</BundleAttribute>
23 </Row> 23 </BundleElement>
24 </CustomTable> 24 </BundleCustomData>
25
26 <BundleCustomData Id="BundleCustomTableBE" Type="bundleExtension" ExtensionId="CustomTableExtension">
27 <BundleAttributeDefinition Id="Id" />
28 <BundleAttributeDefinition Id="Column2" />
29
30 <BundleElement>
31 <BundleAttribute Id="Id">one</BundleAttribute>
32 <BundleAttribute Id="Column2">two</BundleAttribute>
33 </BundleElement>
34 <BundleElement>
35 <BundleAttribute Id="Column2">&lt;</BundleAttribute>
36 <BundleAttribute Id="Id">&gt;</BundleAttribute>
37 </BundleElement>
38 <BundleElement>
39 <BundleAttribute Id="Id">1</BundleAttribute>
40 <BundleAttribute Id="Column2">2</BundleAttribute>
41 </BundleElement>
42 </BundleCustomData>
43
44 <BundleExtension Id="CustomTableExtension" SourceFile="fakeba.dll" />
25 </Fragment> 45 </Fragment>
26</Wix> 46</Wix>
diff --git a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
index 51aee5f2..d6a2521e 100644
--- a/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
+++ b/src/test/WixToolsetTest.CoreIntegration/TestData/CustomTable/CustomTable.wxs
@@ -17,18 +17,5 @@
17 <Data Column="Component_">test.txt</Data> 17 <Data Column="Component_">test.txt</Data>
18 </Row> 18 </Row>
19 </CustomTable> 19 </CustomTable>
20
21 <CustomTable Id="CustomTable2" Unreal="yes">
22 <Column Id="ColumnA" Type="string" PrimaryKey="yes" />
23 <Column Id="Component_" Type="string" Width="72" KeyTable="Component" KeyColumn="1" />
24 <Row>
25 <Data Column="ColumnA">RowA</Data>
26 <Data Column="Component_">test.txt</Data>
27 </Row>
28 <Row>
29 <Data Column="ColumnA">RowB</Data>
30 <Data Column="Component_">test.txt</Data>
31 </Row>
32 </CustomTable>
33 </Fragment> 20 </Fragment>
34</Wix> 21</Wix>