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
+            }
+        }
     }
 }

Reply via email to