org.jpu.patterns.singleton.onePerContext
Class OnePerContextManager

java.lang.Object
  extended byorg.jpu.patterns.singleton.onePerContext.OnePerContextManager
All Implemented Interfaces:
IOnePerContextManager

public class OnePerContextManager
extends java.lang.Object
implements IOnePerContextManager

This class and its associated interfaces implement a pattern that is a variant of Singleton intended for situations where you need one instance of the class per "context", rather than one per classloader as is the case with traditional singletons. A context can be any object of your choice, but can optionally implement IContext if if it wishes to be notified when objects are created on its behalf.

To use it, have your class provide an accessible no-arg constructor, and declare a private static field like this:

private static OnePerContextManager _opcMgr = new OnePerContextManager(C.class);
where C is the name of your class. When you want an instance of it, call
(C)_opcMgr.getInstance(ctx);
where ctx is the context. Typically you would wrap the above call in a public static method of C like this:
public static C getInstance(Object ctx) { return (C)_opcMgr.getInstance(ctx); }
The class may then be treated much like a singleton, except that one instance will be maintained per context, instead of one per classloader. Note ctx can be null, in which case it defaults to C.class, which provides traditional singleton behavior with one instance per classloader.

Custom Instantiation
By default the no-arg constructor of the class passed to the constructor is used to generate the One-Per-Context instances. However you can change this behavior in either of two ways: 1) have the context implement IContext and define a IContext.newInstance(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager) method that instantiates the One-Per-Context and returns it; or 2) write your own IOnePerContextManager.IInstantiator and set it via IOnePerContextManager.setInstantiator(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager.IInstantiator). Method (1) takes precedence, so if IContext.newInstance(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager) returns non-null, its return value will be used as the One-Per-Context instance and the instantiator will not be called.

Method (2) is generally intended for use by the One-Per-Context class itself to control its own instantiation, while Method (1) is intended for use by clients of the One-Per-Context class who need to substitute their own subclass implementation for use in particular contexts.

Custom Initialization
If you want each One-Per-Context instance to be notified of its associated context, you can have it implement IOnePerContext and implement the IOnePerContext.initOnePerContext(java.lang.Object) method. The method will be called on newly-created One-Per-Context's.

You can also perform custom initialization of One-Per-Context's by writing your own IOnePerContextManager.IInitializer and adding it via IOnePerContextManager.addInitializer(int, org.jpu.patterns.singleton.onePerContext.IOnePerContextManager.IInitializer). You can register as many initializers as you want, and they will be called in order on each newly created One-Per-Context instance. This sort of initialization is performed immediately after that described in the previous paragraph.

A third type of custom initialization can be performed by the context. To have the context be notified when a new One-Per-Context is created on its behalf, have it implement IContext and override IContext.initialize(org.jpu.patterns.singleton.onePerContext.IOnePerContextManager, java.lang.Object). This method will be called immediately after that described in the previous paragraph.

Thread local Contexts
To avoid the necessity of passing around context references, you might want to hold the context as a ThreadLocal and adjust its value when you want to change contexts. The code might look something like this:

 
     public class Foo {
          public static final Object DEFAULT_CTX = new Object();
          public static Foo getInstance() {
              return (Foo)_opcMgr.getInstance( _ctx.get() );
          }
          public static void setCtx(Object ctx) {
              _ctx.set(ctx);
          }
          private static ThreadLocal _ctx = new ThreadLocal() {
              protected Object initialValue() { return DEFAULT_CTX; }
          };
          private static OnePerContextManager _opcMgr = new OnePerContextManager(Foo.class);
     }
For the full example see the source code of Foo (source is included in the Javadoc's).

Context References
The One-Per-Context facility supports both weak and strong holding of context references. Strong referencing can be requested by passing true as the second parameter to OnePerContextManager(Class,boolean). If weak referencing is requested (which is the default if the second parameter is omitted), the facility's internal data structures will not prevent garbage collection of the context. When the context is garbage collected, all One-Per-Context's associated with it become inaccessible through this facility (though of course the application may yet retain other references to them).


Nested Class Summary
static class OnePerContextManager.DefaultInstantiator
          Default implementation of IOnePerContextManager.IInstantiator.
 
Nested classes inherited from class org.jpu.patterns.singleton.onePerContext.IOnePerContextManager
IOnePerContextManager.IInitializer, IOnePerContextManager.IInstantiator
 
Field Summary
 
Fields inherited from interface org.jpu.patterns.singleton.onePerContext.IOnePerContextManager
DEFAULT_CONTEXT
 
Constructor Summary
OnePerContextManager(java.lang.Class onePerContextClass)
          Alias for "OnePerContextManager(onePerContextClass, false)".
OnePerContextManager(java.lang.Class onePerContextClass, boolean strong)
          Constructor.
 
Method Summary
 void addInitializer(int i, IOnePerContextManager.IInitializer initializer)
          Adds the given initializer at position "i".
static java.util.List findManagersByClass(java.lang.Class opcClass)
           
static java.util.List findManagersByClass(java.lang.Class opcClass, boolean exact)
           
protected  java.lang.Object getDefaultContext()
           
 java.util.List getInitializers()
          Returns a shallow copy of the internal list of IOnePerContextManager.IInitializer's.
 java.lang.Object getInstance(java.lang.Object ctx)
          Returns the One-Per-Context of the given class associated with the given context.
 IOnePerContextManager.IInstantiator getInstantiator()
          Returns the IOnePerContextManager.IInstantiator used for instantiating One-Per-Context's.
static java.util.Set getManagers()
          Returns the set of all currently active OnePerContextManager's.
 java.util.Map getObjects()
          Returns a shallow copy of the internal map that maps contexts to One-Per-Context instances.
 java.lang.Class getOnePerContextClass()
          Returns the class passed as the first parameter to the constructor.
 IOnePerContextManager.IInitializer removeInitializer(int i)
          Removes the given initializer at position "i".
 boolean removeInitializer(IOnePerContextManager.IInitializer ini)
          Removes the given initializer.
 void setInstantiator(IOnePerContextManager.IInstantiator i)
          Sets the IOnePerContextManager.IInstantiator to be used for instantiating One-Per-Context's.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

OnePerContextManager

public OnePerContextManager(java.lang.Class onePerContextClass)
Alias for "OnePerContextManager(onePerContextClass, false)".


OnePerContextManager

public OnePerContextManager(java.lang.Class onePerContextClass,
                            boolean strong)
Constructor.

Parameters:
onePerContextClass - The class of One-Per-Context's that will be created by subsequent calls to getInstance(Object).
strong - Indicates whether references to newly-created instances should be held strongly or weakly. If the context defines equals() and hashCode() in terms of object identity, this should usually be false; else it should be true. For instance if the context is a String or a primitive type, strong should be true.
Method Detail

findManagersByClass

public static java.util.List findManagersByClass(java.lang.Class opcClass)

findManagersByClass

public static java.util.List findManagersByClass(java.lang.Class opcClass,
                                                 boolean exact)

getManagers

public static java.util.Set getManagers()
Returns the set of all currently active OnePerContextManager's. The returned set is a shallow copy of the internal data structure, so the caller can modify it at will.


getOnePerContextClass

public java.lang.Class getOnePerContextClass()
Description copied from interface: IOnePerContextManager
Returns the class passed as the first parameter to the constructor.

Specified by:
getOnePerContextClass in interface IOnePerContextManager

getObjects

public java.util.Map getObjects()
Description copied from interface: IOnePerContextManager
Returns a shallow copy of the internal map that maps contexts to One-Per-Context instances. Since the Map is a copy, the caller can query and modify it at will without synchronization.

Specified by:
getObjects in interface IOnePerContextManager

getInitializers

public java.util.List getInitializers()
Description copied from interface: IOnePerContextManager
Returns a shallow copy of the internal list of IOnePerContextManager.IInitializer's. Since the List is a copy, the caller can query and modify it at will without synchronization.

Specified by:
getInitializers in interface IOnePerContextManager

addInitializer

public void addInitializer(int i,
                           IOnePerContextManager.IInitializer initializer)
Description copied from interface: IOnePerContextManager
Adds the given initializer at position "i".

Specified by:
addInitializer in interface IOnePerContextManager

removeInitializer

public IOnePerContextManager.IInitializer removeInitializer(int i)
Description copied from interface: IOnePerContextManager
Removes the given initializer at position "i".

Specified by:
removeInitializer in interface IOnePerContextManager

removeInitializer

public boolean removeInitializer(IOnePerContextManager.IInitializer ini)
Description copied from interface: IOnePerContextManager
Removes the given initializer.

Specified by:
removeInitializer in interface IOnePerContextManager

getInstantiator

public IOnePerContextManager.IInstantiator getInstantiator()
Description copied from interface: IOnePerContextManager
Returns the IOnePerContextManager.IInstantiator used for instantiating One-Per-Context's.

Specified by:
getInstantiator in interface IOnePerContextManager

setInstantiator

public void setInstantiator(IOnePerContextManager.IInstantiator i)
Description copied from interface: IOnePerContextManager
Sets the IOnePerContextManager.IInstantiator to be used for instantiating One-Per-Context's.

Specified by:
setInstantiator in interface IOnePerContextManager

getDefaultContext

protected java.lang.Object getDefaultContext()

getInstance

public java.lang.Object getInstance(java.lang.Object ctx)
Description copied from interface: IOnePerContextManager
Returns the One-Per-Context of the given class associated with the given context. If no such instance exists, it is created and stored for subsequent reuse.

Specified by:
getInstance in interface IOnePerContextManager
Parameters:
ctx - The context. Can be null in which case onePerContextClass is used as the context.


Copyright (c) 2001-2003 - Apache Software Foundation