You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,435 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.VisualBasic.Activities.XamlIntegration
|
||||
{
|
||||
using System;
|
||||
using System.Activities.Expressions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Reflection;
|
||||
using System.Xml.Linq;
|
||||
using System.ComponentModel;
|
||||
using System.Xaml;
|
||||
using System.Windows.Markup;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Runtime;
|
||||
using System.Threading;
|
||||
|
||||
static class VisualBasicExpressionConverter
|
||||
{
|
||||
static readonly Regex assemblyQualifiedNamespaceRegex = new Regex(
|
||||
"clr-namespace:(?<namespace>[^;]*);assembly=(?<assembly>.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public static VisualBasicSettings CollectXmlNamespacesAndAssemblies(ITypeDescriptorContext context)
|
||||
{
|
||||
// access XamlSchemaContext.ReferenceAssemblies
|
||||
// for the Compiled Xaml scenario
|
||||
IList<Assembly> xsCtxReferenceAssemblies = null;
|
||||
IXamlSchemaContextProvider xamlSchemaContextProvider = context.GetService(typeof(IXamlSchemaContextProvider)) as IXamlSchemaContextProvider;
|
||||
if (xamlSchemaContextProvider != null && xamlSchemaContextProvider.SchemaContext != null)
|
||||
{
|
||||
xsCtxReferenceAssemblies = xamlSchemaContextProvider.SchemaContext.ReferenceAssemblies;
|
||||
if (xsCtxReferenceAssemblies != null && xsCtxReferenceAssemblies.Count == 0)
|
||||
{
|
||||
xsCtxReferenceAssemblies = null;
|
||||
}
|
||||
}
|
||||
|
||||
VisualBasicSettings settings = null;
|
||||
IXamlNamespaceResolver namespaceResolver = (IXamlNamespaceResolver)context.GetService(typeof(IXamlNamespaceResolver));
|
||||
|
||||
if (namespaceResolver == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
lock (AssemblyCache.XmlnsMappingsLockObject)
|
||||
{
|
||||
// Fetch xmlnsMappings for the prefixes returned by the namespaceResolver service
|
||||
|
||||
foreach (NamespaceDeclaration prefix in namespaceResolver.GetNamespacePrefixes())
|
||||
{
|
||||
ReadOnlyXmlnsMapping mapping;
|
||||
WrapCachedMapping(prefix, out mapping);
|
||||
if (!mapping.IsEmpty)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
settings = new VisualBasicSettings();
|
||||
}
|
||||
|
||||
if (!mapping.IsEmpty)
|
||||
{
|
||||
foreach (ReadOnlyVisualBasicImportReference importReference in mapping.ImportReferences)
|
||||
{
|
||||
if (xsCtxReferenceAssemblies != null)
|
||||
{
|
||||
// this is "compiled Xaml"
|
||||
VisualBasicImportReference newImportReference;
|
||||
|
||||
if (importReference.EarlyBoundAssembly != null)
|
||||
{
|
||||
if (xsCtxReferenceAssemblies.Contains(importReference.EarlyBoundAssembly))
|
||||
{
|
||||
newImportReference = importReference.Clone();
|
||||
newImportReference.EarlyBoundAssembly = importReference.EarlyBoundAssembly;
|
||||
settings.ImportReferences.Add(newImportReference);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int i = 0; i < xsCtxReferenceAssemblies.Count; i++)
|
||||
{
|
||||
AssemblyName xsCtxAssemblyName = VisualBasicHelper.GetFastAssemblyName(xsCtxReferenceAssemblies[i]);
|
||||
if (importReference.AssemblySatisfiesReference(xsCtxAssemblyName))
|
||||
{
|
||||
// bind this assembly early to the importReference
|
||||
// so later AssemblyName resolution can be skipped
|
||||
newImportReference = importReference.Clone();
|
||||
newImportReference.EarlyBoundAssembly = xsCtxReferenceAssemblies[i];
|
||||
settings.ImportReferences.Add(newImportReference);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// this is "loose Xaml"
|
||||
VisualBasicImportReference newImportReference = importReference.Clone();
|
||||
if (importReference.EarlyBoundAssembly != null)
|
||||
{
|
||||
// VBImportReference.Clone() method deliberately doesn't copy
|
||||
// its EarlyBoundAssembly to the cloned instance.
|
||||
// we need to explicitly copy the original's EarlyBoundAssembly
|
||||
newImportReference.EarlyBoundAssembly = importReference.EarlyBoundAssembly;
|
||||
}
|
||||
settings.ImportReferences.Add(newImportReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing critical member AssemblyCache.XmlnsMappings.",
|
||||
Safe = "Safe because we prevent partial trusted code from manipulating the cache directly by creating a read-only wrapper around the cached XmlnsMapping.")]
|
||||
[SecuritySafeCritical]
|
||||
private static void WrapCachedMapping(NamespaceDeclaration prefix, out ReadOnlyXmlnsMapping readOnlyMapping)
|
||||
{
|
||||
XmlnsMapping mapping = new XmlnsMapping();
|
||||
XNamespace xmlns = XNamespace.Get(prefix.Namespace);
|
||||
|
||||
if (!AssemblyCache.XmlnsMappings.TryGetValue(xmlns, out mapping))
|
||||
{
|
||||
// Match a namespace of the form "clr-namespace:<namespace-name>;assembly=<assembly-name>"
|
||||
|
||||
Match match = assemblyQualifiedNamespaceRegex.Match(prefix.Namespace);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
mapping.ImportReferences = new HashSet<VisualBasicImportReference>();
|
||||
mapping.ImportReferences.Add(
|
||||
new VisualBasicImportReference
|
||||
{
|
||||
Assembly = match.Groups["assembly"].Value,
|
||||
Import = match.Groups["namespace"].Value,
|
||||
Xmlns = xmlns
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
mapping.ImportReferences = new HashSet<VisualBasicImportReference>();
|
||||
}
|
||||
AssemblyCache.XmlnsMappings[xmlns] = mapping;
|
||||
}
|
||||
|
||||
// ReadOnlyXmlnsMapping constructor tolerates an empty mapping being passed in.
|
||||
readOnlyMapping = new ReadOnlyXmlnsMapping(mapping);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static class used to cache assembly metadata.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <list type="bullet">
|
||||
/// <item><description>
|
||||
/// XmlnsMappings for static assemblies are not GC'd. In v4.0 we can assume that all static assemblies
|
||||
/// containing XmlnsDefinition attributes are non-collectible. The CLR will provide no public mechanism
|
||||
/// for unloading a static assembly or specifying that a static assembly is collectible. While there
|
||||
/// may be some small number of assemblies identified by the CLR as collectible, none will contain
|
||||
/// XmlnsDefinition attributes. Should the CLR provide a public mechanism for unloading a static assembly
|
||||
/// or specifying that a static assembly is collectible, we should revisit this decision based on scenarios
|
||||
/// that flow from these mechanisms.
|
||||
/// </description></item>
|
||||
/// <item><description>
|
||||
/// XmlnsMappings for dynamic assemblies are not created. This is because the hosted Visual Basic compiler
|
||||
/// does not support dynamic assembly references. Should support for dynamic assembly references be
|
||||
/// added to the Visual Basic compiler, we should strip away Assembly.IsDynamic checks from this class and
|
||||
/// update the code ensure that VisualBasicImportReference instances are removed in a timely manner.
|
||||
/// </description></item>
|
||||
/// </list>
|
||||
/// </remarks>
|
||||
static class AssemblyCache
|
||||
{
|
||||
static bool initialized = false;
|
||||
|
||||
// This is here so that obtaining the lock is not required to be SecurityCritical.
|
||||
public static object XmlnsMappingsLockObject = new object();
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are storing assembly references and if we alloed PT access, they could mess with that.")]
|
||||
[SecurityCritical]
|
||||
static Dictionary<XNamespace, XmlnsMapping> xmlnsMappings;
|
||||
|
||||
public static Dictionary<XNamespace, XmlnsMapping> XmlnsMappings
|
||||
{
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because providing access to the critical xmlnsMappings dictionary.")]
|
||||
[SecurityCritical]
|
||||
get
|
||||
{
|
||||
EnsureInitialized();
|
||||
return xmlnsMappings;
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing critical member xmlnsMappings and CacheLoadedAssembly. Only called from CLR.")]
|
||||
[SecurityCritical]
|
||||
static void OnAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
|
||||
{
|
||||
Assembly assembly = args.LoadedAssembly;
|
||||
|
||||
if (assembly.IsDefined(typeof(XmlnsDefinitionAttribute), false) && !assembly.IsDynamic)
|
||||
{
|
||||
lock (XmlnsMappingsLockObject)
|
||||
{
|
||||
CacheLoadedAssembly(assembly);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing AppDomain.AssemblyLoaded and we are accessing critical member xmlnsMappings.")]
|
||||
[SecurityCritical]
|
||||
static void EnsureInitialized()
|
||||
{
|
||||
if (initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (xmlnsMappings == null)
|
||||
{
|
||||
Interlocked.CompareExchange(ref xmlnsMappings,
|
||||
new Dictionary<XNamespace, XmlnsMapping>(new XNamespaceEqualityComparer()),
|
||||
null);
|
||||
}
|
||||
|
||||
lock (XmlnsMappingsLockObject)
|
||||
{
|
||||
if (AssemblyCache.initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoaded;
|
||||
|
||||
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
|
||||
|
||||
for (int i = 0; i < assemblies.Length; ++i)
|
||||
{
|
||||
Assembly assembly = assemblies[i];
|
||||
|
||||
if (assembly.IsDefined(typeof(XmlnsDefinitionAttribute), false) && ! assembly.IsDynamic)
|
||||
{
|
||||
CacheLoadedAssembly(assembly);
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing critical member xmlnsMappings.")]
|
||||
[SecurityCritical]
|
||||
static void CacheLoadedAssembly(Assembly assembly)
|
||||
{
|
||||
// this VBImportReference is only used as an entry to the xmlnsMappings cache
|
||||
// and is never meant to be Xaml serialized.
|
||||
// those VBImportReferences that are to be Xaml serialized are created by Clone() method.
|
||||
XmlnsDefinitionAttribute[] attributes = (XmlnsDefinitionAttribute[])assembly.GetCustomAttributes(typeof(XmlnsDefinitionAttribute), false);
|
||||
string assemblyName = assembly.FullName;
|
||||
XmlnsMapping mapping;
|
||||
|
||||
for (int i = 0; i < attributes.Length; ++i)
|
||||
{
|
||||
XNamespace xmlns = XNamespace.Get(attributes[i].XmlNamespace);
|
||||
|
||||
if (!xmlnsMappings.TryGetValue(xmlns, out mapping))
|
||||
{
|
||||
mapping.ImportReferences = new HashSet<VisualBasicImportReference>();
|
||||
xmlnsMappings[xmlns] = mapping;
|
||||
}
|
||||
|
||||
VisualBasicImportReference newImportReference = new VisualBasicImportReference
|
||||
{
|
||||
Assembly = assemblyName,
|
||||
Import = attributes[i].ClrNamespace,
|
||||
Xmlns = xmlns,
|
||||
};
|
||||
// early binding the assembly
|
||||
// this leads to the short-cut, skipping the normal assembly resolution routine
|
||||
newImportReference.EarlyBoundAssembly = assembly;
|
||||
mapping.ImportReferences.Add(newImportReference);
|
||||
}
|
||||
}
|
||||
|
||||
class XNamespaceEqualityComparer : IEqualityComparer<XNamespace>
|
||||
{
|
||||
public XNamespaceEqualityComparer()
|
||||
{ }
|
||||
|
||||
bool IEqualityComparer<XNamespace>.Equals(XNamespace x, XNamespace y)
|
||||
{
|
||||
return x == y;
|
||||
}
|
||||
|
||||
int IEqualityComparer<XNamespace>.GetHashCode(XNamespace x)
|
||||
{
|
||||
return x.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Struct used to cache XML Namespace mappings.
|
||||
/// </summary>
|
||||
struct XmlnsMapping
|
||||
{
|
||||
public HashSet<VisualBasicImportReference> ImportReferences;
|
||||
|
||||
public bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.ImportReferences == null || this.ImportReferences.Count == 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing a XmlnsMapping that is stored in the XmlnsMappings cache, which is SecurityCritical.",
|
||||
Safe = "Safe because we are wrapping the XmlnsMapping and not allowing unsafe code to modify it.")]
|
||||
[SecuritySafeCritical]
|
||||
struct ReadOnlyXmlnsMapping
|
||||
{
|
||||
XmlnsMapping wrappedMapping;
|
||||
|
||||
internal ReadOnlyXmlnsMapping(XmlnsMapping mapping)
|
||||
{
|
||||
this.wrappedMapping = mapping;
|
||||
}
|
||||
|
||||
internal bool IsEmpty
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.wrappedMapping.IsEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable<ReadOnlyVisualBasicImportReference> ImportReferences
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (VisualBasicImportReference wrappedReference in this.wrappedMapping.ImportReferences)
|
||||
{
|
||||
yield return new ReadOnlyVisualBasicImportReference(wrappedReference);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fx.Tag.SecurityNote(Critical = "Critical because we are accessing a VisualBasicImportReference that is stored in the XmlnsMappings cache, which is SecurityCritical.",
|
||||
Safe = "Safe because we are wrapping the VisualBasicImportReference and not allowing unsafe code to modify it.")]
|
||||
[SecuritySafeCritical]
|
||||
struct ReadOnlyVisualBasicImportReference
|
||||
{
|
||||
readonly VisualBasicImportReference wrappedReference;
|
||||
|
||||
internal ReadOnlyVisualBasicImportReference(VisualBasicImportReference referenceToWrap)
|
||||
{
|
||||
this.wrappedReference = referenceToWrap;
|
||||
}
|
||||
|
||||
// If this is ever needed, uncomment this. It is commented out now to avoid FxCop violation because it is not called.
|
||||
//internal string Assembly
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return this.wrappedReference.Assembly;
|
||||
// }
|
||||
//}
|
||||
|
||||
// If this is ever needed, uncomment this. It is commented out now to avoid FxCop violation because it is not called.
|
||||
//internal string Import
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
// return this.wrappedReference.Import;
|
||||
// }
|
||||
//}
|
||||
|
||||
internal Assembly EarlyBoundAssembly
|
||||
{
|
||||
get { return this.wrappedReference.EarlyBoundAssembly; }
|
||||
}
|
||||
|
||||
internal VisualBasicImportReference Clone()
|
||||
{
|
||||
return this.wrappedReference.Clone();
|
||||
}
|
||||
|
||||
// this code is borrowed from XamlSchemaContext
|
||||
internal bool AssemblySatisfiesReference(AssemblyName assemblyName)
|
||||
{
|
||||
if (this.wrappedReference.AssemblyName.Name != assemblyName.Name)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.wrappedReference.AssemblyName.Version != null && !this.wrappedReference.AssemblyName.Version.Equals(assemblyName.Version))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (this.wrappedReference.AssemblyName.CultureInfo != null && !this.wrappedReference.AssemblyName.CultureInfo.Equals(assemblyName.CultureInfo))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] requiredToken = this.wrappedReference.AssemblyName.GetPublicKeyToken();
|
||||
if (requiredToken != null)
|
||||
{
|
||||
byte[] actualToken = assemblyName.GetPublicKeyToken();
|
||||
if (!AssemblyNameEqualityComparer.IsSameKeyToken(requiredToken, actualToken))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return this.wrappedReference.GetHashCode();
|
||||
}
|
||||
|
||||
// If this is ever needed, uncomment this. It is commented out now to avoid FxCop violation because it is not called.
|
||||
//public bool Equals(VisualBasicImportReference other)
|
||||
//{
|
||||
// return this.wrappedReference.Equals(other);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.VisualBasic.Activities.XamlIntegration
|
||||
{
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime;
|
||||
using System.Globalization;
|
||||
using System.Activities;
|
||||
|
||||
// this class is necessary in order for our value serializer to get called by XAML,
|
||||
// even though the functionality is a no-op
|
||||
public sealed class VisualBasicSettingsConverter : TypeConverter
|
||||
{
|
||||
public VisualBasicSettingsConverter()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
|
||||
{
|
||||
if (sourceType == TypeHelper.StringType)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.CanConvertFrom(context, sourceType);
|
||||
}
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
if (destinationType == TypeHelper.StringType)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return base.CanConvertTo(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||
{
|
||||
string sourceString = value as string;
|
||||
if (sourceString != null)
|
||||
{
|
||||
if (sourceString.Equals(VisualBasicSettingsValueSerializer.ImplementationVisualBasicSettingsValue))
|
||||
{
|
||||
// this is the VBSettings for the internal implementation
|
||||
// suppress its Xaml serialization
|
||||
VisualBasicSettings settings = CollectXmlNamespacesAndAssemblies(context);
|
||||
if (settings != null)
|
||||
{
|
||||
settings.SuppressXamlSerialization = true;
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
if (!(sourceString.Equals(String.Empty) || sourceString.Equals(VisualBasicSettingsValueSerializer.VisualBasicSettingsValue)))
|
||||
{
|
||||
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.InvalidVisualBasicSettingsValue));
|
||||
}
|
||||
|
||||
return CollectXmlNamespacesAndAssemblies(context);
|
||||
}
|
||||
return base.ConvertFrom(context, culture, value);
|
||||
}
|
||||
|
||||
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
|
||||
{
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
|
||||
VisualBasicSettings CollectXmlNamespacesAndAssemblies(ITypeDescriptorContext context)
|
||||
{
|
||||
return VisualBasicExpressionConverter.CollectXmlNamespacesAndAssemblies(context);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,48 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
namespace Microsoft.VisualBasic.Activities.XamlIntegration
|
||||
{
|
||||
using System.Collections.Generic;
|
||||
using System.Windows.Markup;
|
||||
using System.Xaml;
|
||||
|
||||
// this value serializer always returns false for CanConvertToString, but
|
||||
// needs to add namespace declarations to the context
|
||||
//
|
||||
public sealed class VisualBasicSettingsValueSerializer : ValueSerializer
|
||||
{
|
||||
internal const string VisualBasicSettingsValue = "Assembly references and imported namespaces serialized as XML namespaces";
|
||||
internal const string ImplementationVisualBasicSettingsValue = "Assembly references and imported namespaces for internal implementation";
|
||||
|
||||
public VisualBasicSettingsValueSerializer()
|
||||
: base()
|
||||
{
|
||||
}
|
||||
|
||||
public override bool CanConvertToString(object value, IValueSerializerContext context)
|
||||
{
|
||||
VisualBasicSettings settings = value as VisualBasicSettings;
|
||||
|
||||
// promote settings to xmlns declarations
|
||||
if (settings != null)
|
||||
{
|
||||
settings.GenerateXamlReferences(context);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override string ConvertToString(object value, IValueSerializerContext context)
|
||||
{
|
||||
VisualBasicSettings settings = value as VisualBasicSettings;
|
||||
|
||||
if (settings != null && settings.SuppressXamlSerialization)
|
||||
{
|
||||
return ImplementationVisualBasicSettingsValue;
|
||||
}
|
||||
return VisualBasicSettingsValue;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user