Update of /var/cvs/applications/taglib/src/org/mmbase/bridge/jsp/taglib
In directory
james.mmbase.org:/tmp/cvs-serv9331/applications/taglib/src/org/mmbase/bridge/jsp/taglib
Modified Files:
ContextReferrerTag.java
Added Files:
PageContextThreadLocal.java
Log Message:
MMB-1651 MMBase taglib memory leak
See also:
http://cvs.mmbase.org/viewcvs/applications/taglib/src/org/mmbase/bridge/jsp/taglib
See also: http://www.mmbase.org/jira/browse/MMB-1651
Index: ContextReferrerTag.java
===================================================================
RCS file:
/var/cvs/applications/taglib/src/org/mmbase/bridge/jsp/taglib/ContextReferrerTag.java,v
retrieving revision 1.104
retrieving revision 1.105
diff -u -b -r1.104 -r1.105
--- ContextReferrerTag.java 17 Mar 2008 16:18:15 -0000 1.104
+++ ContextReferrerTag.java 2 May 2008 07:44:14 -0000 1.105
@@ -16,6 +16,7 @@
import java.io.*;
+import org.mmbase.bridge.NodeList;
import org.mmbase.bridge.jsp.taglib.edit.FormTag;
import org.mmbase.bridge.jsp.taglib.util.Attribute;
import org.mmbase.bridge.jsp.taglib.containers.QueryContainer;
@@ -33,7 +34,7 @@
*
*
* @author Michiel Meeuwissen
- * @version $Id: ContextReferrerTag.java,v 1.104 2008/03/17 16:18:15 michiel
Exp $
+ * @version $Id: ContextReferrerTag.java,v 1.105 2008/05/02 07:44:14 nklasens
Exp $
* @see ContextTag
*/
@@ -84,74 +85,38 @@
private String thisPage = null;
-
void setPageContextOnly(final PageContext pc) {
super.setPageContext(pc);
// the 'page' Context
- setThreadPageContext(pc);
- }
-
- private static ThreadLocal<LinkedList<PageContext>> threadPageContexts =
new ThreadLocal<LinkedList<PageContext>>() {
- protected synchronized LinkedList<PageContext> initialValue() {
- return new LinkedList<PageContext>();
- }
- };
-
-
- protected static boolean ok(PageContext pc) {
- return pc == null || pc.getResponse() != null; // works in Tomcat
- }
- protected static PageContext
cleanThreadPageContexts(LinkedList<PageContext> stack) {
- if (stack.size() == 0) return null;
-
- PageContext proposal = stack.peek();
- while(stack.size() > 0) {
- if (ok(proposal)) {
- return proposal;
- } else {
- stack.poll();
- proposal = stack.peek();
- }
- }
- return null;
+ PageContextThreadLocal.setThreadPageContext(pc, this);
}
- protected static void setThreadPageContext(final PageContext pc) {
- LinkedList<PageContext> stack = threadPageContexts.get();
- cleanThreadPageContexts(stack);
- if (stack.size() == 0 || stack.getFirst() != pc) {
- stack.add(0, pc);
- }
- }
-
-
/**
+ * Returns the pageContext which is stored on a trhead local for this
request
+ * @return jsp pageContext
* @since MMBase-1.8.5
*/
public static PageContext getThreadPageContext() {
- LinkedList<PageContext> stack = threadPageContexts.get();
- if (stack.size() == 0) throw new RuntimeException("Used in thread
which did not yet use mmbase tags");
- return cleanThreadPageContexts(stack);
+ return PageContextThreadLocal.getThreadPageContext();
}
/**
* Just exposes the (otherwise protected) pageContext member. Needed by
some helper classes in
* the neighbourhood. Lacking concept of friends.
+ * @return JSP Page Context
*/
public PageContext getPageContext() {
return pageContext;
}
/**
+ * Returns the ContextTag first on the page
+ * @return ContextTag of page
* @since MMBase-1.7.4
*/
protected ContextTag getPageContextTag() {
if (pageContextTag == null) {
pageContextTag = (ContextTag)
pageContext.getAttribute(ContextTag.CONTEXTTAG_KEY);
-
- if (log.isDebugEnabled()) {
- log.debug("Found " + pageContextTag);
- }
if (pageContextTag == null) { // not yet put
if (log.isDebugEnabled()) {
log.debug("No pageContextTag found in pagecontext,
creating.. for "+ pageContext);
@@ -165,10 +130,7 @@
pageLog.service("Parsing JSP page: " + thisPage +
(queryString != null ? "?" + queryString :
"") + " for " + pageContext.getPage());
if (pageLog.isTraceEnabled()) {
- pageLog.trace("req " +
Collections.list(request.getAttributeNames()));
- pageLog.trace("page " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.PAGE_SCOPE)));
- pageLog.trace("app " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.APPLICATION_SCOPE)));
- pageLog.trace("req " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.REQUEST_SCOPE)));
+ logAttributes(request);
}
}
pageContextTag = new ContextTag();
@@ -201,6 +163,14 @@
return pageContextTag;
}
+ @SuppressWarnings("unchecked")
+ private void logAttributes(HttpServletRequest request) {
+ pageLog.trace("req " + Collections.list(request.getAttributeNames()));
+ pageLog.trace("page " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.PAGE_SCOPE)));
+ pageLog.trace("app " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.APPLICATION_SCOPE)));
+ pageLog.trace("req " +
Collections.list(pageContext.getAttributeNamesInScope(PageContext.REQUEST_SCOPE)));
+ }
+
public void setPageContext(PageContext pc) {
if (EVAL_BODY == -1) { // as yet unset
EVAL_BODY =
"true".equals(pc.getServletContext().getInitParameter("mmbase.taglib.eval_body_include"))
?
@@ -222,6 +192,8 @@
* a ContextReferrer has the 'id' attribute it registers its
* output in the surrounding Context. With 'referid' you can 'repeat' a
* tag which had the 'id' attribute.
+ * @param r referid value
+ * @throws JspTagException when parsing of attributes fails
*/
public void setReferid(String r) throws JspTagException {
@@ -267,12 +239,22 @@
* parent tag, so that this knows that it has a body. If a
* write-tag has a body, then on default it will not write itself,
* but only communicate itself tot the body's tags.
+ * @return Writer
+ * @throws JspTagException when parsing of attributes fails
*/
public Writer findWriter() throws JspTagException {
return findWriter(true);
}
+
/**
+ * Find the parent writer tag. It also calls haveBody on this
+ * parent tag, so that this knows that it has a body. If a
+ * write-tag has a body, then on default it will not write itself,
+ * but only communicate itself tot the body's tags.
+ * @param th if it has to throw an exception if the parent can not be
found (default: yes).
+ * @return Writer
+ * @throws JspTagException when parsing of attributes fails
* @since MMBase-1.6.2
*/
public Writer findWriter(boolean th) throws JspTagException {
@@ -287,17 +269,21 @@
/**
* Sets the writer attribute.
+ * @param w unparsed attribute
+ * @throws JspTagException when parsing of attributes fails
*/
public void setWriter(String w) throws JspTagException {
writerid = getAttribute(w);
-
}
+ @SuppressWarnings("unused")
public int doEndTag() throws JspTagException {
return EVAL_PAGE;
}
public void doFinally() {
+ PageContextThreadLocal.cleanThreadPageContexts(this);
+ helper.doFinally();
thisPage = null;
pageContextTag = null;
writerid = Attribute.NULL;
@@ -334,7 +320,8 @@
* write in, another context then the direct parent (but is must
* be an ancestor). This is for analogy with other attributes
* like this.
- *
+ * @param c name of specific context
+ * @throws JspTagException when parsing of attributes fails
*/
public void setContext(String c) throws JspTagException {
@@ -351,20 +338,26 @@
* end of the variable if determined by the closing bracket (${x})
* or by the first non ContextIndentifierChar or end of string ($x).
*
- * Simple aritmetic is possible with ${+...}, and since you can
+ * Simple arithmetic is possible with ${+...}, and since you can
* even use $-vars inside ${}, you can do in this way some
* arithmetic on variables.
*
+ * @param attribute name of attribute
+ * @return Value of attribute
+ * @throws JspTagException when parsing of attributes fails
+ *
* @deprecated Call getAttribute in the set-method and 'toString(tag)'
when using
- * it. This is better for perfomrnace and makes sure the impl.
works in all servlet
+ * it. This is better for performance and makes sure the impl.
works in all servlet
* containers.
*/
-
public String getAttributeValue(String attribute) throws JspTagException {
if (attribute == null) return null;
return getAttribute(attribute).getString(this);
}
/**
+ * @param attribute unparsed attribute
+ * @return Attribute
+ * @throws JspTagException when parsing of attributes fails
* @since MMBase-1.6.1
*/
public Attribute getAttribute(String attribute) throws JspTagException {
@@ -374,6 +367,9 @@
/**
* Like getAttributeValue but converts the result to a Boolean,
* and throws an exception if this cannot be done.
+ * @param b unparsed attribute
+ * @return boolean
+ * @throws JspTagException when parsing of attributes fails
**/
protected Boolean getAttributeBoolean(String b) throws JspTagException {
@@ -390,8 +386,10 @@
* Like getAttributeValue but converts the result to an Integer,
* and throws an exception if this cannot be done. It the incoming string
evaluates to an empty string, then
* it will return 0, unless the second optional parameter specifies
another default value;
+ * @param i unparsed attribute
+ * @return integer value of attribute
+ * @throws JspTagException when parsing of attributes fails
**/
-
protected Integer getAttributeInteger(String i) throws JspTagException {
return getAttributeInteger(i, 0);
}
@@ -414,10 +412,12 @@
* Finds a parent tag by class and id. This is a base function for
* 'getContext', but it is handy in itself, so also available for
* extended classes.
- *
+ * @param <C> type of the tag class
* @param clazz the class of the Tag to find.
* @param tagId the id of the Tag to find.
* @param exception if it has to throw an exception if the parent can not
be found (default: yes).
+ * @return Parent tag
+ * @throws JspTagException when the parent tag is not found
* @since MMBase-1.7
*/
public <C> C findParentTag(Class<C> clazz, String tagId, boolean
exception) throws JspTagException {
@@ -451,11 +451,16 @@
id = cTag instanceof TagSupport ? ((TagSupport) cTag).getId()
: "";
}
}
- return (C) cTag;
+ return (C) cTag;
}
/**
+ * Find loop or query tag using an id
+ * @param tagId the id of the Tag to find.
+ * @param exception if it has to throw an exception if the parent can not
be found (default: yes).
+ * @return Tag
+ * @throws JspTagException when parent tag is not found
* @since MMBase-1.8
*/
public Tag findLoopOrQuery(String tagId, boolean exception) throws
JspTagException {
@@ -472,6 +477,14 @@
}
/**
+ * Finds a parent tag by class and id. This is a base function for
+ * 'getContext', but it is handy in itself, so also available for
+ * extended classes.
+ * @param <C> type of the tag class
+ * @param clazz the class of the Tag to find.
+ * @param id the id of the Tag to find.
+ * @return Parent tag
+ * @throws JspTagException when parent tag is not found
* @since MMBase-1.7
*/
final protected <C> C findParentTag(Class<C> clazz, String id) throws
JspTagException {
@@ -480,9 +493,10 @@
/**
* Finds the parent context provider.
+ * @throws JspTagException when context provider is not found
+ * @return ContextProvider
* @since MMBase-1.7
*/
-
public ContextProvider getContextProvider() throws JspTagException {
return getContextProvider((String) contextId.getValue(this),
ContextProvider.class);
}
@@ -490,9 +504,9 @@
/**
* Finds the parent context tag. In MMBase 1.7 and higher,
* normally you would like to use getContextProvider in stead.
- *
+ * @return ContextTag
+ * @throws JspTagException when context provider is not found
*/
-
public ContextTag getContextTag() throws JspTagException {
return getContextProvider((String) contextId.getValue(this),
ContextTag.class);
}
@@ -500,9 +514,13 @@
/**
* Finds a parent context tag using an id, and a class. The class
* is ContextProvider or ContextTag.
+ * @param <E> SubType of ContextProvider
+ * @param contextid the id of the ContextProvider to find.
+ * @param cl the class of the ContextProvider to find.
+ * @return ContextProvider
+ * @throws JspTagException when context provider is not found
* @since MMBase-1.7
*/
-
private <E extends ContextProvider> E getContextProvider(String contextid,
Class<E> cl) throws JspTagException {
if(log.isDebugEnabled()) {
@@ -511,7 +529,7 @@
E contextTag = findParentTag(cl, contextid, false);
if (contextTag == null ||
- // doesn't count becase it is on a different page, (this tag e.g.
is in a tag-file)
+ // doesn't count because it is on a different page, (this tag e.g.
is in a tag-file)
// necessary in tomcat > 5.5.20 only.
// See http://issues.apache.org/bugzilla/show_bug.cgi?id=31804
contextTag.getContextContainer().getPageContext() != pageContext) {
@@ -537,7 +555,9 @@
/**
* Gets an object from the Context.
- *
+ * @param key key the object is stored under
+ * @return stored object
+ * @throws JspTagException when context provider is not found
*/
public Object getObject(String key) throws JspTagException {
// does the key contain '.', then start searching on pageContextTag,
otherwise in parent.
@@ -557,6 +577,9 @@
/**
* Support '[key]?', which returns the object with name [key] if it is
present, or simply null otherwise.
* If not ends with ?, it simply behaves like [EMAIL PROTECTED]
#getObject(String)}.
+ * @param key key the object is stored under
+ * @return stored object
+ * @throws JspTagException when context provider is not found
* @since MMBase-1.8.1
*/
public Object getObjectConditional(String key) throws JspTagException {
@@ -567,6 +590,7 @@
return getObject(key);
}
}
+
/**
* Gets an object from the Context, and returns it as a
* String. This is not always a simple 'toString'. For example a
@@ -574,8 +598,10 @@
* identifies it.
*
* If the object is 'not present' then it returns an empty string.
+ * @param key key the string is stored under
+ * @return stored string
+ * @throws JspTagException when context provider is not found
*/
-
protected String getString(String key) throws JspTagException {
return Casting.toString(getObject(key));
}
@@ -583,9 +609,10 @@
/**
* Returns the content-tag in which this context-referrer is in,
* or a default (compatible with MMBase 1.6) if there is none.
+ * @return ContextTag
+ * @throws JspTagException when parent tag is not found
* @since MMBase-1.7
*/
-
public ContentTag getContentTag() throws JspTagException {
ContentTag ct = findParentTag(ContentTag.class, null, false);
if (ct == null) {
@@ -598,8 +625,7 @@
/**
* Get the locale which is defined by surrounding tags or the cloud
* @return a locale when defined or otherwise the mmbase locale.
- * @throws JspTagException
-
+ * @throws JspTagException when parent tag is not found
* @since MMBase-1.7.1
*/
public Locale getLocale() throws JspTagException {
@@ -613,7 +639,7 @@
/**
* Get the locale which is defined by surrounding tags or the cloud
* @return a locale when defined or otherwise <code>null</code>
- * @throws JspTagException
+ * @throws JspTagException when parent tag is not found
*
* @since MMBase-1.8.1
*/
@@ -644,7 +670,7 @@
/**
* Get the default locale which is set in mmbase.
- *
+ * @return default locale
* @since MMBase-1.8.1
*/
public Locale getDefaultLocale() {
@@ -652,6 +678,8 @@
}
/**
+ * Get the timezone from the context or the timezone set in mmbase
+ * @return timezone
* @since MMBase-1.8
*/
public TimeZone getTimeZone() {
@@ -659,7 +687,11 @@
if (timeZone != null) return timeZone;
return
org.mmbase.bridge.ContextProvider.getDefaultCloudContext().getDefaultTimeZone();
}
+
/**
+ * Fill standard parameters like request, response, language and locale
+ * @param p the parameters
+ * @throws JspTagException when parent tag is not found
* @since MMBase-1.7.4
*/
public void fillStandardParameters(Parameters p) throws JspTagException {
@@ -676,13 +708,12 @@
- // Writer Implmentation
+ // Writer Implementation
// Not all ContextReferrerTags are actually Writers, but no m.i. in java.
/**
* The helper member is only used by 'Writer' extensions.
*/
-
final protected WriterHelper helper = new WriterHelper(this);
// sigh, we would of course prefer to extend, but no multiple inheritance
possible in Java..
@@ -690,6 +721,9 @@
helper.setVartype(t);
}
/**
+ * Set list delimiter
+ * @param l delimiter
+ * @throws JspTagException when parsing of attributes fails
* @since MMBase-1.8
*/
final public void setListdelimiter(String l) throws JspTagException {
@@ -712,11 +746,19 @@
final public void haveBody() { helper.haveBody(); }
/**
- * Returns the escaped value associated with this tag, but only if the
escape attribute was set explicitely (so not when only inherited from
content-tag).
+ * Returns the escaped value associated with this tag, but only if the
escape attribute was set
+ * explicitly (so not when only inherited from content-tag).
+ * @param value initial value
+ * @return escaped value
+ * @throws JspTagException when parsing of attributes fails
* @since MMBase-1.8
*/
protected Object getEscapedValue(Object value) throws JspTagException {
if (helper.getEscape() == null) {
+// if(value instanceof NodeList) {
+// return value;
+// }
+
// do wrap though, to maintain EL compatibility (also e.g. when
written to request)
return value == null ? null : Casting.wrap(value, null);
} else {
@@ -726,17 +768,21 @@
/**
+ * Get the surrounding form tag
+ * @param excpetion throw exception when form tag not found
+ * @param form name of form
+ * @return FormTag
+ * @throws JspTagException when parsing of attributes fails
* @since MMBase-1.8.5
*/
- public FormTag getFormTag(boolean t, Attribute form) throws
JspTagException {
+ public FormTag getFormTag(boolean excpetion, Attribute form) throws
JspTagException {
FormTag formTag;
if (form == null || form == Attribute.NULL) {
formTag = (FormTag) pageContext.getAttribute(FormTag.KEY,
FormTag.SCOPE);
- if (formTag == null && t) throw new JspTagException("No form-tag
found (" + FormTag.KEY + ")");
+ if (formTag == null && excpetion) throw new JspTagException("No
form-tag found (" + FormTag.KEY + ")");
} else {
- formTag = (FormTag) findParentTag(FormTag.class, form != null ?
(String) form.getValue(this) : null, true);
+ formTag = findParentTag(FormTag.class, form != null ? (String)
form.getValue(this) : null, true);
}
return formTag;
}
-
}
_______________________________________________
Cvs mailing list
[email protected]
http://lists.mmbase.org/mailman/listinfo/cvs