Fix handling of long values and baseUri in path fields
Rob Mensching committed
Dec 6, 2017 at 11:21 UTC
ca376995792d2e2a1a7f39760989496702a8f603
9 files changed
+132
-57
src/WixToolset.Data/Intermediate.cs
+31
-18
@@ -4,8 +4,9 @@ namespace WixToolset.Data
4
{
5
using System;
6
using System.Collections.Generic;
7
- using System.Linq;
7
using System.IO;
8
+ using System.Linq;
9
+ using System.Reflection;
10
using SimpleJson;
11
12
/// <summary>
@@ -99,48 +100,60 @@ namespace WixToolset.Data
100
{
101
using (var stream = File.OpenRead(path))
102
{
103
+ var uri = new Uri(Path.GetFullPath(path));
104
var creator = new SimpleTupleDefinitionCreator();
103
- return Intermediate.Load(stream, path, creator, suppressVersionCheck);
105
+ return Intermediate.Load(stream, uri, creator, suppressVersionCheck);
106
}
107
}
108
109
/// <summary>
110
/// Loads an intermediate from a stream.
111
/// </summary>
110
- /// <param name="stream">Stream to intermediate file.</param>
112
+ /// <param name="assembly">Assembly with intermediate embedded in resource stream.</param>
113
+ /// <param name="resourceName">Name of resource stream.</param>
114
/// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
115
/// <returns>Returns the loaded intermediate.</returns>
113
- public static Intermediate Load(Stream stream, bool suppressVersionCheck = false)
116
+ public static Intermediate Load(Assembly assembly, string resourceName, bool suppressVersionCheck = false)
117
{
118
var creator = new SimpleTupleDefinitionCreator();
116
- return Intermediate.Load(stream, creator, suppressVersionCheck);
119
+ return Intermediate.Load(assembly, resourceName, creator, suppressVersionCheck);
120
}
121
122
/// <summary>
120
- /// Loads an intermediate from a path on disk.
123
+ /// Loads an intermediate from a stream.
124
/// </summary>
122
- /// <param name="path">Path to intermediate file saved on disk.</param>
125
+ /// <param name="assembly">Assembly with intermediate embedded in resource stream.</param>
126
+ /// <param name="resourceName">Name of resource stream.</param>
127
/// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
128
/// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
129
/// <returns>Returns the loaded intermediate.</returns>
126
- public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
130
+ public static Intermediate Load(Assembly assembly, string resourceName, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
131
{
128
- using (var stream = File.OpenRead(path))
132
+ using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
133
{
130
- return Intermediate.Load(stream, path, creator, suppressVersionCheck);
134
+ var uriBuilder = new UriBuilder(assembly.CodeBase);
135
+ uriBuilder.Scheme = "embeddedresource";
136
+ uriBuilder.Fragment = resourceName;
137
+
138
+ return Intermediate.Load(resourceStream, uriBuilder.Uri, creator, suppressVersionCheck);
139
}
140
}
141
142
/// <summary>
143
/// Loads an intermediate from a path on disk.
144
/// </summary>
137
- /// <param name="stream">Stream to intermediate file.</param>
145
+ /// <param name="path">Path to intermediate file saved on disk.</param>
146
/// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
147
/// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
148
/// <returns>Returns the loaded intermediate.</returns>
141
- public static Intermediate Load(Stream stream, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
149
+ public static Intermediate Load(string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
150
{
143
- return Load(stream, "<unknown>", creator, suppressVersionCheck);
151
+ using (var stream = File.OpenRead(path))
152
+ {
153
+ var uri = new Uri(Path.GetFullPath(path));
154
+
155
+ return Intermediate.Load(stream, uri, creator, suppressVersionCheck);
156
+ }
157
}
158
159
/// <summary>
@@ -206,11 +219,11 @@ namespace WixToolset.Data
219
/// Loads an intermediate from a path on disk.
220
/// </summary>
221
/// <param name="stream">Stream to intermediate file.</param>
209
- /// <param name="path">Path name of intermediate file.</param>
222
+ /// <param name="baseUri">Path name of intermediate file.</param>
223
/// <param name="creator">ITupleDefinitionCreator to use when reconstituting the intermediate.</param>
224
/// <param name="suppressVersionCheck">Suppress checking for wix.dll version mismatches.</param>
225
/// <returns>Returns the loaded intermediate.</returns>
213
- internal static Intermediate Load(Stream stream, string path, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
226
+ internal static Intermediate Load(Stream stream, Uri baseUri, ITupleDefinitionCreator creator, bool suppressVersionCheck = false)
227
{
228
JsonObject jsonObject;
229
@@ -218,7 +231,7 @@ namespace WixToolset.Data
231
{
232
if (FileFormat.WixIR != fs.FileFormat)
233
{
221
- throw new WixUnexpectedFileFormatException(path, FileFormat.WixIR, fs.FileFormat);
234
+ throw new WixUnexpectedFileFormatException(baseUri.LocalPath, FileFormat.WixIR, fs.FileFormat);
235
}
236
237
var json = fs.GetData();
@@ -231,7 +244,7 @@ namespace WixToolset.Data
244
245
if (!Version.TryParse(versionJson, out var version) || !Intermediate.CurrentVersion.Equals(version))
246
{
234
- throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(path), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
247
+ throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(baseUri.AbsoluteUri), "intermediate", versionJson, Intermediate.CurrentVersion.ToString()));
248
}
249
}
250
@@ -253,7 +266,7 @@ namespace WixToolset.Data
266
var sectionsJson = jsonObject.GetValueOrDefault<JsonArray>("sections");
267
foreach (JsonObject sectionJson in sectionsJson)
268
{
256
- var section = IntermediateSection.Deserialize(creator, sectionJson);
269
+ var section = IntermediateSection.Deserialize(creator, baseUri, sectionJson);
270
sections.Add(section);
271
}
272
src/WixToolset.Data/IntermediateField.cs
+3
-2
@@ -2,6 +2,7 @@
2
3
namespace WixToolset.Data
4
{
5
+ using System;
6
using System.Diagnostics;
7
using SimpleJson;
8
@@ -50,13 +51,13 @@ namespace WixToolset.Data
51
return field.AsString();
52
}
53
53
- internal static IntermediateField Deserialize(IntermediateFieldDefinition definition, JsonObject jsonObject)
54
+ internal static IntermediateField Deserialize(IntermediateFieldDefinition definition, Uri baseUri, JsonObject jsonObject)
55
{
56
var field = new IntermediateField(definition);
57
58
if (jsonObject != null)
59
{
59
- field.Value = IntermediateFieldValue.Deserialize(jsonObject);
60
+ field.Value = IntermediateFieldValue.Deserialize(jsonObject, baseUri, definition.Type);
61
}
62
63
return field;
src/WixToolset.Data/IntermediateFieldDefinition.cs
+1
@@ -7,6 +7,7 @@ namespace WixToolset.Data
7
String,
8
Bool,
9
Number,
10
+ LargeNumber,
11
Path,
12
}
13
src/WixToolset.Data/IntermediateFieldExtensions.cs
+34
-19
@@ -21,26 +21,15 @@ namespace WixToolset.Data
21
{
22
// Null is always allowed.
23
}
24
- else if (field.Type == IntermediateFieldType.Bool && !(value is bool))
24
+ else if (field.Type == IntermediateFieldType.String && !(value is string))
25
{
26
if (value is int)
27
{
28
- data = ((int)value) != 0;
28
+ data = value.ToString();
29
}
30
- else if (value is string str)
30
+ else if (value is bool b)
31
{
32
- if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase))
33
- {
34
- data = true;
35
- }
36
- else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase))
37
- {
38
- data = false;
39
- }
40
- else
41
- {
42
- throw new ArgumentException(nameof(value));
43
- }
32
+ data = b ? "true" : "false";
33
}
34
else
35
{
@@ -58,15 +47,26 @@ namespace WixToolset.Data
47
throw new ArgumentException(nameof(value));
48
}
49
}
61
- else if (field.Type == IntermediateFieldType.String && !(value is string))
50
+ else if (field.Type == IntermediateFieldType.Bool && !(value is bool))
51
{
52
if (value is int)
53
{
65
- data = value.ToString();
54
+ data = ((int)value) != 0;
55
}
67
- else if (value is bool b)
56
+ else if (value is string str)
57
{
69
- data = b ? "true" : "false";
58
+ if (str.Equals("yes", StringComparison.OrdinalIgnoreCase) || str.Equals("true", StringComparison.OrdinalIgnoreCase))
59
+ {
60
+ data = true;
61
+ }
62
+ else if (str.Equals("no", StringComparison.OrdinalIgnoreCase) || str.Equals("false", StringComparison.OrdinalIgnoreCase))
63
+ {
64
+ data = false;
65
+ }
66
+ else
67
+ {
68
+ throw new ArgumentException(nameof(value));
69
+ }
70
}
71
else
72
{
@@ -84,6 +84,21 @@ namespace WixToolset.Data
84
throw new ArgumentException(nameof(value));
85
}
86
}
87
+ else if (field.Type == IntermediateFieldType.LargeNumber && !(value is long))
88
+ {
89
+ if (value is string str && Int64.TryParse(str, out var number))
90
+ {
91
+ data = number;
92
+ }
93
+ else if (value is int i)
94
+ {
95
+ data = (long)i;
96
+ }
97
+ else
98
+ {
99
+ throw new ArgumentException(nameof(value));
100
+ }
101
+ }
102
103
field.Value = new IntermediateFieldValue
104
{
src/WixToolset.Data/IntermediateFieldValue.cs
+14
-13
@@ -45,7 +45,7 @@ namespace WixToolset.Data
45
return value.AsString();
46
}
47
48
- internal static IntermediateFieldValue Deserialize(JsonObject jsonObject)
48
+ internal static IntermediateFieldValue Deserialize(JsonObject jsonObject, Uri baseUri, IntermediateFieldType type)
49
{
50
var context = jsonObject.GetValueOrDefault<string>("context");
51
if (!jsonObject.TryGetValue("data", out var data))
@@ -55,26 +55,30 @@ namespace WixToolset.Data
55
56
var value = data;
57
58
- if (data is JsonObject jsonData)
58
+ if (data is string)
59
{
60
- Uri baseUri = null;
61
-
62
- if (jsonData.TryGetValue("baseUri", out var baseUriValue) && baseUriValue is string)
60
+ }
61
+ else if (data is long)
62
+ {
63
+ if (type == IntermediateFieldType.Number)
64
{
64
- baseUri = new Uri((string)baseUriValue);
65
+ value = Convert.ToInt32(data);
66
}
67
+ }
68
+ else if (data is JsonObject jsonData)
69
+ {
70
jsonData.TryGetValue("embeddedIndex", out var embeddedIndex);
71
72
value = new IntermediateFieldPathValue
73
{
70
- BaseUri = baseUri,
71
- EmbeddedFileIndex = (int?)embeddedIndex,
74
+ BaseUri = (embeddedIndex == null) ? null : baseUri,
75
+ EmbeddedFileIndex = (embeddedIndex == null) ? null : (int?)Convert.ToInt32(embeddedIndex),
76
Path = jsonData.GetValueOrDefault<string>("path"),
77
};
78
}
79
80
var previousValueJson = jsonObject.GetValueOrDefault<JsonObject>("prev");
77
- var previousValue = (previousValueJson == null) ? null : IntermediateFieldValue.Deserialize(previousValueJson);
81
+ var previousValue = (previousValueJson == null) ? null : IntermediateFieldValue.Deserialize(previousValueJson, baseUri, type);
82
83
return new IntermediateFieldValue
84
{
@@ -97,10 +101,7 @@ namespace WixToolset.Data
101
{
102
var jsonData = new JsonObject();
103
100
- if (pathField.BaseUri != null)
101
- {
102
- jsonData.Add("baseUri", pathField.BaseUri.AbsoluteUri);
103
- }
104
+ // pathField.BaseUri is set during load, not saved.
105
106
if (pathField.EmbeddedFileIndex.HasValue)
107
{
src/WixToolset.Data/IntermediateSection.cs
+2
-2
@@ -61,7 +61,7 @@ namespace WixToolset.Data
61
/// <summary>
62
/// Parse a section from the JSON data.
63
/// </summary>
64
- internal static IntermediateSection Deserialize(ITupleDefinitionCreator creator, JsonObject jsonObject)
64
+ internal static IntermediateSection Deserialize(ITupleDefinitionCreator creator, Uri baseUri, JsonObject jsonObject)
65
{
66
var codepage = jsonObject.GetValueOrDefault("codepage", 0);
67
var id = jsonObject.GetValueOrDefault<string>("id");
@@ -83,7 +83,7 @@ namespace WixToolset.Data
83
84
foreach (JsonObject tupleJson in tuplesJson)
85
{
86
- var tuple = IntermediateTuple.Deserialize(creator, tupleJson);
86
+ var tuple = IntermediateTuple.Deserialize(creator, baseUri, tupleJson);
87
section.Tuples.Add(tuple);
88
}
89
src/WixToolset.Data/IntermediateTuple.cs
+3
-2
@@ -2,6 +2,7 @@
2
3
namespace WixToolset.Data
4
{
5
+ using System;
6
using SimpleJson;
7
8
public class IntermediateTuple
@@ -28,7 +29,7 @@ namespace WixToolset.Data
29
30
public IntermediateField this[int index] => this.Fields[index];
31
31
- internal static IntermediateTuple Deserialize(ITupleDefinitionCreator creator, JsonObject jsonObject)
32
+ internal static IntermediateTuple Deserialize(ITupleDefinitionCreator creator, Uri baseUri, JsonObject jsonObject)
33
{
34
var definitionName = jsonObject.GetValueOrDefault<string>("type");
35
var idJson = jsonObject.GetValueOrDefault<JsonObject>("id");
@@ -45,7 +46,7 @@ namespace WixToolset.Data
46
{
47
if (tuple.Fields.Length > i && fieldsJson[i] is JsonObject fieldJson)
48
{
48
- tuple.Fields[i] = IntermediateField.Deserialize(tuple.Definition.FieldDefinitions[i], fieldJson);
49
+ tuple.Fields[i] = IntermediateField.Deserialize(tuple.Definition.FieldDefinitions[i], baseUri, fieldJson);
50
}
51
}
52
src/WixToolset.Data/SourceLineNumber.cs
+1
-1
@@ -146,7 +146,7 @@ namespace WixToolset.Data
146
}
147
148
// make the local path look like a normal local path
149
- string localPath = new Uri(uri).LocalPath;
149
+ var localPath = new Uri(uri).LocalPath;
150
localPath = localPath.TrimStart(Path.AltDirectorySeparatorChar).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
151
152
return new SourceLineNumber(localPath);
src/test/WixToolsetTest.Data/SerializeFixture.cs
new
+43
@@ -0,0 +1,43 @@
1
+// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information.
2
+
3
+namespace WixToolsetTest.Data
4
+{
5
+ using System;
6
+ using System.IO;
7
+ using System.Linq;
8
+ using WixToolset.Data;
9
+ using WixToolset.Data.Tuples;
10
+ using Xunit;
11
+
12
+ public class SerializeFixture
13
+ {
14
+ [Fact]
15
+ public void CanSaveAndLoadIntermediate()
16
+ {
17
+ var sln = new SourceLineNumber("test.wxs", 1);
18
+
19
+ var section = new IntermediateSection("test", SectionType.Product, 65001);
20
+
21
+ section.Tuples.Add(new ComponentTuple(sln, new Identifier("TestComponent", AccessModifier.Public))
22
+ {
23
+ ComponentId = new Guid(1, 0, 0, new byte[8]).ToString("B"),
24
+ Directory_ = "TestFolder",
25
+ Attributes = 2,
26
+ });
27
+
28
+ var intermediate = new Intermediate("TestIntermediate", new[] { section }, null, null);
29
+
30
+ var path = Path.GetTempFileName();
31
+ intermediate.Save(path);
32
+
33
+ var loaded = Intermediate.Load(path);
34
+
35
+ var tuple = (ComponentTuple)loaded.Sections.Single().Tuples.Single();
36
+
37
+ Assert.Equal("TestComponent", tuple.Id.Id);
38
+ Assert.Equal(AccessModifier.Public, tuple.Id.Access);
39
+ Assert.Equal("TestFolder", tuple.Directory_);
40
+ Assert.Equal(2, tuple.Attributes);
41
+ }
42
+ }
43
+}