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 2012/03/29 06:27:03 UTC
svn commit: r1306710 - in /myfaces/core/branches/2.0.x:
api/src/main/java/javax/faces/component/
impl/src/main/java/org/apache/myfaces/view/facelets/
impl/src/main/java/org/apache/myfaces/view/facelets/impl/
impl/src/main/java/org/apache/myfaces/view/f...
Author: lu4242
Date: Thu Mar 29 04:27:03 2012
New Revision: 1306710
URL: http://svn.apache.org/viewvc?rev=1306710&view=rev
Log:
MYFACES-3515 Duplicate id using a facet and multiple <c:if> blocks in a composite component
Modified:
myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIData.java
myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIForm.java
myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UINamingContainer.java
myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIViewRoot.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java
myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java
Modified: myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIData.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIData.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIData.java (original)
+++ myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIData.java Thu Mar 29 04:27:03 2012
@@ -1063,15 +1063,17 @@ public class UIData extends UIComponentB
{
StringBuilder bld = __getSharedStringBuilder(context);
- Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
- uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
- getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
- // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
+ // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX,
+ // and will be unique within this UIViewRoot.
if(seed==null)
{
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
}
- // Optionally, a unique seed value can be supplied by component creators which should be included in the generated unique id.
+ // Optionally, a unique seed value can be supplied by component creators
+ // which should be included in the generated unique id.
else
{
return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
Modified: myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIForm.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIForm.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIForm.java (original)
+++ myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIForm.java Thu Mar 29 04:27:03 2012
@@ -89,13 +89,13 @@ public class UIForm extends UIComponentB
bld = __getSharedStringBuilder(context);
}
- Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
- uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
- getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
// Generate an identifier for a component. The identifier will be prefixed with
// UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
if(seed==null)
{
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
}
// Optionally, a unique seed value can be supplied by component creators
Modified: myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UINamingContainer.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UINamingContainer.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UINamingContainer.java (original)
+++ myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UINamingContainer.java Thu Mar 29 04:27:03 2012
@@ -73,15 +73,17 @@ public class UINamingContainer extends U
{
StringBuilder bld = __getSharedStringBuilder(context);
- Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
- uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
- getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
- // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
+ // Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX,
+ // and will be unique within this UIViewRoot.
if(seed==null)
{
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
}
- // Optionally, a unique seed value can be supplied by component creators which should be included in the generated unique id.
+ // Optionally, a unique seed value can be supplied by component creators
+ // which should be included in the generated unique id.
else
{
return bld.append(UIViewRoot.UNIQUE_ID_PREFIX).append(seed).toString();
@@ -142,47 +144,56 @@ public class UINamingContainer extends U
setCachedFacesContext(context.getFacesContext());
}
- if (!isVisitable(context)) {
+ if (!isVisitable(context))
+ {
return false;
}
pushComponentToEL(context.getFacesContext(), this);
- try {
+ try
+ {
VisitResult res = context.invokeVisitCallback(this, callback);
- switch (res) {
- //we are done nothing has to be processed anymore
- case COMPLETE:
- return true;
-
- case REJECT:
- return false;
-
- //accept
- default:
- // Take advantage of the fact this is a NamingContainer
- // and we can know if there are ids to visit inside it
- Collection<String> subtreeIdsToVisit = context.getSubtreeIdsToVisit(this);
-
- if (subtreeIdsToVisit != null && !subtreeIdsToVisit.isEmpty())
- {
- if (getFacetCount() > 0) {
- for (UIComponent facet : getFacets().values()) {
- if (facet.visitTree(context, callback)) {
- return true;
+ switch (res)
+ {
+ //we are done nothing has to be processed anymore
+ case COMPLETE:
+ return true;
+
+ case REJECT:
+ return false;
+
+ //accept
+ default:
+ // Take advantage of the fact this is a NamingContainer
+ // and we can know if there are ids to visit inside it
+ Collection<String> subtreeIdsToVisit = context.getSubtreeIdsToVisit(this);
+
+ if (subtreeIdsToVisit != null && !subtreeIdsToVisit.isEmpty())
+ {
+ if (getFacetCount() > 0)
+ {
+ for (UIComponent facet : getFacets().values())
+ {
+ if (facet.visitTree(context, callback))
+ {
+ return true;
+ }
}
}
- }
- for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
- UIComponent child = getChildren().get(i);
- if (child.visitTree(context, callback)) {
- return true;
+ for (int i = 0, childCount = getChildCount(); i < childCount; i++)
+ {
+ UIComponent child = getChildren().get(i);
+ if (child.visitTree(context, callback))
+ {
+ return true;
+ }
}
}
- }
- return false;
+ return false;
}
}
- finally {
+ finally
+ {
//all components must call popComponentFromEl after visiting is finished
popComponentFromEL(context.getFacesContext());
}
Modified: myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIViewRoot.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIViewRoot.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIViewRoot.java (original)
+++ myfaces/core/branches/2.0.x/api/src/main/java/javax/faces/component/UIViewRoot.java Thu Mar 29 04:27:03 2012
@@ -339,13 +339,13 @@ public class UIViewRoot extends UICompon
{
StringBuilder bld = __getSharedStringBuilder(context);
- Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
- uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
- getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
// Generate an identifier for a component. The identifier will be prefixed with
// UNIQUE_ID_PREFIX, and will be unique within this UIViewRoot.
if(seed==null)
{
+ Long uniqueIdCounter = (Long) getStateHelper().get(PropertyKeys.uniqueIdCounter);
+ uniqueIdCounter = (uniqueIdCounter == null) ? 0 : uniqueIdCounter;
+ getStateHelper().put(PropertyKeys.uniqueIdCounter, (uniqueIdCounter+1L));
return bld.append(UNIQUE_ID_PREFIX).append(uniqueIdCounter).toString();
}
// Optionally, a unique seed value can be supplied by component creators which
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/FaceletCompositionContext.java Thu Mar 29 04:27:03 2012
@@ -572,4 +572,9 @@ abstract public class FaceletComposition
{
return isRefreshingTransientBuild() || (!isBuildingViewMetadata() && isInMetadataSection());
}
+
+ public StringBuilder getSharedStringBuilder()
+ {
+ return new StringBuilder();
+ }
}
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/impl/FaceletCompositionContextImpl.java Thu Mar 29 04:27:03 2012
@@ -137,6 +137,8 @@ public class FaceletCompositionContextIm
private SectionUniqueIdCounter _sectionUniqueComponentMetadataIdCounter;
private SectionUniqueIdCounter _sectionUniqueComponentNormalIdCounter;
+ private StringBuilder _sharedStringBuilder;
+
public FaceletCompositionContextImpl(FaceletFactory factory, FacesContext facesContext)
{
super();
@@ -172,6 +174,7 @@ public class FaceletCompositionContextIm
_uniqueIdsIterator = null;
_level = 0;
_isInMetadataSection = 0;
+ _sharedStringBuilder = null;
}
@Override
@@ -232,7 +235,12 @@ public class FaceletCompositionContextIm
_validationGroupsStack = null;
_componentsMarkedForDeletion = null;
_sectionUniqueIdCounter = null;
+ _sectionUniqueNormalIdCounter = null;
+ _sectionUniqueMetadataIdCounter = null;
_sectionUniqueComponentIdCounter = null;
+ _sectionUniqueComponentNormalIdCounter = null;
+ _sectionUniqueComponentMetadataIdCounter = null;
+ _sharedStringBuilder = null;
}
@Override
@@ -945,6 +953,20 @@ public class FaceletCompositionContextIm
return isRefreshingTransientBuild() || (!isBuildingViewMetadata() && isInMetadataSection());
}
+ @Override
+ public StringBuilder getSharedStringBuilder()
+ {
+ if (_sharedStringBuilder == null)
+ {
+ _sharedStringBuilder = new StringBuilder();
+ }
+ else
+ {
+ _sharedStringBuilder.setLength(0);
+ }
+ return _sharedStringBuilder;
+ }
+
private static class KeyEntryIterator<K, V> implements Iterator<K>
{
private Iterator<Map.Entry<K, V>> _delegateIterator;
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/composite/CompositeComponentResourceTagHandler.java Thu Mar 29 04:27:03 2012
@@ -331,7 +331,11 @@ public class CompositeComponentResourceT
{
// UIViewRoot implements UniqueIdVendor, so there is no need to cast to UIViewRoot
// and call createUniqueId()
- String uid = uniqueIdVendor.createUniqueId(faceletContext.getFacesContext(),null);
+ String uid = uniqueIdVendor.createUniqueId(faceletContext.getFacesContext(),
+ mctx.getSharedStringBuilder()
+ .append(compositeComponentBase.getId())
+ .append("__f_")
+ .append("cc_facet").toString());
compositeFacetPanel.setId(uid);
}
}
Modified: myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java
URL: http://svn.apache.org/viewvc/myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java?rev=1306710&r1=1306709&r2=1306710&view=diff
==============================================================================
--- myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java (original)
+++ myfaces/core/branches/2.0.x/impl/src/main/java/org/apache/myfaces/view/facelets/tag/jsf/ComponentSupport.java Thu Mar 29 04:27:03 2012
@@ -30,6 +30,7 @@ import javax.faces.component.UIComponent
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIPanel;
import javax.faces.component.UIViewRoot;
+import javax.faces.component.UniqueIdVendor;
import javax.faces.context.FacesContext;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
@@ -365,10 +366,44 @@ public final class ComponentSupport
* @param facesContext
* @return
*/
- private static UIComponent createFacetUIPanel(FacesContext facesContext)
+ private static UIComponent createFacetUIPanel(FaceletContext ctx, UIComponent parent, String facetName)
{
+ FacesContext facesContext = ctx.getFacesContext();
UIComponent panel = facesContext.getApplication().createComponent(UIPanel.COMPONENT_TYPE);
- panel.setId(facesContext.getViewRoot().createUniqueId());
+
+ // The panel created by this method is special. To be restored properly and do not
+ // create duplicate ids or any other unwanted conflicts, it requires an unique id.
+ // This code is usually called when more than one component is added to a facet and
+ // it is necessary to create a shared container.
+ // Use FaceletCompositionContext.generateUniqueComponentId() is not possible, because
+ // <c:if> blocks inside a facet will make component ids unstable. Use UniqueIdVendor
+ // is feasible but also will be affected by <c:if> blocks inside a facet.
+ // The only solution that will generate real unique ids is use the parent id and the
+ // facet name and derive an unique id that cannot be generated by SectionUniqueIdCounter,
+ // doing the same trick as with metadata: use a double __ and add a prefix (f).
+ // Note this id will never be printed into the response, because this is just a container.
+ FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
+ UniqueIdVendor uniqueIdVendor = mctx.getUniqueIdVendorFromStack();
+ if (uniqueIdVendor == null)
+ {
+ uniqueIdVendor = ComponentSupport.getViewRoot(ctx, parent);
+ }
+ if (uniqueIdVendor != null)
+ {
+ // UIViewRoot implements UniqueIdVendor, so there is no need to cast to UIViewRoot
+ // and call createUniqueId(). See ComponentTagHandlerDelegate
+ int index = facetName.indexOf('.');
+ String cleanFacetName = facetName;
+ if (index >= 0)
+ {
+ cleanFacetName = facetName.replace('.', '_');
+ }
+ panel.setId(uniqueIdVendor.createUniqueId(facesContext,
+ mctx.getSharedStringBuilder()
+ .append(parent.getId())
+ .append("__f_")
+ .append(cleanFacetName).toString()));
+ }
panel.getAttributes().put(FACET_CREATED_UIPANEL_MARKER, Boolean.TRUE);
return panel;
}
@@ -387,7 +422,7 @@ public final class ComponentSupport
{
// there is a facet, but it is not an instance of UIPanel
UIComponent child = facet;
- facet = createFacetUIPanel(ctx.getFacesContext());
+ facet = createFacetUIPanel(ctx, parent, facetName);
facet.getChildren().add(child);
facet.getChildren().add(c);
parent.getFacets().put(facetName, facet);
@@ -405,7 +440,7 @@ public final class ComponentSupport
// the facet is an instance of UIPanel, but it is not marked,
// so we have to create a new UIPanel and store this one in it
UIComponent oldPanel = facet;
- facet = createFacetUIPanel(ctx.getFacesContext());
+ facet = createFacetUIPanel(ctx, parent, facetName);
facet.getChildren().add(oldPanel);
facet.getChildren().add(c);
parent.getFacets().put(facetName, facet);