|
From: <fab...@us...> - 2009-06-12 15:34:45
|
Revision: 4458
http://nhibernate.svn.sourceforge.net/nhibernate/?rev=4458&view=rev
Author: fabiomaulo
Date: 2009-06-12 15:34:31 +0000 (Fri, 12 Jun 2009)
Log Message:
-----------
Fix NH-1623
Modified Paths:
--------------
trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs
trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs
trunk/nhibernate/src/NHibernate/Cfg/Environment.cs
trunk/nhibernate/src/NHibernate/NHibernate.csproj
trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd
trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs
trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
Added Paths:
-----------
trunk/nhibernate/src/NHibernate/Bytecode/IInjectableCollectionTypeFactoryClass.cs
trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/ProductLine.hbm.xml
Modified: trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate/Bytecode/AbstractBytecodeProvider.cs 2009-06-12 15:34:31 UTC (rev 4458)
@@ -4,11 +4,12 @@
namespace NHibernate.Bytecode
{
- public abstract class AbstractBytecodeProvider : IBytecodeProvider, IInjectableProxyFactoryFactory
+ public abstract class AbstractBytecodeProvider : IBytecodeProvider, IInjectableProxyFactoryFactory, IInjectableCollectionTypeFactoryClass
{
private readonly IObjectsFactory objectsFactory = new ActivatorObjectsFactory();
protected System.Type proxyFactoryFactory;
private ICollectionTypeFactory collectionTypeFactory;
+ private System.Type collectionTypeFactoryClass = typeof(Type.DefaultCollectionTypeFactory);
#region IBytecodeProvider Members
@@ -39,7 +40,7 @@
get { return objectsFactory; }
}
- public ICollectionTypeFactory CollectionTypeFactory
+ public virtual ICollectionTypeFactory CollectionTypeFactory
{
get
{
@@ -48,7 +49,7 @@
try
{
collectionTypeFactory =
- (ICollectionTypeFactory) ObjectsFactory.CreateInstance(typeof (Type.DefaultCollectionTypeFactory));
+ (ICollectionTypeFactory) ObjectsFactory.CreateInstance(collectionTypeFactoryClass);
}
catch (Exception e)
{
@@ -57,14 +58,6 @@
}
return collectionTypeFactory;
}
- protected set
- {
- if(value == null)
- {
- throw new InvalidOperationException("The CollectionTypeFactory can't be null.");
- }
- collectionTypeFactory = value;
- }
}
#endregion
@@ -92,5 +85,36 @@
}
#endregion
+
+ #region Implementation of IInjectableCollectionTypeFactoryClass
+
+ public void SetCollectionTypeFactoryClass(string typeAssemblyQualifiedName)
+ {
+ if (string.IsNullOrEmpty(typeAssemblyQualifiedName))
+ {
+ throw new ArgumentNullException("typeAssemblyQualifiedName");
+ }
+ System.Type ctf= ReflectHelper.ClassForName(typeAssemblyQualifiedName);
+ SetCollectionTypeFactoryClass(ctf);
+ }
+
+ public void SetCollectionTypeFactoryClass(System.Type type)
+ {
+ if (type == null)
+ {
+ throw new ArgumentNullException("type");
+ }
+ if (typeof(ICollectionTypeFactory).IsAssignableFrom(type) == false)
+ {
+ throw new HibernateByteCodeException(type.FullName + " does not implement " + typeof(ICollectionTypeFactory).FullName);
+ }
+ if (collectionTypeFactory != null)
+ {
+ throw new InvalidOperationException("CollectionTypeFactory in use, can't change it.");
+ }
+ collectionTypeFactoryClass = type;
+ }
+
+ #endregion
}
}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate/Bytecode/IInjectableCollectionTypeFactoryClass.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Bytecode/IInjectableCollectionTypeFactoryClass.cs (rev 0)
+++ trunk/nhibernate/src/NHibernate/Bytecode/IInjectableCollectionTypeFactoryClass.cs 2009-06-12 15:34:31 UTC (rev 4458)
@@ -0,0 +1,8 @@
+namespace NHibernate.Bytecode
+{
+ public interface IInjectableCollectionTypeFactoryClass
+ {
+ void SetCollectionTypeFactoryClass(string typeAssemblyQualifiedName);
+ void SetCollectionTypeFactoryClass(System.Type type);
+ }
+}
\ No newline at end of file
Modified: trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate/Cfg/Configuration.cs 2009-06-12 15:34:31 UTC (rev 4458)
@@ -55,6 +55,7 @@
public const string DefaultHibernateCfgFileName = "hibernate.cfg.xml";
private string currentDocumentName;
+ private bool preMappingBuildProcessed;
protected IDictionary<string, PersistentClass> classes; // entityName, PersistentClass
protected IDictionary<string, NHibernate.Mapping.Collection> collections;
@@ -523,12 +524,38 @@
/// </summary>
public Mappings CreateMappings(Dialect.Dialect dialect)
{
+ ProcessPreMappingBuildProperties();
return new Mappings(classes, collections, tables, NamedQueries, NamedSQLQueries, SqlResultSetMappings, Imports,
secondPasses, propertyReferences, namingStrategy, typeDefs, FilterDefinitions, extendsQueue,
auxiliaryDatabaseObjects, tableNameBinding, columnNameBindingPerTable, defaultAssembly,
defaultNamespace, dialect);
}
+ private void ProcessPreMappingBuildProperties()
+ {
+ if(preMappingBuildProcessed)
+ {
+ return;
+ }
+ ConfigureCollectionTypeFactory();
+ preMappingBuildProcessed = true;
+ }
+
+ private void ConfigureCollectionTypeFactory()
+ {
+ var ctfc = GetProperty(Environment.CollectionTypeFactoryClass);
+ if(string.IsNullOrEmpty(ctfc))
+ {
+ return;
+ }
+ var ictfc = Environment.BytecodeProvider as IInjectableCollectionTypeFactoryClass;
+ if(ictfc == null)
+ {
+ return;
+ }
+ ictfc.SetCollectionTypeFactoryClass(ctfc);
+ }
+
/// <summary>
/// Read mappings from a <see cref="Stream" />.
/// </summary>
Modified: trunk/nhibernate/src/NHibernate/Cfg/Environment.cs
===================================================================
--- trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate/Cfg/Environment.cs 2009-06-12 15:34:31 UTC (rev 4458)
@@ -158,6 +158,8 @@
public const string DefaultBatchFetchSize = "default_batch_fetch_size";
+ public const string CollectionTypeFactoryClass = "collectiontype.factory_class";
+
private static readonly Dictionary<string, string> GlobalProperties;
private static IBytecodeProvider BytecodeProviderInstance;
Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2009-06-12 15:34:31 UTC (rev 4458)
@@ -451,6 +451,7 @@
<Compile Include="Bytecode\AbstractBytecodeProvider.cs" />
<Compile Include="Bytecode\ActivatorObjectsFactory.cs" />
<Compile Include="Bytecode\HibernateByteCodeException.cs" />
+ <Compile Include="Bytecode\IInjectableCollectionTypeFactoryClass.cs" />
<Compile Include="Bytecode\IObjectsFactory.cs" />
<Compile Include="Bytecode\ProxyFactoryFactoryNotConfiguredException.cs" />
<Compile Include="Bytecode\UnableToLoadProxyFactoryFactoryException.cs" />
Modified: trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd
===================================================================
--- trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate/nhibernate-configuration.xsd 2009-06-12 15:34:31 UTC (rev 4458)
@@ -102,6 +102,7 @@
<xs:enumeration value="default_entity_mode" />
<xs:enumeration value="use_sql_comments" />
<xs:enumeration value="format_sql" />
+ <xs:enumeration value="collectiontype.factory_class" />
</xs:restriction>
</xs:simpleType>
</xs:attribute>
Modified: trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/BytecodeProviderFixture.cs 2009-06-12 15:34:31 UTC (rev 4458)
@@ -1,6 +1,8 @@
+using System;
using NHibernate.Bytecode;
using NHibernate.Bytecode.Lightweight;
using NUnit.Framework;
+using Environment=NHibernate.Cfg.Environment;
namespace NHibernate.Test.Bytecode.Lightweight
{
@@ -71,5 +73,85 @@
Assert.That(e.Message,Text.StartsWith("Failed to create an instance of"));
}
}
+
+ [Test]
+ public void NotConfiguredCollectionTypeFactory()
+ {
+ // our BytecodeProvider should ever have a CollectionTypeFactory
+ var bcp = new BytecodeProviderImpl();
+ Assert.That(bcp.CollectionTypeFactory, Is.Not.Null);
+ }
+
+ [Test]
+ public void SetCollectionTypeFactoryClassByName()
+ {
+ string nullName = null;
+ var bcp = new BytecodeProviderImpl();
+
+ Assert.Throws<ArgumentNullException>(() => bcp.SetCollectionTypeFactoryClass(nullName));
+ Assert.Throws<ArgumentNullException>(() => bcp.SetCollectionTypeFactoryClass(string.Empty));
+ Assert.Throws<TypeLoadException>(() => bcp.SetCollectionTypeFactoryClass("whatever"));
+ }
+
+ [Test]
+ public void SetCollectionTypeFactoryClassByType()
+ {
+ System.Type nullType = null;
+ var bcp = new BytecodeProviderImpl();
+ Assert.Throws<ArgumentNullException>(() => bcp.SetCollectionTypeFactoryClass(nullType));
+ Assert.Throws<HibernateByteCodeException>(() => bcp.SetCollectionTypeFactoryClass(GetType()), "should allow only ICollectionTypeFactory type");
+ }
+
+ private class NoDefaultCtor: Type.DefaultCollectionTypeFactory
+ {
+ public NoDefaultCtor(int something) {}
+ }
+
+ [Test]
+ public void InvalidCollectionTypeFactoryCtor()
+ {
+ ICollectionTypeFactory ctf;
+ var bcp = new BytecodeProviderImpl();
+ bcp.SetCollectionTypeFactoryClass(typeof (NoDefaultCtor));
+ Assert.Throws<HibernateByteCodeException>(() => ctf = bcp.CollectionTypeFactory);
+ }
+
+ [Test]
+ public void CollectionTypeFactoryCantChangeAfterUsage()
+ {
+ ICollectionTypeFactory ctf;
+ var bcp = new BytecodeProviderImpl();
+ ctf = bcp.CollectionTypeFactory; // initialize the instance
+ // try to set it
+ Assert.Throws<InvalidOperationException>(() => bcp.SetCollectionTypeFactoryClass(typeof(Type.DefaultCollectionTypeFactory)));
+ }
+
+ private class CustomCollectionTypeFactory : Type.DefaultCollectionTypeFactory
+ {
+ }
+
+ [Test]
+ [Explicit("The BytecodeProvider is static and can't be different in the same application.")]
+ public void AllowCustomCollectionTypeFactoryBeforeBuildFirstMapping()
+ {
+ // Allow set of CustomCollectionTypeFactory class after configure BUT before add the first mapping.
+ // for real we need CustomCollectionTypeFactory before BuildSessionFactory but for possible future
+ // "mapping-sources" is better to limitate the moment of injectability.
+ var cfg = TestConfigurationHelper.GetDefaultConfiguration();
+ cfg.SetProperty(Environment.CollectionTypeFactoryClass, typeof(CustomCollectionTypeFactory).AssemblyQualifiedName);
+ Dialect.Dialect dialect = Dialect.Dialect.GetDialect(cfg.Properties);
+ cfg.CreateMappings(dialect);
+ Assert.That(Environment.BytecodeProvider.CollectionTypeFactory, Is.TypeOf<CustomCollectionTypeFactory>());
+ }
+
+ [Test]
+ [Explicit("The BytecodeProvider is static and can't be different in the same application.")]
+ public void WorkAddingMappings()
+ {
+ var cfg = TestConfigurationHelper.GetDefaultConfiguration();
+ cfg.SetProperty(Environment.CollectionTypeFactoryClass, typeof(CustomCollectionTypeFactory).AssemblyQualifiedName);
+ cfg.AddResource("NHibernate.Test.Bytecode.Lightweight.ProductLine.hbm.xml", GetType().Assembly);
+ Assert.That(Environment.BytecodeProvider.CollectionTypeFactory, Is.TypeOf<CustomCollectionTypeFactory>());
+ }
}
}
\ No newline at end of file
Added: trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/ProductLine.hbm.xml
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/ProductLine.hbm.xml (rev 0)
+++ trunk/nhibernate/src/NHibernate.Test/Bytecode/Lightweight/ProductLine.hbm.xml 2009-06-12 15:34:31 UTC (rev 4458)
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8" ?>
+
+<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
+
+ <class entity-name="ProductLine">
+ <id name="Id" type="int">
+ <generator class="hilo"/>
+ </id>
+ <property name="Description" not-null="true" length="200" type="string"/>
+
+ <bag name="Models" cascade="all" inverse="true">
+ <key column="productId"/>
+ <one-to-many class="Model"/>
+ </bag>
+
+ </class>
+
+ <class entity-name="Model">
+ <id name="Id" type="int">
+ <generator class="hilo"/>
+ </id>
+
+ <property name="Name" not-null="true" length="25" type="string"/>
+ <property name="Description" not-null="true" length="200" type="string"/>
+ <many-to-one name="ProductLine" column="productId" not-null="true" class="ProductLine"/>
+ </class>
+
+</hibernate-mapping>
Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj
===================================================================
--- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-06-11 21:49:52 UTC (rev 4457)
+++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2009-06-12 15:34:31 UTC (rev 4458)
@@ -1901,6 +1901,7 @@
<EmbeddedResource Include="Ado\AlmostSimple.hbm.xml" />
<EmbeddedResource Include="CacheTest\EntityWithFilters.xml" />
<EmbeddedResource Include="Classic\EntityWithLifecycle.hbm.xml" />
+ <EmbeddedResource Include="Bytecode\Lightweight\ProductLine.hbm.xml" />
<Content Include="DynamicEntity\package.html" />
<EmbeddedResource Include="NHSpecificTest\NH1821\Mappings.hbm.xml" />
<EmbeddedResource Include="TypeParameters\EntityCustomId.hbm.xml" />
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|