sprnet-1047, sprnet-1027, sprnet-1046, sprnet-1048
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
55
src/Spring/Spring.Core/Objects/ISharedStateFactory.cs
Normal file
55
src/Spring/Spring.Core/Objects/ISharedStateFactory.cs
Normal 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 );
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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"/>.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user