sprnet-1047, sprnet-1027, sprnet-1046, sprnet-1048

This commit is contained in:
eeichinger
2008-10-05 20:53:22 +00:00
parent eb9be5a0f0
commit 83098fe045
46 changed files with 2844 additions and 2395 deletions

View File

@@ -1,4 +1,4 @@
Changes (1.1.2 to 1.2 M1)
Changes (1.1.2 to 1.2 RC1)
Spring.Core
-----------
@@ -21,4 +21,14 @@ Spring.Data
Spring.Services
---------------
1. Removed WebServiceProxyFactory.ClientProtocolType property (obsolete)
2. WebServiceExporter generates WebServiceBinding attribute with WSI basic profile 1.1 by default.
Spring.Web
----------
1. Moved Spring.Web.Support.ISharedStateAware to Spring.Objects.ISharedStateAware
2. Dropped IProcess support
3. IHttpHandler instance dependencies won't be injected until PreRequestHandlerExecute stage (to support "session"-scoped deps)

View File

@@ -1,393 +1,391 @@
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
#endregion
namespace Spring.Collections
{
/// <summary>
/// <see cref="Spring.Collections.DictionarySet"/> is an
/// <see langword="abstract"/> class that supports the creation of new
/// <see cref="Spring.Collections.ISet"/> types where the underlying data
/// store is an <see cref="System.Collections.IDictionary"/> instance.
/// </summary>
/// <remarks>
/// <p>
/// You can use any object that implements the
/// <see cref="System.Collections.IDictionary"/> interface to hold set
/// data. You can define your own, or you can use one of the objects
/// provided in the framework. The type of
/// <see cref="System.Collections.IDictionary"/> you
/// choose will affect both the performance and the behavior of the
/// <see cref="Spring.Collections.ISet"/> using it.
/// </p>
/// <p>
/// This object overrides the <see cref="System.Object.Equals(object)"/> method,
/// but not the <see cref="System.Object.GetHashCode"/> method, because
/// the <see cref="Spring.Collections.DictionarySet"/> class is mutable.
/// Therefore, it is not safe to use as a key value in a dictionary.
/// </p>
/// <p>
/// To make a <see cref="Spring.Collections.ISet"/> typed based on your
/// own <see cref="System.Collections.IDictionary"/>, simply derive a new
/// class with a constructor that takes no parameters. Some
/// <see cref="Spring.Collections.ISet"/> implmentations cannot be defined
/// with a default constructor. If this is the case for your class, you
/// will need to override <b>clone</b> as well.
/// </p>
/// <p>
/// It is also standard practice that at least one of your constructors
/// takes an <see cref="System.Collections.ICollection"/> or an
/// <see cref="Spring.Collections.ISet"/> as an argument.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Collections.ISet"/>
[Serializable]
public abstract class DictionarySet : Set
{
private IDictionary _internalDictionary;
private static readonly object PlaceholderObject = new object();
private static readonly object NullPlaceHolderKey = new object();
/// <summary>
/// Provides the storage for elements in the
/// <see cref="Spring.Collections.ISet"/>, stored as the key-set
/// of the <see cref="System.Collections.IDictionary"/> object.
/// </summary>
/// <remarks>
/// <p>
/// Set this object in the constructor if you create your own
/// <see cref="Spring.Collections.ISet"/> class.
/// </p>
/// </remarks>
protected IDictionary InternalDictionary
{
get { return _internalDictionary; }
set { _internalDictionary = value; }
}
/// <summary>
/// The placeholder object used as the value for the
/// <see cref="System.Collections.IDictionary"/> instance.
/// </summary>
/// <remarks>
/// There is a single instance of this object globally, used for all
/// <see cref="Spring.Collections.ISet"/>s.
/// </remarks>
protected static object Placeholder
{
get { return PlaceholderObject; }
}
/// <summary>
/// Adds the specified element to this set if it is not already present.
/// </summary>
/// <param name="element">The object to add to the set.</param>
/// <returns>
/// <see langword="true"/> is the object was added,
/// <see langword="true"/> if the object was already present.
/// </returns>
public override bool Add(object element)
{
element = MaskNull(element);
if (InternalDictionary[element] != null)
{
return false;
}
else
{
//The object we are adding is just a placeholder. The thing we are
//really concerned with is 'o', the key.
InternalDictionary.Add(element, PlaceholderObject);
return true;
}
}
/// <summary>
/// Adds all the elements in the specified collection to the set if
/// they are not already present.
/// </summary>
/// <param name="collection">A collection of objects to add to the set.</param>
/// <returns>
/// <see langword="true"/> is the set changed as a result of this
/// operation.
/// </returns>
public override bool AddAll(ICollection collection)
{
bool changed = false;
foreach (object o in collection)
{
changed |= this.Add(o);
}
return changed;
}
/// <summary>
/// Removes all objects from this set.
/// </summary>
public override void Clear()
{
InternalDictionary.Clear();
}
/// <summary>
/// Returns <see langword="true"/> if this set contains the specified
/// element.
/// </summary>
/// <param name="element">The element to look for.</param>
/// <returns>
/// <see langword="true"/> if this set contains the specified element.
/// </returns>
public override bool Contains(object element)
{
element = MaskNull(element);
return InternalDictionary[element] != null;
}
/// <summary>
/// Returns <see langword="true"/> if the set contains all the
/// elements in the specified collection.
/// </summary>
/// <param name="collection">A collection of objects.</param>
/// <returns>
/// <see langword="true"/> if the set contains all the elements in the
/// specified collection; also <see langword="false"/> if the
/// supplied <paramref name="collection"/> is <see langword="null"/>.
/// </returns>
public override bool ContainsAll(ICollection collection)
{
if(collection == null)
{
return false;
}
foreach (object o in collection)
{
if (!this.Contains(MaskNull(o)))
{
return false;
}
}
return true;
}
/// <summary>
/// Returns <see langword="true"/> if this set contains no elements.
/// </summary>
public override bool IsEmpty
{
get { return InternalDictionary.Count == 0; }
}
/// <summary>
/// Removes the specified element from the set.
/// </summary>
/// <param name="element">The element to be removed.</param>
/// <returns>
/// <see langword="true"/> if the set contained the specified element.
/// </returns>
public override bool Remove(object element)
{
element = MaskNull(element);
bool contained = this.Contains(element);
if (contained)
{
InternalDictionary.Remove(element);
}
return contained;
}
/// <summary>
/// Remove all the specified elements from this set, if they exist in
/// this set.
/// </summary>
/// <param name="collection">A collection of elements to remove.</param>
/// <returns>
/// <see langword="true"/> if the set was modified as a result of this
/// operation.
/// </returns>
public override bool RemoveAll(ICollection collection)
{
bool changed = false;
foreach (object o in collection)
{
changed |= this.Remove(o);
}
return changed;
}
/// <summary>
/// Retains only the elements in this set that are contained in the
/// specified collection.
/// </summary>
/// <param name="collection">
/// The collection that defines the set of elements to be retained.
/// </param>
/// <returns>
/// <see langword="true"/> if this set changed as a result of this
/// operation.
/// </returns>
public override bool RetainAll(ICollection collection)
{
//Put data from C into a set so we can use the Contains() method.
Set cSet = new HybridSet(collection);
//We are going to build a set of elements to remove.
Set removeSet = new HybridSet();
foreach (object o in this)
{
//If C does not contain O, then we need to remove O from our
//set. We can't do this while iterating through our set, so
//we put it into RemoveSet for later.
if (!cSet.Contains(o))
{
removeSet.Add(o);
}
}
return this.RemoveAll(removeSet);
}
/// <summary>
/// Copies the elements in the <see cref="Spring.Collections.ISet"/> to
/// an array.
/// </summary>
/// <remarks>
/// <p>
/// The type of array needs to be compatible with the objects in the
/// <see cref="Spring.Collections.ISet"/>, obviously.
/// </p>
/// </remarks>
/// <param name="array">
/// An array that will be the target of the copy operation.
/// </param>
/// <param name="index">
/// The zero-based index where copying will start.
/// </param>
public override void CopyTo(Array array, int index)
{
int i = index;
foreach (object o in this)
{
array.SetValue(UnmaskNull(o), i++);
}
}
/// <summary>
/// The number of elements currently contained in this collection.
/// </summary>
public override int Count
{
get { return InternalDictionary.Count; }
}
/// <summary>
/// Returns <see langword="true"/> if the
/// <see cref="Spring.Collections.ISet"/> is synchronized across
/// threads.
/// </summary>
/// <seealso cref="Spring.Collections.Set.IsSynchronized"/>
public override bool IsSynchronized
{
get { return false; }
}
/// <summary>
/// An object that can be used to synchronize this collection to make
/// it thread-safe.
/// </summary>
/// <value>
/// An object that can be used to synchronize this collection to make
/// it thread-safe.
/// </value>
/// <seealso cref="Spring.Collections.Set.SyncRoot"/>
public override object SyncRoot
{
get { return InternalDictionary.SyncRoot; }
}
/// <summary>
/// Gets an enumerator for the elements in the
/// <see cref="Spring.Collections.ISet"/>.
/// </summary>
/// <returns>
/// An <see cref="System.Collections.IEnumerator"/> over the elements
/// in the <see cref="Spring.Collections.ISet"/>.
/// </returns>
public override IEnumerator GetEnumerator()
{
return new DictionarySetEnumerator(InternalDictionary.Keys.GetEnumerator());
}
private static object MaskNull(object key)
{
return key == null ? NullPlaceHolderKey : key;
}
private static object UnmaskNull(object key)
{
return key == NullPlaceHolderKey ? null : key;
}
#region Inner Class : DictionarySetEnumerator
private sealed class DictionarySetEnumerator : IEnumerator
{
#region Constructor (s) / Destructor
public DictionarySetEnumerator(IEnumerator enumerator)
{
_enumerator = enumerator;
}
#endregion
#region IEnumerator Members
public void Reset()
{
_enumerator.Reset();
}
public object Current
{
get { return UnmaskNull(_enumerator.Current); }
}
public bool MoveNext()
{
return _enumerator.MoveNext();
}
#endregion
private IEnumerator _enumerator;
}
#endregion
}
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
#endregion
namespace Spring.Collections
{
/// <summary>
/// <see cref="Spring.Collections.DictionarySet"/> is an
/// <see langword="abstract"/> class that supports the creation of new
/// <see cref="Spring.Collections.ISet"/> types where the underlying data
/// store is an <see cref="System.Collections.IDictionary"/> instance.
/// </summary>
/// <remarks>
/// <p>
/// You can use any object that implements the
/// <see cref="System.Collections.IDictionary"/> interface to hold set
/// data. You can define your own, or you can use one of the objects
/// provided in the framework. The type of
/// <see cref="System.Collections.IDictionary"/> you
/// choose will affect both the performance and the behavior of the
/// <see cref="Spring.Collections.ISet"/> using it.
/// </p>
/// <p>
/// This object overrides the <see cref="System.Object.Equals(object)"/> method,
/// but not the <see cref="System.Object.GetHashCode"/> method, because
/// the <see cref="Spring.Collections.DictionarySet"/> class is mutable.
/// Therefore, it is not safe to use as a key value in a dictionary.
/// </p>
/// <p>
/// To make a <see cref="Spring.Collections.ISet"/> typed based on your
/// own <see cref="System.Collections.IDictionary"/>, simply derive a new
/// class with a constructor that takes no parameters. Some
/// <see cref="Spring.Collections.ISet"/> implmentations cannot be defined
/// with a default constructor. If this is the case for your class, you
/// will need to override <b>clone</b> as well.
/// </p>
/// <p>
/// It is also standard practice that at least one of your constructors
/// takes an <see cref="System.Collections.ICollection"/> or an
/// <see cref="Spring.Collections.ISet"/> as an argument.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Collections.ISet"/>
[Serializable]
public abstract class DictionarySet : Set
{
private IDictionary _internalDictionary;
private static readonly object PlaceholderObject = new object();
private static readonly object NullPlaceHolderKey = new object();
/// <summary>
/// Provides the storage for elements in the
/// <see cref="Spring.Collections.ISet"/>, stored as the key-set
/// of the <see cref="System.Collections.IDictionary"/> object.
/// </summary>
/// <remarks>
/// <p>
/// Set this object in the constructor if you create your own
/// <see cref="Spring.Collections.ISet"/> class.
/// </p>
/// </remarks>
protected IDictionary InternalDictionary
{
get { return _internalDictionary; }
set { _internalDictionary = value; }
}
/// <summary>
/// The placeholder object used as the value for the
/// <see cref="System.Collections.IDictionary"/> instance.
/// </summary>
/// <remarks>
/// There is a single instance of this object globally, used for all
/// <see cref="Spring.Collections.ISet"/>s.
/// </remarks>
protected static object Placeholder
{
get { return PlaceholderObject; }
}
/// <summary>
/// Adds the specified element to this set if it is not already present.
/// </summary>
/// <param name="element">The object to add to the set.</param>
/// <returns>
/// <see langword="true"/> is the object was added,
/// <see langword="false"/> if the object was already present.
/// </returns>
public override bool Add(object element)
{
element = MaskNull(element);
if (InternalDictionary[element] != null)
{
return false;
}
//The object we are adding is just a placeholder. The thing we are
//really concerned with is 'o', the key.
InternalDictionary.Add(element, PlaceholderObject);
return true;
}
/// <summary>
/// Adds all the elements in the specified collection to the set if
/// they are not already present.
/// </summary>
/// <param name="collection">A collection of objects to add to the set.</param>
/// <returns>
/// <see langword="true"/> is the set changed as a result of this
/// operation.
/// </returns>
public override bool AddAll(ICollection collection)
{
bool changed = false;
foreach (object o in collection)
{
changed |= this.Add(o);
}
return changed;
}
/// <summary>
/// Removes all objects from this set.
/// </summary>
public override void Clear()
{
InternalDictionary.Clear();
}
/// <summary>
/// Returns <see langword="true"/> if this set contains the specified
/// element.
/// </summary>
/// <param name="element">The element to look for.</param>
/// <returns>
/// <see langword="true"/> if this set contains the specified element.
/// </returns>
public override bool Contains(object element)
{
element = MaskNull(element);
return InternalDictionary[element] != null;
}
/// <summary>
/// Returns <see langword="true"/> if the set contains all the
/// elements in the specified collection.
/// </summary>
/// <param name="collection">A collection of objects.</param>
/// <returns>
/// <see langword="true"/> if the set contains all the elements in the
/// specified collection; also <see langword="false"/> if the
/// supplied <paramref name="collection"/> is <see langword="null"/>.
/// </returns>
public override bool ContainsAll(ICollection collection)
{
if (collection == null)
{
return false;
}
foreach (object o in collection)
{
if (!this.Contains(MaskNull(o)))
{
return false;
}
}
return true;
}
/// <summary>
/// Returns <see langword="true"/> if this set contains no elements.
/// </summary>
public override bool IsEmpty
{
get { return InternalDictionary.Count == 0; }
}
/// <summary>
/// Removes the specified element from the set.
/// </summary>
/// <param name="element">The element to be removed.</param>
/// <returns>
/// <see langword="true"/> if the set contained the specified element.
/// </returns>
public override bool Remove(object element)
{
element = MaskNull(element);
bool contained = this.Contains(element);
if (contained)
{
InternalDictionary.Remove(element);
}
return contained;
}
/// <summary>
/// Remove all the specified elements from this set, if they exist in
/// this set.
/// </summary>
/// <param name="collection">A collection of elements to remove.</param>
/// <returns>
/// <see langword="true"/> if the set was modified as a result of this
/// operation.
/// </returns>
public override bool RemoveAll(ICollection collection)
{
bool changed = false;
foreach (object o in collection)
{
changed |= this.Remove(o);
}
return changed;
}
/// <summary>
/// Retains only the elements in this set that are contained in the
/// specified collection.
/// </summary>
/// <param name="collection">
/// The collection that defines the set of elements to be retained.
/// </param>
/// <returns>
/// <see langword="true"/> if this set changed as a result of this
/// operation.
/// </returns>
public override bool RetainAll(ICollection collection)
{
//Put data from C into a set so we can use the Contains() method.
Set cSet = new HybridSet(collection);
//We are going to build a set of elements to remove.
Set removeSet = new HybridSet();
foreach (object o in this)
{
//If C does not contain O, then we need to remove O from our
//set. We can't do this while iterating through our set, so
//we put it into RemoveSet for later.
if (!cSet.Contains(o))
{
removeSet.Add(o);
}
}
return this.RemoveAll(removeSet);
}
/// <summary>
/// Copies the elements in the <see cref="Spring.Collections.ISet"/> to
/// an array.
/// </summary>
/// <remarks>
/// <p>
/// The type of array needs to be compatible with the objects in the
/// <see cref="Spring.Collections.ISet"/>, obviously.
/// </p>
/// </remarks>
/// <param name="array">
/// An array that will be the target of the copy operation.
/// </param>
/// <param name="index">
/// The zero-based index where copying will start.
/// </param>
public override void CopyTo(Array array, int index)
{
int i = index;
foreach (object o in this)
{
array.SetValue(UnmaskNull(o), i++);
}
}
/// <summary>
/// The number of elements currently contained in this collection.
/// </summary>
public override int Count
{
get { return InternalDictionary.Count; }
}
/// <summary>
/// Returns <see langword="true"/> if the
/// <see cref="Spring.Collections.ISet"/> is synchronized across
/// threads.
/// </summary>
/// <seealso cref="Spring.Collections.Set.IsSynchronized"/>
public override bool IsSynchronized
{
get { return false; }
}
/// <summary>
/// An object that can be used to synchronize this collection to make
/// it thread-safe.
/// </summary>
/// <value>
/// An object that can be used to synchronize this collection to make
/// it thread-safe.
/// </value>
/// <seealso cref="Spring.Collections.Set.SyncRoot"/>
public override object SyncRoot
{
get { return InternalDictionary.SyncRoot; }
}
/// <summary>
/// Gets an enumerator for the elements in the
/// <see cref="Spring.Collections.ISet"/>.
/// </summary>
/// <returns>
/// An <see cref="System.Collections.IEnumerator"/> over the elements
/// in the <see cref="Spring.Collections.ISet"/>.
/// </returns>
public override IEnumerator GetEnumerator()
{
return new DictionarySetEnumerator(InternalDictionary.Keys.GetEnumerator());
}
private static object MaskNull(object key)
{
return key == null ? NullPlaceHolderKey : key;
}
private static object UnmaskNull(object key)
{
return key == NullPlaceHolderKey ? null : key;
}
#region Inner Class : DictionarySetEnumerator
private sealed class DictionarySetEnumerator : IEnumerator
{
#region Constructor (s) / Destructor
public DictionarySetEnumerator(IEnumerator enumerator)
{
_enumerator = enumerator;
}
#endregion
#region IEnumerator Members
public void Reset()
{
_enumerator.Reset();
}
public object Current
{
get { return UnmaskNull(_enumerator.Current); }
}
public bool MoveNext()
{
return _enumerator.MoveNext();
}
#endregion
private IEnumerator _enumerator;
}
#endregion
}
}

View File

@@ -1,78 +1,88 @@
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
#endregion
namespace Spring.Collections
{
/// <summary>
/// Implements an <see cref="Spring.Collections.ISet"/> based on a sorted
/// tree.
/// </summary>
/// <remarks>
/// <p>
/// This gives good performance for operations on very large data-sets,
/// though not as good - asymptotically - as a
/// <see cref="Spring.Collections.HashedSet"/>. However, iteration occurs
/// in order.
/// </p>
/// <p>
/// Elements that you put into this type of collection must implement
/// <see cref="System.IComparable"/>, and they must actually be comparable.
/// You can't mix <see cref="System.String"/> and
/// <see cref="System.Int32"/> values, for example.
/// </p>
/// <p>
/// This <see cref="Spring.Collections.ISet"/> implementation does
/// <b>not</b> support elements that are <see langword="null"/>.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Collections.ISet"/>
[Serializable]
public class SortedSet : DictionarySet
{
/// <summary>
/// Creates a new set instance based on a sorted tree.
/// </summary>
public SortedSet()
{
InternalDictionary = new SortedList();
}
/// <summary>
/// Creates a new set instance based on a sorted tree and initializes
/// it based on a collection of elements.
/// </summary>
/// <param name="initialValues">
/// A collection of elements that defines the initial set contents.
/// </param>
public SortedSet(ICollection initialValues) : this()
{
this.AddAll(initialValues);
}
}
/* Copyright <20> 2002-2004 by Aidant Systems, Inc., and by Jason Smith. */
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using Spring.Util;
#endregion
namespace Spring.Collections
{
/// <summary>
/// Implements an <see cref="Spring.Collections.ISet"/> based on a sorted
/// tree.
/// </summary>
/// <remarks>
/// <p>
/// This gives good performance for operations on very large data-sets,
/// though not as good - asymptotically - as a
/// <see cref="Spring.Collections.HashedSet"/>. However, iteration occurs
/// in order.
/// </p>
/// <p>
/// Elements that you put into this type of collection must implement
/// <see cref="System.IComparable"/>, and they must actually be comparable.
/// You can't mix <see cref="System.String"/> and
/// <see cref="System.Int32"/> values, for example.
/// </p>
/// <p>
/// This <see cref="Spring.Collections.ISet"/> implementation does
/// <b>not</b> support elements that are <see langword="null"/>.
/// </p>
/// </remarks>
/// <seealso cref="Spring.Collections.ISet"/>
[Serializable]
public class SortedSet : DictionarySet
{
/// <summary>
/// Creates a new set instance based on a sorted tree.
/// </summary>
public SortedSet()
{
InternalDictionary = new SortedList();
}
/// <summary>
/// Creates a new set instance based on a sorted tree using <param name="comparer"/> for ordering.
/// </summary>
public SortedSet(IComparer comparer)
{
AssertUtils.ArgumentNotNull(comparer, "comparer");
InternalDictionary = new SortedList(comparer);
}
/// <summary>
/// Creates a new set instance based on a sorted tree and initializes
/// it based on a collection of elements.
/// </summary>
/// <param name="initialValues">
/// A collection of elements that defines the initial set contents.
/// </param>
public SortedSet(ICollection initialValues) : this()
{
this.AddAll(initialValues);
}
}
}

View File

@@ -33,6 +33,7 @@ using Spring.Objects.Events;
using Spring.Objects.Events.Support;
using Spring.Objects.Factory;
using Spring.Objects.Factory.Config;
using Spring.Objects.Support;
using Spring.Util;
#endregion
@@ -158,7 +159,8 @@ namespace Spring.Context.Support
/// no public constructors.
/// </p>
/// </remarks>
protected AbstractApplicationContext() : this(null, true, null)
protected AbstractApplicationContext()
: this(null, true, null)
{
}
@@ -173,7 +175,8 @@ namespace Spring.Context.Support
/// </p>
/// </remarks>
/// <param name="caseSensitive">Flag specifying whether to make this context case sensitive or not.</param>
protected AbstractApplicationContext(bool caseSensitive) : this(null, caseSensitive, null)
protected AbstractApplicationContext(bool caseSensitive)
: this(null, caseSensitive, null)
{
}
@@ -200,6 +203,7 @@ namespace Spring.Context.Support
_defaultObjectPostProcessors = new ArrayList();
AddDefaultObjectPostProcessor(new ObjectPostProcessorChecker());
AddDefaultObjectPostProcessor(new ApplicationContextAwareProcessor(this));
AddDefaultObjectPostProcessor(new SharedStateAwareProcessor(new ISharedStateFactory[] { new ByTypeSharedStateFactory() }, Int32.MaxValue));
}
/// <summary>
@@ -279,7 +283,7 @@ namespace Spring.Context.Support
/// </returns>
public long StartupDateMilliseconds
{
get { return (StartupDate.Ticks - TicksAtEpoch)/10000; }
get { return (StartupDate.Ticks - TicksAtEpoch) / 10000; }
}
@@ -482,10 +486,10 @@ namespace Spring.Context.Support
private void RegisterObjectPostProcessors(IConfigurableListableObjectFactory objectFactory)
{
RegisterObjectPostProcessorChecker(objectFactory);
RefreshObjectPostProcessorChecker(objectFactory);
IDictionary dict = GetObjectsOfType(typeof(IObjectPostProcessor), true, false);
ArrayList objectProcessors = new ArrayList(dict.Values);
objectProcessors.Sort(new OrderComparator());
// objectProcessors.Sort(new OrderComparator());
foreach (IObjectPostProcessor objectPostProcessor in objectProcessors)
{
ObjectFactory.AddObjectPostProcessor(objectPostProcessor);
@@ -502,19 +506,17 @@ namespace Spring.Context.Support
}
/// <summary>
/// Register an IObjectPostProcessorChecker that logs an info
/// Resets the well-known ObjectPostProcessorChecker that logs an info
/// message when an object is created during IObjectPostProcessor
/// instantiation, i.e. when an object is not eligible for being
/// processed by all IObjectPostProcessors.
/// </summary>
private void RegisterObjectPostProcessorChecker(IConfigurableListableObjectFactory objectFactory)
private void RefreshObjectPostProcessorChecker(IConfigurableListableObjectFactory objectFactory)
{
int objectPostProcessorCount
= ObjectFactory.ObjectPostProcessorCount + 1
+ GetObjectNamesForType(typeof(IObjectPostProcessor), true, false).Length;
// ObjectFactory.AddObjectPostProcessor(
// new ObjectPostProcessorChecker(objectFactory, objectPostProcessorCount));
((ObjectPostProcessorChecker) _defaultObjectPostProcessors[0]).Reset(objectFactory, objectPostProcessorCount);
int registeredObjectPostProcessorCount = GetObjectNamesForType(typeof(IObjectPostProcessor), true, false).Length;
int objectPostProcessorCount = ObjectFactory.ObjectPostProcessorCount + 1
+ registeredObjectPostProcessorCount;
((ObjectPostProcessorChecker)_defaultObjectPostProcessors[0]).Reset(objectFactory, objectPostProcessorCount);
}
/// <summary>
@@ -527,7 +529,7 @@ namespace Spring.Context.Support
object candidateRegistry = GetObject(EventRegistryObjectName);
if (candidateRegistry is IEventRegistry)
{
_eventRegistry = (IEventRegistry) candidateRegistry;
_eventRegistry = (IEventRegistry)candidateRegistry;
#region Instrumentation
@@ -612,7 +614,7 @@ namespace Spring.Context.Support
if (candidateSource is IMessageSource)
{
_messageSource
= (IMessageSource) GetObject(MessageSourceObjectName);
= (IMessageSource)GetObject(MessageSourceObjectName);
// make IMessageSource aware of any parent IMessageSource...
if (ParentContext != null)
@@ -758,7 +760,7 @@ namespace Spring.Context.Support
lock (SyncRoot)
{
_startupDate = DateTime.Now;
RefreshObjectFactory();
@@ -823,7 +825,7 @@ namespace Spring.Context.Support
// index 0 contains the ObjectPostProcessorChecker that is handled separately!
for (int i = 1; i < _defaultObjectPostProcessors.Count; i++)
{
objectFactory.AddObjectPostProcessor((IObjectPostProcessor) this._defaultObjectPostProcessors[i]);
objectFactory.AddObjectPostProcessor((IObjectPostProcessor)this._defaultObjectPostProcessors[i]);
}
}
@@ -1223,6 +1225,45 @@ namespace Spring.Context.Support
return ObjectFactory.GetAliases(name);
}
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
/// <param name="name">The name of the object to return.</param>
/// <param name="requiredType">
/// The <see cref="System.Type"/> the object may match. Can be an interface or
/// superclass of the actual class. For example, if the value is the
/// <see cref="System.Object"/> class, this method will succeed whatever the
/// class of the returned instance.
/// </param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
/// match the argument values by type and call the object's constructor.
/// </param>
/// <returns>The unconfigured(!) instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="IObjectFactory.CreateObject"/>
/// <remarks>
/// This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
/// </remarks>
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return ObjectFactory.CreateObject(name, requiredType, arguments);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -1335,7 +1376,7 @@ namespace Spring.Context.Support
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
public object GetObject(string name, Type requiredType, object[] arguments)
{
return ObjectFactory.GetObject(name, requiredType, arguments);
@@ -1819,9 +1860,9 @@ namespace Spring.Context.Support
}
}
#region IPostProcessor implementation
#region IPostProcessor implementation
private sealed class ObjectPostProcessorChecker : IObjectPostProcessor
private sealed class ObjectPostProcessorChecker : IObjectPostProcessor, IOrdered
{
private int _objectPostProcessorTargetCount;
private IConfigurableListableObjectFactory _objectFactory;
@@ -1859,6 +1900,11 @@ namespace Spring.Context.Support
}
return obj;
}
public int Order
{
get { return Int32.MinValue; }
}
}
#endregion

View File

@@ -39,7 +39,8 @@ namespace Spring.Core
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Aleksandar Seovic (.Net)</author>
/// <author>Aleksandar Seovic (.Net)</author>
[Serializable]
public class OrderComparator : IComparer
{
/// <summary>
@@ -73,8 +74,22 @@ namespace Spring.Core
}
else
{
return 0;
return CompareEqualOrder(o1, o2);
}
}
/// <summary>
/// Handle the case when both objects have equal sort order priority. By default returns 0,
/// but may be overriden for handling special cases.
/// </summary>
/// <param name="o1">The first object to compare.</param>
/// <param name="o2">The second object to compare.</param>
/// <returns>
/// -1 if first object is less then second, 1 if it is greater, or 0 if they are equal.
/// </returns>
protected virtual int CompareEqualOrder(object o1, object o2)
{
return 0;
}
}
}

View File

@@ -1,125 +1,125 @@
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
#endregion
#region License
/*
* Copyright <20> 2002-2005 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
#endregion
using System;
using Spring.Objects.Factory;
namespace Spring.Objects.Factory.Config
{
/// <summary>
/// SPI interface to be implemented by most if not all listable object factories.
/// </summary>
/// <remarks>
/// <p>
/// Allows for framework-internal plug'n'play, e.g. in
/// <see cref="Spring.Context.Support.AbstractApplicationContext"/>.
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public interface IConfigurableListableObjectFactory
: IListableObjectFactory,
IConfigurableObjectFactory,
IAutowireCapableObjectFactory
{
/// <summary>
/// Return the registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
/// given object, allowing access to its property values and constructor
/// argument values.
/// </summary>
/// <param name="name">The name of the object.</param>
/// <returns>
/// The registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
/// </returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors.
/// </exception>
IObjectDefinition GetObjectDefinition(string name);
/// <summary>
/// Return the registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
/// given object, allowing access to its property values and constructor
/// argument values.
/// </summary>
/// <param name="name">The name of the object.</param>
/// <param name="includeAncestors">Whether to search parent object factories.</param>
/// <returns>
/// The registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
/// </returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors.
/// </exception>
IObjectDefinition GetObjectDefinition(string name, bool includeAncestors);
/// <summary>
/// Injects dependencies into the supplied <paramref name="target"/> instance
/// using the supplied <paramref name="definition"/>.
/// </summary>
/// <param name="target">
/// The object instance that is to be so configured.
/// </param>
/// <param name="name">
/// The name of the object definition expressing the dependencies that are to
/// be injected into the supplied <parameref name="target"/> instance.
/// </param>
/// <param name="definition">
/// An object definition that should be used to configure object.
/// </param>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
object ConfigureObject(object target, string name, IObjectDefinition definition);
/// <summary>
/// Ensure that all non-lazy-init singletons are instantiated, also
/// considering <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <remarks>
/// <p>
/// Typically invoked at the end of factory setup, if desired.
/// </p>
/// <p>
/// As this is a startup method, it should destroy already created singletons if
/// it fails, to avoid dangling resources. In other words, after invocation
/// of that method, either all or no singletons at all should be
/// instantiated.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// If one of the singleton objects could not be created.
/// </exception>
namespace Spring.Objects.Factory.Config
{
/// <summary>
/// SPI interface to be implemented by most if not all listable object factories.
/// </summary>
/// <remarks>
/// <p>
/// Allows for framework-internal plug'n'play, e.g. in
/// <see cref="Spring.Context.Support.AbstractApplicationContext"/>.
/// </p>
/// </remarks>
/// <author>Juergen Hoeller</author>
/// <author>Rick Evans (.NET)</author>
public interface IConfigurableListableObjectFactory
: IListableObjectFactory,
IConfigurableObjectFactory,
IAutowireCapableObjectFactory
{
/// <summary>
/// Return the registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
/// given object, allowing access to its property values and constructor
/// argument values.
/// </summary>
/// <param name="name">The name of the object.</param>
/// <returns>
/// The registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
/// </returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors.
/// </exception>
IObjectDefinition GetObjectDefinition(string name);
/// <summary>
/// Return the registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/> for the
/// given object, allowing access to its property values and constructor
/// argument values.
/// </summary>
/// <param name="name">The name of the object.</param>
/// <param name="includeAncestors">Whether to search parent object factories.</param>
/// <returns>
/// The registered
/// <see cref="Spring.Objects.Factory.Config.IObjectDefinition"/>.
/// </returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there is no object with the given name.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// In the case of errors.
/// </exception>
IObjectDefinition GetObjectDefinition(string name, bool includeAncestors);
/// <summary>
/// Injects dependencies into the supplied <paramref name="target"/> instance
/// using the supplied <paramref name="definition"/>.
/// </summary>
/// <param name="target">
/// The object instance that is to be so configured.
/// </param>
/// <param name="name">
/// The name of the object definition expressing the dependencies that are to
/// be injected into the supplied <parameref name="target"/> instance.
/// </param>
/// <param name="definition">
/// An object definition that should be used to configure object.
/// </param>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.ConfigureObject(object, string)"/>
object ConfigureObject(object target, string name, IObjectDefinition definition);
/// <summary>
/// Ensure that all non-lazy-init singletons are instantiated, also
/// considering <see cref="Spring.Objects.Factory.IFactoryObject"/>s.
/// </summary>
/// <remarks>
/// <p>
/// Typically invoked at the end of factory setup, if desired.
/// </p>
/// <p>
/// As this is a startup method, it should destroy already created singletons if
/// it fails, to avoid dangling resources. In other words, after invocation
/// of that method, either all or no singletons at all should be
/// instantiated.
/// </p>
/// </remarks>
/// <exception cref="Spring.Objects.ObjectsException">
/// If one of the singleton objects could not be created.
/// </exception>
void PreInstantiateSingletons ();
/// <summary>
@@ -157,5 +157,5 @@ namespace Spring.Objects.Factory.Config
/// </returns>
/// <exception cref="NoSuchObjectDefinitionException">if there is no object with the given name.</exception>
bool IsAutowireCandidate(string objectName, DependencyDescriptor descriptor);
}
}
}
}

View File

@@ -0,0 +1,153 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Configuration;
using System.Text;
using System.Threading;
using Common.Logging;
using Spring.Core;
using Spring.Util;
#endregion
namespace Spring.Objects.Factory.Config
{
/// <summary>
/// Configure all ISharedStateAware objects, delegating concrete handling to the list of <see cref="SharedStateFactories"/>.
/// </summary>
public class SharedStateAwareProcessor : IObjectPostProcessor, IOrdered
{
// holds the logger for this processor instance
private readonly ILog Log = LogManager.GetLogger( typeof( SharedStateAwareProcessor ) );
// holds a list of ISharedStateProvider instances (if any)
private ISharedStateFactory[] _sharedStateFactories = new ISharedStateFactory[0];
// holds prio
private int _order = Int32.MaxValue;
/// <summary>
/// Return the order value of this object, where a higher value means greater in
/// terms of sorting.
/// </summary>
/// <remarks>
/// <p>
/// Normally starting with 0 or 1, with <see cref="System.Int32.MaxValue"/> indicating
/// greatest. Same order values will result in arbitrary positions for the affected
/// objects.
/// </p>
/// <p>
/// Higher value can be interpreted as lower priority, consequently the first object
/// has highest priority.
/// </p>
/// </remarks>
/// <returns>The order value.</returns>
public int Order
{
get { return _order; }
set { _order = value; }
}
/// <summary>
/// Get/Set the (already ordererd!) list of <see cref="ISharedStateFactory"/> instances.
/// </summary>
/// <remarks>
/// If this list is not set, the containing object factory will automatically
/// be scanned for <see cref="ISharedStateFactory"/> instances.
/// </remarks>
public ISharedStateFactory[] SharedStateFactories
{
get { return _sharedStateFactories; }
set
{
AssertUtils.ArgumentHasElements( value, "SharedStateFactories" );
_sharedStateFactories = value;
}
}
/// <summary>
/// Creates a new empty instance.
/// </summary>
public SharedStateAwareProcessor()
{ }
/// <summary>
/// Creates a new preconfigured instance.
/// </summary>
/// <param name="sharedStateFactories"></param>
/// <param name="order">priority value affecting order of invocation of this processor. See <see cref="IOrdered"/> interface.</param>
public SharedStateAwareProcessor( ISharedStateFactory[] sharedStateFactories, int order )
{
SharedStateFactories = sharedStateFactories;
}
/// <summary>
/// Iterates over configured list of <see cref="ISharedStateFactory"/>s until
/// the first provider is found that<br/>
/// a) true == provider.CanProvideState( instance, name )<br/>
/// b) null != provider.GetSharedState( instance, name )<br/>
/// </summary>
public object PostProcessBeforeInitialization( object instance, string name )
{
if (SharedStateFactories.Length == 0)
{
return instance;
}
ISharedStateAware ssa = instance as ISharedStateAware;
if (ssa != null && ssa.SharedState == null)
{
// probe for first factory willing to serve shared state
foreach (ISharedStateFactory ssf in _sharedStateFactories)
{
if (ssf.CanProvideState( ssa, name ))
{
IDictionary sharedState = ssf.GetSharedStateFor( ssa, name );
if (sharedState != null)
{
ssa.SharedState = sharedState;
break;
}
}
}
}
return instance;
}
/// <summary>
/// A NoOp for this processor
/// </summary>
/// <param name="instance">
/// The new object instance.
/// </param>
/// <param name="name">
/// The name of the object.
/// </param>
/// <returns>
/// the original <paramref name="instance"/>.
/// </returns>
public object PostProcessAfterInitialization( object instance, string name )
{
return instance;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -729,44 +729,44 @@ namespace Spring.Objects.Factory.Support
ignoredDependencyInterfaces.Add(type);
}
/// <summary>
/// Create an object instance for the given object definition.
/// </summary>
/// <param name="name">The name of the object.</param>
/// <param name="definition">
/// The object definition for the object that is to be instantiated.
/// </param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a static factory method. It is invalid to use a non-<see langword="null"/> arguments value
/// in any other case.
/// </param>
/// <returns>
/// A new instance of the object.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
/// <remarks>
/// <p>
/// Delegates to the
/// <see cref="Spring.Objects.Factory.Support.AbstractAutowireCapableObjectFactory.CreateObject (string,RootObjectDefinition,object[],bool)"/>
/// method version with the <c>allowEagerCaching</c> parameter set to <b>true</b>.
/// </p>
/// <p>
/// The object definition will already have been merged with the parent
/// definition in case of a child definition.
/// </p>
/// <p>
/// All the other methods in this class invoke this method, although objects
/// may be cached after being instantiated by this method. All object
/// instantiation within this class is performed by this method.
/// </p>
/// </remarks>
protected internal override object CreateObject(string name, RootObjectDefinition definition, object[] arguments)
{
return CreateObject(name, definition, arguments, true);
}
// /// <summary>
// /// Create an object instance for the given object definition.
// /// </summary>
// /// <param name="name">The name of the object.</param>
// /// <param name="definition">
// /// The object definition for the object that is to be instantiated.
// /// </param>
// /// <param name="arguments">
// /// The arguments to use if creating a prototype using explicit arguments to
// /// a static factory method. It is invalid to use a non-<see langword="null"/> arguments value
// /// in any other case.
// /// </param>
// /// <returns>
// /// A new instance of the object.
// /// </returns>
// /// <exception cref="Spring.Objects.ObjectsException">
// /// In case of errors.
// /// </exception>
// /// <remarks>
// /// <p>
// /// Delegates to the
// /// <see cref="Spring.Objects.Factory.Support.AbstractAutowireCapableObjectFactory.CreateObject (string,RootObjectDefinition,object[],bool)"/>
// /// method version with the <c>allowEagerCaching</c> parameter set to <b>true</b>.
// /// </p>
// /// <p>
// /// The object definition will already have been merged with the parent
// /// definition in case of a child definition.
// /// </p>
// /// <p>
// /// All the other methods in this class invoke this method, although objects
// /// may be cached after being instantiated by this method. All object
// /// instantiation within this class is performed by this method.
// /// </p>
// /// </remarks>
// protected internal override object CreateObject(string name, RootObjectDefinition definition, object[] arguments)
// {
// return CreateObject(name, definition, arguments, true, false);
// }
/// <summary>
/// Create an object instance for the given object definition.
@@ -784,6 +784,9 @@ namespace Spring.Objects.Factory.Support
/// Whether eager caching of singletons is allowed... typically true for
/// singlton objects, but never true for inner object definitions.
/// </param>
/// <param name="suppressConfigure">
/// Suppress injecting dependencies yet.
/// </param>
/// <returns>
/// A new instance of the object.
/// </returns>
@@ -801,7 +804,7 @@ namespace Spring.Objects.Factory.Support
/// instantiation within this class is performed by this method.
/// </p>
/// </remarks>
protected internal override object CreateObject(string name, RootObjectDefinition definition, object[] arguments, bool allowEagerCaching)
protected internal override object InstantiateObject(string name, RootObjectDefinition definition, object[] arguments, bool allowEagerCaching, bool suppressConfigure)
{
// guarantee the initialization of objects that the current one depends on..
if (definition.DependsOn != null && definition.DependsOn.Length > 0)
@@ -875,7 +878,10 @@ namespace Spring.Objects.Factory.Support
eagerlyCached = true;
}
instance = ConfigureObject(name, definition, instanceWrapper);
if (!suppressConfigure)
{
instance = ConfigureObject(name, definition, instanceWrapper);
}
}
catch (ObjectCreationException)
{
@@ -1634,7 +1640,7 @@ namespace Spring.Objects.Factory.Support
object result;
try
{
instance = CreateObject(innerObjectName, mod, ObjectUtils.EmptyObjects, false);
instance = InstantiateObject(innerObjectName, mod, ObjectUtils.EmptyObjects, false, false);
result = GetObjectForInstance(innerObjectName, instance);
}
catch (ObjectsException ex)

View File

@@ -54,6 +54,32 @@ namespace Spring.Objects.Factory.Support
[Serializable]
public abstract class AbstractObjectFactory : IConfigurableObjectFactory
{
/// <summary>
/// Makes a distinction between sort order and object identity.
/// This is important when used with <see cref="ISet"/>, since most
/// implementations assume Order == Identity
/// </summary>
[Serializable]
private class ObjectOrderComparator : OrderComparator
{
/// <summary>
/// Handle the case when both objects have equal sort order priority. By default returns 0,
/// but may be overriden for handling special cases.
/// </summary>
/// <param name="o1">The first object to compare.</param>
/// <param name="o2">The second object to compare.</param>
/// <returns>
/// -1 if first object is less then second, 1 if it is greater, or 0 if they are equal.
/// </returns>
protected override int CompareEqualOrder(object o1, object o2)
{
if (ReferenceEquals(o1,o2)) return 0;
if (o1 == null) return 1;
if (o2 == null) return -1;
return o1.GetHashCode().CompareTo(o2.GetHashCode());
}
}
/// <summary>
/// Marker object to be temporarily registered in the singleton cache,
/// while instantiating an object (in order to be able to detect circular references).
@@ -160,11 +186,11 @@ namespace Spring.Objects.Factory.Support
}
/// <summary>
/// Gets the <see cref="System.Collections.IList"/> of
/// Gets the <see cref="ISet"/> of
/// <see cref="Spring.Objects.Factory.Config.IObjectPostProcessor"/>s
/// that will be applied to objects created by this factory.
/// </summary>
public IList ObjectPostProcessors
public ISet ObjectPostProcessors
{
get { return objectPostProcessors; }
}
@@ -203,6 +229,7 @@ namespace Spring.Objects.Factory.Support
#region Methods
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
@@ -235,78 +262,9 @@ namespace Spring.Objects.Factory.Support
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
public object GetObject(string name, Type requiredType, object[] arguments)
{
string objectName = TransformedObjectName(name);
object instance = null;
// eagerly check singleton cache for manually registered singletons...
object sharedInstance = GetSingleton(objectName);
if (sharedInstance != null)
{
#region Instrumentation
if (IsSingletonCurrentlyInCreation(objectName))
{
if (log.IsDebugEnabled)
{
log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
}
else
{
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
}
}
#endregion
instance = GetObjectForInstance(name, sharedInstance);
}
else
{
// check if object definition exists
RootObjectDefinition mergedObjectDefinition = null;
mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
if (mergedObjectDefinition == null)
{
if (ParentObjectFactory != null)
{
return ParentObjectFactory.GetObject(name, requiredType, arguments);
}
throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
}
CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
// return IObjectDefinition instance itself for an abstract object-definition
if (mergedObjectDefinition.IsAbstract)
{
instance = mergedObjectDefinition;
}
else if (mergedObjectDefinition.IsSingleton)
{
// create object instance...
sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
instance = GetObjectForInstance(name, sharedInstance);
}
else
{
// it's a prototype, so create a new instance...
instance = CreateObject(name, mergedObjectDefinition, arguments);
}
}
// check that any required type matches the type of the actual object instance...
if (requiredType != null && !requiredType.IsAssignableFrom(instance.GetType()))
{
throw new ObjectNotOfRequiredTypeException(name, requiredType, instance);
}
return instance;
return GetObjectInternal(name, requiredType, arguments, false);
}
/// <summary>
/// Apply the property values of the object definition with the supplied
/// <paramref name="name"/> to the supplied <paramref name="instance"/>.
@@ -334,37 +292,37 @@ namespace Spring.Objects.Factory.Support
// explicit no-op...
}
/// <summary>
/// Create an object instance for the given object definition.
/// </summary>
/// <remarks>
/// <p>
/// The object definition will already have been merged with the parent
/// definition in case of a child definition.
/// </p>
/// <p>
/// All the other methods in this class invoke this method, although objects
/// may be cached after being instantiated by this method. All object
/// instantiation within this class is performed by this method.
/// </p>
/// </remarks>
/// <param name="name">The name of the object.</param>
/// <param name="definition">
/// The object definition for the object that is to be instantiated.
/// </param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>,
/// then match the argument values by type and call the object's constructor.
/// </param>
/// <returns>
/// A new instance of the object.
/// </returns>
/// <exception cref="Spring.Objects.ObjectsException">
/// In case of errors.
/// </exception>
protected internal abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments);
// /// <summary>
// /// Create an object instance for the given object definition.
// /// </summary>
// /// <remarks>
// /// <p>
// /// The object definition will already have been merged with the parent
// /// definition in case of a child definition.
// /// </p>
// /// <p>
// /// All the other methods in this class invoke this method, although objects
// /// may be cached after being instantiated by this method. All object
// /// instantiation within this class is performed by this method.
// /// </p>
// /// </remarks>
// /// <param name="name">The name of the object.</param>
// /// <param name="definition">
// /// The object definition for the object that is to be instantiated.
// /// </param>
// /// <param name="arguments">
// /// The arguments to use if creating a prototype using explicit arguments to
// /// a <see lang="static"/> factory method. If there is no factory method and the
// /// supplied <paramref name="arguments"/> array is not <see lang="null"/>,
// /// then match the argument values by type and call the object's constructor.
// /// </param>
// /// <returns>
// /// A new instance of the object.
// /// </returns>
// /// <exception cref="Spring.Objects.ObjectsException">
// /// In case of errors.
// /// </exception>
// protected internal abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments);
/// <summary>
@@ -383,6 +341,9 @@ namespace Spring.Objects.Factory.Support
/// Whether eager caching of singletons is allowed... typically true for
/// singlton objects, but never true for inner object definitions.
/// </param>
/// <param name="suppressConfigure">
/// Create instance only - suppress injecting dependencies yet.
/// </param>
/// <returns>
/// A new instance of the object.
/// </returns>
@@ -400,8 +361,8 @@ namespace Spring.Objects.Factory.Support
/// instantiation within this class is performed by this method.
/// </p>
/// </remarks>
protected internal abstract object CreateObject(string name, RootObjectDefinition definition, object[] arguments,
bool allowEagerCaching);
protected internal abstract object InstantiateObject(string name, RootObjectDefinition definition, object[] arguments,
bool allowEagerCaching, bool suppressConfigure);
/// <summary>
/// Destroy the target object.
@@ -1380,6 +1341,7 @@ namespace Spring.Objects.Factory.Support
throw new ObjectNotOfRequiredTypeException(objectName, requiredType, objectType);
}
}
// check validity of the usage of the args parameter; this can
// only be used for prototypes constructed via a factory method...
if (arguments != null && arguments.Length > 0)
@@ -1429,7 +1391,7 @@ namespace Spring.Objects.Factory.Support
/// <summary>
/// ObjectPostProcessors to apply in CreateObject
/// </summary>
private IList objectPostProcessors = new ArrayList();
private ISet objectPostProcessors = new SortedSet(new ObjectOrderComparator());
/// <summary>
/// Indicates whether any IInstantiationAwareBeanPostProcessors have been registered
@@ -1688,13 +1650,34 @@ namespace Spring.Objects.Factory.Support
get { return GetObject(name); }
}
/// <summary>
/// Return an unconfigured(!) instance (possibly shared or independent) of the given object name.
/// </summary>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.CreateObject(string, Type, object[])"/>
/// <remarks>
/// This method will only <b>instantiate</b> the requested object. It does <b>NOT</b> inject any dependencies!
/// </remarks>
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return GetObjectInternal(name, requiredType, arguments, true);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <see cref="Spring.Objects.Factory.IObjectFactory.GetObject(string)"/>.
public object GetObject(string name)
{
return GetObject(name, typeof(object), null);
return GetObjectInternal(name, typeof(object), null, false);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
public object GetObject(string name, Type requiredType)
{
return GetObjectInternal(name, requiredType, null, false);
}
/// <summary>
@@ -1734,33 +1717,147 @@ namespace Spring.Objects.Factory.Support
/// </exception>
public object GetObject(string name, object[] arguments)
{
object instance = null;
string objectName = TransformedObjectName(name);
return GetObjectInternal(name, typeof(object), arguments, false);
// check if object definition exists
RootObjectDefinition mergedObjectDefinition = null;
mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
if (mergedObjectDefinition == null)
{
if (ParentObjectFactory != null)
{
return ParentObjectFactory.GetObject(name, arguments);
}
throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
}
// Override constructor values and configure as a prototype
RootObjectDefinition tmpObjectDefinition = new RootObjectDefinition(mergedObjectDefinition);
tmpObjectDefinition.ConstructorArgumentValues = null;
tmpObjectDefinition.IsSingleton = false;
// create a new instance...
instance = CreateObject(name, tmpObjectDefinition, arguments);
return GetObjectForInstance(name, instance);
// string objectName = TransformedObjectName(name);
// object instance = null;
//
// // check if object definition exists
// RootObjectDefinition mergedObjectDefinition = null;
// mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
// if (mergedObjectDefinition == null)
// {
// if (ParentObjectFactory != null)
// {
// return ParentObjectFactory.GetObject(name, arguments);
// }
// throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
// }
//
// // Override constructor values and configure as a prototype
// RootObjectDefinition tmpObjectDefinition = new RootObjectDefinition(mergedObjectDefinition);
// tmpObjectDefinition.ConstructorArgumentValues = null;
// tmpObjectDefinition.IsSingleton = false;
//
// // create a new instance...
// instance = CreateObject(name, tmpObjectDefinition, arguments);
//
// return GetObjectForInstance(name, instance);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name,
/// optionally injecting dependencies.
/// </summary>
/// <param name="name">The name of the object to return.</param>
/// <param name="requiredType">
/// The <see cref="System.Type"/> the object may match. Can be an interface or
/// superclass of the actual class. For example, if the value is the
/// <see cref="System.Object"/> class, this method will succeed whatever the
/// class of the returned instance.
/// </param>
/// <param name="arguments">
/// The arguments to use if creating a prototype using explicit arguments to
/// a <see lang="static"/> factory method. If there is no factory method and the
/// supplied <paramref name="arguments"/> array is not <see lang="null"/>, then
/// match the argument values by type and call the object's constructor.
/// </param>
/// <param name="suppressConfigure">whether to inject dependencies or not.</param>
/// <returns>The instance of the object.</returns>
/// <exception cref="Spring.Objects.Factory.NoSuchObjectDefinitionException">
/// If there's no such object definition.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If the object could not be created.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectNotOfRequiredTypeException">
/// If the object is not of the required type.
/// </exception>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="name"/> is <see langword="null"/>.
/// </exception>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.CreateObject(string, Type, object[])"/>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type, object[])"/>
protected object GetObjectInternal(string name, Type requiredType, object[] arguments, bool suppressConfigure)
{
string objectName = TransformedObjectName(name);
object instance = null;
// eagerly check singleton cache for manually registered singletons...
object sharedInstance = GetSingleton(objectName);
if (sharedInstance != null)
{
#region Instrumentation
if (IsSingletonCurrentlyInCreation(objectName))
{
if (log.IsDebugEnabled)
{
log.Debug("Returning eagerly cached instance of singleton object '" + objectName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
}
else
{
if (log.IsDebugEnabled)
{
log.Debug(string.Format("Returning cached instance of singleton object '{0}'.", objectName));
}
}
#endregion
instance = GetObjectForInstance(name, sharedInstance);
}
else
{
// check if object definition exists
RootObjectDefinition mergedObjectDefinition = null;
mergedObjectDefinition = GetMergedObjectDefinition(objectName, false);
if (mergedObjectDefinition == null)
{
if (ParentObjectFactory != null)
{
return ParentObjectFactory.GetObject(name, requiredType, arguments);
}
throw new NoSuchObjectDefinitionException(name, "Cannot find definition for object [" + name + "]");
}
if (arguments != null)
{
// Override constructor values and configure as a prototype if arguments are specified
mergedObjectDefinition = new RootObjectDefinition(mergedObjectDefinition);
mergedObjectDefinition.ConstructorArgumentValues = null;
mergedObjectDefinition.IsSingleton = false;
mergedObjectDefinition.ConstructorArgumentValues = null;
}
CheckMergedObjectDefinition(mergedObjectDefinition, objectName, requiredType, arguments);
// return IObjectDefinition instance itself for an abstract object-definition
if (mergedObjectDefinition.IsAbstract)
{
instance = mergedObjectDefinition;
}
else if (mergedObjectDefinition.IsSingleton)
{
// create object instance...
sharedInstance = CreateAndCacheSingletonInstance(objectName, mergedObjectDefinition, arguments);
instance = GetObjectForInstance(name, sharedInstance);
}
else
{
// it's a prototype, so create a new instance...
instance = InstantiateObject(name, mergedObjectDefinition, arguments, true, suppressConfigure);
}
}
// check that any required type matches the type of the actual object instance...
if (requiredType != null && !requiredType.IsAssignableFrom(instance.GetType()))
{
throw new ObjectNotOfRequiredTypeException(name, requiredType, instance);
}
return instance;
}
/// <summary>
/// Creates a singleton instance for the specified object name and definition.
@@ -1797,7 +1894,7 @@ namespace Spring.Objects.Factory.Support
BeforeSingletonCreation(objectName);
try
{
sharedInstance = CreateObject(objectName, objectDefinition, arguments);
sharedInstance = InstantiateObject(objectName, objectDefinition, arguments, true, false);
}
finally
{
@@ -1827,15 +1924,6 @@ namespace Spring.Objects.Factory.Support
singletonsInCreation.Add(name, emptyObject);
}
/// <summary>
/// Return an instance (possibly shared or independent) of the given object name.
/// </summary>
/// <seealso cref="Spring.Objects.Factory.IObjectFactory.GetObject(string, Type)"/>
public object GetObject(string name, Type requiredType)
{
return GetObject(name, requiredType, null);
}
/// <summary>
/// Injects dependencies into the supplied <paramref name="target"/> instance
/// using the named object definition.

View File

@@ -263,7 +263,7 @@ namespace Spring.Objects.Factory.Support
try
{
//SPRNET-986 ObjectUtils.EmptyObjects -> null
instance = objectFactory.CreateObject(actualInnerObjectName, mod, null, false);
instance = objectFactory.InstantiateObject(actualInnerObjectName, mod, null, false, false);
result = objectFactory.GetObjectForInstance(actualInnerObjectName, instance);
}
catch (ObjectsException ex)

View File

@@ -80,6 +80,15 @@ namespace Spring.Objects.Factory.Support
get { return GetObject(name); }
}
/// <summary>
/// This method is not supported by <see cref="StaticListableObjectFactory"/>.
/// </summary>
/// <exception cref="NotSupportedException" />
public object CreateObject(string name, Type requiredType, object[] arguments)
{
throw new NotSupportedException("StaticListableObjectFactory does not support this method.");
}
/// <summary>
/// Return an instance of the given object name.
/// </summary>

View File

@@ -25,19 +25,19 @@ using System.Web;
#endregion
namespace Spring.Web.Support
namespace Spring.Objects
{
/// <summary>
/// This interface should be implemented by <see cref="IHttpHandler"/>s that want to
/// have access to the shared state for the handler.
/// This interface should be implemented by classes that want to
/// have access to the shared state.
/// </summary>
/// <remarks>
/// <p>
/// Shared state is very useful if you have data that needs to be shared by all instances
/// of the same page (or other <see cref="IHttpHandler"/>).
/// of e.g. the same webform (or other <c>IHttpHandler</c>s).
/// </p>
/// <p>
/// For example, <see cref="Spring.Web.UI.Page"/> class implements this interface, which allows
/// For example, <c>Spring.Web.UI.Page</c> class implements this interface, which allows
/// each page derived from it to cache localizalization resources and parsed data binding
/// expressions only once and then reuse the cached values, regardless of how many instances
/// of the page are created.
@@ -47,12 +47,8 @@ namespace Spring.Web.Support
{
/// <summary>
/// Gets or sets the <see cref="IDictionary"/> that should be used
/// to store shared state for the <see cref="IHttpHandler"/>.
/// to store shared state for this instance.
/// </summary>
/// <value>
/// The <see cref="IDictionary"/> that should be used
/// to store shared state for the <see cref="IHttpHandler"/>.
/// </value>
IDictionary SharedState { get; set; }
}
}

View File

@@ -0,0 +1,55 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System.Collections;
#endregion
namespace Spring.Objects
{
/// <summary>
/// Abstracts the state sharing strategy used
/// by <see cref="Spring.Objects.Factory.Config.SharedStateAwareProcessor"/>
/// </summary>
/// <author>Erich Eichinger</author>
public interface ISharedStateFactory
{
/// <summary>
/// Indicate, whether the given instance can be served by this factory
/// </summary>
/// <param name="instance">the instance to serve state</param>
/// <param name="name">the name of the instance</param>
/// <returns>
/// a boolean value indicating, whether state can
/// be served for the given instance or not.
/// </returns>
bool CanProvideState(object instance, string name);
/// <summary>
/// Returns the shared state for the given instance.
/// </summary>
/// <param name="instance">the instance to obtain shared state for.</param>
/// <param name="name">the name of this instance</param>
/// <returns>a dictionary containing shared state for <paramref name="instance"/> or null.</returns>
IDictionary GetSharedStateFor( object instance, string name );
}
}

View File

@@ -0,0 +1,145 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using Spring.Collections;
using Spring.Core;
using Spring.Util;
#endregion
namespace Spring.Objects.Support
{
/// <summary>
/// Convenience base class for <see cref="ISharedStateFactory"/> implementations.
/// </summary>
public abstract class AbstractSharedStateFactory : ISharedStateFactory, IOrdered
{
private bool _caseSensitiveState;
private int _order = Int32.MaxValue;
private readonly IDictionary _sharedStateCache = new Hashtable();
/// <summary>
/// Create shared state dictionaries case-sensitive or case-insensitive?
/// </summary>
public bool CaseSensitiveState
{
get { return _caseSensitiveState; }
set { _caseSensitiveState = value; }
}
/// <summary>
/// Gets a dictionary acc. to the type of <paramref name="instance"/>.
/// If no dictionary is found, create it according to <see cref="CaseSensitiveState"/>
/// </summary>
/// <param name="instance">the instance to obtain shared state for</param>
/// <param name="name">the name of the instance.</param>
/// <returns>
/// A dictionary containing the <paramref name="instance"/>'s state,
/// or null if no state can be served by this provider.
/// </returns>
public IDictionary GetSharedStateFor( object instance, string name )
{
AssertUtils.ArgumentNotNull(instance, "instance");
if (!CanProvideState(instance, name))
{
return null;
}
object key = GetKey(instance, name);
if (key == null)
{
return null;
}
IDictionary sharedState = (IDictionary) _sharedStateCache[key];
if (sharedState == null)
{
lock(_sharedStateCache)
{
sharedState = (IDictionary) _sharedStateCache[key];
if (sharedState == null)
{
sharedState = CreateSharedStateDictionary(key);
_sharedStateCache[key] = sharedState;
}
}
}
return sharedState;
}
/// <summary>
/// A number indicating the priority of this <see cref="AbstractSharedStateFactory"/> (<see cref="IOrdered"/> for more).
/// </summary>
public virtual int Order
{
get { return _order; }
set { _order = value; }
}
/// <summary>
/// Creates a dictionary to hold the shared state identified by <paramref name="key"/>.
/// </summary>
/// <param name="key">a key to create the dictionary for.</param>
/// <returns>a dictionary according to <paramref name="key"/> and <see cref="CaseSensitiveState"/>.</returns>
protected virtual IDictionary CreateSharedStateDictionary(object key)
{
return _caseSensitiveState ? new Hashtable() : new CaseInsensitiveHashtable();
}
/// <summary>
/// Indicate, whether the given instance will be served by this provider
/// </summary>
/// <param name="instance">the instance to serve state</param>
/// <param name="name">the name of the instance</param>
/// <returns>
/// a boolean value indicating, whether state shall
/// be resolved for the given instance or not.
/// </returns>
public virtual bool CanProvideState(object instance, string name)
{
return true;
}
/// <summary>
/// Create the key used for obtaining the state dictionary for <paramref name="instance"/>.
/// </summary>
/// <param name="instance">the instance to create the key for</param>
/// <param name="name">the name of the instance.</param>
/// <returns>
/// the key identifying the state dictionary to be used for <paramref name="instance"/>
/// or null, if this state manager doesn't serve the given instance.
/// </returns>
/// <remarks>
/// <para>
/// Implementations may choose to return null from this method to indicate,
/// that they won't serve state for the given instance.
/// </para>
/// <para>
/// <b>Note:</b>Keys returned by this method are always treated case-sensitive!
/// </para>
/// </remarks>
protected abstract object GetKey(object instance, string name);
}
}

View File

@@ -0,0 +1,104 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
#endregion
namespace Spring.Objects.Support
{
/// <summary>
/// Serves shared state on a by-type basis.
/// </summary>
public class ByTypeSharedStateFactory : AbstractSharedStateFactory
{
private Type[] typeFilter;
/// <summary>
/// Limit object types to be served by this state manager.
/// </summary>
/// <remarks>
/// Only objects assignable to one of the types in this list
/// will be served state by this manager.
/// </remarks>
public Type[] TypeFilter
{
set { typeFilter = value; }
}
/// <summary>
/// Creates a new instance matching all types by default.
/// </summary>
public ByTypeSharedStateFactory()
{}
/// <summary>
/// Creates a new instance matching only specified list of types.
/// </summary>
/// <param name="typeFilter">the list of types to serve.</param>
public ByTypeSharedStateFactory(Type[] typeFilter)
{
this.typeFilter = typeFilter;
}
/// <summary>
/// Indicate, whether the given instance will be served by this provider
/// </summary>
/// <param name="instance">the instance to serve state</param>
/// <param name="name">the name of the instance</param>
/// <returns>
/// a boolean value indicating, whether state shall
/// be resolved for the given instance or not.
/// </returns>
public override bool CanProvideState( object instance, string name )
{
if (instance == null)
return false;
if (typeFilter == null)
return true;
Type instanceType = instance.GetType();
foreach (Type type in typeFilter)
{
if (type.IsAssignableFrom( instanceType ))
return true;
}
return false;
}
/// <summary>
/// Returns the <see cref="Type"/> for the given <paramref name="instance"/>.
/// </summary>
/// <param name="instance">the instance to obtain the key for.</param>
/// <param name="name">the name of the instance (ignored by this provider)</param>
/// <returns>instance.GetType() if it matches the <see cref="TypeFilter"/> list. Null otherwise.</returns>
/// <remarks>
/// This method will only be called if <see cref="CanProvideState"/> returned true previously.
/// </remarks>
protected override object GetKey( object instance, string name )
{
Type key = instance.GetType();
return key;
}
}
}

View File

@@ -554,6 +554,7 @@
<Compile Include="Objects\Factory\Config\ObjectDefinitionHolder.cs" />
<Compile Include="Objects\Factory\Config\ObjectDefinitionVisitor.cs" />
<Compile Include="Objects\Factory\Config\ResourceHandlerConfigurer.cs" />
<Compile Include="Objects\Factory\Config\SharedStateAwareProcessor.cs" />
<Compile Include="Objects\Factory\Config\SmartInstantiationAwareObjectPostProcessor.cs" />
<Compile Include="Objects\Factory\Config\TypeAliasConfigurer.cs" />
<Compile Include="Objects\Factory\Config\PropertyFileVariableSource.cs" />
@@ -587,6 +588,8 @@
<Compile Include="Objects\Factory\Xml\XmlObjectDefinitionStoreException.cs" />
<Compile Include="Objects\Factory\Xml\XmlReaderContext.cs" />
<Compile Include="Objects\FatalObjectException.cs" />
<Compile Include="Objects\ISharedStateAware.cs" />
<Compile Include="Objects\ISharedStateFactory.cs" />
<Compile Include="Objects\MutablePropertyValues.cs" />
<Compile Include="Objects\ObjectWrapper.cs" />
<Compile Include="Objects\Events\IEventRegistry.cs">
@@ -888,6 +891,7 @@
<Compile Include="Objects\Support\AbstractEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Support\AbstractSharedStateFactory.cs" />
<Compile Include="Objects\Support\AbstractWiringEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
@@ -897,6 +901,7 @@
<Compile Include="Objects\Support\AutoWiringEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Support\ByTypeSharedStateFactory.cs" />
<Compile Include="Objects\Support\InstanceEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -570,6 +570,7 @@
<Compile Include="Objects\Factory\Config\ObjectDefinitionHolder.cs" />
<Compile Include="Objects\Factory\Config\ObjectDefinitionVisitor.cs" />
<Compile Include="Objects\Factory\Config\ResourceHandlerConfigurer.cs" />
<Compile Include="Objects\Factory\Config\SharedStateAwareProcessor.cs" />
<Compile Include="Objects\Factory\Config\SmartInstantiationAwareObjectPostProcessor.cs" />
<Compile Include="Objects\Factory\Config\TypeAliasConfigurer.cs" />
<Compile Include="Objects\Factory\Config\PropertyFileVariableSource.cs" />
@@ -603,6 +604,8 @@
<Compile Include="Objects\Factory\Xml\XmlObjectDefinitionStoreException.cs" />
<Compile Include="Objects\Factory\Xml\XmlReaderContext.cs" />
<Compile Include="Objects\FatalObjectException.cs" />
<Compile Include="Objects\ISharedStateAware.cs" />
<Compile Include="Objects\ISharedStateFactory.cs" />
<Compile Include="Objects\MutablePropertyValues.cs" />
<Compile Include="Objects\ObjectWrapper.cs" />
<Compile Include="Objects\Events\IEventRegistry.cs">
@@ -904,6 +907,7 @@
<Compile Include="Objects\Support\AbstractEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Support\AbstractSharedStateFactory.cs" />
<Compile Include="Objects\Support\AbstractWiringEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
@@ -913,6 +917,7 @@
<Compile Include="Objects\Support\AutoWiringEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Objects\Support\ByTypeSharedStateFactory.cs" />
<Compile Include="Objects\Support\InstanceEventHandlerValue.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -34,6 +34,22 @@ namespace Spring.Util
/// <author>Aleksandar Seovic</author>
public sealed class ArrayUtils
{
/// <summary>
/// Checks if the given array or collection has elements and none of the elements is null.
/// </summary>
/// <param name="collection">the collection to be checked.</param>
/// <returns>true if the collection has a length and contains only non-null elements.</returns>
public static bool HasElements(ICollection collection)
{
if (!HasLength(collection)) return false;
IEnumerator it = collection.GetEnumerator();
while(it.MoveNext())
{
if (it.Current == null ) return false;
}
return true;
}
/// <summary>
/// Checks if the given array or collection is null or has no elements.
/// </summary>

View File

@@ -168,6 +168,29 @@ namespace Spring.Util
}
}
/// <summary>
/// Checks the value of the supplied <see cref="ICollection"/> <paramref name="argument"/> and throws
/// an <see cref="ArgumentException"/> if it is <see langword="null"/>, contains no elements or only null elements.
/// </summary>
/// <param name="argument">The array or collection to check.</param>
/// <param name="name">The argument name.</param>
/// <exception cref="System.ArgumentNullException">
/// If the supplied <paramref name="argument"/> is <see langword="null"/>,
/// contains no elements or only null elements.
/// </exception>
public static void ArgumentHasElements(ICollection argument, string name)
{
if (!ArrayUtils.HasElements(argument))
{
throw new ArgumentException(
name,
string.Format(
CultureInfo.InvariantCulture,
"Argument '{0}' must not be null or resolve to an empty collection and must contain non-null elements", name));
}
}
/// <summary>
/// Checks whether the specified <paramref name="argument"/> can be cast
/// into the <paramref name="requiredType"/>.

View File

@@ -26,7 +26,6 @@ using System.Web;
using System.Web.Script.Services;
using Spring.Context;
using Spring.Context.Support;
using Spring.Util;
using Spring.Web.Services;
using Spring.Web.Support;

View File

@@ -29,8 +29,11 @@ using System.Web;
using System.Web.Hosting;
using Common.Logging;
using Spring.Collections;
using Spring.Objects;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Objects.Factory.Xml;
using Spring.Objects.Support;
using Spring.Util;
#endregion

View File

@@ -26,15 +26,17 @@ using System.Reflection;
using System.Web;
using System.Web.Caching;
using System.Web.SessionState;
using System.Web.UI;
using Common.Logging;
using Spring.Core.IO;
using Spring.Core.TypeConversion;
using Spring.Core.TypeResolution;
using Spring.Expressions;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
using Spring.Threading;
using Spring.Util;
using Spring.Web.Support;
#endregion
@@ -46,6 +48,28 @@ namespace Spring.Context.Support
/// <author>Erich Eichinger</author>
public class WebSupportModule : IHttpModule
{
/// <summary>
/// Identifies the Objectdefinition used for the current IHttpHandler instance in TLS
/// </summary>
private static readonly string CURRENTHANDLER_OBJECTDEFINITION = "__spring.web" + new Guid().ToString();
/// <summary>
/// Holds the handler configuration information.
/// </summary>
private class HandlerConfigurationMetaData
{
public readonly IConfigurableApplicationContext ApplicationContext;
public readonly string ObjectDefinitionName;
public readonly bool IsContainerManaged;
public HandlerConfigurationMetaData(IConfigurableApplicationContext applicationContext, string objectDefinitionName, bool isContainerManaged)
{
ApplicationContext = applicationContext;
ObjectDefinitionName = objectDefinitionName;
IsContainerManaged = isContainerManaged;
}
}
private static readonly ILog s_log;
private static bool s_isInitialized = false;
@@ -64,28 +88,28 @@ namespace Spring.Context.Support
/// </summary>
static WebSupportModule()
{
s_log = LogManager.GetLogger(typeof(WebSupportModule));
s_log = LogManager.GetLogger( typeof( WebSupportModule ) );
// register additional resource handler
ResourceHandlerRegistry.RegisterResourceHandler(WebUtils.DEFAULT_RESOURCE_PROTOCOL, typeof(WebResource));
ResourceHandlerRegistry.RegisterResourceHandler( WebUtils.DEFAULT_RESOURCE_PROTOCOL, typeof( WebResource ) );
// replace default IResource converter
TypeConverterRegistry.RegisterConverter(typeof(IResource),
TypeConverterRegistry.RegisterConverter( typeof( IResource ),
new ResourceConverter(
new ConfigurableResourceLoader(WebUtils.DEFAULT_RESOURCE_PROTOCOL)));
new ConfigurableResourceLoader( WebUtils.DEFAULT_RESOURCE_PROTOCOL ) ) );
// default to hybrid thread storage implementation
LogicalThreadContext.SetStorage(new HybridContextStorage());
LogicalThreadContext.SetStorage( new HybridContextStorage() );
s_log.Debug("Set default resource protocol to 'web' and installed HttpContext-aware HybridContextStorage");
s_log.Debug( "Set default resource protocol to 'web' and installed HttpContext-aware HybridContextStorage" );
}
/// <summary>
/// Registers this module for all events required by the Spring.Web framework
/// </summary>
public virtual void Init(HttpApplication app)
public virtual void Init( HttpApplication app )
{
lock (typeof(WebSupportModule))
lock (typeof( WebSupportModule ))
{
s_log.Debug("Initializing Application instance");
s_log.Debug( "Initializing Application instance" );
if (!s_isInitialized)
{
HttpModuleCollection modules = app.Modules;
@@ -94,7 +118,7 @@ namespace Spring.Context.Support
if (modules[moduleKey] is SessionStateModule)
{
#if !NET_1_1
HookSessionEvent((SessionStateModule) modules[moduleKey]);
HookSessionEvent( (SessionStateModule)modules[moduleKey] );
#else
HookSessionEvent11();
#endif
@@ -108,16 +132,85 @@ namespace Spring.Context.Support
VirtualEnvironment.SetInitialized();
}
app.EndRequest += new EventHandler(VirtualEnvironment.RaiseEndRequest);
app.PreRequestHandlerExecute += new EventHandler( OnPreRequestHandlerExecute );
app.EndRequest += new EventHandler( VirtualEnvironment.RaiseEndRequest );
// ensure context is instantiated
IConfigurableApplicationContext appContext = WebApplicationContext.GetRootContext() as IConfigurableApplicationContext;
// configure this app + it's module instances
if (appContext == null)
{
throw new InvalidOperationException("Implementations of IApplicationContext must also implement IConfigurableApplicationContext");
throw new InvalidOperationException( "Implementations of IApplicationContext must also implement IConfigurableApplicationContext" );
}
HttpApplicationConfigurer.Configure( appContext, app );
}
///<summary>
/// Configures the current IHttpHandler as specified by <see cref="Spring.Web.Support.PageHandlerFactory"/>.
///</summary>
private void OnPreRequestHandlerExecute( object sender, EventArgs e )
{
HandlerConfigurationMetaData hCfg = (HandlerConfigurationMetaData)LogicalThreadContext.GetData( CURRENTHANDLER_OBJECTDEFINITION );
if (hCfg != null)
{
HttpApplication app = (HttpApplication)sender;
//app.Context.Handler =
ConfigureHandler( app.Context.Handler, hCfg.ApplicationContext, hCfg.ObjectDefinitionName, hCfg.IsContainerManaged );
}
}
///<summary>
///</summary>
///<param name="applicationContext"></param>
///<param name="name"></param>
///<param name="isContainerManaged"></param>
public static void SetCurrentHandlerConfiguration( IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged )
{
LogicalThreadContext.SetData( CURRENTHANDLER_OBJECTDEFINITION, new HandlerConfigurationMetaData(applicationContext, name, isContainerManaged) );
}
///<summary>
///</summary>
///<param name="handler"></param>
///<param name="applicationContext"></param>
///<param name="name"></param>
///<param name="isContainerManaged"></param>
public IHttpHandler ConfigureHandler( IHttpHandler handler, IConfigurableApplicationContext applicationContext, string name, bool isContainerManaged)
{
ApplyDependencyInjectionInfrastructure(handler, applicationContext);
if (isContainerManaged)
{
handler = (IHttpHandler)applicationContext.ObjectFactory.ConfigureObject( handler, name );
}
else
{
// at a minimum we'll apply ObjectPostProcessors
handler = (IHttpHandler)applicationContext.ObjectFactory.ApplyObjectPostProcessorsBeforeInitialization(handler, name);
handler = (IHttpHandler)applicationContext.ObjectFactory.ApplyObjectPostProcessorsAfterInitialization(handler, name);
}
return handler;
}
/// <summary>
/// Apply dependency injection stuff on the handler.
/// </summary>
/// <param name="handler">the handler to be intercepted</param>
/// <param name="applicationContext">the context responsible for configuring this handler</param>
private static void ApplyDependencyInjectionInfrastructure(IHttpHandler handler, IApplicationContext applicationContext)
{
if (handler is Control)
{
ControlInterceptor.EnsureControlIntercepted(applicationContext, (Control)handler);
}
else
{
if (handler is ISupportsWebDependencyInjection)
{
((ISupportsWebDependencyInjection)handler).DefaultApplicationContext = applicationContext;
}
}
HttpApplicationConfigurer.Configure(appContext, app);
}
/// <summary>
@@ -130,15 +223,15 @@ namespace Spring.Context.Support
#region Session Handling Stuff
private static void OnCacheItemRemoved(string key, object value, CacheItemRemovedReason reason)
private static void OnCacheItemRemoved( string key, object value, CacheItemRemovedReason reason )
{
s_log.Debug("end session " + key + " because of " + reason);
s_log.Debug( "end session " + key + " because of " + reason );
try
{
HttpSessionState ss = CreateSessionState(key, value);
HttpSessionState ss = CreateSessionState( key, value );
VirtualEnvironment.RaiseEndSession(ss, reason);
VirtualEnvironment.RaiseEndSession( ss, reason );
}
catch (Exception ex)
{
@@ -146,51 +239,51 @@ namespace Spring.Context.Support
// are we on a current request?
if (HttpContext.Current != null)
{
s_log.Error(msg, ex);
s_log.Error( msg, ex );
}
else
{
// this is an async session timout - log as fatal since this is the thread's exit point!
s_log.Fatal(msg, ex);
s_log.Fatal( msg, ex );
}
}
finally
{
if (s_originalCallback != null)
{
s_originalCallback(key, value, reason);
}
s_originalCallback( key, value, reason );
}
}
}
#if !NET_1_1
private static void HookSessionEvent(SessionStateModule sessionStateModule)
private static void HookSessionEvent( SessionStateModule sessionStateModule )
{
// Hook only into InProcState - all others ignore SessionEnd anyway
object store = ExpressionEvaluator.GetValue(sessionStateModule, "_store");
object store = ExpressionEvaluator.GetValue( sessionStateModule, "_store" );
if ((store != null) && store.GetType().Name == "InProcSessionStateStore")
{
s_log.Debug("attaching to InProcSessionStateStore");
s_originalCallback = (CacheItemRemovedCallback) ExpressionEvaluator.GetValue(store, "_callback");
ExpressionEvaluator.SetValue(store, "_callback", new CacheItemRemovedCallback(OnCacheItemRemoved));
s_log.Debug( "attaching to InProcSessionStateStore" );
s_originalCallback = (CacheItemRemovedCallback)ExpressionEvaluator.GetValue( store, "_callback" );
ExpressionEvaluator.SetValue( store, "_callback", new CacheItemRemovedCallback( OnCacheItemRemoved ) );
CACHEKEYPREFIXLENGTH = (int) ExpressionEvaluator.GetValue(store, "CACHEKEYPREFIXLENGTH");
CACHEKEYPREFIXLENGTH = (int)ExpressionEvaluator.GetValue( store, "CACHEKEYPREFIXLENGTH" );
}
}
private static HttpSessionState CreateSessionState(string key, object state)
private static HttpSessionState CreateSessionState( string key, object state )
{
string id = key.Substring(CACHEKEYPREFIXLENGTH);
string id = key.Substring( CACHEKEYPREFIXLENGTH );
ISessionStateItemCollection sessionItems =
(ISessionStateItemCollection) ExpressionEvaluator.GetValue(state, "_sessionItems");
(ISessionStateItemCollection)ExpressionEvaluator.GetValue( state, "_sessionItems" );
HttpStaticObjectsCollection staticObjects =
(HttpStaticObjectsCollection) ExpressionEvaluator.GetValue(state, "_staticObjects");
int timeout = (int) ExpressionEvaluator.GetValue(state, "_timeout");
TypeRegistry.RegisterType("SessionStateModule", typeof(SessionStateModule));
(HttpStaticObjectsCollection)ExpressionEvaluator.GetValue( state, "_staticObjects" );
int timeout = (int)ExpressionEvaluator.GetValue( state, "_timeout" );
TypeRegistry.RegisterType( "SessionStateModule", typeof( SessionStateModule ) );
HttpCookieMode cookieMode =
(HttpCookieMode) ExpressionEvaluator.GetValue(null, "SessionStateModule.s_configCookieless");
(HttpCookieMode)ExpressionEvaluator.GetValue( null, "SessionStateModule.s_configCookieless" );
SessionStateMode stateMode =
(SessionStateMode) ExpressionEvaluator.GetValue(null, "SessionStateModule.s_configMode");
(SessionStateMode)ExpressionEvaluator.GetValue( null, "SessionStateModule.s_configMode" );
HttpSessionStateContainer container = new HttpSessionStateContainer(
id
, sessionItems
@@ -202,11 +295,11 @@ namespace Spring.Context.Support
, true
);
return (HttpSessionState) Activator.CreateInstance(
typeof(HttpSessionState)
return (HttpSessionState)Activator.CreateInstance(
typeof( HttpSessionState )
, BindingFlags.Instance | BindingFlags.NonPublic
, null
, new object[] {container}
, new object[] { container }
, CultureInfo.InvariantCulture
);
}

View File

@@ -327,7 +327,7 @@ namespace Spring.Objects.Factory.Support
scopedSingletonCache.Add(objectName, TemporarySingletonPlaceHolder);
try
{
instance = CreateObject(objectName, objectDefinition, arguments, true);
instance = InstantiateObject(objectName, objectDefinition, arguments, true, false);
AssertUtils.ArgumentNotNull(instance, "instance");
scopedSingletonCache[objectName] = instance;
}

View File

@@ -159,9 +159,6 @@
<Compile Include="Util\WebUtils.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Web\Support\AbstractProcessHandler.cs" />
<Compile Include="Web\Process\IProcess.cs" />
<Compile Include="Web\Process\IProcessAware.cs" />
<Compile Include="Web\Providers\ConfigurableActiveDirectoryMembershipProvider.cs" />
<Compile Include="Web\Providers\ConfigurableSqlMembershipProvider.cs" />
<Compile Include="Web\Providers\ConfigurableSqlProfileProvider.cs" />
@@ -184,7 +181,6 @@
<Compile Include="Web\Support\AbstractHandlerFactory.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Web\Process\ProcessManager.cs" />
<Compile Include="Web\Support\ContextMonitor.cs">
<SubType>Code</SubType>
</Compile>
@@ -192,10 +188,8 @@
<Compile Include="Web\Support\IInterceptionStrategy.cs" />
<Compile Include="Web\Support\InterceptControlCollectionOwnerStrategy.cs" />
<Compile Include="Web\Support\InterceptControlCollectionStrategy.cs" />
<Compile Include="Web\Support\ISharedStateAware.cs" />
<Compile Include="Web\Support\ISupportsWebDependencyInjection.cs" />
<Compile Include="Web\Support\PageHandlerFactory.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="Web\Support\Result.cs">
<SubType>Code</SubType>

View File

@@ -160,9 +160,6 @@
<Compile Include="Util\WebUtils.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Web\Support\AbstractProcessHandler.cs" />
<Compile Include="Web\Process\IProcess.cs" />
<Compile Include="Web\Process\IProcessAware.cs" />
<Compile Include="Web\Providers\ConfigurableActiveDirectoryMembershipProvider.cs" />
<Compile Include="Web\Providers\ConfigurableSqlMembershipProvider.cs" />
<Compile Include="Web\Providers\ConfigurableSqlProfileProvider.cs" />
@@ -185,7 +182,6 @@
<Compile Include="Web\Support\AbstractHandlerFactory.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Web\Process\ProcessManager.cs" />
<Compile Include="Web\Support\ContextMonitor.cs">
<SubType>Code</SubType>
</Compile>
@@ -193,10 +189,8 @@
<Compile Include="Web\Support\IInterceptionStrategy.cs" />
<Compile Include="Web\Support\InterceptControlCollectionOwnerStrategy.cs" />
<Compile Include="Web\Support\InterceptControlCollectionStrategy.cs" />
<Compile Include="Web\Support\ISharedStateAware.cs" />
<Compile Include="Web\Support\ISupportsWebDependencyInjection.cs" />
<Compile Include="Web\Support\PageHandlerFactory.cs">
<SubType>ASPXCodeBehind</SubType>
</Compile>
<Compile Include="Web\Support\Result.cs">
<SubType>Code</SubType>

View File

@@ -1,52 +0,0 @@
using System;
namespace Spring.Web.Process
{
/// <summary>
/// An interface that different process implementations need to support.
/// </summary>
public interface IProcess
{
/// <summary>
/// Unique ID of this process instance.
/// </summary>
string Id { get; }
/// <summary>
/// Controller for the component.
/// </summary>
/// <remarks>
/// Process controller will be shared by all the views
/// that belong to this process.
/// </remarks>
object Controller { get; set; }
/// <summary>
/// Gets the name of the current view.
/// </summary>
string CurrentView { get; }
/// <summary>
/// Gets the the flag that indicates if selected view
/// has changed during the current request.
/// </summary>
bool ViewChanged { get; }
/// <summary>
/// Starts the process.
/// </summary>
/// <param name="referrerUrl">Referrer URL.</param>
void Start(string referrerUrl);
/// <summary>
/// Resolves view for the specified view name.
/// </summary>
/// <param name="viewName">Name of the view to go to.</param>
void SetView(string viewName);
/// <summary>
/// Ends the process.
/// </summary>
void End();
}
}

View File

@@ -1,69 +0,0 @@
#region License
/*
* Copyright 2002-2004 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
using System.Collections;
namespace Spring.Web.Process
{
/// <summary>
/// Singleton that keeps track of all active process instances.
/// </summary>
/// <author>Aleksandar Seovic</author>
public class ProcessManager
{
private static readonly ProcessManager instance = new ProcessManager();
private IDictionary processInstances = new Hashtable();
/// <summary>
/// Creates singleton instance.
/// </summary>
private ProcessManager()
{}
/// <summary>
/// Registers process instance.
/// </summary>
/// <param name="process">Process instance to register.</param>
public static void RegisterProcess(IProcess process)
{
instance.processInstances.Add(process.Id, process);
}
/// <summary>
/// Returns process with the specified ID.
/// </summary>
/// <param name="id">Process ID to use for lookup.</param>
/// <returns>Process with the specified ID, or <c>null</c> if process with that ID is not registered.</returns>
public static IProcess GetProcess(string id)
{
return (IProcess) instance.processInstances[id];
}
/// <summary>
/// Unregisters process with the specified ID.
/// </summary>
/// <param name="id">ID of the process to unregister.</param>
public static void UnregisterProcess(string id)
{
instance.processInstances.Remove(id);
}
}
}

View File

@@ -29,6 +29,7 @@ using System.Web.Services;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Util;
using Spring.Web.Support;

View File

@@ -48,6 +48,43 @@ namespace Spring.Web.Support
/// <author>Aleksandar Seovic</author>
public abstract class AbstractHandlerFactory : IHttpHandlerFactory
{
#region NamedObjectDefinition Utility
/// <summary>
/// Holds a named <see cref="IObjectDefinition"/>
/// </summary>
/// <author>Erich Eichinger</author>
protected internal class NamedObjectDefinition
{
private readonly string _name;
private readonly IObjectDefinition _objectDefinition;
/// <summary>
/// Creates a new name/objectdefinition pair.
/// </summary>
public NamedObjectDefinition(string name, IObjectDefinition objectDefinition)
{
_name = name;
_objectDefinition = objectDefinition;
}
/// <summary>
/// Get the name of the attached object definition
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// Get the <see cref="IObjectDefinition"/>.
/// </summary>
public IObjectDefinition ObjectDefinition
{
get { return _objectDefinition; }
}
}
#endregion
/// <summary>
/// Holds all handlers having <see cref="IHttpHandler.IsReusable"/> == true.
/// </summary>
@@ -255,39 +292,5 @@ namespace Spring.Web.Support
return (pageDefinition == null) ? (NamedObjectDefinition)null : new NamedObjectDefinition( objectDefinitionName, pageDefinition );
}
/// <summary>
/// DO NOT USE - this is subject to change!
/// </summary>
protected internal class NamedObjectDefinition
{
private readonly string _name;
private readonly IObjectDefinition _objectDefinition;
/// <summary>
/// DO NOT USE
/// </summary>
public NamedObjectDefinition( string name, IObjectDefinition objectDefinition )
{
_name = name;
_objectDefinition = objectDefinition;
}
/// <summary>
/// DO NOT USE
/// </summary>
public string Name
{
get { return _name; }
}
/// <summary>
/// DO NOT USE
/// </summary>
public IObjectDefinition ObjectDefinition
{
get { return _objectDefinition; }
}
}
}
}

View File

@@ -1,312 +0,0 @@
#region License
/*
* Copyright 2002-2007 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Web;
using System.Web.SessionState;
using Spring.Collections;
using Spring.Context;
using Spring.Util;
using Spring.Web.Process;
using Spring.Web.Support;
#endregion
namespace Spring.Web.Support
{
/// <summary>
/// An abstract base class that defines common behavior for different process implementations.
/// </summary>
/// <author>Aleksandar Seovic</author>
public abstract class AbstractProcessHandler : IProcess, ISharedStateAware, IApplicationContextAware, IHttpHandler, IRequiresSessionState
{
/// <summary>
/// Parameter name that is used for process ID.
/// </summary>
protected internal const string ProcessIdParamName = "pid";
#region Fields
private string id = Guid.NewGuid().ToString("N");
private IProcess parent;
private object controller;
private string defaultView;
private string currentView;
private IDictionary views = new CaseInsensitiveHashtable(); //CollectionsUtil.CreateCaseInsensitiveHashtable();
private IDictionary sharedState;
private IApplicationContext applicationContext;
private string processUrl;
private bool viewChanged;
#endregion
#region Constructors
/// <summary>
/// Creates instance of the process and registers it with the <see cref="Spring.Web.Process.ProcessManager"/>.
/// </summary>
public AbstractProcessHandler()
{
ProcessManager.RegisterProcess(this);
}
#endregion
#region Properties
/// <summary>
/// Unique ID of this component instance.
/// </summary>
public string Id
{
get { return this.id; }
}
/// <summary>
/// Gets or sets the parent process.
/// </summary>
internal IProcess Parent
{
get { return this.parent; }
set { this.parent = value; }
}
/// <summary>
/// Returns a thread-safe dictionary that contains state that is shared by
/// all views of this component.
/// </summary>
public IDictionary SharedState
{
get { return this.sharedState; }
set { this.sharedState = value; }
}
/// <summary>
/// Controller for the component.
/// </summary>
/// <remarks>
/// Process controller will be shared by all the views
/// that belong to this component.
/// </remarks>
public object Controller
{
get { return this.controller; }
set { this.controller = value; }
}
/// <summary>
/// Default view for the component.
/// </summary>
public string DefaultView
{
get { return this.defaultView; }
set { this.defaultView = value; }
}
/// <summary>
/// Gets the name of the current view.
/// </summary>
public string CurrentView
{
get
{
if (this.currentView == null)
{
this.CurrentView = this.defaultView;
}
return this.currentView;
}
set
{
string oldView = this.currentView;
if (this.views.Contains(value))
{
this.currentView = (string) this.views[value];
}
else
{
this.currentView = value;
}
this.viewChanged = (oldView != this.currentView);
}
}
/// <summary>
/// Gets the the flag that indicates if selected view
/// has changed during the current request.
/// </summary>
public bool ViewChanged
{
get { return this.viewChanged; }
}
/// <summary>
/// Gets a map of process views.
/// </summary>
public IDictionary Views
{
get { return this.views; }
}
/// <summary>
/// Gets the process URL.
/// </summary>
protected string ProcessUrl
{
get { return this.processUrl; }
}
#endregion
#region Public methods
/// <summary>
/// Starts the process.
/// </summary>
/// <param name="url">Process URL.</param>
public void Start(string url)
{
this.processUrl = url;
this.NavigateToStartView();
}
/// <summary>
/// Resolves and sets the view for the specified view name.
/// </summary>
/// <param name="viewName">Name of the view to go to.</param>
public virtual void SetView(string viewName)
{
this.CurrentView = viewName;
this.NavigateToCurrentView();
}
/// <summary>
/// Ends the process by unregistering it from the <see cref="ProcessManager"/>.
/// </summary>
public virtual void End()
{
ProcessManager.UnregisterProcess(this.id);
if (this.parent != null)
{
this.parent.SetView(this.parent.CurrentView);
}
}
#endregion
#region Abstract methods
/// <summary>
/// Method that needs to be implemented by specific process implementations
/// in order to navigate to the first view in the process.
/// </summary>
protected abstract void NavigateToStartView();
/// <summary>
/// Method that needs to be implemented by specific process implementations
/// in order to navigate to the current view.
/// </summary>
protected abstract void NavigateToCurrentView();
#endregion
#region IHttpHandler implementation
/// <summary>
/// Processes the request by delegating to appropriate view, which could be
/// another process.
/// </summary>
/// <param name="context"></param>
void IHttpHandler.ProcessRequest(HttpContext context)
{
IHttpHandler handler = (IHttpHandler) this.applicationContext.GetObject(WebUtils.GetPageName(this.CurrentView));
this.viewChanged = false;
if (handler is AbstractProcessHandler)
{
((AbstractProcessHandler) handler).Parent = this;
// TODO: start child process
}
if (handler is IProcessAware)
{
((IProcessAware) handler).Process = this;
}
if (handler is ISharedStateAware)
{
((ISharedStateAware) handler).SharedState = this.sharedState;
}
context.Handler = handler;
handler.ProcessRequest(context);
}
/// <summary>
/// Returns true because this wrapper handler can be reused.
/// Actual page is instantiated at the beginning of the ProcessRequest method.
/// </summary>
bool IHttpHandler.IsReusable
{
get { return false; }
}
#endregion
#region IApplicationContextAware implementation
/// <summary>
/// Sets the <see cref="Spring.Context.IApplicationContext"/> that this
/// object runs in.
/// </summary>
/// <value></value>
/// <remarks>
/// <p>
/// Normally this call will be used to initialize the object.
/// </p>
/// <p>
/// Invoked after population of normal object properties but before an
/// init callback such as
/// <see cref="Spring.Objects.Factory.IInitializingObject"/>'s
/// <see cref="Spring.Objects.Factory.IInitializingObject.AfterPropertiesSet"/>
/// or a custom init-method. Invoked after the setting of any
/// <see cref="Spring.Context.IResourceLoaderAware"/>'s
/// <see cref="Spring.Context.IResourceLoaderAware.ResourceLoader"/>
/// property.
/// </p>
/// </remarks>
/// <exception cref="Spring.Context.ApplicationContextException">
/// In the case of application context initialization errors.
/// </exception>
/// <exception cref="Spring.Objects.ObjectsException">
/// If thrown by any application context methods.
/// </exception>
/// <exception cref="Spring.Objects.Factory.ObjectInitializationException"/>
public IApplicationContext ApplicationContext
{
set { this.applicationContext = value; }
}
#endregion
}
}

View File

@@ -32,10 +32,9 @@ using Common.Logging;
using Spring.Collections;
using Spring.Context;
using Spring.Context.Support;
using Spring.Objects.Factory.Config;
using Spring.Objects;
using Spring.Objects.Factory.Support;
using Spring.Util;
using Spring.Web.Process;
#endregion
@@ -78,9 +77,9 @@ namespace Spring.Web.Support
/// <param name="url">Requested page URL</param>
/// <param name="physicalPath">Translated server path for the page</param>
/// <returns>Instance of the IHttpHandler object that should be used to process request.</returns>
public override IHttpHandler GetHandler( HttpContext context, string requestType, string url, string physicalPath )
public override IHttpHandler GetHandler(HttpContext context, string requestType, string url, string physicalPath)
{
new SecurityPermission( SecurityPermissionFlag.UnmanagedCode ).Assert();
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
return base.GetHandler(context, requestType, url, physicalPath);
}
@@ -93,321 +92,31 @@ namespace Spring.Web.Support
/// <param name="url">The requested <see cref="HttpRequest.RawUrl"/>.</param>
/// <param name="physicalPath">The physical path of the requested resource.</param>
/// <returns>A handler instance for the current request.</returns>
protected override IHttpHandler CreateHandlerInstance( HttpContext context, string requestType, string url, string physicalPath )
protected override IHttpHandler CreateHandlerInstance(HttpContext context, string requestType, string url, string physicalPath)
{
IHttpHandler pageHandlerWrapper;
IConfigurableApplicationContext appContext = GetCheckedApplicationContext( url );
IHttpHandler handler;
IConfigurableApplicationContext appContext = GetCheckedApplicationContext(url);
if (appContext == null)
{
throw new InvalidOperationException(
"Implementations of IApplicationContext must also implement IConfigurableApplicationContext" );
throw new InvalidOperationException("PageHandlerFactory requires an IConfigurableApplicationContext");
}
string appRelativeVirtualPath = WebUtils.GetAppRelativePath( url );
NamedObjectDefinition namedPageDefinition = FindWebObjectDefinition( appRelativeVirtualPath, appContext.ObjectFactory );
string appRelativeVirtualPath = WebUtils.GetAppRelativePath(url);
NamedObjectDefinition namedPageDefinition = FindWebObjectDefinition(appRelativeVirtualPath, appContext.ObjectFactory);
if (namedPageDefinition != null)
{
Type pageType = namedPageDefinition.ObjectDefinition.ObjectType;
if (typeof( IRequiresSessionState ).IsAssignableFrom( pageType ))
{
pageHandlerWrapper = new SessionAwarePageHandlerWrapper( appContext, namedPageDefinition.Name, url, null );
}
else
{
pageHandlerWrapper = new PageHandlerWrapper( appContext, namedPageDefinition.Name, url, null );
}
handler = (IHttpHandler)appContext.CreateObject(namedPageDefinition.Name, typeof(IHttpHandler), null);
WebSupportModule.SetCurrentHandlerConfiguration(appContext, namedPageDefinition.Name, true);
}
else
{
Type pageType = WebObjectUtils.GetCompiledPageType( url );
if (typeof( IRequiresSessionState ).IsAssignableFrom( pageType ))
{
pageHandlerWrapper = new SessionAwarePageHandlerWrapper( appContext, appRelativeVirtualPath, url, physicalPath );
}
else
{
pageHandlerWrapper = new PageHandlerWrapper( appContext, appRelativeVirtualPath, url, physicalPath );
}
}
return pageHandlerWrapper;
}
}
/// <summary>
/// Wrapper for handlers that do not require <see cref="HttpSessionState"/>.
/// </summary>
/// <remarks>
/// NOTE: This class has to extend System.Web.UI.Page instead of simply
/// implementing IHttpHandler in order for Server.Transfer to work properly.
/// This in turn requires explicit IHttpHandler implementation in order to
/// override non-virtual methods from the base Page class.
/// </remarks>
internal class PageHandlerWrapper : Page, IHttpHandler
{
#if NET_2_0 && !MONO_2_0
private static readonly FieldInfo fiHttpContext_CurrentHandler =
typeof( HttpContext ).GetField( "_currentHandler", BindingFlags.NonPublic | BindingFlags.Instance );
#endif
#if MONO_2_0
private static readonly FieldInfo fiHttpContext_CurrentHandler =
typeof(HttpContext).GetField("handler", BindingFlags.NonPublic | BindingFlags.Instance);
#endif
#if NET_2_0 || !MONO_2_0
private static readonly MethodInfo miPage_SetPreviousPage =
typeof( System.Web.UI.Page ).GetMethod( "SetPreviousPage", BindingFlags.NonPublic | BindingFlags.Instance );
#endif
private readonly IApplicationContext appContext;
private readonly string pageId;
private readonly string url;
private readonly string path;
// cache handler if IsReusable == true
// since we don't use sync, make it volatile
private volatile IHttpHandler cachedHandler;
// holds shared state for handlerType
private Type handlerType;
private IDictionary handlerState;
private readonly object syncRoot = new object();
/// <summary>
/// Initializes a new instance of the <see cref="PageHandlerWrapper"/> class.
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
/// <param name="url">Requested page URL.</param>
/// <param name="path">Translated server path for the page.</param>
public PageHandlerWrapper( IApplicationContext appContext, string pageName, string url, string path )
{
this.appContext = appContext;
this.pageId = pageName;
this.url = url;
this.path = path;
}
/// <summary>
/// Initializes a new instance of the <see cref="PageHandlerWrapper"/> class.
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
public PageHandlerWrapper( IApplicationContext appContext, string pageName )
: this( appContext, pageName, null, null )
{
}
#region Properties
/// <summary>
/// Use for sync access to this PageHandler instance.
/// </summary>
public object SyncRoot
{
get { return syncRoot; }
}
/// <summary>
/// Gets <see cref="IDictionary"/> that contains handler state.
/// </summary>
/// <remarks>
/// This <see cref="IDictionary"/> will be assigned to the <c>SharedState</c>
/// property of <see cref="IHttpHandler"/> instances that implement
/// <see cref="ISharedStateAware"/> interface.
/// </remarks>
public IDictionary HandlerState
{
get { return handlerState; }
}
#endregion
void IHttpHandler.ProcessRequest( HttpContext context )
{
IHttpHandler handler = cachedHandler;
if (handler == null)
{
if (path != null)
{
handler = CreatePageInstance();
}
else
{
handler = GetOrCreateProcessHandler( context );
}
// note, that we don't care about sync here. The last call wins (it's the most current handler instance anyway)
if (handler.IsReusable)
cachedHandler = handler;
handler = WebObjectUtils.CreatePageInstance(url);
WebSupportModule.SetCurrentHandlerConfiguration(appContext, url, false);
}
// replace handler proxy on context with "real" handler
if (this == context.Handler)
{
context.Handler = handler;
}
#if NET_2_0
// this may happen under load, if GetHandler()
// and ProcessRequest() are executed under different threads
// fix this...
if (this == context.CurrentHandler)
{
fiHttpContext_CurrentHandler.SetValue( context, handler );
}
if (handler is System.Web.UI.Page)
{
System.Web.UI.Page page = (Page)handler;
// TODO: to fix this would require a change to the Mono source as there is no mechanisim (public or private) for explicitly setting the
// PreviousPage at the moment
#if !MONO_2_0
// During Server.Transfer/Execute() the PreviousPage property gets set
if (this.PreviousPage != null)
{
miPage_SetPreviousPage.Invoke( page, new object[] { this.PreviousPage } );
}
#endif
}
#endif
ApplySharedState( handler );
ApplyDependencyInjection( handler );
handler.ProcessRequest( context );
}
/// <summary>
/// Returns true because this wrapper handler can be reused.
/// Actual page is instantiated at the beginning of the ProcessRequest method.
/// </summary>
bool IHttpHandler.IsReusable
{
get { return true; }
}
/// <summary>
/// Creates a page instance corresponding to this handler's url.
/// </summary>
private IHttpHandler CreatePageInstance()
{
IHttpHandler handler;
handler = WebObjectUtils.CreatePageInstance( url );
if (handler is IApplicationContextAware)
{
((IApplicationContextAware)handler).ApplicationContext = appContext;
}
return handler;
}
/// <summary>
/// Gets or - if not found - creates a process handler instance.
/// </summary>
private IHttpHandler GetOrCreateProcessHandler( HttpContext context )
{
IHttpHandler handler = null;
string processId = context.Request[AbstractProcessHandler.ProcessIdParamName];
if (processId != null)
{
handler = (IHttpHandler)ProcessManager.GetProcess( processId );
}
if (handler == null)
{
handler = (IHttpHandler)this.appContext.GetObject( this.pageId );
if (handler is IProcess)
{
((IProcess)handler).Start( url );
}
}
return handler;
}
/// <summary>
/// Apply dependency injection stuff on the handler.
/// </summary>
/// <param name="handler"></param>
private void ApplyDependencyInjection( IHttpHandler handler )
{
if (handler is Control)
{
ControlInterceptor.EnsureControlIntercepted( appContext, (Control)handler );
}
else
{
if (handler is ISupportsWebDependencyInjection)
{
((ISupportsWebDependencyInjection)handler).DefaultApplicationContext = appContext;
}
}
}
/// <summary>
/// Applies <see cref="HandlerState"/> to the given handler if applicable.
/// </summary>
private void ApplySharedState( IHttpHandler handler )
{
if (handler is ISharedStateAware)
{
CheckIfPageWasRecompiled( handler );
((ISharedStateAware)handler).SharedState = this.handlerState;
}
}
/// <summary>
/// Checks, if page has been recompiled. Creates/discards handlerState if necessary.
/// </summary>
/// <param name="handler"></param>
private void CheckIfPageWasRecompiled( IHttpHandler handler )
{
if (handlerType != handler.GetType())
{
lock (SyncRoot)
{
if (handlerType != handler.GetType())
{
// discard old handlerState and cache new pagetype
handlerState = new SynchronizedHashtable();
handlerType = handler.GetType();
}
}
}
}
}
/// <summary>
/// Wrapper for handlers that require <see cref="HttpSessionState"/>.
/// </summary>
/// <remarks>
/// Delays page object instantiation until ProcessRequest is called
/// in order to be able to access session state.
/// </remarks>
internal class SessionAwarePageHandlerWrapper : PageHandlerWrapper, IRequiresSessionState
{
/// <summary>
/// Initializes a new instance of the <see cref="SessionAwarePageHandlerWrapper"/> class.
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
/// <param name="url">Requested page URL.</param>
/// <param name="path">Translated server path for the page.</param>
public SessionAwarePageHandlerWrapper( IApplicationContext appContext, string pageName, string url, string path )
: base( appContext, pageName, url, path )
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SessionAwarePageHandlerWrapper"/> class.
/// </summary>
/// <param name="appContext">Application context instance to retrieve page from.</param>
/// <param name="pageName">Name of the page object to execute.</param>
public SessionAwarePageHandlerWrapper( IApplicationContext appContext, string pageName )
: base( appContext, pageName )
{
}
}
}

View File

@@ -22,6 +22,7 @@
using System.Collections;
using Spring.Globalization;
using Spring.Objects;
using Spring.Util;
#endregion

File diff suppressed because it is too large Load Diff

View File

@@ -138,6 +138,11 @@ namespace Spring
return false;
}
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return null;
}
public string[] GetAliases(string name)
{
return null;
@@ -232,7 +237,13 @@ namespace Spring
return null;
}
public object GetObject(string name, Type requiredType)
public object CreateObject(string name, Type requiredType, object[] arguments)
{
innerExecute();
return null;
}
public object GetObject(string name, Type requiredType)
{
innerExecute();
return null;

View File

@@ -431,6 +431,11 @@ namespace Spring.Context
return null;
}
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return null;
}
public object GetObject(string name, Type requiredType)
{
return null;

View File

@@ -173,6 +173,11 @@ namespace Spring.Context.Support
return null;
}
public object CreateObject(string name, Type requiredType, object[] arguments)
{
return null;
}
public object GetObject(string name, Type requiredType)
{
return null;

View File

@@ -31,11 +31,6 @@ namespace Spring.Objects.Factory
{
public class TestAbstractObjectFactory : AbstractObjectFactory
{
protected override object CreateObject(string name, RootObjectDefinition definition, object[] arguments)
{
throw new System.NotImplementedException();
}
protected override void DestroyObject(string name, object target)
{
throw new System.NotImplementedException();
@@ -66,8 +61,8 @@ namespace Spring.Objects.Factory
throw new System.NotImplementedException();
}
protected override object CreateObject(string name, RootObjectDefinition definition, object[] arguments,
bool allowEagerCaching)
protected override object InstantiateObject(string name, RootObjectDefinition definition, object[] arguments,
bool allowEagerCaching, bool suppressConfigure)
{
throw new NotImplementedException();
}

View File

@@ -0,0 +1,232 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using System.Web.UI;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Objects.Factory.Support;
using Spring.Objects.Support;
#endregion
namespace Spring.Objects.Factory.Config
{
/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class SharedStateAwareProcessorTests
{
[Test]
public void DoesNotAllowNullOrEmptyFactoryList()
{
// check default ctor init
SharedStateAwareProcessor ssap = new SharedStateAwareProcessor();
Assert.IsNotNull( ssap.SharedStateFactories );
Assert.AreEqual( 0, ssap.SharedStateFactories.Length );
// check we accept a list at all
ssap = new SharedStateAwareProcessor( new ISharedStateFactory[] { new ByTypeSharedStateFactory() }, Int32.MaxValue );
// now ensure that SharedStateFactories will never be null or empty
ssap = new SharedStateAwareProcessor();
try
{
ssap.SharedStateFactories = null;
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
try
{
ssap.SharedStateFactories = new ISharedStateFactory[0];
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
try
{
ssap.SharedStateFactories = new ISharedStateFactory[] { null };
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
try
{
ssap = new SharedStateAwareProcessor( null, Int32.MaxValue );
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
try
{
ssap = new SharedStateAwareProcessor( new ISharedStateFactory[0], Int32.MaxValue );
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
try
{
ssap = new SharedStateAwareProcessor( new ISharedStateFactory[] { null }, Int32.MaxValue );
Assert.Fail( "should throw ArgumentException" );
}
catch (ArgumentException)
{ }
}
[Test]
public void BeforeInitializationIsNoOp()
{
SharedStateAwareProcessor ssap = new SharedStateAwareProcessor();
object res = ssap.PostProcessBeforeInitialization( this, null );
Assert.AreSame( this, res );
}
[Test]
public void IgnoresAlreadyPopulatedState()
{
DefaultListableObjectFactory of = new DefaultListableObjectFactory();
MockRepository mocks = new MockRepository();
ISharedStateFactory ssf1 = (ISharedStateFactory)mocks.CreateMock( typeof( ISharedStateFactory ) );
ISharedStateAware ssa = (ISharedStateAware)mocks.DynamicMock( typeof( ISharedStateAware ) );
SharedStateAwareProcessor ssap = new SharedStateAwareProcessor();
ssap.SharedStateFactories = new ISharedStateFactory[] { ssf1 };
of.RegisterSingleton( "ssap", ssap );
using (Record( mocks ))
{
// preset SharedState - ssap must ignore it
Expect.Call( ssa.SharedState ).Return( new Hashtable() );
// expect nothing else!
}
using (Playback( mocks ))
{
ssap.PostProcessBeforeInitialization( ssa, "myPage" );
}
}
[Test]
public void ProbesSharedStateFactories()
{
DefaultListableObjectFactory of = new DefaultListableObjectFactory();
MockRepository mocks = new MockRepository();
ISharedStateFactory ssf1 = (ISharedStateFactory)mocks.CreateMock( typeof( ISharedStateFactory ) );
ISharedStateFactory ssf2 = (ISharedStateFactory)mocks.CreateMock( typeof( ISharedStateFactory ) );
ISharedStateFactory ssf3 = (ISharedStateFactory)mocks.CreateMock( typeof( ISharedStateFactory ) );
ISharedStateFactory ssf4 = (ISharedStateFactory)mocks.CreateMock( typeof( ISharedStateFactory ) );
IDictionary ssf3ProvidedState = new Hashtable();
SharedStateAwareProcessor ssap = new SharedStateAwareProcessor();
ssap.SharedStateFactories = new ISharedStateFactory[] { ssf1, ssf2, ssf3, ssf4 };
of.RegisterSingleton( "ssap", ssap );
ISharedStateAware ssa = (ISharedStateAware)mocks.DynamicMock( typeof( ISharedStateAware ) );
// Ensure we iterate over configured SharedStateFactories until
// the first provider is found that
// a) true == provider.CanProvideState( instance, name )
// b) null != provider.GetSharedState( instance, name )
using (Record( mocks ))
{
Expect.Call( ssa.SharedState ).Return( null );
Expect.Call( ssf1.CanProvideState( ssa, "pageName" ) ).Return( false );
Expect.Call( ssf2.CanProvideState( ssa, "pageName" ) ).Return( true );
Expect.Call( ssf2.GetSharedStateFor( ssa, "pageName" ) ).Return( null );
Expect.Call( ssf3.CanProvideState( ssa, "pageName" ) ).Return( true );
Expect.Call( ssf3.GetSharedStateFor( ssa, "pageName" ) ).Return( ssf3ProvidedState );
Expect.Call( ssa.SharedState = ssf3ProvidedState );
}
using (Playback( mocks ))
{
ssap.PostProcessBeforeInitialization( ssa, "pageName" );
}
}
#region Rhino.Mocks Compatibility Adapter
private static IDisposable Record( MockRepository mocks )
{
#if !NET_1_1
return mocks.Record();
#else
return new RecordModeChanger(mocks);
#endif
}
private static IDisposable Playback( MockRepository mocks )
{
#if !NET_1_1
return mocks.Playback();
#else
return new PlaybackModeChanger(mocks);
#endif
}
#if NET_1_1
private class RecordModeChanger : IDisposable
{
private MockRepository _mocks;
public RecordModeChanger(MockRepository mocks)
{
_mocks = mocks;
}
public void Dispose()
{
_mocks.ReplayAll();
}
}
private class PlaybackModeChanger : IDisposable
{
private MockRepository _mocks;
public PlaybackModeChanger(MockRepository mocks)
{
_mocks = mocks;
}
public void Dispose()
{
_mocks.VerifyAll();
}
}
#endif
#endregion Rhino.Mocks Compatibility Adapter
}
}

View File

@@ -0,0 +1,110 @@
#region License
/*
* Copyright <20> 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#endregion
#region Imports
using System;
using System.Collections;
using NUnit.Framework;
#endregion
namespace Spring.Objects.Support
{
/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[TestFixture]
public class AbstractSharedStateFactoryTests
{
private class TestSharedStateFactory : AbstractSharedStateFactory
{
public static readonly object SPECIAL_OBJECT = new object();
protected override object GetKey(object instance, string name)
{
if (instance == SPECIAL_OBJECT) return null;
return name+"|"+instance.GetHashCode();
}
}
[Test]
public void DefaultsToCaseInsensitiveState()
{
TestSharedStateFactory p = new TestSharedStateFactory();
Assert.IsFalse(p.CaseSensitiveState);
IDictionary state = p.GetSharedStateFor(new object(), "no name" );
state["foo"] = this;
Assert.AreSame(this, state["FOO"]);
}
[Test]
public void StateDictionaryBehavesAccordingToCaseSensitiveState()
{
TestSharedStateFactory p = new TestSharedStateFactory();
// create case-insensitive dict
Assert.IsFalse(p.CaseSensitiveState);
IDictionary state = p.GetSharedStateFor(new object(), "no name" );
state["foo"] = this;
Assert.AreSame(this, state["FOO"]);
// create case-sensitive dict
p.CaseSensitiveState = true;
state = p.GetSharedStateFor(new object(), "no name" );
state["foo"] = this;
Assert.IsFalse(state.Contains("FOO"));
}
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ThrowsOnNullInstance()
{
TestSharedStateFactory p = new TestSharedStateFactory();
// allow "null" for name
IDictionary state = p.GetSharedStateFor(new object(), null);
Assert.IsNotNull(state);
// throws on null for instance
p.GetSharedStateFor(null, "no name");
}
[Test]
public void SharedStateCacheIsCaseSensitive()
{
TestSharedStateFactory p = new TestSharedStateFactory();
// allow "null" for name
IDictionary state = p.GetSharedStateFor(this, "foo");
IDictionary state2 = p.GetSharedStateFor(this, "FOO");
Assert.IsNotNull(state);
Assert.IsNotNull(state2);
Assert.AreNotSame(state, state2);
}
[Test]
public void ReturnsNullStateIfKeyIsNull()
{
TestSharedStateFactory p = new TestSharedStateFactory();
// force provider to produce a null key
IDictionary state = p.GetSharedStateFor(TestSharedStateFactory.SPECIAL_OBJECT, null);
Assert.IsNull(state);
}
}
}

View File

@@ -1,7 +1,7 @@
#region License
/*
* Copyright 2002-2004 the original author or authors.
* Copyright © 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,20 +18,22 @@
#endregion
using System.Web;
#region Imports
namespace Spring.Web.Process
using System;
using NUnit.Framework;
#endregion
namespace Spring.Objects.Support
{
/// <summary>
/// Interface that should be implemented by all <see cref="IHttpHandler"/>s
/// that want to be aware of the <see cref="IProcess"/> they belong to.
///
/// </summary>
/// <author>Aleksandar Seovic</author>
public interface IProcessAware
/// <author>Erich Eichinger</author>
[TestFixture]
public class ByTypeSharedStateProviderTests
{
/// <summary>
/// Gets or sets a process instance.
/// </summary>
IProcess Process { get; set; }
// TODO
}
}

View File

@@ -315,6 +315,7 @@
<Compile Include="Objects\Factory\Config\ObjectDefinitionVisitorTests.cs" />
<Compile Include="Objects\Factory\Config\ResourceHandlerConfigurerTests.cs" />
<Compile Include="Objects\Factory\Config\PropertyFileVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\SharedStateAwareProcessorTests.cs" />
<Compile Include="Objects\Factory\Config\SpecialFolderVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\EnvironmentVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\RegistryVariableSourceTests.cs" />
@@ -330,6 +331,8 @@
<Compile Include="Objects\Factory\Xml\ObjectNameGenerationTests.cs" />
<Compile Include="Objects\Factory\Xml\SiimpleCtorWiringTests.cs" />
<Compile Include="Objects\LazyTestObject.cs" />
<Compile Include="Objects\Support\AbstractSharedStateFactoryTests.cs" />
<Compile Include="Objects\Support\ByTypeSharedStateProviderTests.cs" />
<Compile Include="Objects\Support\MethodInvokerTests.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{44B16BAA-6DF8-447C-9D7F-3AD3D854D904}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -315,6 +315,7 @@
<Compile Include="Objects\Factory\Config\ObjectDefinitionVisitorTests.cs" />
<Compile Include="Objects\Factory\Config\ResourceHandlerConfigurerTests.cs" />
<Compile Include="Objects\Factory\Config\PropertyFileVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\SharedStateAwareProcessorTests.cs" />
<Compile Include="Objects\Factory\Config\SpecialFolderVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\EnvironmentVariableSourceTests.cs" />
<Compile Include="Objects\Factory\Config\RegistryVariableSourceTests.cs" />
@@ -329,6 +330,8 @@
<Compile Include="Objects\Factory\Xml\ObjectFactorySectionHandlerTests.cs" />
<Compile Include="Objects\Factory\Xml\SiimpleCtorWiringTests.cs" />
<Compile Include="Objects\LazyTestObject.cs" />
<Compile Include="Objects\Support\AbstractSharedStateFactoryTests.cs" />
<Compile Include="Objects\Support\ByTypeSharedStateProviderTests.cs" />
<Compile Include="Objects\Support\MethodInvokerTests.cs">
<SubType>Code</SubType>
</Compile>

View File

@@ -147,5 +147,32 @@ namespace Spring.Util
{
AssertUtils.ArgumentHasLength(new byte[1], "foo", "Bang!");
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void ArgumentHasElementsArgumentIsNull()
{
AssertUtils.ArgumentHasElements(null, "foo");
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void ArgumentHasElementsArgumentIsEmpty()
{
AssertUtils.ArgumentHasElements(new object[0], "foo");
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void ArgumentHasElementsArgumentContainsNull()
{
AssertUtils.ArgumentHasElements(new object[] { new object(), null, new object() }, "foo");
}
[Test]
public void ArgumentHasElementsArgumentContainsNonNullsOnly()
{
AssertUtils.ArgumentHasElements(new object[] { new object(), new object(), new object() }, "foo");
}
}
}

View File

@@ -1,7 +1,7 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<PropertyGroup>
<ProjectType>Local</ProjectType>
<ProductVersion>9.0.21022</ProductVersion>
<ProductVersion>9.0.30729</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{C67E47AA-1ACD-41B4-A465-4D336A2319CA}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>

View File

@@ -25,6 +25,7 @@ using System.Web;
using NUnit.Framework;
using Rhino.Mocks;
using Spring.Context;
using Spring.Objects.Factory.Config;
using Spring.Objects.Factory.Support;
#endregion