|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
//
// Description:
// Creates a PackWebRequest object
//
//
#if DEBUG
#define TRACE
#endif
using System.Net;
using MS.Internal.IO.Packaging; // for PackageCache
using MS.Internal.PresentationCore; // for ExceptionStringTable
using MS.Internal;
namespace System.IO.Packaging
{
/// <summary>
/// Invoked by .NET framework when our schema is recognized during a WebRequest
/// </summary>
public sealed class PackWebRequestFactory : IWebRequestCreate
{
static PackWebRequestFactory()
{
#if DEBUG
_traceSwitch = new BooleanSwitch("PackWebRequest", "PackWebRequest/Response and NetStream trace messages");
#endif
}
//------------------------------------------------------
//
// IWebRequestCreate
//
//------------------------------------------------------
/// <summary>
/// Create
/// </summary>
/// <param name="uri">uri</param>
/// <returns>PackWebRequest</returns>
/// <remarks>Note that this factory may or may not be "registered" with the .NET WebRequest factory as handler
/// for "pack" scheme web requests. Because of this, callers should be sure to use the PackUriHelper static class
/// to prepare their Uri's. Calling any PackUriHelper method has the side effect of registering
/// the "pack" scheme and associating this factory class as its default handler.</remarks>
WebRequest IWebRequestCreate.Create(Uri uri)
{
ArgumentNullException.ThrowIfNull(uri);
// Ensure uri is absolute - if we don't check now, the get_Scheme property will throw
// InvalidOperationException which would be misleading to the caller.
if (!uri.IsAbsoluteUri)
throw new ArgumentException(SR.UriMustBeAbsolute, "uri");
// Ensure uri is correct scheme because we can be called directly. Case sensitive
// is fine because Uri.Scheme contract is to return in lower case only.
if (!string.Equals(uri.Scheme, PackUriHelper.UriSchemePack, StringComparison.Ordinal))
throw new ArgumentException(SR.Format(SR.UriSchemeMismatch, PackUriHelper.UriSchemePack), "uri");
#if DEBUG
if (_traceSwitch.Enabled)
System.Diagnostics.Trace.TraceInformation(
DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " +
Environment.CurrentManagedThreadId + ": " +
"PackWebRequestFactory - responding to uri: " + uri);
#endif
// only inspect cache if part name is present because cache only contains an object, not
// the stream it was derived from
Uri packageUri = System.IO.Packaging.PackUriHelper.GetPackageUri(uri);
Uri partUri = System.IO.Packaging.PackUriHelper.GetPartUri(uri);
if (partUri != null)
{
// Note: we look at PreloadedPackages first before we examine the PackageStore
// This is to make sure that an app cannot override any predefine packages
// match cached object by authority component only - ignore the local path (part name)
// inspect local package cache and default to that if possible
// All predefined packages such as a package activated by DocumentApplication,
// ResourceContainer, and SiteOfOriginContainer are placed in PreloadedPackages
bool cachedPackageIsThreadSafe;
Package c = PreloadedPackages.GetPackage(packageUri, out cachedPackageIsThreadSafe);
// If we don't find anything in the preloaded packages, look into the PackageStore
bool cachedPackageIsFromPublicStore = false;
if (c == null)
{
cachedPackageIsThreadSafe = false; // always assume PackageStore packages are not thread-safe
cachedPackageIsFromPublicStore = true;
// Try to get a package from the package store
c = PackageStore.GetPackage(packageUri);
}
// do we have a package?
if (c != null)
{
#if DEBUG
if (_traceSwitch.Enabled)
System.Diagnostics.Trace.TraceInformation(
DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " +
Environment.CurrentManagedThreadId + ": " +
"PackWebRequestFactory - cache hit - returning CachedPackWebRequest");
#endif
// use the cached object
return new PackWebRequest(uri, packageUri, partUri, c,
cachedPackageIsFromPublicStore, cachedPackageIsThreadSafe);
}
}
#if DEBUG
if (_traceSwitch.Enabled)
System.Diagnostics.Trace.TraceInformation(
DateTime.Now.ToLongTimeString() + " " + DateTime.Now.Millisecond + " " +
Environment.CurrentManagedThreadId + ": " +
"PackWebRequestFactory - spawning regular PackWebRequest");
#endif
return new PackWebRequest(uri, packageUri, partUri);
}
//------------------------------------------------------
//
// Internal Methods
//
//------------------------------------------------------
// CreateWebRequest: Explicitly calls Create on PackWebRequest if uri is pack scheme
// Ideally we would want to use RegisterPrefix and WebRequest.Create.
// However, these two functions regress 700k working set in System.dll and System.xml.dll
// which is mostly for logging and config.
// This helper function provides a way to bypass the regression
internal static WebRequest CreateWebRequest(Uri uri)
{
if (string.Equals(uri.Scheme, PackUriHelper.UriSchemePack, StringComparison.Ordinal))
{
return ((IWebRequestCreate) _factorySingleton).Create(uri);
}
else
{
return WpfWebRequestHelper.CreateRequest(uri);
}
}
#if DEBUG
internal static bool TraceSwitchEnabled
{
get
{
return _traceSwitch.Enabled;
}
set
{
_traceSwitch.Enabled = value;
}
}
internal static System.Diagnostics.BooleanSwitch _traceSwitch;
#endif
//------------------------------------------------------
//
// Private Members
//
//------------------------------------------------------
private static PackWebRequestFactory _factorySingleton = new PackWebRequestFactory();
}
}
|