T
- Type of object stored context locally.public class ContextLocal<T> extends ContextKey implements WeightedToken
ThreadLocal
class in J2SE, in terms of setting and accessing the reference, and
generating an initial value for the container. This implementation adds
an additional feature: context-specific finalization. Subclasses can be
hooked at the end of a context's life by overriding the cleanup(T)
method to perform any necessary housekeeping.
This class serves a dual role, in that it falls back to a mode which uses
a ThreadLocal
as backing storage if not running within a
security context. When in server mode, it uses the context-specific
token-storing services of SecurityManager
. More recently, a
client mode has been added (see below).
Server Mode
This is the mode used in production server use cases (i.e., when a security
environment is present). When running in this mode, the implementation
relies upon the following SecurityManager
methods:
SecurityManager.getToken(ContextKey)
SecurityManager.addToken(ContextKey, Object)
SecurityManager.removeToken(ContextKey)
An instance of this class uses itself as the lookup key for these methods.
We thus rely upon object identity to guarantee a lookup key is unique.
Because of this, this class' ContextKey.equals(Object)
and ContextKey.hashCode()
methods are identity-based implementations which may not be
overridden.
Fallback Mode
This mode, which stores the object reference in a ThreadLocal
,
is useful in cases where subsystem code which uses a context local
variable is executed in a standalone mode, where no security environment
has been created. In this mode, since there is no security context
present, there is no context finalization. In this mode, the
cleanup
method will NOT be executed when the local thread
expires. This mode is only used if no SecurityManager
instance exists.
Client Mode
This mode is used in a production, client environment (i.e., a security
manager is available and it reports that it is a client). This mode
assumes a single context and uses a simple map as backing storage. As
with server mode, an instance of this class uses itself as the lookup key.
Note
Do not use ContextLocal
object references in the
cleanup()
method of Cleanable
objects as, at the
time of this call, the context-local variables are already deleted from the
SecurityContext (inside the SecurityContext.cleanup()
method).
Value initialization
Optionally, the stored object may implement Initializable
to separate
instantiation from object initialization. This may be useful in cases
the initialization logic of the stored object causes a recursive call to
get() which would end up in multiple instances to be registered
in the context. With the implemented interface the initialization life cycle
is as follows: get() is called, initialValue() is
invoked to retrieve the initial value, the value is registered in the context,
Initializable.init() is invoked on the initial value.
When exception is thrown during the call to Initializable.init()
the value is removed from the context and the exception is re-raised.
Modifier and Type | Class and Description |
---|---|
private class |
ContextLocal.Fallback
An implementation of
ThreadLocal which is used as the
backing storage for this context local variable when no security
environment is present. |
private class |
ContextLocal.Wrapper
An instance of this class is used to wrap the variable value when it is
stored in the security context.
|
Modifier and Type | Field and Description |
---|---|
private static java.util.Map |
contextStorage
Client side storage for security context tokens
|
private static boolean |
debug
Flag indicating if dependencies should be collected or not, by
checkCaller(java.lang.Class<? extends com.goldencode.p2j.security.ContextLocal>) . |
private static java.util.Map<java.lang.String,java.util.Set<java.lang.String>> |
dependencies
Map holding dependencies.
|
private ContextLocal.Fallback |
fallback
An instance of our fallback (ThreadLocal-based) storage mechanism
|
private int |
mode
Storage mode
|
private static int |
MODE_CLIENT
Constant indicating client side storage mode
|
private static int |
MODE_SERVER
Constant indicating security context based storage mode
|
private static int |
MODE_STANDALONE
Constant indicating thread local based storage mode
|
private static int |
MODE_UNSET
Constant indicating storage mode has not been set
|
private SecurityManager |
security
Security manager instance (null if no security environment exists)
|
HEADLESS_KEY
Constructor and Description |
---|
ContextLocal()
Default constructor.
|
Modifier and Type | Method and Description |
---|---|
private static void |
checkCaller(java.lang.Class<? extends ContextLocal> localVar)
Debug aid method to check the dependencies between context-local vars.
|
protected void |
cleanup(T value)
This method is invoked at the end of the security context's life.
|
protected static void |
clearInstance()
Clean the storage caches.
|
protected static void |
dumpDependencies()
If
debug mode is enabled, dump the dependencies to STDOUT. |
T |
get()
Get the value of the current context's copy of this context local
variable.
|
T |
get(boolean create)
Get the value of the current context's copy of this context local
variable.
|
WeightFactor |
getWeight()
Get the weight of this context-local var.
|
private void |
initializeValue(T value)
Performs value initialization.
|
protected T |
initialValue()
|
protected boolean |
isResetAllowed()
Check if this instance is allowed to be reset.
|
void |
set(T value)
Set the current value of this context local variable.
|
protected static void |
setDebug(boolean state)
Set the debug mode, to enable or stop caller dependency checks.
|
private void |
setMode()
Set the mode used to store the local copy of the variable.
|
equals, hashCode
private static final int MODE_UNSET
private static final int MODE_SERVER
private static final int MODE_CLIENT
private static final int MODE_STANDALONE
private static java.util.Map contextStorage
private static boolean debug
checkCaller(java.lang.Class<? extends com.goldencode.p2j.security.ContextLocal>)
.private static final java.util.Map<java.lang.String,java.util.Set<java.lang.String>> dependencies
debug
is enabled.private SecurityManager security
private ContextLocal.Fallback fallback
private volatile int mode
protected static void clearInstance()
protected static void dumpDependencies()
debug
mode is enabled, dump the dependencies to STDOUT.protected static void setDebug(boolean state)
It will clear all existing dependencies.
WARNING! Do not enable debugging in a production environment, as the checkCaller(java.lang.Class<? extends com.goldencode.p2j.security.ContextLocal>)
API is very time expensive!
state
- The new debug state.private static void checkCaller(java.lang.Class<? extends ContextLocal> localVar)
For each variable, it will load the back-dependencies (i.e. context-local variables which access this context-local var).
localVar
- The type of the context local variable being accessed.public WeightFactor getWeight()
weight
, when security context is being reset. Note that the security
context reset can't ensure a specific order among vars with the same weight.getWeight
in interface WeightedToken
WeightFactor.NO_DEPENDENCY
- thus, unless overwritten, the context-local
var will be cleaned up first.public final T get()
initialValue()
will be invoked.public final T get(boolean create)
initialValue()
will be invoked.create
- Flag indicating if the context local variable needs to be created, if it was not
already set.public final void set(T value)
value
- Current value.protected T initialValue()
get()
is invoked (but
only if set(T)
was not previously invoked. The returned value
will be stored as the variable's initial value.
This default implementation simply returns null
.
Subclasses which require a different initial value must override this
method.
null
by default.protected void cleanup(T value)
value
- The last value this context local variable contained.protected boolean isResetAllowed()
true
by default.private void initializeValue(T value)
value
implements Initializable
the method calls its Initializable.init()
. When an exception is thrown inside
the init routine, the value is removed from the context and the exception is re-raised.value
- The value to be initialized.private void setMode()