zweb/src/main/java/org/zkoss/web/servlet/xel/RequestContexts.java
/* RequestContexts.java
Purpose:
Description:
History:
Fri Apr 8 12:16:23 2005, Created by tomyeh
Copyright (C) 2005 Potix Corporation. All Rights Reserved.
{{IS_RIGHT
This program is distributed under LGPL Version 2.1 in the hope that
it will be useful, but WITHOUT ANY WARRANTY.
}}IS_RIGHT
*/
package org.zkoss.web.servlet.xel;
import java.util.LinkedList;
import java.util.List;
/**
* RequestContexts maintains a stack of {@link RequestContext} to simplify
* the signatures of the XEL function.
*
* <p>It is designed to make the signature of XEL functions
* (see {@link org.zkoss.web.fn.ServletFns}) simpler.
* For example, {@link org.zkoss.web.fn.ServletFns#getCurrentContext} requires
* no argument, since it assumes the current context can be retrieved
* from {@link #getCurrent}.
*
* <p>Spec Issue:<br/>
* It is controversial whether the introduction of {@link RequestContext} and
* {@link RequestContexts} is worth. However, we have to maintain the backward
* compatibility of the XEL/EL function signatures.
*
* @author tomyeh
* @since 3.0.0
*/
public class RequestContexts {
protected RequestContexts() {
} //prevent from instantiated
/** A list of RequestContext. */
private static final ThreadLocal<List<RequestContext>> _elCtxs = new ThreadLocal<>();
/** Returns the current page context if this thread is evaluating a page,
* or null if not.
*/
public static final RequestContext getCurrent() {
final List<RequestContext> jcs = _elCtxs.get();
return jcs != null && !jcs.isEmpty() ? jcs.get(0) : null;
}
/** Pushes the context as the current context, such that it will
* be returned by {@link #getCurrent}. The reason this method exists is
* many functions ({@link org.zkoss.web.fn.ServletFns}) counts on it.
*
* <p>However, you don't need to invoke this method if you are using
* DSP.
* <ol>
* <li>If go thru DSP, it is done automatically
* (by {@link org.zkoss.web.servlet.dsp.Interpreter}</li>
* </ol>
*
* <p>Note: you must use try/finally as follows:
* <pre><code>RequestContexts.push(jc);
*try {
* ...
*} finally {
* RequestContexts.pop();
*}</code></pre>
*/
public static final void push(RequestContext jc) {
if (jc == null)
throw new IllegalArgumentException("null");
List<RequestContext> jcs = _elCtxs.get();
if (jcs == null)
_elCtxs.set(jcs = new LinkedList<>());
jcs.add(0, jc);
}
/** Pops the context out and use the previous one as the current context.
*
* <p>However, you don't need to invoke this method if you are using
* DSP.
*
* @see #push
*/
public static final void pop() {
final List<RequestContext> l = _elCtxs.get();
if (l.size() == 1)
_elCtxs.remove();
else
l.remove(0);
}
}