You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by je...@apache.org on 2008/04/14 04:57:27 UTC

svn commit: r647650 - in /struts/struts2/trunk/core/src: main/java/org/apache/struts2/components/I18n.java test/java/org/apache/struts2/views/jsp/I18nTagTest.java

Author: jeromy
Date: Sun Apr 13 19:57:22 2008
New Revision: 647650

URL: http://svn.apache.org/viewvc?rev=647650&view=rev
Log:
The closing I18n tag now throws an exception if it popped an unexpected object from the stack.

WW-2539


Modified:
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/I18n.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/I18n.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/I18n.java?rev=647650&r1=647649&r2=647650&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/I18n.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/components/I18n.java Sun Apr 13 19:57:22 2008
@@ -31,10 +31,13 @@
 import com.opensymphony.xwork2.ActionContext;
 import com.opensymphony.xwork2.LocaleProvider;
 import com.opensymphony.xwork2.TextProviderFactory;
+import com.opensymphony.xwork2.TextProvider;
 import com.opensymphony.xwork2.inject.Container;
 import com.opensymphony.xwork2.inject.Inject;
 import com.opensymphony.xwork2.util.LocalizedTextUtil;
 import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.logging.Logger;
+import com.opensymphony.xwork2.util.logging.LoggerFactory;
 
 /**
  * <!-- START SNIPPET: javadoc -->
@@ -84,9 +87,13 @@
 @StrutsTag(name="i18n", tldTagClass="org.apache.struts2.views.jsp.I18nTag", description="Get a resource bundle" +
                 " and place it on the value stack")
 public class I18n extends Component {
+
+    private static final Logger LOG = LoggerFactory.getLogger(I18n.class);
+
     protected boolean pushed;
     protected String name;
     protected Container container;
+    private TextProvider textProvider;
 
     public I18n(ValueStack stack) {
         super(stack);
@@ -112,11 +119,12 @@
                 final Locale locale = (Locale) getStack().getContext().get(ActionContext.LOCALE);
                 TextProviderFactory tpf = new TextProviderFactory();
                 container.inject(tpf);
-                getStack().push(tpf.createInstance(bundle, new LocaleProvider() {
-                     public Locale getLocale() {
-                         return locale;
-                     }
-                }));
+                textProvider = tpf.createInstance(bundle, new LocaleProvider() {
+                    public Locale getLocale() {
+                        return locale;
+                    }
+                });
+                getStack().push(textProvider);
                 pushed = true;
             }
         } catch (Exception e) {
@@ -127,9 +135,15 @@
         return result;
     }
 
-    public boolean end(Writer writer, String body) {
+    public boolean end(Writer writer, String body) throws StrutsException {
         if (pushed) {
-            getStack().pop();
+            Object o = getStack().pop();
+            if ((o == null) || (!o.equals(textProvider))) {
+                LOG.error("A closing i18n tag attempted to pop its own TextProvider from the top of the ValueStack but popped an unexpected object ("+(o != null ? o.getClass() : "null")+"). " +
+                            "Refactor the page within the i18n tags to ensure no objects are pushed onto the ValueStack without popping them prior to the closing tag. " +
+                            "If you see this message it's likely that the i18n's TextProvider is still on the stack and will continue to provide message resources after the closing tag.");
+                throw new StrutsException("A closing i18n tag attempted to pop its TextProvider from the top of the ValueStack but popped an unexpected object ("+(o != null ? o.getClass() : "null")+")");
+            }
         }
 
         return super.end(writer, body);

Modified: struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java?rev=647650&r1=647649&r2=647650&view=diff
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java (original)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/views/jsp/I18nTagTest.java Sun Apr 13 19:57:22 2008
@@ -3,6 +3,7 @@
 import org.apache.struts2.TestAction;
 import org.apache.struts2.StrutsTestCase;
 import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsException;
 import com.mockobjects.servlet.MockPageContext;
 import com.mockobjects.servlet.MockJspWriter;
 import com.opensymphony.xwork2.util.ValueStack;
@@ -59,5 +60,41 @@
             e.printStackTrace();
             fail();
         }
+    }
+
+    /**
+     * Asserts that an exception is thrown when something unexpected is popped off the stack by the closing tag
+     *
+     * @throws Exception
+     */
+    public void testUnexpectedPop() throws Exception {
+
+         // set the resource bundle
+        tag.setName("testmessages");
+
+        int result = 0;
+
+        try {
+            result = tag.doStartTag();
+        } catch (JspException e) {
+            e.printStackTrace();
+            fail();
+        }
+
+        stack.push("An new object on top of the stack");
+
+        assertEquals(TagSupport.EVAL_BODY_INCLUDE, result);
+
+        try {
+            result = tag.doEndTag();
+            fail();
+        } catch (JspException e) {
+            e.printStackTrace();
+            fail();
+        } catch (StrutsException e) {
+            e.printStackTrace();
+            // pass
+        }
+
     }
 }