You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2011/06/16 20:01:26 UTC
svn commit: r1136573 - in
/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets: ./
el/ impl/ tag/ tag/jstl/core/ tag/ui/
Author: lu4242
Date: Thu Jun 16 18:01:26 2011
New Revision: 1136573
URL: http://svn.apache.org/viewvc?rev=1136573&view=rev
Log:
MYFACES-3160 [PERF] TagAttributeImpl part II: object allocations (cache ELExpressions)
Added:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ELExpressionCacheMode.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperBase.java
Modified:
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/PageContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/TemplateContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/DefaultVariableMapper.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperWrapper.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/PageContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/TemplateContextImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributeImpl.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/UserTagHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jstl/core/SetHandler.java
myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/ui/ParamHandler.java
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/AbstractFaceletContext.java Thu Jun 16 18:01:26 2011
@@ -227,4 +227,50 @@ public abstract class AbstractFaceletCon
{
return null;
}
+
+ /**
+ * Check if a variable has been resolved by this variable mapper
+ * or any parent "facelets contextual" variable mapper.
+ *
+ * @return
+ * @since 2.0.8
+ */
+ public boolean isAnyFaceletsVariableResolved()
+ {
+ return true;
+ }
+
+ public boolean isAllowCacheELExpressions()
+ {
+ return false;
+ }
+
+ /**
+ * Indicates an expression will be resolved, so preparations
+ * should be done to detect if a contextual variable has been resolved.
+ *
+ * @since 2.0.8
+ */
+ public void beforeConstructELExpression()
+ {
+ }
+
+ /**
+ * Cleanup all initialization done for construct an EL Expression.
+ *
+ * @since 2.0.8
+ */
+ public void afterConstructELExpression()
+ {
+ }
+
+ /**
+ * Return the mode used to decide whether to cache or not EL expressions
+ *
+ * @since 2.0.8
+ */
+ public ELExpressionCacheMode getELExpressionCacheMode()
+ {
+ return ELExpressionCacheMode.noCache;
+ }
}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ELExpressionCacheMode.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ELExpressionCacheMode.java?rev=1136573&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ELExpressionCacheMode.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/ELExpressionCacheMode.java Thu Jun 16 18:01:26 2011
@@ -0,0 +1,56 @@
+/*
+ * 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.view.facelets;
+
+public enum ELExpressionCacheMode
+{
+ /**
+ * Does not cache expressions.
+ */
+ noCache,
+
+ /**
+ * Does not cache expressions on these cases:
+ * - A c:set tag with only var and value properties was used on the current page.
+ * - ui:param was used on the current template context
+ * - Inside user tags
+ * - An expression uses a variable resolved through VariableMapper
+ */
+ strict,
+
+ /**
+ * Does not cache expressions on these cases:
+ * - ui:param was used on the current template context
+ * - Inside user tags
+ * - An expression uses a variable resolved through VariableMapper
+ *
+ * In this case, c:set is assumed to be always on the parent node.
+ */
+ allowCset,
+
+ /**
+ * Does not cache expressions on these cases:
+ * - Inside user tags
+ * - An expression uses a variable resolved through VariableMapper
+ *
+ * Note if ui:param is used, each template call should define the same
+ * param count, even if only just a few are used.
+ */
+ always
+}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java Thu Jun 16 18:01:26 2011
@@ -18,10 +18,8 @@
*/
package org.apache.myfaces.view.facelets;
-import java.util.Collection;
import java.util.Iterator;
import java.util.List;
-import java.util.Map;
import javax.faces.component.UIComponent;
import javax.faces.component.UniqueIdVendor;
@@ -333,5 +331,15 @@ abstract public class FaceletComposition
* @return A value that could be useful to revert its effects.
*/
public abstract Object removeMethodExpressionTargeted(UIComponent targetedComponent, String attributeName);
-
+
+ /**
+ * Indicates if a EL Expression can be or not cached by facelets vdl.
+ *
+ * @since 2.0.8
+ * @return
+ */
+ public ELExpressionCacheMode getELExpressionCacheMode()
+ {
+ return ELExpressionCacheMode.noCache;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/PageContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/PageContext.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/PageContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/PageContext.java Thu Jun 16 18:01:26 2011
@@ -34,4 +34,9 @@ public abstract class PageContext
public abstract Map<String, ValueExpression> getAttributes();
public abstract int getAttributeCount();
+
+ public abstract boolean isAllowCacheELExpressions();
+
+ public abstract void setAllowCacheELExpressions(boolean cacheELExpressions);
+
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/TemplateContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/TemplateContext.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/TemplateContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/TemplateContext.java Thu Jun 16 18:01:26 2011
@@ -126,4 +126,18 @@ public abstract class TemplateContext
* @return
*/
public abstract Map<String, ValueExpression> getParameterMap();
+
+ /**
+ *
+ * @since 2.0.8
+ * @return
+ */
+ public abstract boolean isAllowCacheELExpressions();
+
+ /**
+ *
+ * @since 2.0.8
+ * @return
+ */
+ public abstract void setAllowCacheELExpressions(boolean cacheELExpressions);
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/DefaultVariableMapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/DefaultVariableMapper.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/DefaultVariableMapper.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/DefaultVariableMapper.java Thu Jun 16 18:01:26 2011
@@ -37,7 +37,7 @@ import org.apache.myfaces.view.facelets.
* @author Jacob Hookom
* @version $Id: DefaultVariableMapper.java,v 1.3 2008/07/13 19:01:43 rlubke Exp $
*/
-public final class DefaultVariableMapper extends VariableMapper
+public final class DefaultVariableMapper extends VariableMapperBase
{
private Map<String, ValueExpression> _vars;
@@ -46,10 +46,16 @@ public final class DefaultVariableMapper
private TemplateContext _templateContext;
private VariableMapper _delegate;
+
+ public boolean _trackResolveVariables;
+
+ public boolean _variableResolved;
public DefaultVariableMapper()
{
super();
+ _trackResolveVariables = false;
+ _variableResolved = false;
}
public DefaultVariableMapper(VariableMapper delegate)
@@ -69,26 +75,47 @@ public final class DefaultVariableMapper
{
returnValue = _vars.get(name);
}
-
- if (returnValue == null && _pageContext != null)
+
+ //If the variable is not on the VariableMapper
+ if (returnValue == null)
{
- if (returnValue == null && _pageContext.getAttributeCount() > 0)
+ //Check on page and template context
+ if (_pageContext != null && _pageContext.getAttributeCount() > 0)
{
- returnValue = _pageContext.getAttributes().get(name);
+ if (_pageContext.getAttributes().containsKey(name))
+ {
+ returnValue = _pageContext.getAttributes().get(name);
+ if (_trackResolveVariables)
+ {
+ _variableResolved = true;
+ }
+ return returnValue;
+ }
}
- }
-
- if (returnValue == null && _templateContext != null)
- {
- if (returnValue == null && !_templateContext.isParameterEmpty())
+
+ if (_templateContext != null && !_templateContext.isParameterEmpty())
{
- returnValue = _templateContext.getParameter(name);
+ if (_templateContext.getParameterMap().containsKey(name))
+ {
+ returnValue = _templateContext.getParameter(name);
+ if (_trackResolveVariables)
+ {
+ _variableResolved = true;
+ }
+ return returnValue;
+ }
}
- }
-
- if (returnValue == null && _delegate != null)
+
+ if (_delegate != null)
+ {
+ returnValue = _delegate.resolveVariable(name);
+ }
+ }
+ else if (_trackResolveVariables)
{
- returnValue = _delegate.resolveVariable(name);
+ // Is this code in a block that wants to cache
+ // the resulting expression(s) and variable has been resolved?
+ _variableResolved = true;
}
return returnValue;
@@ -126,4 +153,32 @@ public final class DefaultVariableMapper
{
this._templateContext = templateContext;
}
+
+ @Override
+ public boolean isAnyFaceletsVariableResolved()
+ {
+ if (_trackResolveVariables)
+ {
+ return _variableResolved;
+ }
+ else
+ {
+ //Force expression creation
+ return true;
+ }
+ }
+
+ @Override
+ public void beforeConstructELExpression()
+ {
+ _trackResolveVariables = true;
+ _variableResolved = false;
+ }
+
+ @Override
+ public void afterConstructELExpression()
+ {
+ _trackResolveVariables = false;
+ _variableResolved = false;
+ }
}
Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperBase.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperBase.java?rev=1136573&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperBase.java (added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperBase.java Thu Jun 16 18:01:26 2011
@@ -0,0 +1,54 @@
+/*
+ * 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.view.facelets.el;
+
+import javax.el.VariableMapper;
+
+/**
+ * Defines an interface to detect when an EL expression has been
+ * resolved by a facelets variable mapper and in that way allow cache it
+ * if it is possible. This class should be implemented by any
+ * "facelets contextual" variable mapper.
+ *
+ * @since 2.0.8
+ * @author Leonardo Uribe
+ *
+ */
+public abstract class VariableMapperBase extends VariableMapper
+{
+
+ /**
+ * Check if a variable has been resolved by this variable mapper
+ * or any parent "facelets contextual" variable mapper.
+ *
+ * @return
+ */
+ public abstract boolean isAnyFaceletsVariableResolved();
+
+ /**
+ * Indicates an expression will be resolved, so preparations
+ * should be done to detect if a contextual variable has been resolved.
+ */
+ public abstract void beforeConstructELExpression();
+
+ /**
+ * Cleanup all initialization done.
+ */
+ public abstract void afterConstructELExpression();
+}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperWrapper.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperWrapper.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperWrapper.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/el/VariableMapperWrapper.java Thu Jun 16 18:01:26 2011
@@ -24,6 +24,7 @@ import java.util.Map;
import javax.el.ELException;
import javax.el.ValueExpression;
import javax.el.VariableMapper;
+import javax.faces.FacesWrapper;
/**
* Utility class for wrapping another VariableMapper with a new context, represented by a {@link java.util.Map Map}.
@@ -33,12 +34,20 @@ import javax.el.VariableMapper;
* @author Jacob Hookom
* @version $Id: VariableMapperWrapper.java,v 1.7 2008/07/13 19:01:43 rlubke Exp $
*/
-public final class VariableMapperWrapper extends VariableMapper
+public final class VariableMapperWrapper extends VariableMapperBase implements FacesWrapper<VariableMapper>
{
private final VariableMapper _target;
+
+ private final VariableMapperBase _targetBase;
private Map<String, ValueExpression> _vars;
+
+ //private final boolean _checkTargetBase;
+
+ public boolean _trackResolveVariables;
+
+ public boolean _variableResolved;
/**
*
@@ -47,6 +56,10 @@ public final class VariableMapperWrapper
{
super();
_target = orig;
+ _targetBase = (orig instanceof VariableMapperBase) ? (VariableMapperBase) orig : null;
+ //_checkTargetBase = true;
+ _trackResolveVariables = false;
+ _variableResolved = false;
}
/**
@@ -62,6 +75,13 @@ public final class VariableMapperWrapper
if (_vars != null)
{
ve = (ValueExpression) _vars.get(variable);
+
+ // Is this code in a block that wants to cache
+ // the resulting expression(s) and variable has been resolved?
+ if (_trackResolveVariables && ve != null)
+ {
+ _variableResolved = true;
+ }
}
if (ve == null)
@@ -91,4 +111,77 @@ public final class VariableMapperWrapper
return _vars.put(variable, expression);
}
+
+ @Override
+ public boolean isAnyFaceletsVariableResolved()
+ {
+ if (_trackResolveVariables)
+ {
+ if (_variableResolved)
+ {
+ //Force EL creation!
+ return true;
+ }
+ else
+ {
+ //Otherwise check parent variable mapper
+ //if (_checkTargetBase)
+ //{
+ if (_targetBase != null)
+ {
+ return _targetBase.isAnyFaceletsVariableResolved();
+ }
+ else
+ {
+ // Another VariableMapper not extending from the base one was used.
+ // (that's the reason why _targetBase is null).
+ // It is not possible to be sure the EL expression could use that mapper,
+ // so return true to force EL expression creation.
+ return true;
+ }
+ //}
+ //else
+ //{
+ // If no check for targetBase is required, we are in a context that suppose there will not
+ // be variables resolved that could affect the expressions. So return false, indicating
+ // the resulting expression can be cached.
+ //return false;
+ //}
+ }
+ }
+ else
+ {
+ // Force expression creation, because the call is outside caching block.
+ return true;
+ }
+ }
+
+ public VariableMapper getWrapped()
+ {
+ return _target;
+ }
+
+ @Override
+ public void beforeConstructELExpression()
+ {
+ _trackResolveVariables = true;
+ _variableResolved = false;
+ //if (_checkTargetBase && _targetBase != null)
+ if (_targetBase != null)
+ {
+ _targetBase.beforeConstructELExpression();
+ }
+ }
+
+ @Override
+ public void afterConstructELExpression()
+ {
+ //if (_checkTargetBase && _targetBase != null)
+ if (_targetBase != null)
+ {
+ _targetBase.afterConstructELExpression();
+ }
+ _trackResolveVariables = false;
+ _variableResolved = false;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/DefaultFaceletContext.java Thu Jun 16 18:01:26 2011
@@ -45,12 +45,14 @@ import javax.faces.view.facelets.Facelet
import org.apache.myfaces.view.facelets.AbstractFacelet;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
+import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
import org.apache.myfaces.view.facelets.FaceletCompositionContext;
import org.apache.myfaces.view.facelets.PageContext;
import org.apache.myfaces.view.facelets.TemplateClient;
import org.apache.myfaces.view.facelets.TemplateContext;
import org.apache.myfaces.view.facelets.TemplateManager;
import org.apache.myfaces.view.facelets.el.DefaultVariableMapper;
+import org.apache.myfaces.view.facelets.el.VariableMapperBase;
import org.apache.myfaces.view.facelets.tag.jsf.core.AjaxHandler;
/**
@@ -74,6 +76,7 @@ final class DefaultFaceletContext extend
private VariableMapper _varMapper;
private final DefaultVariableMapper _defaultVarMapper;
+ private VariableMapperBase _varMapperBase;
private FunctionMapper _fnMapper;
@@ -92,6 +95,10 @@ final class DefaultFaceletContext extend
private final List<TemplateContext> _isolatedTemplateContext;
private int _currentTemplateContext;
+
+ private ELExpressionCacheMode _elExpressionCacheMode;
+
+ private boolean _isCacheELExpressions;
private final List<PageContext> _isolatedPageContext;
@@ -106,6 +113,7 @@ final class DefaultFaceletContext extend
_fnMapper = ctx._fnMapper;
_varMapper = ctx._varMapper;
_defaultVarMapper = ctx._defaultVarMapper;
+ _varMapperBase = ctx._varMapperBase;
_faceletHierarchy = new ArrayList<AbstractFacelet>(ctx._faceletHierarchy
.size() + 1);
_faceletHierarchy.addAll(ctx._faceletHierarchy);
@@ -140,6 +148,9 @@ final class DefaultFaceletContext extend
_currentTemplateContext = ctx._currentTemplateContext;
_isolatedPageContext = ctx._isolatedPageContext;
+
+ _elExpressionCacheMode = ctx._elExpressionCacheMode;
+ _isCacheELExpressions = ctx._isCacheELExpressions;
//Update FACELET_CONTEXT_KEY on FacesContext attribute map, to
//reflect the current facelet context instance
@@ -160,11 +171,13 @@ final class DefaultFaceletContext extend
{
_defaultVarMapper = new DefaultVariableMapper();
_varMapper = _defaultVarMapper;
+ _varMapperBase = _defaultVarMapper;
}
else
{
_defaultVarMapper = new DefaultVariableMapper(_varMapper);
_varMapper = _defaultVarMapper;
+ _varMapperBase = _defaultVarMapper;
}
_faceletHierarchy = new ArrayList<AbstractFacelet>(1);
@@ -178,6 +191,9 @@ final class DefaultFaceletContext extend
_defaultVarMapper.setTemplateContext(_isolatedTemplateContext.get(_currentTemplateContext));
_isolatedPageContext = new ArrayList<PageContext>(8);
+
+ _elExpressionCacheMode = mctx.getELExpressionCacheMode();
+ _isCacheELExpressions = !ELExpressionCacheMode.noCache.equals(_elExpressionCacheMode);
//Set FACELET_CONTEXT_KEY on FacesContext attribute map, to
//reflect the current facelet context instance
@@ -210,6 +226,7 @@ final class DefaultFaceletContext extend
{
// Assert.param("varMapper", varMapper);
_varMapper = varMapper;
+ _varMapperBase = (_varMapper instanceof VariableMapperBase) ? (VariableMapperBase) varMapper : null;
}
/**
@@ -798,4 +815,43 @@ final class DefaultFaceletContext extend
{
return _mctx;
}
+
+ public boolean isAnyFaceletsVariableResolved()
+ {
+ //if (isAllowCacheELExpressions() && _varMapperBase != null)
+ if (_varMapperBase != null)
+ {
+ return _varMapperBase.isAnyFaceletsVariableResolved();
+ }
+ return true;
+ }
+
+ public boolean isAllowCacheELExpressions()
+ {
+ return _isCacheELExpressions && getTemplateContext().isAllowCacheELExpressions() && getPageContext().isAllowCacheELExpressions();
+ }
+
+ public void beforeConstructELExpression()
+ {
+ //if (isAllowCacheELExpressions() && _varMapperBase != null)
+ if (_varMapperBase != null)
+ {
+ _varMapperBase.beforeConstructELExpression();
+ }
+ }
+
+ public void afterConstructELExpression()
+ {
+ //if (isAllowCacheELExpressions() && _varMapperBase != null)
+ if (_varMapperBase != null)
+ {
+ _varMapperBase.afterConstructELExpression();
+ }
+ }
+
+ public ELExpressionCacheMode getELExpressionCacheMode()
+ {
+ return _elExpressionCacheMode;
+ }
+
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java Thu Jun 16 18:01:26 2011
@@ -18,6 +18,9 @@
*/
package org.apache.myfaces.view.facelets.impl;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
+import org.apache.myfaces.shared_impl.util.WebConfigParamUtils;
+import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
import org.apache.myfaces.view.facelets.FaceletCompositionContext;
import org.apache.myfaces.view.facelets.FaceletFactory;
import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
@@ -41,6 +44,20 @@ import java.util.Map;
*/
public class FaceletCompositionContextImpl extends FaceletCompositionContext
{
+ /**
+ * Indicates if expressions generated by facelets should be cached or not. Default is noCache. There there are four modes:
+ *
+ * <ul>
+ * <li>always: Only does not cache when expressions are inside user tags or the expression contains a variable resolved using VariableMapper</li>
+ * <li>allowCset: Like always, but does not allow cache when ui:param was used on the current template context</li>
+ * <li>strict: Like allowCset, but does not allow cache when c:set with var and value properties only is used on the current page context</li>
+ * <li>noCache: All expression are created each time the view is built</li>
+ * </ul>
+ *
+ */
+ @JSFWebConfigParam(since="2.0.8", defaultValue="noCache", expectedValues="noCache, strict, allowCset, always")
+ public static final String INIT_PARAM_CACHE_EL_EXPRESSIONS = "org.apache.myfaces.CACHE_EL_EXPRESSIONS";
+
private FacesContext _facesContext;
private FaceletFactory _factory;
@@ -62,6 +79,8 @@ public class FaceletCompositionContextIm
private Boolean _refreshTransientBuildOnPSS;
private Boolean _usingPSSOnThisView;
+
+ private ELExpressionCacheMode _elExpressionCacheMode;
private List<Map<String, UIComponent>> _componentsMarkedForDeletion;
@@ -346,6 +365,19 @@ public class FaceletCompositionContextIm
}
@Override
+ public ELExpressionCacheMode getELExpressionCacheMode()
+ {
+ if (_elExpressionCacheMode == null)
+ {
+ String value = WebConfigParamUtils.getStringInitParameter(
+ _facesContext.getExternalContext(), INIT_PARAM_CACHE_EL_EXPRESSIONS, ELExpressionCacheMode.noCache.name());
+
+ _elExpressionCacheMode = Enum.valueOf(ELExpressionCacheMode.class, value);
+ }
+ return _elExpressionCacheMode;
+ }
+
+ @Override
public void addAttachedObjectHandler(UIComponent compositeComponentParent, AttachedObjectHandler handler)
{
List<AttachedObjectHandler> list = _attachedObjectHandlers.get(compositeComponentParent);
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/PageContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/PageContextImpl.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/PageContextImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/PageContextImpl.java Thu Jun 16 18:01:26 2011
@@ -29,8 +29,11 @@ public class PageContextImpl extends Pag
private Map<String, ValueExpression> _attributes = null;
+ private boolean _isCacheELExpressions;
+
public PageContextImpl()
{
+ _isCacheELExpressions = true;
}
@Override
@@ -48,4 +51,16 @@ public class PageContextImpl extends Pag
{
return _attributes == null ? 0 : _attributes.size();
}
+
+ @Override
+ public boolean isAllowCacheELExpressions()
+ {
+ return _isCacheELExpressions;
+ }
+
+ @Override
+ public void setAllowCacheELExpressions(boolean cacheELExpressions)
+ {
+ _isCacheELExpressions = cacheELExpressions;
+ }
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/TemplateContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/TemplateContextImpl.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/TemplateContextImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/impl/TemplateContextImpl.java Thu Jun 16 18:01:26 2011
@@ -68,6 +68,8 @@ public class TemplateContextImpl extends
private TemplateManager _compositeComponentClient;
private TemplateManagerImpl _lastClient;
+
+ private boolean _isCacheELExpressions;
public TemplateContextImpl()
{
@@ -81,6 +83,7 @@ public class TemplateContextImpl extends
// to this manager.
_clients.add(new TemplateManagerImpl(null, INITIAL_TEMPLATE_CLIENT, true, INITIAL_PAGE_CONTEXT));
_lastClient = _clients.getFirst();
+ _isCacheELExpressions = true;
}
@Override
@@ -369,6 +372,13 @@ public class TemplateContextImpl extends
public static final class InitialPageContext extends PageContext
{
+ private boolean _isCacheELExpressions;
+
+ public InitialPageContext()
+ {
+ _isCacheELExpressions = true;
+ }
+
@Override
public Map<String, ValueExpression> getAttributes()
{
@@ -380,5 +390,32 @@ public class TemplateContextImpl extends
{
return 0;
}
+
+ @Override
+ public boolean isAllowCacheELExpressions()
+ {
+ return _isCacheELExpressions;
+ }
+
+ @Override
+ public void setAllowCacheELExpressions(boolean cacheELExpressions)
+ {
+ _isCacheELExpressions = cacheELExpressions;
+ }
+ }
+
+
+ @Override
+ public boolean isAllowCacheELExpressions()
+ {
+ return _isCacheELExpressions;
}
+
+ @Override
+ public void setAllowCacheELExpressions(boolean cacheELExpressions)
+ {
+ _isCacheELExpressions = cacheELExpressions;
+ }
+
+
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributeImpl.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributeImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/TagAttributeImpl.java Thu Jun 16 18:01:26 2011
@@ -18,6 +18,8 @@
*/
package org.apache.myfaces.view.facelets.tag;
+import java.util.Arrays;
+
import javax.el.ELException;
import javax.el.ExpressionFactory;
import javax.el.MethodExpression;
@@ -28,6 +30,7 @@ import javax.faces.view.facelets.TagAttr
import javax.faces.view.facelets.TagAttributeException;
import org.apache.myfaces.util.ExternalSpecifications;
+import org.apache.myfaces.view.facelets.AbstractFaceletContext;
import org.apache.myfaces.view.facelets.el.CompositeComponentELUtils;
import org.apache.myfaces.view.facelets.el.ELText;
import org.apache.myfaces.view.facelets.el.LocationMethodExpression;
@@ -72,6 +75,14 @@ public final class TagAttributeImpl exte
private String string;
+ /**
+ * This variable is used to cache created expressions using
+ * getValueExpression or getMethodExpression methods. It uses
+ * a racy single check strategy, because if the expression can be
+ * cached the same instance will be built.
+ */
+ private volatile Object[] cachedExpression;
+
public TagAttributeImpl(Location location, String ns, String localName, String qName, String value)
{
boolean literal;
@@ -185,6 +196,26 @@ public final class TagAttributeImpl exte
*/
public MethodExpression getMethodExpression(FaceletContext ctx, Class type, Class[] paramTypes)
{
+ AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
+
+ //volatile reads are atomic, so take the tuple to later comparison.
+ Object[] localCachedExpression = cachedExpression;
+
+ if (actx.isAllowCacheELExpressions() && localCachedExpression != null && (localCachedExpression.length % 3 == 0))
+ {
+ //If the expected type and paramTypes are the same return the cached one
+ for (int i = 0; i < (localCachedExpression.length/3); i++)
+ {
+ if ( ((type == null && localCachedExpression[(i*3)] == null ) ||
+ (type != null && type.equals(localCachedExpression[(i*3)])) ) &&
+ (Arrays.equals(paramTypes, (Class[]) localCachedExpression[(i*3)+1])) )
+ {
+ return (MethodExpression) localCachedExpression[(i*3)+2];
+ }
+ }
+ }
+
+ actx.beforeConstructELExpression();
try
{
MethodExpression methodExpression = null;
@@ -229,12 +260,40 @@ public final class TagAttributeImpl exte
}
}
- return new TagMethodExpression(this, methodExpression);
+ methodExpression = new TagMethodExpression(this, methodExpression);
+
+ if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
+ {
+ if (localCachedExpression != null && (localCachedExpression.length % 3 == 0))
+ {
+ // If you use a racy single check, assign
+ // the volatile variable at the end.
+ Object[] array = new Object[localCachedExpression.length+3];
+ array[0] = type;
+ array[1] = paramTypes;
+ array[2] = methodExpression;
+ for (int i = 0; i < localCachedExpression.length; i++)
+ {
+ array[i+3] = localCachedExpression[i];
+ }
+ cachedExpression = array;
+ }
+ else
+ {
+ cachedExpression = new Object[]{type, paramTypes, methodExpression};
+ }
+ }
+
+ return methodExpression;
}
catch (Exception e)
{
throw new TagAttributeException(this, e);
}
+ finally
+ {
+ actx.afterConstructELExpression();
+ }
}
/**
@@ -360,6 +419,24 @@ public final class TagAttributeImpl exte
*/
public ValueExpression getValueExpression(FaceletContext ctx, Class type)
{
+ AbstractFaceletContext actx = (AbstractFaceletContext) ctx;
+
+ //volatile reads are atomic, so take the tuple to later comparison.
+ Object[] localCachedExpression = cachedExpression;
+ if (actx.isAllowCacheELExpressions() && localCachedExpression != null && localCachedExpression.length == 2)
+ {
+ //If the expected type is the same return the cached one
+ if (localCachedExpression[0] == null && type == null)
+ {
+ return (ValueExpression) localCachedExpression[1];
+ }
+ else if (localCachedExpression[0] != null && localCachedExpression[0].equals(type))
+ {
+ return (ValueExpression) localCachedExpression[1];
+ }
+ }
+
+ actx.beforeConstructELExpression();
try
{
ExpressionFactory f = ctx.getExpressionFactory();
@@ -402,12 +479,21 @@ public final class TagAttributeImpl exte
}
}
+
+ if (actx.isAllowCacheELExpressions() && !actx.isAnyFaceletsVariableResolved())
+ {
+ cachedExpression = new Object[]{type, valueExpression};
+ }
return valueExpression;
}
catch (Exception e)
{
throw new TagAttributeException(this, e);
}
+ finally
+ {
+ actx.afterConstructELExpression();
+ }
}
/**
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/UserTagHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/UserTagHandler.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/UserTagHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/UserTagHandler.java Thu Jun 16 18:01:26 2011
@@ -112,18 +112,28 @@ final class UserTagHandler extends TagHa
// eval include
try
{
- String[] names = new String[_vars.length];
- ValueExpression[] values = new ValueExpression[_vars.length];
- for (int i = 0; i < _vars.length; i++)
- {
- names[i] = _vars[i].getLocalName();
- values[i] = _vars[i].getValueExpression(ctx, Object.class);
+ String[] names = null;
+ ValueExpression[] values = null;
+ if (this._vars.length > 0)
+ {
+ names = new String[_vars.length];
+ values = new ValueExpression[_vars.length];
+ for (int i = 0; i < _vars.length; i++)
+ {
+ names[i] = _vars[i].getLocalName();
+ values[i] = _vars[i].getValueExpression(ctx, Object.class);
+ }
}
actx.pushTemplateContext(new TemplateContextImpl());
- for (int i = 0; i < this._vars.length; i++)
+ if (this._vars.length > 0)
{
- ((AbstractFaceletContext) ctx).getTemplateContext().setParameter(names[i], values[i]);
+ for (int i = 0; i < this._vars.length; i++)
+ {
+ ((AbstractFaceletContext) ctx).getTemplateContext().setParameter(names[i], values[i]);
+ }
}
+ //Disable caching always, even in 'always' mode
+ actx.getTemplateContext().setAllowCacheELExpressions(false);
actx.pushClient(this);
ctx.includeFacelet(parent, this._location);
}
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jstl/core/SetHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jstl/core/SetHandler.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jstl/core/SetHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jstl/core/SetHandler.java Thu Jun 16 18:01:26 2011
@@ -35,6 +35,7 @@ import javax.faces.view.facelets.TagHand
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
+import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
/**
* Simplified implementation of c:set
@@ -132,7 +133,15 @@ public class SetHandler extends TagHandl
expr.setValue(elCtx, veObj.getValue(elCtx));
} else {
//ctx.getVariableMapper().setVariable(varStr, veObj);
- ((AbstractFaceletContext) ctx).getPageContext().getAttributes().put(varStr, veObj);
+ AbstractFaceletContext actx = ((AbstractFaceletContext) ctx);
+ actx.getPageContext().getAttributes().put(varStr, veObj);
+ if (actx.getPageContext().isAllowCacheELExpressions())
+ {
+ if (ELExpressionCacheMode.strict.equals(actx.getELExpressionCacheMode()))
+ {
+ actx.getPageContext().setAllowCacheELExpressions(false);
+ }
+ }
}
}
else
Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/ui/ParamHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/ui/ParamHandler.java?rev=1136573&r1=1136572&r2=1136573&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/ui/ParamHandler.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/view/facelets/tag/ui/ParamHandler.java Thu Jun 16 18:01:26 2011
@@ -33,6 +33,7 @@ import javax.faces.view.facelets.TagHand
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletAttribute;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFFaceletTag;
import org.apache.myfaces.view.facelets.AbstractFaceletContext;
+import org.apache.myfaces.view.facelets.ELExpressionCacheMode;
/**
* @author Jacob Hookom
@@ -88,7 +89,17 @@ public class ParamHandler extends TagHan
ELException
{
//((AbstractFaceletContext) ctx).getTemplateContext().getAttributes().put(nameStr, valueVE);
- ((AbstractFaceletContext) ctx).getTemplateContext().setParameter(nameStr, valueVE);
+ AbstractFaceletContext actx = ((AbstractFaceletContext) ctx);
+ actx.getTemplateContext().setParameter(nameStr, valueVE);
+
+ if (actx.getTemplateContext().isAllowCacheELExpressions())
+ {
+ if (ELExpressionCacheMode.strict.equals(actx.getELExpressionCacheMode()) ||
+ ELExpressionCacheMode.allowCset.equals(actx.getELExpressionCacheMode()))
+ {
+ actx.getTemplateContext().setAllowCacheELExpressions(false);
+ }
+ }
}
public String getName(FaceletContext ctx)