BUG: Lazy-initialize the default codec and delay any Reflection code until the first access to DefaultCodecFactory, DefaultDocValuesFactory, and DefaultPostingsFormatFactory. Also don't use Activator.CreateInstance(Type, bool) with nonPublic unless the current AppDomain is running in full trust.
Project: http://git-wip-us.apache.org/repos/asf/lucenenet/repo Commit: http://git-wip-us.apache.org/repos/asf/lucenenet/commit/8a58d858 Tree: http://git-wip-us.apache.org/repos/asf/lucenenet/tree/8a58d858 Diff: http://git-wip-us.apache.org/repos/asf/lucenenet/diff/8a58d858 Branch: refs/heads/master Commit: 8a58d858b99ec7bae2430e9cb0c24938c80f1bf6 Parents: 675fc16 Author: Shad Storhaug <[email protected]> Authored: Thu May 18 18:50:22 2017 +0700 Committer: Shad Storhaug <[email protected]> Committed: Thu May 18 18:53:26 2017 +0700 ---------------------------------------------------------------------- .../Codecs/TestCodecFactory.cs | 3 +- .../Codecs/TestDocValuesFormatFactory.cs | 3 +- .../Codecs/TestPostingsFormatFactory.cs | 3 +- .../Util/LuceneTestCase.cs | 2 - src/Lucene.Net/Codecs/Codec.cs | 19 ++++--- .../Support/Codecs/DefaultCodecFactory.cs | 43 +++++++++++----- .../Codecs/DefaultDocValuesFormatFactory.cs | 43 +++++++++++----- .../Codecs/DefaultPostingsFormatFactory.cs | 45 +++++++++++------ .../Support/Util/NamedServiceFactory.cs | 52 +++++++++++++++++--- 9 files changed, 151 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net.TestFramework/Codecs/TestCodecFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.TestFramework/Codecs/TestCodecFactory.cs b/src/Lucene.Net.TestFramework/Codecs/TestCodecFactory.cs index e19037e..874bac2 100644 --- a/src/Lucene.Net.TestFramework/Codecs/TestCodecFactory.cs +++ b/src/Lucene.Net.TestFramework/Codecs/TestCodecFactory.cs @@ -29,8 +29,9 @@ namespace Lucene.Net.Codecs /// </summary> public class TestCodecFactory : DefaultCodecFactory { - public TestCodecFactory() + protected override void Initialize() { + base.Initialize(); base.ScanForCodecs(this.GetType().GetTypeInfo().Assembly); } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net.TestFramework/Codecs/TestDocValuesFormatFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.TestFramework/Codecs/TestDocValuesFormatFactory.cs b/src/Lucene.Net.TestFramework/Codecs/TestDocValuesFormatFactory.cs index 813d5c5..2c83ca7 100644 --- a/src/Lucene.Net.TestFramework/Codecs/TestDocValuesFormatFactory.cs +++ b/src/Lucene.Net.TestFramework/Codecs/TestDocValuesFormatFactory.cs @@ -28,8 +28,9 @@ namespace Lucene.Net.Codecs /// </summary> public class TestDocValuesFormatFactory : DefaultDocValuesFormatFactory { - public TestDocValuesFormatFactory() + protected override void Initialize() { + base.Initialize(); base.ScanForDocValuesFormats(this.GetType().GetTypeInfo().Assembly); } } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net.TestFramework/Codecs/TestPostingsFormatFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.TestFramework/Codecs/TestPostingsFormatFactory.cs b/src/Lucene.Net.TestFramework/Codecs/TestPostingsFormatFactory.cs index 64a7188..a0bec24 100644 --- a/src/Lucene.Net.TestFramework/Codecs/TestPostingsFormatFactory.cs +++ b/src/Lucene.Net.TestFramework/Codecs/TestPostingsFormatFactory.cs @@ -28,8 +28,9 @@ namespace Lucene.Net.Codecs /// </summary> public class TestPostingsFormatFactory : DefaultPostingsFormatFactory { - public TestPostingsFormatFactory() + protected override void Initialize() { + base.Initialize(); base.ScanForPostingsFormats(this.GetType().GetTypeInfo().Assembly); } } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs b/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs index 2796502..8f3eaf3 100644 --- a/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs +++ b/src/Lucene.Net.TestFramework/Util/LuceneTestCase.cs @@ -639,8 +639,6 @@ namespace Lucene.Net.Util DocValuesFormat.SetDocValuesFormatFactory(TEST_DOCVALUES_FORMAT_FACTORY); PostingsFormat.SetPostingsFormatFactory(TEST_POSTINGS_FORMAT_FACTORY); - // IMPORTANT: Call this line after calling Codec.SetCodecFactory() because both - // of them change Codec.Default ClassEnvRule.Before(this); } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net/Codecs/Codec.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net/Codecs/Codec.cs b/src/Lucene.Net/Codecs/Codec.cs index 34c083e..816547c 100644 --- a/src/Lucene.Net/Codecs/Codec.cs +++ b/src/Lucene.Net/Codecs/Codec.cs @@ -60,15 +60,9 @@ namespace Lucene.Net.Codecs // the Java-centric NamedSPILoader public abstract class Codec //: NamedSPILoader.INamedSPI { - private static ICodecFactory codecFactory; + private static ICodecFactory codecFactory = new DefaultCodecFactory(); private readonly string name; - static Codec() - { - codecFactory = new DefaultCodecFactory(); - defaultCodec = Codec.ForName("Lucene46"); - } - /// <summary> /// Sets the <see cref="ICodecFactory"/> instance used to instantiate /// <see cref="Codec"/> subclasses. @@ -80,7 +74,6 @@ namespace Lucene.Net.Codecs if (codecFactory == null) throw new ArgumentNullException("codecFactory"); Codec.codecFactory = codecFactory; - defaultCodec = Codec.ForName("Lucene46"); } /// <summary> @@ -95,13 +88,13 @@ namespace Lucene.Net.Codecs /// <summary> /// Creates a new codec. /// <para/> - /// The provided name will be written into the index segment: in order for + /// The <see cref="Codec.Name"/> will be written into the index segment: in order for /// the segment to be read this class should be registered by subclassing <see cref="DefaultCodecFactory"/> and /// calling <see cref="DefaultCodecFactory.ScanForCodecs(System.Reflection.Assembly)"/> in the class constructor. /// The new <see cref="ICodecFactory"/> can be registered by calling <see cref="SetCodecFactory"/> at application startup.</summary> protected Codec() { - this.name = NamedServiceFactory<Codec>.GetServiceName(this.GetType()); + name = NamedServiceFactory<Codec>.GetServiceName(this.GetType()); } /// <summary> @@ -181,6 +174,12 @@ namespace Lucene.Net.Codecs { get { + // Lazy load the default codec if not already supplied + if (defaultCodec == null) + { + defaultCodec = Codec.ForName("Lucene46"); + } + return defaultCodec; } set http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs index 1499596..18084c9 100644 --- a/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs +++ b/src/Lucene.Net/Support/Codecs/DefaultCodecFactory.cs @@ -36,11 +36,11 @@ namespace Lucene.Net.Codecs /// <item>subclass <see cref="DefaultCodecFactory"/> and override /// <see cref="DefaultCodecFactory.GetCodecType(string)"/> so a type new type can be /// supplied that is not in the <see cref="DefaultCodecFactory.codecNameToTypeMap"/>.</item> + /// <item>subclass <see cref="DefaultCodecFactory"/> to add new or override the default <see cref="Codec"/> + /// types by overriding <see cref="Initialize()"/> and calling <see cref="PutPostingsFormatType(Type)"/>.</item> /// <item>subclass <see cref="DefaultCodecFactory"/> to scan additional assemblies for <see cref="Codec"/> - /// subclasses in the constructor by calling <see cref="ScanForCodecs(Assembly)"/>. + /// subclasses in by overriding <see cref="Initialize()"/> and calling <see cref="ScanForPostingsFormats(Assembly)"/>. /// For performance reasons, the default behavior only loads Lucene.Net codecs.</item> - /// <item>subclass <see cref="DefaultCodecFactory"/> to add override the default <see cref="Codec"/> - /// types by calling <see cref="PutCodecType(Type)"/>.</item> /// </list> /// <para/> /// To set the <see cref="ICodecFactory"/>, call <see cref="Codec.SetCodecFactory(ICodecFactory)"/>. @@ -51,8 +51,18 @@ namespace Lucene.Net.Codecs // variable in the Codec class. private readonly IDictionary<string, Type> codecNameToTypeMap = new Dictionary<string, Type>(); private readonly IDictionary<Type, Codec> codecInstanceCache = new Dictionary<Type, Codec>(); + private object syncLock = new object(); - public DefaultCodecFactory() + /// <summary> + /// Initializes the codec type cache with the known <see cref="Codec"/> types. + /// Override this method (and optionally call <c>base.Initialize()</c>) to add your + /// own <see cref="Codec"/> types by calling <see cref="PutCodecType(Type)"/> + /// or <see cref="ScanForCodecs(Assembly)"/>. + /// <para/> + /// If two types have the same name by using the <see cref="CodecNameAttribute"/>, the + /// last one registered wins. + /// </summary> + protected override void Initialize() { ScanForCodecs(new Assembly[] { typeof(Codec).GetTypeInfo().Assembly, @@ -111,7 +121,7 @@ namespace Lucene.Net.Codecs } if (!typeof(Codec).GetTypeInfo().IsAssignableFrom(codec)) { - throw new ArgumentException("System.Type passed dose not subclass Codec."); + throw new ArgumentException("The supplied codec does not subclass Codec."); } PutCodecTypeImpl(codec); @@ -130,8 +140,8 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="Codec"/> instance.</returns> public virtual Codec GetCodec(string name) { + EnsureInitialized(); // Safety in case a subclass doesn't call it Type codecType = GetCodecType(name); - return GetCodec(codecType); } @@ -145,8 +155,14 @@ namespace Lucene.Net.Codecs Codec instance; if (!codecInstanceCache.TryGetValue(type, out instance)) { - instance = (Codec)Activator.CreateInstance(type, true); - codecInstanceCache[type] = instance; + lock (syncLock) + { + if (!codecInstanceCache.TryGetValue(type, out instance)) + { + instance = (Codec)Activator.CreateInstance(type, IsFullyTrusted); + codecInstanceCache[type] = instance; + } + } } return instance; @@ -159,13 +175,13 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="Codec"/> <see cref="Type"/>.</returns> protected virtual Type GetCodecType(string name) { + EnsureInitialized(); Type codecType; - codecNameToTypeMap.TryGetValue(name, out codecType); - if (codecType == null) + if (!codecNameToTypeMap.TryGetValue(name, out codecType) && codecType == null) { throw new ArgumentException(string.Format("Codec '{0}' cannot be loaded. If the codec is not " + - "in a Lucene.Net assembly, you must subclass DefaultCodecFactory and call ScanForCodecs() with the " + - "target assembly from the subclass constructor.", name)); + "in a Lucene.Net assembly, you must subclass DefaultCodecFactory and call PutCodecType() or " + + "ScanForCodecs() from the Initialize() method.", name)); } return codecType; @@ -175,8 +191,9 @@ namespace Lucene.Net.Codecs /// Gets a list of the available <see cref="Codec"/>s (by name). /// </summary> /// <returns>A <see cref="T:ICollection{string}"/> of <see cref="Codec"/> names.</returns> - public ICollection<string> AvailableServices() + public virtual ICollection<string> AvailableServices() { + EnsureInitialized(); return codecNameToTypeMap.Keys; } } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs index 91e5ac3..d5f0e75 100644 --- a/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs +++ b/src/Lucene.Net/Support/Codecs/DefaultDocValuesFormatFactory.cs @@ -36,11 +36,11 @@ namespace Lucene.Net.Codecs /// <item>subclass <see cref="DefaultDocValuesFormatFactory"/> and override /// <see cref="DefaultDocValuesFormatFactory.GetDocValuesFormatType(string)"/> so a type new type can be /// supplied that is not in the <see cref="DefaultDocValuesFormatFactory.docValuesFormatNameToTypeMap"/>.</item> + /// <item>subclass <see cref="DefaultDocValuesFormatFactory"/> to add new or override the default <see cref="DocValuesFormat"/> + /// types by overriding <see cref="Initialize()"/> and calling <see cref="PutPostingsFormatType(Type)"/>.</item> /// <item>subclass <see cref="DefaultDocValuesFormatFactory"/> to scan additional assemblies for <see cref="DocValuesFormat"/> - /// subclasses in the constructor by calling <see cref="ScanForDocValuesFormats(Assembly)"/>. + /// subclasses in by overriding <see cref="Initialize()"/> and calling <see cref="ScanForPostingsFormats(Assembly)"/>. /// For performance reasons, the default behavior only loads Lucene.Net codecs.</item> - /// <item>subclass <see cref="DefaultDocValuesFormatFactory"/> to add override the default <see cref="DocValuesFormat"/> - /// types by calling <see cref="PutDocValuesFormatType(Type)"/>.</item> /// </list> /// <para/> /// To set the <see cref="IDocValuesFormatFactory"/>, call <see cref="DocValuesFormat.SetDocValuesFormatFactory(IDocValuesFormatFactory)"/>. @@ -51,8 +51,18 @@ namespace Lucene.Net.Codecs // variable in the Codec class. private readonly IDictionary<string, Type> docValuesFormatNameToTypeMap = new Dictionary<string, Type>(); private readonly IDictionary<Type, DocValuesFormat> docValuesFormatInstanceCache = new Dictionary<Type, DocValuesFormat>(); + private object syncLock = new object(); - public DefaultDocValuesFormatFactory() + /// <summary> + /// Initializes the doc values type cache with the known <see cref="DocValuesFormat"/> types. + /// Override this method (and optionally call <c>base.Initialize()</c>) to add your + /// own <see cref="DocValuesFormat"/> types by calling <see cref="PutDocValuesFormatType(Type)"/> + /// or <see cref="ScanForDocValuesFormats(Assembly)"/>. + /// <para/> + /// If two types have the same name by using the <see cref="DocValuesFormatNameAttribute"/>, the + /// last one registered wins. + /// </summary> + protected override void Initialize() { ScanForDocValuesFormats(new Assembly[] { typeof(Codec).GetTypeInfo().Assembly, @@ -111,7 +121,7 @@ namespace Lucene.Net.Codecs } if (!typeof(DocValuesFormat).GetTypeInfo().IsAssignableFrom(docValuesFormat)) { - throw new ArgumentException("System.Type passed dose not subclass DocValuesFormat."); + throw new ArgumentException("The supplied docValuesFormat does not subclass DocValuesFormat."); } PutCodecTypeImpl(docValuesFormat); @@ -130,8 +140,8 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="DocValuesFormat"/> instance.</returns> public virtual DocValuesFormat GetDocValuesFormat(string name) { + EnsureInitialized(); // Safety in case a subclass doesn't call it Type codecType = GetDocValuesFormatType(name); - return GetDocValuesFormat(codecType); } @@ -145,8 +155,14 @@ namespace Lucene.Net.Codecs DocValuesFormat instance; if (!docValuesFormatInstanceCache.TryGetValue(type, out instance)) { - instance = (DocValuesFormat)Activator.CreateInstance(type, true); - docValuesFormatInstanceCache[type] = instance; + lock (syncLock) + { + if (!docValuesFormatInstanceCache.TryGetValue(type, out instance)) + { + instance = (DocValuesFormat)Activator.CreateInstance(type, IsFullyTrusted); + docValuesFormatInstanceCache[type] = instance; + } + } } return instance; @@ -159,13 +175,13 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="DocValuesFormat"/> <see cref="Type"/>.</returns> protected virtual Type GetDocValuesFormatType(string name) { + EnsureInitialized(); Type codecType; - docValuesFormatNameToTypeMap.TryGetValue(name, out codecType); - if (codecType == null) + if (!docValuesFormatNameToTypeMap.TryGetValue(name, out codecType) && codecType == null) { throw new ArgumentException(string.Format("DocValuesFormat '{0}' cannot be loaded. If the format is not " + - "in a Lucene.Net assembly, you must subclass DefaultDocValuesFormatFactory and call ScanForDocValuesFormats() with the " + - "target assembly from the subclass constructor.", name)); + "in a Lucene.Net assembly, you must subclass DefaultDocValuesFormatFactory and call PutDocValuesFormatType() " + + "or ScanForDocValuesFormats() from the Initialize() method.", name)); } return codecType; @@ -175,8 +191,9 @@ namespace Lucene.Net.Codecs /// Gets a list of the available <see cref="DocValuesFormat"/>s (by name). /// </summary> /// <returns>A <see cref="ICollection{string}"/> of <see cref="DocValuesFormat"/> names.</returns> - public ICollection<string> AvailableServices() + public virtual ICollection<string> AvailableServices() { + EnsureInitialized(); return docValuesFormatNameToTypeMap.Keys; } } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs b/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs index bbf7ecf..c1a3982 100644 --- a/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs +++ b/src/Lucene.Net/Support/Codecs/DefaultPostingsFormatFactory.cs @@ -33,14 +33,14 @@ namespace Lucene.Net.Codecs /// container can be used to supply the instances (lifetime should be singleton). Note that you could /// alternately use the "named type" feature that many DI containers have to supply the type based on name by /// overriding <see cref="GetDocValuesFormat(string)"/>.</item> - /// <item>subclass <see cref="DefaultDPostingsFormatFactory"/> and override + /// <item>subclass <see cref="DefaultPostingsFormatFactory"/> and override /// <see cref="DefaultPostingsFormatFactory.GetPostingsFormatType(string)"/> so a type new type can be /// supplied that is not in the <see cref="DefaultPostingsFormatFactory.postingsFormatNameToTypeMap"/>.</item> + /// <item>subclass <see cref="DefaultPostingsFormatFactory"/> to add new or override the default <see cref="PostingsFormat"/> + /// types by overriding <see cref="Initialize()"/> and calling <see cref="PutPostingsFormatType(Type)"/>.</item> /// <item>subclass <see cref="DefaultPostingsFormatFactory"/> to scan additional assemblies for <see cref="PostingsFormat"/> - /// subclasses in the constructor by calling <see cref="ScanForPostingsFormats(Assembly)"/>. + /// subclasses in by overriding <see cref="Initialize()"/> and calling <see cref="ScanForPostingsFormats(Assembly)"/>. /// For performance reasons, the default behavior only loads Lucene.Net codecs.</item> - /// <item>subclass <see cref="DefaultPostingsFormatFactory"/> to add override the default <see cref="PostingsFormat"/> - /// types by calling <see cref="PutPostingsFormatType(Type)"/>.</item> /// </list> /// <para/> /// To set the <see cref="IPostingsFormatFactory"/>, call <see cref="DocValuesFormat.SetPostingsFormatFactory(IPostingsFormatFactory)"/>. @@ -51,8 +51,18 @@ namespace Lucene.Net.Codecs // variable in the Codec class. private readonly IDictionary<string, Type> postingsFormatNameToTypeMap = new Dictionary<string, Type>(); private readonly IDictionary<Type, PostingsFormat> postingsFormatInstanceCache = new Dictionary<Type, PostingsFormat>(); + private object syncLock = new object(); - public DefaultPostingsFormatFactory() + /// <summary> + /// Initializes the codec type cache with the known <see cref="PostingsFormat"/> types. + /// Override this method (and optionally call <c>base.Initialize()</c>) to add your + /// own <see cref="PostingsFormat"/> types by calling <see cref="PutDocPostingsFormatType(Type)"/> + /// or <see cref="ScanForPostingsFormats(Assembly)"/>. + /// <para/> + /// If two types have the same name by using the <see cref="PostingsFormatNameAttribute"/>, the + /// last one registered wins. + /// </summary> + protected override void Initialize() { ScanForPostingsFormats(new Assembly[] { typeof(Codec).GetTypeInfo().Assembly, @@ -111,7 +121,7 @@ namespace Lucene.Net.Codecs } if (!typeof(PostingsFormat).GetTypeInfo().IsAssignableFrom(postingsFormat)) { - throw new ArgumentException("System.Type passed dose not subclass PostingsFormat."); + throw new ArgumentException("The supplied postingsFormat does not subclass PostingsFormat."); } PutPostingsFormatTypeImpl(postingsFormat); @@ -130,8 +140,8 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="PostingsFormat"/> instance.</returns> public virtual PostingsFormat GetPostingsFormat(string name) { + EnsureInitialized(); // Safety in case a subclass doesn't call it Type codecType = GetPostingsFormatType(name); - return GetPostingsFormat(codecType); } @@ -145,8 +155,14 @@ namespace Lucene.Net.Codecs PostingsFormat instance; if (!postingsFormatInstanceCache.TryGetValue(type, out instance)) { - instance = (PostingsFormat)Activator.CreateInstance(type, true); - postingsFormatInstanceCache[type] = instance; + lock (syncLock) + { + if (!postingsFormatInstanceCache.TryGetValue(type, out instance)) + { + instance = (PostingsFormat)Activator.CreateInstance(type, IsFullyTrusted); + postingsFormatInstanceCache[type] = instance; + } + } } return instance; @@ -159,13 +175,13 @@ namespace Lucene.Net.Codecs /// <returns>The <see cref="PostingsFormat"/> <see cref="Type"/>.</returns> protected virtual Type GetPostingsFormatType(string name) { + EnsureInitialized(); Type codecType; - postingsFormatNameToTypeMap.TryGetValue(name, out codecType); - if (codecType == null) + if (!postingsFormatNameToTypeMap.TryGetValue(name, out codecType) && codecType == null) { throw new ArgumentException(string.Format("PostingsFormat '{0}' cannot be loaded. If the format is not " + - "in a Lucene.Net assembly, you must subclass DefaultPostingsFormatFactory and call ScanForPostingsFormats() with the " + - "target assembly from the subclass constructor.", name)); + "in a Lucene.Net assembly, you must subclass DefaultPostingsFormatFactory and call PutPostingsFormatType() " + + "or ScanForPostingsFormats() from the Initialize() method.", name)); } return codecType; @@ -175,8 +191,9 @@ namespace Lucene.Net.Codecs /// Gets a list of the available <see cref="PostingsFormat"/>s (by name). /// </summary> /// <returns>A <see cref="ICollection{string}"/> of <see cref="PostingsFormat"/> names.</returns> - public ICollection<string> AvailableServices() + public virtual ICollection<string> AvailableServices() { + EnsureInitialized(); return postingsFormatNameToTypeMap.Keys; } } http://git-wip-us.apache.org/repos/asf/lucenenet/blob/8a58d858/src/Lucene.Net/Support/Util/NamedServiceFactory.cs ---------------------------------------------------------------------- diff --git a/src/Lucene.Net/Support/Util/NamedServiceFactory.cs b/src/Lucene.Net/Support/Util/NamedServiceFactory.cs index 0ca474b..03ac82c 100644 --- a/src/Lucene.Net/Support/Util/NamedServiceFactory.cs +++ b/src/Lucene.Net/Support/Util/NamedServiceFactory.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Reflection; +using System.Threading; namespace Lucene.Net.Util { @@ -28,19 +29,30 @@ namespace Lucene.Net.Util public abstract class NamedServiceFactory<TService> { private static Assembly codecsAssembly = null; + private bool initialized = false; + private object initializationLock = new object(); + private object initializationTarget; // Dummy variable required by LazyInitializer.EnsureInitialized - protected NamedServiceFactory() + /// <summary> + /// Ensures the <see cref="Initialize"/> method has been called since the + /// last application start. This method is thread-safe. + /// </summary> + protected void EnsureInitialized() { - // Attempt to load the SimpleTextCodec type. If it loads it will not be null, - // which means the assembly is referenced so we can load all of the named services from that assembly. - Type simpleTextType = Type.GetType("Lucene.Net.Codecs.SimpleText.SimpleTextCodec, Lucene.Net.Codecs"); - if (simpleTextType != null) + LazyInitializer.EnsureInitialized(ref this.initializationTarget, ref this.initialized, ref this.initializationLock, () => { - codecsAssembly = simpleTextType.GetTypeInfo().Assembly; - } + Initialize(); + return null; + }); } /// <summary> + /// Initializes the dependencies of this factory (such as using Reflection to populate the type cache). + /// </summary> + protected abstract void Initialize(); + + + /// <summary> /// The Lucene.Net.Codecs assembly or <c>null</c> if the assembly is not referenced /// in the host project. /// </summary> @@ -48,6 +60,17 @@ namespace Lucene.Net.Util { get { + if (codecsAssembly == null) + { + // Attempt to load the SimpleTextCodec type. If it loads it will not be null, + // which means the assembly is referenced so we can load all of the named services from that assembly. + Type simpleTextType = Type.GetType("Lucene.Net.Codecs.SimpleText.SimpleTextCodec, Lucene.Net.Codecs"); + if (simpleTextType != null) + { + codecsAssembly = simpleTextType.GetTypeInfo().Assembly; + } + } + return codecsAssembly; } } @@ -143,5 +166,20 @@ namespace Lucene.Net.Util { return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9'); } + + /// <summary> + /// Gets a value that indicates whether the current application domain executes with full trust. + /// </summary> + protected bool IsFullyTrusted + { + get + { +#if NETSTANDARD + return true; // Partial trust is obsolete +#else + return AppDomain.CurrentDomain.IsFullyTrusted; // Partial trust support +#endif + } + } } }
