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 2007/11/23 10:00:14 UTC

svn commit: r597603 - in /myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared: config/MyfacesConfig.java renderkit/html/HTML.java renderkit/html/HtmlLinkRendererBase.java

Author: manolito
Date: Fri Nov 23 01:00:12 2007
New Revision: 597603

URL: http://svn.apache.org/viewvc?rev=597603&view=rev
Log:
MYFACES-1774 HtmlLinkRenderer should output & instead of & as the url param separator within href attribute according to HTML Spec

Modified:
    myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
    myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HTML.java
    myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java?rev=597603&r1=597602&r2=597603&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/config/MyfacesConfig.java Fri Nov 23 01:00:12 2007
@@ -78,6 +78,9 @@
     private static final String  INIT_PARAM_RENDER_VIEWSTATE_ID = "org.apache.myfaces.RENDER_VIEWSTATE_ID";
     private static final boolean INIT_PARAM_RENDER_VIEWSTATE_ID_DEFAULT = true;
 
+    private static final String  INIT_PARAM_STRICT_XHTML_LINKS = "org.apache.myfaces.STRICT_XHTML_LINKS";
+    private static final boolean INIT_PARAM_STRICT_XHTML_LINKS_DEFAULT = true;
+
     private boolean _prettyHtml;
     private boolean _detectJavascript;
     private boolean _allowJavascript;
@@ -88,6 +91,7 @@
     private boolean _checkExtensionsFilter;
     private boolean _readonlyAsDisabledForSelect;
     private boolean _renderViewStateId;
+    private boolean _strictXhtmlLinks;
 
     private static final boolean TOMAHAWK_AVAILABLE;
     private static final boolean MYFACES_IMPL_AVAILABLE;
@@ -165,7 +169,9 @@
         myfacesConfig.setReadonlyAsDisabledForSelect(getBooleanInitParameter(extCtx, INIT_READONLY_AS_DISABLED_FOR_SELECT,
                                                                  INIT_READONLY_AS_DISABLED_FOR_SELECT_DEFAULT));
         myfacesConfig.setRenderViewStateId(getBooleanInitParameter(extCtx, INIT_PARAM_RENDER_VIEWSTATE_ID,
-                                                            INIT_PARAM_RENDER_VIEWSTATE_ID_DEFAULT));
+                                                                   INIT_PARAM_RENDER_VIEWSTATE_ID_DEFAULT));
+        myfacesConfig.setStrictXhtmlLinks(getBooleanInitParameter(extCtx, INIT_PARAM_STRICT_XHTML_LINKS,
+                                                                  INIT_PARAM_STRICT_XHTML_LINKS_DEFAULT));
 
         myfacesConfig.setConfigRefreshPeriod(getLongInitParameter(extCtx, INIT_PARAM_CONFIG_REFRESH_PERIOD,
                 INIT_PARAM_CONFIG_REFRESH_PERIOD_DEFAULT));
@@ -335,6 +341,28 @@
 
     public void setRenderViewStateId(boolean renderViewStateId) {
         _renderViewStateId = renderViewStateId;
+    }
+
+    /**
+     * <p>W3C recommends to use the "&amp;amp;" entity instead of a plain "&amp;" character within HTML.
+     * This also applies to attribute values and thus to the "href" attribute of &lt;a&gt; elements as well.
+     * Even more, when XHTML is used as output the usage of plain "&amp;" characters is forbidden and would lead to
+     * invalid XML code.
+     * Therefore, since version 1.1.6 MyFaces renders the correct "&amp;amp;" entity for links.</p>
+     * <p>The init parameter
+     * {@link #INIT_PARAM_STRICT_XHTML_LINKS} makes it possible to restore the old behaviour and to make MyFaces
+     * "bug compatible" to the Sun RI which renders plain "&amp;" chars in links as well.</p>
+     * @see <a href="http://www.w3.org/TR/html401/charset.html#h-5.3.2">HTML 4.01 Specification</a>
+     * @see <a href="http://issues.apache.org/jira/browse/MYFACES-1774">Jira: MYFACES-1774</a>
+     * @return true if ampersand characters ("&amp;") should be correctly rendered as "&amp;amp;" entities within link urls (=default),
+     *         false for old (XHTML incompatible) behaviour
+     */
+    public boolean isStrictXhtmlLinks() {
+        return _strictXhtmlLinks;
+    }
+
+    public void setStrictXhtmlLinks(boolean strictXhtmlLinks) {
+        _strictXhtmlLinks = strictXhtmlLinks;
     }
 
     public boolean isTomahawkAvailable()

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HTML.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HTML.java?rev=597603&r1=597602&r2=597603&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HTML.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HTML.java Fri Nov 23 01:00:12 2007
@@ -485,7 +485,7 @@
 
     String HREF_PATH_SEPARATOR = "/";
     String HREF_PATH_FROM_PARAM_SEPARATOR = "?";
-    String HREF_PARAM_SEPARATOR = "&";
+    //removed because wrong for XHTML and not used anyway: String HREF_PARAM_SEPARATOR = "&";
     String HREF_PARAM_NAME_FROM_VALUE_SEPARATOR = "=";
 
 }

Modified: myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java
URL: http://svn.apache.org/viewvc/myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java?rev=597603&r1=597602&r2=597603&view=diff
==============================================================================
--- myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java (original)
+++ myfaces/shared/trunk/core/src/main/java/org/apache/myfaces/shared/renderkit/html/HtmlLinkRendererBase.java Fri Nov 23 01:00:12 2007
@@ -22,6 +22,7 @@
 import org.apache.myfaces.shared.renderkit.RendererUtils;
 import org.apache.myfaces.shared.renderkit.html.util.FormInfo;
 import org.apache.myfaces.shared.renderkit.html.util.JavascriptUtils;
+import org.apache.myfaces.shared.config.MyfacesConfig;
 
 import javax.faces.application.StateManager;
 import javax.faces.application.ViewHandler;
@@ -321,6 +322,9 @@
         String viewId = facesContext.getViewRoot().getViewId();
         String path = viewHandler.getActionURL(facesContext, viewId);
 
+        boolean strictXhtmlLinks
+                = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictXhtmlLinks();
+
         StringBuffer hrefBuf = new StringBuffer(path);
 
         //add clientId parameter for decode
@@ -329,7 +333,11 @@
             hrefBuf.append('?');
         }
         else {
-            hrefBuf.append('&');
+            if (strictXhtmlLinks) {
+                hrefBuf.append("&amp;");
+            } else {
+                hrefBuf.append('&');
+            }
         }
         String hiddenFieldName = HtmlRendererUtils.getHiddenCommandLinkFieldName(findNestingForm(component, facesContext));
         hrefBuf.append(hiddenFieldName);
@@ -337,13 +345,17 @@
         hrefBuf.append(clientId);
 
         if (getChildCount(component) > 0) {
-            addChildParametersToHref(component, hrefBuf,
+            addChildParametersToHref(facesContext, component, hrefBuf,
                                      false, //not the first url parameter
                                      writer.getCharacterEncoding());
         }
 
         StateManager stateManager = facesContext.getApplication().getStateManager();
-        hrefBuf.append("&");
+        if (strictXhtmlLinks) {
+            hrefBuf.append("&amp;");
+        } else {
+            hrefBuf.append('&');
+        }
         if (stateManager.isSavingStateInClient(facesContext)) {
             hrefBuf.append(URL_STATE_MARKER);
         }
@@ -354,18 +366,19 @@
                                  null);
     }
 
-    private void addChildParametersToHref(UIComponent linkComponent,
+    private void addChildParametersToHref(FacesContext facesContext,
+                                          UIComponent linkComponent,
                                           StringBuffer hrefBuf,
                                           boolean firstParameter,
-                                          String charEncoding)
-        throws IOException {
+                                          String charEncoding) throws IOException {
+        boolean strictXhtmlLinks
+                = MyfacesConfig.getCurrentInstance(facesContext.getExternalContext()).isStrictXhtmlLinks();
         for (Iterator it = getChildren(linkComponent).iterator(); it.hasNext();) {
             UIComponent child = (UIComponent) it.next();
             if (child instanceof UIParameter) {
                 String name = ((UIParameter) child).getName();
                 Object value = ((UIParameter) child).getValue();
-
-                addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding);
+                addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding, strictXhtmlLinks);
                 firstParameter = false;
             }
         }
@@ -379,7 +392,7 @@
         String href = org.apache.myfaces.shared.renderkit.RendererUtils.getStringValue(facesContext, output);
         if (getChildCount(output) > 0) {
             StringBuffer hrefBuf = new StringBuffer(href);
-            addChildParametersToHref(output, hrefBuf,
+            addChildParametersToHref(facesContext, output, hrefBuf,
                                      (href.indexOf('?') == -1), //first url parameter?
                                      writer.getCharacterEncoding());
             href = hrefBuf.toString();
@@ -397,13 +410,26 @@
         writer.flush();
     }
 
-    private static void addParameterToHref(String name, Object value, StringBuffer hrefBuf, boolean firstParameter, String charEncoding)
-        throws UnsupportedEncodingException {
+    private static void addParameterToHref(String name,
+                                           Object value,
+                                           StringBuffer hrefBuf,
+                                           boolean firstParameter,
+                                           String charEncoding,
+                                           boolean strictXhtmlLinks) throws UnsupportedEncodingException {
         if (name == null) {
             throw new IllegalArgumentException("Unnamed parameter value not allowed within command link.");
         }
 
-        hrefBuf.append(firstParameter ? "?" : "&amp;");
+        if (firstParameter) {
+            hrefBuf.append('?');
+        } else {
+            if (strictXhtmlLinks) {
+                hrefBuf.append("&amp;");
+            } else {
+                hrefBuf.append('&');
+            }
+        }
+
         hrefBuf.append(URLEncoder.encode(name, charEncoding));
         hrefBuf.append('=');
         if (value != null) {