You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ma...@apache.org on 2008/10/23 11:26:33 UTC
svn commit: r707325 - in /myfaces/trinidad/branches/1.2.9.1-branch:
trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/
trinidad-api/src/main/java/org/apache/myfaces/trinidad/co...
Author: matzew
Date: Thu Oct 23 02:26:32 2008
New Revision: 707325
URL: http://svn.apache.org/viewvc?rev=707325&view=rev
Log:
TRINIDAD-1273 - Apply a request lifecuycle to ThreadLocals so that their contents don't leak across requests
Thanks to Blake Sullivan for his patch
Added:
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ThreadLocalUtils.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ThreadLocalResetter.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle.REQUEST
Modified:
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/FacesBeanFactory.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RenderingContext.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/FastMessageFormat.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/MessageFactory.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/table/TableRenderingContext.java
myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/FacesBeanFactory.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/FacesBeanFactory.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/FacesBeanFactory.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/bean/FacesBeanFactory.java Thu Oct 23 02:26:32 2008
@@ -32,6 +32,7 @@
import java.util.concurrent.ConcurrentHashMap;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
/**
@@ -272,7 +273,7 @@
static private Map<Object, Object> _TYPES_MAP;
static private Map<String, Class<?>> _TYPES_CLASS = new ConcurrentHashMap<String, Class<?>>();
static private final ThreadLocal<StringBuilder> _STRING_BUILDER =
- new ThreadLocal<StringBuilder>();
+ ThreadLocalUtils.newRequestThreadLocal();
static
{
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/component/UIXComponentBase.java Thu Oct 23 02:26:32 2008
@@ -59,6 +59,7 @@
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.render.ExtendedRenderer;
import org.apache.myfaces.trinidad.render.LifecycleRenderer;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
/**
@@ -1478,7 +1479,7 @@
static private final ThreadLocal<StringBuilder> _STRING_BUILDER =
- new ThreadLocal<StringBuilder>();
+ ThreadLocalUtils.newRequestThreadLocal();
static private FacesBean.Type _createType()
{
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RenderingContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RenderingContext.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RenderingContext.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/context/RenderingContext.java Thu Oct 23 02:26:32 2008
@@ -25,6 +25,7 @@
import org.apache.myfaces.trinidad.skin.Skin;
import org.apache.myfaces.trinidad.skin.Icon;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
/**
*/
@@ -150,7 +151,7 @@
static private final ThreadLocal<RenderingContext> _CURRENT_CONTEXT =
- new ThreadLocal<RenderingContext>();
+ ThreadLocalUtils.newRequestThreadLocal();
static private final TrinidadLogger _LOG =
TrinidadLogger.createTrinidadLogger(RenderingContext.class);
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/FastMessageFormat.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/FastMessageFormat.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/FastMessageFormat.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/FastMessageFormat.java Thu Oct 23 02:26:32 2008
@@ -6,9 +6,9 @@
* to you 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
@@ -24,7 +24,7 @@
* The FastMessageFormat class is a greatly reduced version
* of the java.text.MessageFormat class. It's also much faster
* and much less expensive to create, which is especially
- * valuable when it is created and thrown away many times -
+ * valuable when it is created and thrown away many times -
* a common use case in web applications.
* <p>
* The only syntax supported by this class is simple index-based
@@ -130,33 +130,29 @@
}
else
{
- if ((patternChar < '0') ||
- (patternChar > '9'))
- throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
- "FASTMESSAGEFORMAT_ONLY_SUPPORT_NUMERIC_ARGUMENTS"));
+ if ((patternChar < '0') || (patternChar > '9'))
+ throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString("FASTMESSAGEFORMAT_ONLY_SUPPORT_NUMERIC_ARGUMENTS"));
sourceIndex = (sourceIndex * 10) + (patternChar - '0');
}
}
if (j == formatLength)
- throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
- "END_OF_PATTERN_NOT_FOUND"));
+ throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString("END_OF_PATTERN_NOT_FOUND"));
if (j == i + 1)
- throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString(
- "FASTMESSAGEFORMAT_FIND_EMPTY_ARGUMENT"));
+ throw new IllegalArgumentException(_LOG.getLogger().getResourceBundle().getString("FASTMESSAGEFORMAT_FIND_EMPTY_ARGUMENT"));
if (sourceIndex < sourceCount)
{
Object sourceString = source[sourceIndex];
if (sourceString != null)
buffer.append(sourceString.toString());
}
-
+
i = j;
lastStart = i + 1;
}
else
{
- // Do nothing. The character will be added in later
+ // Do nothing. The character will be added in later
;
}
}
@@ -167,11 +163,85 @@
return new String(buffer);
}
- private final char[] _formatText;
- private static final TrinidadLogger _LOG = TrinidadLogger.createTrinidadLogger(
- FastMessageFormat.class);
-}
+ /**
+ * Formats the given array of strings based on the initial
+ * pattern. It is legal for this array to be shorter
+ * than that indicated by the pattern, or to have null
+ * entries - these will simply be ignored.
+ * This formatter will only replace expressions of the type "{[0-9]+}".
+ * Any other use of '{}' will be interpreted as literal text.
+ * This is the same behavior as TrFastMessageFormatUtils.format on the client.
+ * <p>
+ * @param source an array of strings
+ */
+ public String formatLikeClient(Object[] source)
+ {
+ int formatLength = _formatText.length;
+ int length = 0;
+ int sourceCount = source.length;
+ for (int i = 0; i < sourceCount; i++)
+ {
+ Object sourceString = source[i];
+ if (sourceString != null)
+ {
+ length += sourceString.toString().length();
+ }
+ }
+
+ StringBuffer buffer = new StringBuffer(length + formatLength);
+
+ int lastStart = 0;
+ for (int i = 0; i < formatLength; i++)
+ {
+ char ch = _formatText[i];
+ if (ch == '{')
+ {
+ buffer.append(_formatText, lastStart, i - lastStart);
+
+ int sourceIndex = 0;
+ int j = i + 1;
+ char patternChar = ' ';
+ for (; j < formatLength; j++)
+ {
+ patternChar = _formatText[j];
+ if ((patternChar < '0') || (patternChar > '9'))
+ break;
+ sourceIndex = (sourceIndex * 10) + (patternChar - '0');
+ }
+
+ if (j > i + 1 && patternChar == '}')
+ {
+ if (sourceIndex < sourceCount)
+ {
+ Object sourceString = source[sourceIndex];
+ if (sourceString != null)
+ buffer.append(sourceString.toString());
+ }
+ i = j;
+ }
+ else
+ {
+ // interpret the chars literally
+ buffer.append(_formatText, i, j - i);
+ i = j - 1;
+ }
+
+ lastStart = i + 1;
+ }
+ else
+ {
+ // Do nothing. The character will be added in later
+ ;
+ }
+ }
+ buffer.append(_formatText, lastStart, formatLength - lastStart);
+ return new String(buffer);
+ }
+ private final char[] _formatText;
+ private static final TrinidadLogger _LOG =
+ TrinidadLogger.createTrinidadLogger(FastMessageFormat.class);
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/MessageFactory.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/MessageFactory.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/MessageFactory.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/MessageFactory.java Thu Oct 23 02:26:32 2008
@@ -430,7 +430,7 @@
{
if (parameters == null)
return pattern;
-
+
FastMessageFormat formatter = new FastMessageFormat(pattern);
String fmtedMsgStr = formatter.format(parameters);
return fmtedMsgStr;
@@ -610,7 +610,7 @@
_customDetailErrorMessage = customDetailErrorMessage;
_hasBoundParameters = hasBoundParameters;
}
-
+
// Currently only detail message can be customized. So we override the
// detail message. If summary is to be overridden we have to do the
// same to it also.
@@ -619,6 +619,7 @@
{
FacesContext context = FacesContext.getCurrentInstance();
String detailMsgPattern = (String)_customDetailErrorMessage.getValue(context.getELContext());
+
if(detailMsgPattern == null)
{
// Set a default message that might get used by FacesException
@@ -631,7 +632,10 @@
// Since that string will get parsed by FastMessageFormat, the { }
// of the EL must be escaped
- detailMsgPattern = '\'' + detailMsgPattern + '\'';
+ //detailMsgPattern = '\'' + detailMsgPattern + '\'';
+
+ // No need to format this string, just return it here.
+ return detailMsgPattern;
}
Object[] params = super.getParameters();
Added: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ThreadLocalUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ThreadLocalUtils.java?rev=707325&view=auto
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ThreadLocalUtils.java (added)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-api/src/main/java/org/apache/myfaces/trinidad/util/ThreadLocalUtils.java Thu Oct 23 02:26:32 2008
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.trinidad.util;
+
+import java.lang.ref.WeakReference;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+/**
+ * Utility functions related to ThreadLocals.
+ * This class provides utilities for managing the lifecycles of ThreadLocals.
+ * In particular, many application servers do not clean up the ThreadLocals
+ * added to the request thread before returning the request thread to
+ * its thread pool. This may have several severe side-effects, including
+ * <ol>
+ * <li>Leakage of objects referenced by the thread local</li>
+ * <li>Possible security holes if the ThreadLocals contents are reused
+ * on a request for a different user.</li>
+ * <li>Leakage of the entire class loader in live patching scenarios</li>
+ * <li>ClassCastExceptions in live patching scenarios</li>
+ * </ol>
+ * To avoid these problems, this class provides utilities for creating
+ * and registering ThreadLocals that will be removed from the thread
+ * automatically at the end of the current request.
+ * @see #newRequestThreadLocal
+ * @see #registerRequestThreadLocal
+ */
+public final class ThreadLocalUtils
+{
+ /**
+ * Integration interface implemented by object holding onto ThreadLocals
+ * with a specified lifetime
+ * @see ThreadLocalLifecycle
+ */
+ public static abstract class ThreadLocalManager
+ {
+ /**
+ * Called by the ThreadLocalLifeCycle when the ThreadLocals managed by
+ * this ThreadLocalManager need to be cleaned up by removing their
+ * instances from the current Thread.
+ */
+ public abstract void removeThreadLocals();
+ }
+
+ /**
+ * Integration interface implemented by an object that cleans up the
+ * ThreadLocals in a ThreadLocalManager with the specified lifetime.
+ * The ThreadLocalLifecycle cleans up the ThreadLocals by calling
+ * <code>removeThreadLocals</code> on the ThreadLocalManager passed
+ * to it in <code>init</code> at the appropriate time.
+ * @see ThreadLocalManager
+ * @see #init
+ */
+ public static abstract class ThreadLocalLifecycle
+ {
+ /**
+ * Called after instantiating the ThreadLocalLifecycle so that the
+ * ThreadLocalLifecycle can clean up the ThreadLocalManager at the
+ * appropriate moment.
+ * @param manager Manager of ThreadLocals that will be cleaned up by
+ * this ThreadLocalLifecycle.
+ * @see ThreadLocalManager#removeThreadLocals
+ */
+ public abstract void init(ThreadLocalManager manager);
+ }
+
+ // don't allow instantiation
+ private ThreadLocalUtils()
+ {
+ }
+
+ /**
+ * Creates and returns a new ThreadLocal that will be automatically removed from
+ * the each request thread when the request finishes.
+ * @return The ThreadLocal
+ * @see #registerRequestThreadLocal
+ */
+ public static <T> ThreadLocal<T> newRequestThreadLocal()
+ {
+ return registerRequestThreadLocal(new ThreadLocal<T>());
+ }
+
+ /**
+ * Registers and returns the ThreadLocal to be automatically removed from
+ * the each request thread when the request finishes.
+ * @param threadLocal ThreadLocal to register for automatic removal
+ * @return The reigistered ThreadLocal
+ * @see #newRequestThreadLocal
+ */
+ public static <T> ThreadLocal<T> registerRequestThreadLocal(ThreadLocal<T> threadLocal)
+ {
+ return _getThreadLocalManager(_REQUEST_SERVICE).registerThreadLocal(threadLocal);
+ }
+
+ /**
+ * Returns the ResettableThreadLocalManager for the specified threadLocalGroup name. If no
+ * ResettableThreadLocalManager is currently registered for the threadLocalGroup, one will
+ * be instantiated, its related ThreadLocalLifecycle instantiated and the ThreadLocalManager
+ * registered with the ThreadLocalLifecycle
+ * @param threadLocalGroup Identifier for this group
+ * @return the ResettableThreadLocalManager for this threadLocalGroup name
+ */
+ private static ResettableThreadLocalManager _getThreadLocalManager(String threadLocalGroup)
+ {
+ // see if we already have a ResettableThreadLocalManager registered
+ ResettableThreadLocalManager threadLocalManager = _threadLocalManagers.get(threadLocalGroup);
+
+ // if we don't, create one
+ if (threadLocalManager == null)
+ {
+ threadLocalManager = new ResettableThreadLocalManager();
+
+ // handle simultaneous registration
+ ResettableThreadLocalManager oldThreadLocalManager =
+ _threadLocalManagers.putIfAbsent(threadLocalGroup, threadLocalManager);
+
+ if (oldThreadLocalManager != null)
+ {
+ // simultaneous registration, use the one that was registered first
+ threadLocalManager = oldThreadLocalManager;
+ }
+ else
+ {
+ // find the ThreadLocalLifecycle for this threadLocalGroup by looking in
+ // META-INF/Services, instantiate it and register ourselves with it so that we
+ // can be cleaned up
+ List<ThreadLocalLifecycle> lifecycles = ClassLoaderUtils.getServices(threadLocalGroup);
+
+ if (!lifecycles.isEmpty())
+ {
+ lifecycles.get(0).init(threadLocalManager);
+ }
+ }
+ }
+
+ return threadLocalManager;
+ }
+
+ /**
+ * ThreadLocalManager implementation class
+ */
+ private static class ResettableThreadLocalManager extends ThreadLocalManager
+ {
+ public ResettableThreadLocalManager()
+ {
+ // create the list of resettable ThreadLocals for this group
+ _threadLocals = new CopyOnWriteArrayList<WeakReference<ThreadLocal<?>>>();
+ }
+
+ /**
+ * Registers the ThreadLocal for cleanup when this ThreadLocalManager is cleaned up
+ * @param threadLocal ThreadLocal to register for clean up
+ * @return The registered ThreadLocal
+ */
+ public <T> ThreadLocal<T> registerThreadLocal(ThreadLocal<T> threadLocal)
+ {
+ if (threadLocal == null)
+ throw new NullPointerException();
+
+ // WeakReference might be overkill here, but make sure we don't pin ThreadLocals
+ _threadLocals.add(new WeakReference<ThreadLocal<?>>(threadLocal));
+
+ return threadLocal;
+ }
+
+ /**
+ * Called by the ThreadLocalLifecycle to clean up all of the ThreadLocals registered
+ * with this ThreadLocalManager
+ */
+ public void removeThreadLocals()
+ {
+ Iterator<WeakReference<ThreadLocal<?>>> iterator = _threadLocals.iterator();
+
+ while (iterator.hasNext())
+ {
+ ThreadLocal<?> threadLocal = iterator.next().get();
+
+ if (threadLocal == null)
+ {
+ // the threadLocal has been released, so remove this entry. It will be
+ // readded if the ThreadLocal is ever recreated
+ iterator.remove();
+ }
+ else
+ {
+ // reset the threadlocal for this thread
+ threadLocal.remove();
+ }
+ }
+ }
+
+ private final Collection<WeakReference<ThreadLocal<?>>> _threadLocals;
+ }
+
+ // Name used for the request-scoped ThreadLocalManager
+ private static final String _REQUEST_SERVICE = ThreadLocalUtils.class.getName() +
+ ".ThreadLocalLifecycle.REQUEST";
+
+ // threadLocalGroup -> ThreadLocalManager Map
+ private static final ConcurrentMap<String, ResettableThreadLocalManager>_threadLocalManagers
+ = new ConcurrentHashMap<String, ResettableThreadLocalManager>();
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/GlobalConfiguratorImpl.java Thu Oct 23 02:26:32 2008
@@ -23,6 +23,8 @@
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
import javax.faces.context.ExternalContext;
import javax.servlet.ServletRequest;
@@ -383,6 +385,19 @@
}
/**
+ * Hackily called by the ThreadLocalResetter to register itself so that the
+ * GlobalConfiguratorImpl can tell the ThreadLocalResetter to clean up the
+ * ThreadLocals at the appropriate time.
+ */
+ void __setThreadLocalResetter(ThreadLocalResetter resetter)
+ {
+ if (resetter == null)
+ throw new NullPointerException();
+
+ _threadResetter.set(resetter);
+ }
+
+ /**
* @param externalContext
* @return
*/
@@ -401,6 +416,10 @@
_LOG.warning("REQUESTCONTEXT_NOT_PROPERLY_RELEASED");
}
context.release();
+ ThreadLocalResetter resetter = _threadResetter.get();
+
+ if (resetter != null)
+ resetter.__removeRequestThreadLocals();
}
// See if we've got a cached RequestContext instance; if so,
@@ -440,6 +459,13 @@
{
context.release();
assert RequestContext.getCurrentInstance() == null;
+
+ // now that the request is over, clean up all of the request-scoped
+ // ThreadLocals.
+ ThreadLocalResetter resetter = _threadResetter.get();
+
+ if (resetter != null)
+ resetter.__removeRequestThreadLocals();
}
}
@@ -719,6 +745,10 @@
".TEST_PARAM";
}
+ // hacky reference to the ThreadLocalResetter used to clean up request-scoped
+ // ThreadLocals
+ private AtomicReference<ThreadLocalResetter> _threadResetter =
+ new AtomicReference<ThreadLocalResetter>();
static private final TrinidadLogger _LOG =
TrinidadLogger.createTrinidadLogger(GlobalConfiguratorImpl.class);
Added: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ThreadLocalResetter.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ThreadLocalResetter.java?rev=707325&view=auto
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ThreadLocalResetter.java (added)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/config/ThreadLocalResetter.java Thu Oct 23 02:26:32 2008
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.myfaces.trinidadinternal.config;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalManager;
+
+/**
+ * Implementation of ThreadLocalLifecycle for request-scoped ThreadLocals, registered
+ * through META-INF/SERVICES. This class cooperates with GlobalConfiguratorImpl in order
+ * to ensure that the request-scoped ThreadLocals are cleaned up at the end of each
+ * request.
+ */
+public class ThreadLocalResetter extends ThreadLocalLifecycle
+{
+ /**
+ * All class to be instatiated through reflection
+ */
+ public ThreadLocalResetter()
+ {
+ }
+
+ /**
+ * Called by ThreadLocalUtils after instantiating the ThreadLocalResetter in order to
+ * pass the ThreadLocalManager to use to clean up the request-scoped ThreadLocals.
+ */
+ public void init(ThreadLocalManager manager)
+ {
+ if (manager == null)
+ throw new NullPointerException();
+
+ // save the ThreadLocalManager to use to clean up the request-scoped ThreadLocals
+ _threadLocalManager.set(manager);
+
+ // slam a reference to our instance on the GlobalConfiguratorImpl so that it can
+ // call __removeRequestThreadLocals when the request is finished
+ GlobalConfiguratorImpl.getInstance().__setThreadLocalResetter(this);
+ }
+
+ /**
+ * Called by the GlobalConfiguratorImpl when the request is finished so that the
+ * ThreadLocalResetter can ask the ThreadLocalManager to clean itself up
+ */
+ void __removeRequestThreadLocals()
+ {
+ ThreadLocalManager threadLocalManager = _threadLocalManager.get();
+
+ if (threadLocalManager != null)
+ {
+ // clean up all of the request-scoped ThreadLocals
+ threadLocalManager.removeThreadLocals();
+ }
+ }
+
+ // ThreadLocalManager to clean up
+ private AtomicReference<ThreadLocalManager> _threadLocalManager = new
+ AtomicReference<ThreadLocalManager>();
+}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/menu/MenuUtils.java Thu Oct 23 02:26:32 2008
@@ -33,11 +33,12 @@
import javax.faces.webapp.UIComponentTag;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
/**
* Menu Utilities used by the Menu Model internal code.
* All classes are package private.
- *
+ *
*/
class MenuUtils
{
@@ -299,7 +300,7 @@
@SuppressWarnings("unchecked")
static void loadBundle(String resBundleName, String resBundleKey)
{
- ThreadLocal<String> bundleKey = new ThreadLocal<String>();
+ ThreadLocal<String> bundleKey = ThreadLocalUtils.newRequestThreadLocal();
bundleKey.set(resBundleKey);
loadBundle(resBundleName, bundleKey);
@@ -455,3 +456,4 @@
+
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/table/TableRenderingContext.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/table/TableRenderingContext.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/table/TableRenderingContext.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/renderkit/core/xhtml/table/TableRenderingContext.java Thu Oct 23 02:26:32 2008
@@ -32,6 +32,7 @@
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidad.render.CoreRenderer;
+import org.apache.myfaces.trinidad.util.ThreadLocalUtils;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.SkinSelectors;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlRenderer;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.XhtmlUtils;
@@ -597,5 +598,5 @@
static private final ThreadLocal<TableRenderingContext> _CURRENT_CONTEXT =
- new ThreadLocal<TableRenderingContext>();
+ ThreadLocalUtils.newRequestThreadLocal();
}
Modified: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java?rev=707325&r1=707324&r2=707325&view=diff
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java (original)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/java/org/apache/myfaces/trinidadinternal/webapp/TrinidadFilterImpl.java Thu Oct 23 02:26:32 2008
@@ -288,11 +288,7 @@
"org.apache.myfaces.trinidadinternal.webapp.AdfacesFilterImpl.EXECUTED";
private static ThreadLocal<PseudoFacesContext> _PSEUDO_FACES_CONTEXT =
- new ThreadLocal<PseudoFacesContext>()
- {
- @Override
- protected PseudoFacesContext initialValue() { return null; }
- };
+ new ThreadLocal<PseudoFacesContext>();
private static final TrinidadLogger _LOG =
TrinidadLogger.createTrinidadLogger(TrinidadFilterImpl.class);
Added: myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle.REQUEST
URL: http://svn.apache.org/viewvc/myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle.REQUEST?rev=707325&view=auto
==============================================================================
--- myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle.REQUEST (added)
+++ myfaces/trinidad/branches/1.2.9.1-branch/trinidad-impl/src/main/resources/META-INF/services/org.apache.myfaces.trinidad.util.ThreadLocalUtils.ThreadLocalLifecycle.REQUEST Thu Oct 23 02:26:32 2008
@@ -0,0 +1 @@
+org.apache.myfaces.trinidadinternal.config.ThreadLocalResetter