fixed SPRNET-1204: added Server Component support
This commit is contained in:
@@ -279,7 +279,9 @@ namespace Spring.EnterpriseServices
|
||||
/// </summary>
|
||||
public virtual void Export()
|
||||
{
|
||||
string assemblyFileName = AppDomain.CurrentDomain.DynamicDirectory.Trim('\\', '/') + "\\" + assemblyName + ".dll";
|
||||
string ext = (ActivationMode == ActivationOption.Library) ? ".dll" : ".exe";
|
||||
string moduleName = assemblyName + ext;
|
||||
string assemblyFileName = AppDomain.CurrentDomain.DynamicDirectory.Trim('\\', '/') + "\\" + moduleName;
|
||||
FileInfo assemblyFile = new FileInfo(assemblyFileName);
|
||||
|
||||
GenerateComponentAssembly(assemblyFile);
|
||||
@@ -292,12 +294,13 @@ namespace Spring.EnterpriseServices
|
||||
public Assembly GenerateComponentAssembly(FileInfo assemblyFile)
|
||||
{
|
||||
AssemblyName an = new AssemblyName();
|
||||
an.Name = assemblyName;
|
||||
an.Name = Path.GetFileNameWithoutExtension(assemblyFile.Name);
|
||||
an.Version = new Version("1.0.0.0");
|
||||
an.KeyPair = new StrongNameKeyPair(GetKeyPair());
|
||||
|
||||
AssemblyBuilder proxyAssembly = DefineProxyAssembly(an, assemblyFile);
|
||||
GenerateComponentTypes(proxyAssembly, objectFactory, components, UseSpring);
|
||||
ModuleBuilder module = proxyAssembly.DefineDynamicModule(an.Name, assemblyFile.Name, true);
|
||||
GenerateComponentTypes(module, objectFactory, components, UseSpring);
|
||||
|
||||
// Assembly.Save() does not allow paths...
|
||||
string dynamicFileName = assemblyFile.Name;
|
||||
@@ -310,14 +313,12 @@ namespace Spring.EnterpriseServices
|
||||
/// Generates service types from the <paramref name="components"/> list of <see cref="ServicedComponentExporter"/> instances
|
||||
/// into the given assembly.
|
||||
/// </summary>
|
||||
/// <param name="proxyAssembly">the assembly to export types to</param>
|
||||
/// <param name="module">the module to export types to</param>
|
||||
/// <param name="objectFactory">the object factory to resolve target types</param>
|
||||
/// <param name="components">the list of <see cref="ServicedComponentExporter"/> instances.</param>
|
||||
/// <param name="springManaged">whether to generate context lookups, <see cref="ServicedComponentExporter.CreateWrapperType"/></param>
|
||||
private static AssemblyBuilder GenerateComponentTypes(AssemblyBuilder proxyAssembly, IObjectFactory objectFactory, IList components, bool springManaged)
|
||||
private static void GenerateComponentTypes(ModuleBuilder module, IObjectFactory objectFactory, IList components, bool springManaged)
|
||||
{
|
||||
string moduleName = proxyAssembly.GetName().Name;
|
||||
ModuleBuilder module = proxyAssembly.DefineDynamicModule(moduleName, moduleName + ".dll", true);
|
||||
Type baseType = typeof(ServicedComponent);
|
||||
if (springManaged)
|
||||
{
|
||||
@@ -328,7 +329,6 @@ namespace Spring.EnterpriseServices
|
||||
{
|
||||
definition.CreateWrapperType(module, baseType, objectFactory.GetType(definition.TargetName), springManaged);
|
||||
}
|
||||
return proxyAssembly;
|
||||
}
|
||||
|
||||
private AssemblyBuilder DefineProxyAssembly(AssemblyName an, FileInfo assemblyFile)
|
||||
|
||||
@@ -258,19 +258,6 @@ namespace Spring.EnterpriseServices
|
||||
il.Emit(OpCodes.Ret);
|
||||
}
|
||||
|
||||
// TODO:remove
|
||||
// protected void ImplementFactoryMethod(TypeBuilder builder, ConstructorBuilder cb)
|
||||
// {
|
||||
// base.ImplementCustom(builder);
|
||||
// TypeBuilder factory = builder.DefineNestedType("Factory", System.Reflection.TypeAttributes.NestedPublic);
|
||||
// MethodBuilder newMethod = factory.DefineMethod("New", MethodAttributes.Public | MethodAttributes.Static|MethodAttributes.HideBySig,
|
||||
// CallingConventions.Standard, builder, new Type[0]);
|
||||
// ILGenerator il = newMethod.GetILGenerator();
|
||||
// il.Emit(OpCodes.Newobj, cb);
|
||||
// il.Emit(OpCodes.Ret);
|
||||
// factory.CreateType();
|
||||
// }
|
||||
|
||||
protected override IProxyMethodBuilder CreateTargetProxyMethodBuilder(TypeBuilder typeBuilder)
|
||||
{
|
||||
return new ServicedComponentTargetProxyMethodBuilder(typeBuilder, this,
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Spring.EnterpriseServices
|
||||
if (isInitialized) return;
|
||||
isInitialized = true;
|
||||
|
||||
// this is to ensure, that assemblies place next to the component assembly can be loaded
|
||||
// this is to ensure, that assemblies placed next to the component assembly can be loaded
|
||||
// even when they are not strong named.
|
||||
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
|
||||
FileInfo componentAssemblyFile = new FileInfo(componentType.Assembly.Location);
|
||||
|
||||
@@ -34,6 +34,7 @@ using NUnit.Framework;
|
||||
using DotNetMock.Dynamic;
|
||||
using Rhino.Mocks;
|
||||
using Spring.Aop.Framework;
|
||||
using Spring.Context;
|
||||
using Spring.Context.Support;
|
||||
using Spring.Objects.Factory;
|
||||
using Spring.Objects;
|
||||
@@ -43,13 +44,13 @@ using Spring.Objects.Factory.Support;
|
||||
|
||||
namespace Spring.EnterpriseServices
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Unit tests for the ServicedComponentExporter class.
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
/// </summary>
|
||||
/// <author>Bruno Baia</author>
|
||||
[TestFixture]
|
||||
public class ServicedComponentExporterTests
|
||||
{
|
||||
{
|
||||
[TearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
@@ -58,10 +59,10 @@ namespace Spring.EnterpriseServices
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(ArgumentException))]
|
||||
public void BailsWhenNotConfigured ()
|
||||
public void BailsWhenNotConfigured()
|
||||
{
|
||||
ServicedComponentExporter exp = new ServicedComponentExporter();
|
||||
exp.AfterPropertiesSet ();
|
||||
exp.AfterPropertiesSet();
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -76,7 +77,7 @@ namespace Spring.EnterpriseServices
|
||||
|
||||
Type type = CreateWrapperType(exp, typeof(TestObject), false);
|
||||
|
||||
TransactionAttribute[] attrs = (TransactionAttribute[])type.GetCustomAttributes(typeof(TransactionAttribute), false);
|
||||
TransactionAttribute[] attrs = (TransactionAttribute[])type.GetCustomAttributes(typeof(TransactionAttribute), false);
|
||||
Assert.AreEqual(1, attrs.Length);
|
||||
Assert.AreEqual(TransactionOption.RequiresNew, attrs[0].Value);
|
||||
}
|
||||
@@ -93,48 +94,30 @@ namespace Spring.EnterpriseServices
|
||||
|
||||
Type type = CreateWrapperType(exp, typeof(TestObject), true);
|
||||
|
||||
TransactionAttribute[] attrs = (TransactionAttribute[])type.GetCustomAttributes(typeof(TransactionAttribute), false);
|
||||
TransactionAttribute[] attrs = (TransactionAttribute[])type.GetCustomAttributes(typeof(TransactionAttribute), false);
|
||||
Assert.AreEqual(1, attrs.Length);
|
||||
Assert.AreEqual(TransactionOption.RequiresNew, attrs[0].Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CanExportAopProxy()
|
||||
public void CanExportAopProxyToLibrary()
|
||||
{
|
||||
// create an advised proxy and add to objectFactory
|
||||
// note, that we need to implement a signed interface here
|
||||
ProxyFactory aopProxyFactory = new ProxyFactory(new Type[] { typeof(IComparable) });
|
||||
MockMethodInterceptor methodInterceptor = new MockMethodInterceptor();
|
||||
aopProxyFactory.AddAdvice(methodInterceptor);
|
||||
IComparable aopProxy = (IComparable) aopProxyFactory.GetProxy();
|
||||
// ((AssemblyBuilder)aopProxy.GetType().Assembly).Save("Spring.Proxy.dll");
|
||||
|
||||
// sanity check
|
||||
methodInterceptor.NextResult = 2;
|
||||
Assert.AreEqual(methodInterceptor.NextResult, aopProxy.CompareTo(this));
|
||||
Assert.AreEqual(1, methodInterceptor.Calls);
|
||||
|
||||
StaticApplicationContext appCtx = new StaticApplicationContext(AbstractApplicationContext.DefaultRootContextName, null);
|
||||
appCtx.ObjectFactory.RegisterSingleton("objectTest", aopProxy);
|
||||
|
||||
// NOTE: the method interceptor will return the number of method calls intercepted
|
||||
FileInfo assemblyFile = new FileInfo("ServiceComponentExporterTests.TestServicedComponents.dll");
|
||||
XmlApplicationContext appCtx = new XmlApplicationContext("ServiceComponentExporterTests.TestServicedComponents.Services.xml");
|
||||
EnterpriseServicesExporter exporter = new EnterpriseServicesExporter();
|
||||
exporter.ActivationMode = ActivationOption.Library;
|
||||
Type serviceType = ExportObject(exporter, assemblyFile, appCtx, "objectTest");
|
||||
try
|
||||
{
|
||||
// ServiceComponent will obtain its target from root context
|
||||
ContextRegistry.RegisterContext(appCtx);
|
||||
methodInterceptor.Calls = 0;
|
||||
|
||||
IComparable testObject;
|
||||
testObject = (IComparable)Activator.CreateInstance(serviceType);
|
||||
methodInterceptor.NextResult = 3;
|
||||
Assert.AreEqual(methodInterceptor.NextResult, testObject.CompareTo(null));
|
||||
Assert.AreEqual(1, testObject.CompareTo(null));
|
||||
testObject = (IComparable)Activator.CreateInstance(serviceType);
|
||||
methodInterceptor.NextResult = 4;
|
||||
Assert.AreEqual(methodInterceptor.NextResult, testObject.CompareTo(null));
|
||||
|
||||
Assert.AreEqual(2, methodInterceptor.Calls);
|
||||
Assert.AreEqual(2, testObject.CompareTo(null));
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -143,41 +126,62 @@ namespace Spring.EnterpriseServices
|
||||
}
|
||||
}
|
||||
|
||||
private Type ExportObject(EnterpriseServicesExporter exporter, FileInfo assemblyFile, StaticApplicationContext appCtx, string objectName)
|
||||
{
|
||||
exporter.ObjectFactory = appCtx.ObjectFactory;
|
||||
exporter.Assembly = Path.GetFileNameWithoutExtension(assemblyFile.Name);
|
||||
exporter.ApplicationName = exporter.Assembly;
|
||||
exporter.ActivationMode = ActivationOption.Library;
|
||||
exporter.UseSpring = true;
|
||||
[Test]
|
||||
public void CanExportAopProxyToServer()
|
||||
{
|
||||
FileInfo assemblyFile = new FileInfo("ServiceComponentExporterTests.TestServicedComponents.exe");
|
||||
XmlApplicationContext appCtx = new XmlApplicationContext("ServiceComponentExporterTests.TestServicedComponents.Services.xml");
|
||||
EnterpriseServicesExporter exporter = new EnterpriseServicesExporter();
|
||||
exporter.ActivationMode = ActivationOption.Server;
|
||||
Type serviceType = ExportObject(exporter, assemblyFile, appCtx, "objectTest");
|
||||
try
|
||||
{
|
||||
// ServiceComponent will obtain its target from root context
|
||||
IComparable testObject;
|
||||
testObject = (IComparable)Activator.CreateInstance(serviceType);
|
||||
Assert.AreEqual(1, testObject.CompareTo(null));
|
||||
testObject = (IComparable)Activator.CreateInstance(serviceType);
|
||||
Assert.AreEqual(2, testObject.CompareTo(null));
|
||||
}
|
||||
finally
|
||||
{
|
||||
exporter.UnregisterServicedComponents(assemblyFile);
|
||||
ContextRegistry.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
ServicedComponentExporter exp = new ServicedComponentExporter();
|
||||
exp.TargetName = objectName;
|
||||
exp.ObjectName = objectName + "Service";
|
||||
exp.TypeAttributes = new ArrayList();
|
||||
exp.TypeAttributes.Add(new TransactionAttribute(TransactionOption.RequiresNew));
|
||||
exp.AfterPropertiesSet();
|
||||
private Type ExportObject(EnterpriseServicesExporter exporter, FileInfo assemblyFile, IConfigurableApplicationContext appCtx, string objectName)
|
||||
{
|
||||
exporter.ObjectFactory = appCtx.ObjectFactory;
|
||||
exporter.Assembly = Path.GetFileNameWithoutExtension(assemblyFile.Name);
|
||||
exporter.ApplicationName = exporter.Assembly;
|
||||
exporter.AccessControl = new ApplicationAccessControlAttribute(false);
|
||||
exporter.UseSpring = true;
|
||||
|
||||
exporter.Components.Add(exp);
|
||||
ServicedComponentExporter exp = new ServicedComponentExporter();
|
||||
exp.TargetName = objectName;
|
||||
exp.ObjectName = objectName + "Service";
|
||||
exp.TypeAttributes = new ArrayList();
|
||||
exp.TypeAttributes.Add(new TransactionAttribute(TransactionOption.RequiresNew));
|
||||
exp.AfterPropertiesSet();
|
||||
|
||||
Assembly assembly = exporter.GenerateComponentAssembly(assemblyFile);
|
||||
exporter.Components.Add(exp);
|
||||
|
||||
Assembly assembly = exporter.GenerateComponentAssembly(assemblyFile);
|
||||
exporter.RegisterServicedComponents(assemblyFile);
|
||||
return assembly.GetType(objectName + "Service");
|
||||
}
|
||||
}
|
||||
|
||||
#region Private helpers & classes
|
||||
#region Private helpers & classes
|
||||
|
||||
private class MockMethodInterceptor : IMethodInterceptor
|
||||
public class CountingMethodInterceptor : IMethodInterceptor
|
||||
{
|
||||
public object NextResult = null;
|
||||
public int Calls = 0;
|
||||
public IMethodInvocation LastInvocation;
|
||||
private int Calls = 0;
|
||||
|
||||
public object Invoke(IMethodInvocation invocation)
|
||||
{
|
||||
Calls++;
|
||||
LastInvocation = invocation;
|
||||
return NextResult;
|
||||
return Calls;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +192,7 @@ namespace Spring.EnterpriseServices
|
||||
AssemblyBuilder proxyAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.RunAndSave);
|
||||
ModuleBuilder module = proxyAssembly.DefineDynamicModule(an.Name, an.Name + ".dll", true);
|
||||
|
||||
Type baseType = typeof (ServicedComponent);
|
||||
Type baseType = typeof(ServicedComponent);
|
||||
if (useSpring)
|
||||
{
|
||||
baseType = EnterpriseServicesExporter.CreateSpringServicedComponentType(module, baseType);
|
||||
@@ -202,7 +206,7 @@ namespace Spring.EnterpriseServices
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // (!NET_1_0)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<objects xmlns="http://www.springframework.net">
|
||||
|
||||
<object id="countingInterceptor" type="Spring.EnterpriseServices.ServicedComponentExporterTests+CountingMethodInterceptor, Spring.Services.Tests" />
|
||||
|
||||
<object name="objectTest" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
|
||||
<property name="ProxyInterfaces">
|
||||
<list>
|
||||
<value>System.IComparable</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="InterceptorNames">
|
||||
<list>
|
||||
<idref local="countingInterceptor"/>
|
||||
</list>
|
||||
</property>
|
||||
</object>
|
||||
</objects>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<spring>
|
||||
<context>
|
||||
<resource uri="ServiceComponentExporterTests.TestServicedComponents.Services.xml" />
|
||||
</context>
|
||||
</spring>
|
||||
@@ -189,6 +189,14 @@
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Data\Spring\Remoting\saoSingleton-autowired.xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="ServiceComponentExporterTests.TestServicedComponents.exe.spring-context.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="ServiceComponentExporterTests.TestServicedComponents.Services.xml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PreBuildEvent>
|
||||
|
||||
@@ -10,23 +10,23 @@
|
||||
<if test="${net-3.0.installed and net-3.0}">
|
||||
<property name="bin.dir.to.use" value="${current.bin.dir}\..\..\2.0\${project.build.config}"/>
|
||||
<copy todir="${current.bin.dir}">
|
||||
<fileset basedir="${bin.dir.to.use}">
|
||||
<include name="*.dll"/>
|
||||
<include name="*.pdb"/>
|
||||
<include name="*.xml"/>
|
||||
<exclude name="Spring.Services.dll"/>
|
||||
<exclude name="Spring.Services.pdb"/>
|
||||
<exclude name="Spring.Services.xml"/>
|
||||
<fileset basedir="${bin.dir.to.use}">
|
||||
<include name="*.dll"/>
|
||||
<include name="*.pdb"/>
|
||||
<include name="*.xml"/>
|
||||
<exclude name="Spring.Services.dll"/>
|
||||
<exclude name="Spring.Services.pdb"/>
|
||||
<exclude name="Spring.Services.xml"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
</if>
|
||||
|
||||
<!-- build Spring.Services.Tests -->
|
||||
<csc target="library" define="${current.build.defines.csc}"
|
||||
warnaserror="true"
|
||||
debug="${current.build.debug}"
|
||||
output="${current.bin.dir}/${project::get-name()}.dll"
|
||||
doc="${current.bin.dir}/${project::get-name()}.xml">
|
||||
warnaserror="true"
|
||||
debug="${current.build.debug}"
|
||||
output="${current.bin.dir}/${project::get-name()}.dll"
|
||||
doc="${current.bin.dir}/${project::get-name()}.xml">
|
||||
<nowarn>
|
||||
<warning number="${nowarn.numbers.test}" />
|
||||
</nowarn>
|
||||
@@ -43,7 +43,7 @@
|
||||
<include name="*.dll" />
|
||||
<include if="${net-3.0.installed and net-3.0}" name="${net-3.0.ReferenceInstallPath}\System.ServiceModel.dll" />-->
|
||||
<exclude name="${project::get-name()}.dll" />
|
||||
<exclude name="CloverRuntime.dll" />
|
||||
<exclude name="CloverRuntime.dll" />
|
||||
</references>
|
||||
</csc>
|
||||
<copy todir="${current.bin.dir}">
|
||||
@@ -56,6 +56,7 @@
|
||||
<copy todir="${current.bin.dir}">
|
||||
<fileset basedir="${project::get-base-directory()}">
|
||||
<include name="**/*.config" />
|
||||
<include name="**/*.xml" />
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy file="${project::get-base-directory()}/${project::get-name()}.dll.config"
|
||||
@@ -66,7 +67,7 @@
|
||||
<nunit2outproc>
|
||||
<formatter type="Plain" />
|
||||
<formatter type="Xml" usefile="true" extension=".xml"
|
||||
outputdir="${current.bin.dir}/results" />
|
||||
outputdir="${current.bin.dir}/results" />
|
||||
<test assemblyname="${current.bin.dir}/${project::get-name()}.dll" />
|
||||
</nunit2outproc>
|
||||
</target>
|
||||
|
||||
Reference in New Issue
Block a user