You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ja...@apache.org on 2010/07/08 23:40:56 UTC

svn commit: r961954 - in /myfaces/core/trunk/impl/src: main/java/org/apache/myfaces/application/ViewHandlerImpl.java test/java/org/apache/myfaces/application/ViewHandlerImplTest.java

Author: jakobk
Date: Thu Jul  8 21:40:56 2010
New Revision: 961954

URL: http://svn.apache.org/viewvc?rev=961954&view=rev
Log:
MYFACES-2792 Redirect with include-view-params in faces-config.xml

Added:
    myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java   (with props)
Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ViewHandlerImpl.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ViewHandlerImpl.java?rev=961954&r1=961953&r2=961954&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ViewHandlerImpl.java (original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/application/ViewHandlerImpl.java Thu Jul  8 21:40:56 2010
@@ -21,6 +21,7 @@ package org.apache.myfaces.application;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Locale;
@@ -345,10 +346,19 @@ public class ViewHandlerImpl extends Vie
         {
             return parametersFromArg;
         }
+        
+        // we need to use a custom Map to add the view parameters,
+        // otherwise the current value of the view parameter will be added to
+        // the navigation case as a static (!!!) parameter, thus the value
+        // won't be updated on any following request
+        // (Note that parametersFromArg is the Map from the NavigationCase)
+        // Also note that we don't have to copy the Lists, because they won't be changed
+        Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+        parameters.putAll(parametersFromArg);
 
         for (UIViewParameter viewParameter : toViewParams)
         {
-            if (!parametersFromArg.containsKey(viewParameter.getName()))
+            if (!parameters.containsKey(viewParameter.getName()))
             {
                 String parameterValue = viewParameter.getStringValueFromModel(context);
                 if (parameterValue == null)
@@ -359,32 +369,31 @@ public class ViewHandlerImpl extends Vie
                     }
                     else
                     {
-                        boolean found = false;
-                        for (UIViewParameter curParam : currentViewParams) {
-                            if (curParam.getName() != null && viewParameter.getName() != null &&
-                                    curParam.getName().equals(viewParameter.getName())) 
+                        if (viewParameter.getName() != null)
+                        {
+                            for (UIViewParameter curParam : currentViewParams)
                             {
-                                parameterValue = curParam.getStringValue(context);
-                                found = true;
+                                if (viewParameter.getName().equals(curParam.getName())) 
+                                {
+                                    parameterValue = curParam.getStringValue(context);
+                                    break;
+                                }
                             }
-                            if (found)
-                                break;
                         }
                     }
                 }
                 if (parameterValue != null)
                 {
-                    List<String> parameterValueList = parametersFromArg.get(viewParameter.getName());
-                    if (parameterValueList == null)
-                    {
-                        parameterValueList = new ArrayList<String>();
-                    }
+                    // since we have checked !parameters.containsKey(viewParameter.getName())
+                    // here already, the parameters Map will never contain a List under the
+                    // key viewParameter.getName(), thus we do not have to check it here (again).
+                    List<String> parameterValueList = new ArrayList<String>();
                     parameterValueList.add(parameterValue);
-                    parametersFromArg.put(viewParameter.getName(),parameterValueList);
+                    parameters.put(viewParameter.getName(), parameterValueList);
                 }
             }
         }        
-        return parametersFromArg;
+        return parameters;
     }
     
     private void checkNull(final Object o, final String param)

Added: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java
URL: http://svn.apache.org/viewvc/myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java?rev=961954&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java (added)
+++ myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java Thu Jul  8 21:40:56 2010
@@ -0,0 +1,251 @@
+/*
+ * 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.application;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.FactoryFinder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIPanel;
+import javax.faces.component.UIViewParameter;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.view.ViewDeclarationLanguage;
+import javax.faces.view.ViewMetadata;
+
+import junit.framework.Assert;
+
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.apache.myfaces.test.el.MockValueExpression;
+import org.apache.myfaces.view.ViewDeclarationLanguageFactoryImpl;
+import org.apache.myfaces.view.facelets.FaceletViewDeclarationLanguage;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test class for ViewHandlerImpl
+ * 
+ * @author Jakob Korherr (latest modification by $Author$)
+ * @version $Revision$ $Date$
+ */
+@RunWith(JUnit4.class)
+public class ViewHandlerImplTest extends AbstractJsfTestCase
+{
+    
+    private ViewHandlerImpl _viewHandler;
+    
+    @Before
+    @Override
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        
+        // configure VDL factory
+        FactoryFinder.setFactory(FactoryFinder.VIEW_DECLARATION_LANGUAGE_FACTORY,
+                ViewDeclarationLanguageFactoryImpl.class.getName());
+        
+        // configure the ViewHandler
+        _viewHandler = new TestViewHandlerImpl();
+        facesContext.getApplication().setViewHandler(_viewHandler);
+        
+        // add UIViewRoot as component
+        facesContext.getApplication().addComponent(UIViewRoot.COMPONENT_TYPE,
+                UIViewRoot.class.getName());
+    }
+
+    @After
+    @Override
+    public void tearDown() throws Exception
+    {
+        _viewHandler = null;
+        
+        super.tearDown();
+    }
+
+    /**
+     *  Checks if ViewHandler.getBookmarkableURL() wants to change the parameter Map,
+     *  which is not allowed, because this Map comes from the NavigationCase and
+     *  any changes on it will change the NavigationCase itself.
+     *  Normally this would mean that a <f:viewParam> is added as a static value
+     *  to the NavigationCase (which is, of course, not allowed).
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testGetBookmarkableURLDoesNotChangeParametersMap()
+    {
+        // set the required path elements
+        request.setPathElements("/", null, "/newview.jsf", null);
+        
+        // set the value for the ValueExpression #{paramvalue}
+        externalContext.getApplicationMap().put("paramvalue", "paramvalue");
+        
+        // create a parameter map and make everything unmodifiable (Map and Lists)
+        Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+        parameters.put("key1", Collections.unmodifiableList(Arrays.asList("value11", "value12")));
+        parameters.put("key2", Collections.unmodifiableList(Arrays.asList("value2")));
+        parameters = Collections.unmodifiableMap(parameters);
+        
+        String url = null;
+        try
+        {
+            url = _viewHandler.getBookmarkableURL(facesContext, "/newview.xhtml", parameters, true);
+        }
+        catch (UnsupportedOperationException uoe)
+        {
+            // an UnsupportedOperationException occured, which means getBookmarkableURL()
+            // wanted to change the Map or any of the Lists and this is not allowed!
+            Assert.fail("ViewHandler.getBookmarkableURL() must not change the parameter Map!");
+        }
+        
+        // additional checks:
+        // the URL must contain all params from the parameters map
+        // and from the <f:viewParam> components of the target view
+        Assert.assertTrue(url.contains("key1=value11"));
+        Assert.assertTrue(url.contains("key1=value12"));
+        Assert.assertTrue(url.contains("key2=value2"));
+        Assert.assertTrue(url.contains("myparam=paramvalue"));
+    }
+    
+    /**
+     *  Checks if ViewHandler.getRedirectURL() wants to change the parameter Map,
+     *  which is not allowed, because this Map comes from the NavigationCase and
+     *  any changes on it will change the NavigationCase itself.
+     *  Normally this would mean that a <f:viewParam> is added as a static value
+     *  to the NavigationCase (which is, of course, not allowed).
+     */
+    @Test
+    @SuppressWarnings("unchecked")
+    public void testGetRedirectURLDoesNotChangeParametersMap()
+    {
+        // set the required path elements
+        request.setPathElements("/", null, "/newview.jsf", null);
+        
+        // set the value for the ValueExpression #{paramvalue}
+        externalContext.getApplicationMap().put("paramvalue", "paramvalue");
+        
+        // create a parameter map and make everything unmodifiable (Map and Lists)
+        Map<String, List<String>> parameters = new HashMap<String, List<String>>();
+        parameters.put("key1", Collections.unmodifiableList(Arrays.asList("value11", "value12")));
+        parameters.put("key2", Collections.unmodifiableList(Arrays.asList("value2")));
+        parameters = Collections.unmodifiableMap(parameters);
+        
+        String url = null;
+        try
+        {
+            url = _viewHandler.getRedirectURL(facesContext, "/newview.xhtml", parameters, true);
+        }
+        catch (UnsupportedOperationException uoe)
+        {
+            // an UnsupportedOperationException occured, which means getRedirectURL()
+            // wanted to change the Map or any of the Lists and this is not allowed!
+            Assert.fail("ViewHandler.getRedirectURL() must not change the parameter Map!");
+        }
+        
+        // additional checks:
+        // the URL must contain all params from the parameters map
+        // and from the <f:viewParam> components of the target view
+        Assert.assertTrue(url.contains("key1=value11"));
+        Assert.assertTrue(url.contains("key1=value12"));
+        Assert.assertTrue(url.contains("key2=value2"));
+        Assert.assertTrue(url.contains("myparam=paramvalue"));
+    }
+    
+    /**
+     * A ViewHandler implementation that extends the default implementation
+     * and returns a TestFaceletViewDeclarationLanguage in getVDL() for test purposes.
+     * @author Jakob Korherr
+     */
+    private class TestViewHandlerImpl extends ViewHandlerImpl
+    {
+
+        @Override
+        public ViewDeclarationLanguage getViewDeclarationLanguage(
+                FacesContext context, String viewId)
+        {
+            return new TestFaceletViewDeclarationLanguage(context);
+        }
+        
+    }
+    
+    /**
+     * A VDL implementation which extends FaceletViewDeclarationLanguage, but
+     * returns a TestViewMetadata instance on getViewMetadata().
+     * @author Jakob Korherr
+     */
+    private class TestFaceletViewDeclarationLanguage extends FaceletViewDeclarationLanguage
+    {
+
+        public TestFaceletViewDeclarationLanguage(FacesContext context)
+        {
+            super(context);
+        }
+
+        @Override
+        public ViewMetadata getViewMetadata(FacesContext context, String viewId)
+        {
+            return new TestViewMetadata(viewId);
+        }
+        
+    }
+    
+    /**
+     * A custom ViewMetadata implementation for the test, which returns
+     * one UIViewParameter with a name of myparam and a value of #{paramvalue}.
+     * @author Jakob Korherr
+     */
+    private class TestViewMetadata extends ViewMetadata
+    {
+        
+        private String _viewId;
+        
+        public TestViewMetadata(String viewId)
+        {
+            _viewId = viewId;
+        }
+
+        @Override
+        public UIViewRoot createMetadataView(FacesContext context)
+        {
+            UIViewRoot root = new UIViewRoot();
+            root.setViewId(_viewId);
+            UIComponent metadataFacet = new UIPanel();
+            root.getFacets().put(UIViewRoot.METADATA_FACET_NAME, metadataFacet);
+            UIViewParameter viewparam = new UIViewParameter();
+            viewparam.setName("myparam");
+            viewparam.setValueExpression("value", new MockValueExpression("#{paramvalue}", String.class));
+            metadataFacet.getChildren().add(viewparam);
+            return root;
+        }
+
+        @Override
+        public String getViewId()
+        {
+            return _viewId;
+        }
+        
+    }
+    
+}

Propchange: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: myfaces/core/trunk/impl/src/test/java/org/apache/myfaces/application/ViewHandlerImplTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain