Enable better trimming of derived XmlReader/Writer-derived types (dotnet/corefx#41235)
authorStephen Toub <stoub@microsoft.com>
Fri, 20 Sep 2019 20:29:39 +0000 (16:29 -0400)
committerGitHub <noreply@github.com>
Fri, 20 Sep 2019 20:29:39 +0000 (16:29 -0400)
Commit migrated from https://github.com/dotnet/corefx/commit/b893e604ce832ccf4e9cbcbdfe0b0ae2b23195bf

src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReader.cs
src/libraries/System.Private.Xml/src/System/Xml/Core/XmlReaderSettings.cs
src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriter.cs
src/libraries/System.Private.Xml/src/System/Xml/Core/XmlWriterSettings.cs
src/libraries/System.Private.Xml/src/System/Xml/Xslt/XslCompiledTransform.cs

index e02d5b9..5f62b31 100644 (file)
@@ -2,14 +2,15 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
-using System.IO;
-using System.Text;
-using System.Security;
-using System.Diagnostics;
 using System.Collections;
+using System.Diagnostics;
 using System.Globalization;
-using System.Xml.Schema;
+using System.IO;
 using System.Runtime.Versioning;
+using System.Security;
+using System.Text;
+using System.Threading;
+using System.Xml.Schema;
 
 namespace System.Xml
 {
@@ -1752,7 +1753,18 @@ namespace System.Xml
         // Creates an XmlReader for parsing XML from the given Uri.
         public static XmlReader Create(string inputUri)
         {
-            return XmlReader.Create(inputUri, (XmlReaderSettings)null, (XmlParserContext)null);
+            if (inputUri == null)
+            {
+                throw new ArgumentNullException(nameof(inputUri));
+            }
+            if (inputUri.Length == 0)
+            {
+                throw new ArgumentException(SR.XmlConvert_BadUri, nameof(inputUri));
+            }
+
+            // Avoid using XmlReader.Create(string, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            return new XmlTextReaderImpl(inputUri, XmlReaderSettings.s_defaultReaderSettings, null, new XmlUrlResolver());
         }
 
         // Creates an XmlReader according to the settings for parsing XML from the given Uri.
@@ -1764,17 +1776,21 @@ namespace System.Xml
         // Creates an XmlReader according to the settings and parser context for parsing XML from the given Uri.
         public static XmlReader Create(string inputUri, XmlReaderSettings settings, XmlParserContext inputContext)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(inputUri, inputContext);
         }
 
         // Creates an XmlReader according for parsing XML from the given stream.
         public static XmlReader Create(Stream input)
         {
-            return Create(input, (XmlReaderSettings)null, (string)string.Empty);
+            if (input == null)
+            {
+                throw new ArgumentNullException(nameof(input));
+            }
+
+            // Avoid using XmlReader.Create(Stream, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            return new XmlTextReaderImpl(input, null, 0, XmlReaderSettings.s_defaultReaderSettings, null, string.Empty, null, false);
         }
 
         // Creates an XmlReader according to the settings for parsing XML from the given stream.
@@ -1786,27 +1802,28 @@ namespace System.Xml
         // Creates an XmlReader according to the settings and base Uri for parsing XML from the given stream.
         public static XmlReader Create(Stream input, XmlReaderSettings settings, string baseUri)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(input, null, (string)baseUri, null);
         }
 
         // Creates an XmlReader according to the settings and parser context for parsing XML from the given stream.
         public static XmlReader Create(Stream input, XmlReaderSettings settings, XmlParserContext inputContext)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(input, null, (string)string.Empty, inputContext);
         }
 
         // Creates an XmlReader according for parsing XML from the given TextReader.
         public static XmlReader Create(TextReader input)
         {
-            return Create(input, (XmlReaderSettings)null, (string)string.Empty);
+            if (input == null)
+            {
+                throw new ArgumentNullException(nameof(input));
+            }
+
+            // Avoid using XmlReader.Create(TextReader, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            return new XmlTextReaderImpl(input, XmlReaderSettings.s_defaultReaderSettings, string.Empty, null);
         }
 
         // Creates an XmlReader according to the settings for parsing XML from the given TextReader.
@@ -1818,30 +1835,21 @@ namespace System.Xml
         // Creates an XmlReader according to the settings and baseUri for parsing XML from the given TextReader.
         public static XmlReader Create(TextReader input, XmlReaderSettings settings, string baseUri)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(input, baseUri, null);
         }
 
         // Creates an XmlReader according to the settings and parser context for parsing XML from the given TextReader.
         public static XmlReader Create(TextReader input, XmlReaderSettings settings, XmlParserContext inputContext)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(input, string.Empty, inputContext);
         }
 
         // Creates an XmlReader according to the settings wrapped over the given reader.
         public static XmlReader Create(XmlReader reader, XmlReaderSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
             return settings.CreateReader(reader);
         }
 
@@ -1854,10 +1862,7 @@ namespace System.Xml
             {
                 throw new ArgumentNullException(nameof(input));
             }
-            if (settings == null)
-            {
-                settings = new XmlReaderSettings();
-            }
+            settings ??= XmlReaderSettings.s_defaultReaderSettings;
 
             XmlReader reader;
 
index 4d9c43e..e74adf0 100644 (file)
@@ -13,6 +13,8 @@ namespace System.Xml
     // XmlReaderSettings class specifies basic features of an XmlReader.
     public sealed class XmlReaderSettings
     {
+        internal static readonly XmlReaderSettings s_defaultReaderSettings = new XmlReaderSettings() { ReadOnly = true };
+
         //
         // Fields
         //
@@ -424,11 +426,7 @@ namespace System.Xml
             }
 
             // resolve and open the url
-            XmlResolver tmpResolver = this.GetXmlResolver();
-            if (tmpResolver == null)
-            {
-                tmpResolver = CreateDefaultResolver();
-            }
+            XmlResolver tmpResolver = this.GetXmlResolver() ?? new XmlUrlResolver();
 
             // create text XML reader
             XmlReader reader = new XmlTextReaderImpl(inputUri, this, inputContext, tmpResolver);
@@ -579,11 +577,6 @@ namespace System.Xml
             IsXmlResolverSet = false;
         }
 
-        private static XmlResolver CreateDefaultResolver()
-        {
-            return new XmlUrlResolver();
-        }
-
         internal XmlReader AddValidation(XmlReader reader)
         {
             XmlResolver resolver = null;
index 04897e5..1327eb9 100644 (file)
@@ -659,68 +659,100 @@ namespace System.Xml
         // Creates an XmlWriter for writing into the provided file.
         public static XmlWriter Create(string outputFileName)
         {
-            return Create(outputFileName, null);
+            if (outputFileName == null)
+            {
+                throw new ArgumentNullException(nameof(outputFileName));
+            }
+
+            // Avoid using XmlWriter.Create(string, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            var fs = new FileStream(outputFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
+            try
+            {
+                var settings = new XmlWriterSettings() { CloseOutput = true };
+                XmlWriter writer = new XmlEncodedRawTextWriter(fs, settings);
+                return new XmlWellFormedWriter(writer, settings);
+            }
+            catch
+            {
+                fs.Dispose();
+                throw;
+            }
         }
 
         // Creates an XmlWriter for writing into the provided file with the specified settings.
         public static XmlWriter Create(string outputFileName, XmlWriterSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlWriterSettings();
-            }
+            settings ??= XmlWriterSettings.s_defaultWriterSettings;
             return settings.CreateWriter(outputFileName);
         }
 
         // Creates an XmlWriter for writing into the provided stream.
         public static XmlWriter Create(Stream output)
         {
-            return Create(output, null);
+            if (output == null)
+            {
+                throw new ArgumentNullException(nameof(output));
+            }
+
+            // Avoid using XmlWriter.Create(Stream, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            XmlWriterSettings settings = XmlWriterSettings.s_defaultWriterSettings;
+            XmlWriter writer = new XmlUtf8RawTextWriter(output, settings);
+            return new XmlWellFormedWriter(writer, settings);
         }
 
         // Creates an XmlWriter for writing into the provided stream with the specified settings.
         public static XmlWriter Create(Stream output, XmlWriterSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlWriterSettings();
-            }
+            settings ??= XmlWriterSettings.s_defaultWriterSettings;
             return settings.CreateWriter(output);
         }
 
         // Creates an XmlWriter for writing into the provided TextWriter.
         public static XmlWriter Create(TextWriter output)
         {
-            return Create(output, null);
+            if (output == null)
+            {
+                throw new ArgumentNullException(nameof(output));
+            }
+
+            // Avoid using XmlWriter.Create(TextWriter, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            XmlWriterSettings settings = XmlWriterSettings.s_defaultWriterSettings;
+            XmlWriter writer = new XmlEncodedRawTextWriter(output, settings);
+            return new XmlWellFormedWriter(writer, settings);
         }
 
         // Creates an XmlWriter for writing into the provided TextWriter with the specified settings.
         public static XmlWriter Create(TextWriter output, XmlWriterSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlWriterSettings();
-            }
+            settings ??= XmlWriterSettings.s_defaultWriterSettings;
             return settings.CreateWriter(output);
         }
 
         // Creates an XmlWriter for writing into the provided StringBuilder.
         public static XmlWriter Create(StringBuilder output)
         {
-            return Create(output, null);
+            if (output == null)
+            {
+                throw new ArgumentNullException(nameof(output));
+            }
+
+            // Avoid using XmlWriter.Create(StringBuilder, XmlReaderSettings), as it references a lot of types
+            // that then can't be trimmed away.
+            return Create(new StringWriter(output, CultureInfo.InvariantCulture));
         }
 
         // Creates an XmlWriter for writing into the provided StringBuilder with the specified settings.
         public static XmlWriter Create(StringBuilder output, XmlWriterSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlWriterSettings();
-            }
             if (output == null)
             {
                 throw new ArgumentNullException(nameof(output));
             }
+
+            settings ??= XmlWriterSettings.s_defaultWriterSettings;
             return settings.CreateWriter(new StringWriter(output, CultureInfo.InvariantCulture));
         }
 
@@ -733,10 +765,7 @@ namespace System.Xml
         // Creates an XmlWriter wrapped around the provided XmlWriter with the specified settings.
         public static XmlWriter Create(XmlWriter output, XmlWriterSettings settings)
         {
-            if (settings == null)
-            {
-                settings = new XmlWriterSettings();
-            }
+            settings ??= XmlWriterSettings.s_defaultWriterSettings;
             return settings.CreateWriter(output);
         }
     }
index 1cab648..db261c3 100644 (file)
@@ -43,6 +43,8 @@ namespace System.Xml
     // XmlWriterSettings class specifies basic features of an XmlWriter.
     public sealed class XmlWriterSettings
     {
+        internal static readonly XmlWriterSettings s_defaultWriterSettings = new XmlWriterSettings() { ReadOnly = true };
+
         //
         // Fields
         //
index 1df93e6..f1ea427 100644 (file)
@@ -45,9 +45,6 @@ namespace System.Xml.Xsl
 
     public sealed class XslCompiledTransform
     {
-        // Reader settings used when creating XmlReader from inputUri
-        private static readonly XmlReaderSettings s_readerSettings = new XmlReaderSettings();
-
 #if FEATURE_COMPILED_XSL
         // Version for GeneratedCodeAttribute
         private static readonly Version s_version = typeof(XslCompiledTransform).Assembly.GetName().Version;
@@ -362,7 +359,7 @@ namespace System.Xml.Xsl
         public void Transform(string inputUri, XmlWriter results)
         {
             CheckArguments(inputUri, results);
-            using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
+            using (XmlReader reader = XmlReader.Create(inputUri))
             {
                 Transform(reader, (XsltArgumentList)null, results, CreateDefaultResolver());
             }
@@ -372,7 +369,7 @@ namespace System.Xml.Xsl
         public void Transform(string inputUri, XsltArgumentList arguments, XmlWriter results)
         {
             CheckArguments(inputUri, results);
-            using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
+            using (XmlReader reader = XmlReader.Create(inputUri))
             {
                 Transform(reader, arguments, results, CreateDefaultResolver());
             }
@@ -382,7 +379,7 @@ namespace System.Xml.Xsl
         public void Transform(string inputUri, XsltArgumentList arguments, TextWriter results)
         {
             CheckArguments(inputUri, results);
-            using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
+            using (XmlReader reader = XmlReader.Create(inputUri))
             using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
             {
                 Transform(reader, arguments, writer, CreateDefaultResolver());
@@ -394,7 +391,7 @@ namespace System.Xml.Xsl
         public void Transform(string inputUri, XsltArgumentList arguments, Stream results)
         {
             CheckArguments(inputUri, results);
-            using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
+            using (XmlReader reader = XmlReader.Create(inputUri))
             using (XmlWriter writer = XmlWriter.Create(results, OutputSettings))
             {
                 Transform(reader, arguments, writer, CreateDefaultResolver());
@@ -412,7 +409,7 @@ namespace System.Xml.Xsl
                 throw new ArgumentNullException(nameof(resultsFile));
 
             // SQLBUDT 276415: Prevent wiping out the content of the input file if the output file is the same
-            using (XmlReader reader = XmlReader.Create(inputUri, s_readerSettings))
+            using (XmlReader reader = XmlReader.Create(inputUri))
             using (XmlWriter writer = XmlWriter.Create(resultsFile, OutputSettings))
             {
                 Transform(reader, (XsltArgumentList)null, writer, CreateDefaultResolver());