Author: awiner
Date: Tue Mar 10 00:19:40 2009
New Revision: 751919

URL: http://svn.apache.org/viewvc?rev=751919&view=rev
Log:
SHINDIG-748: OpenSocial templates (in part)
- Add support for ${Msg} variable in server-side templates, including recursive 
EL execution

Added:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java
   (with props)
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java
   (with props)
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java
   (with props)
Modified:
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/TemplateRewriter.java
    
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/TemplateELResolver.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
    
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/TemplateRewriterTest.java

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/TemplateRewriter.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/TemplateRewriter.java?rev=751919&r1=751918&r2=751919&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/TemplateRewriter.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/rewrite/TemplateRewriter.java
 Tue Mar 10 00:19:40 2009
@@ -18,22 +18,28 @@
 package org.apache.shindig.gadgets.rewrite;
 
 import org.apache.shindig.common.xml.DomUtil;
+import org.apache.shindig.expressions.Expressions;
 import org.apache.shindig.gadgets.Gadget;
 import org.apache.shindig.gadgets.GadgetELResolver;
+import org.apache.shindig.gadgets.GadgetException;
+import org.apache.shindig.gadgets.MessageBundleFactory;
 import org.apache.shindig.gadgets.http.HttpRequest;
 import org.apache.shindig.gadgets.http.HttpResponse;
 import org.apache.shindig.gadgets.spec.Feature;
+import org.apache.shindig.gadgets.spec.MessageBundle;
+import org.apache.shindig.gadgets.templates.MessageELResolver;
 import org.apache.shindig.gadgets.templates.TemplateContext;
 import org.apache.shindig.gadgets.templates.TemplateProcessor;
+import org.json.JSONObject;
+import org.w3c.dom.DocumentFragment;
+import org.w3c.dom.Element;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.StringTokenizer;
 
-import org.json.JSONObject;
-import org.w3c.dom.DocumentFragment;
-import org.w3c.dom.Element;
+import javax.el.CompositeELResolver;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
@@ -61,10 +67,15 @@
    * processors are not.
    */
   private final Provider<TemplateProcessor> processor;
+  private final MessageBundleFactory messageBundleFactory;
+  private final Expressions expressions;
 
   @Inject
-  public TemplateRewriter(Provider<TemplateProcessor> processor) {
+  public TemplateRewriter(Provider<TemplateProcessor> processor,
+      MessageBundleFactory messageBundleFactory, Expressions expressions) {
     this.processor = processor;
+    this.messageBundleFactory = messageBundleFactory;
+    this.expressions = expressions;
   }
 
   public RewriterResults rewrite(HttpRequest request, HttpResponse original,
@@ -76,7 +87,13 @@
     Feature f = gadget.getSpec().getModulePrefs().getFeatures()
         .get("opensocial-templates");
     if (f != null && isServerTemplatingEnabled(f)) {
-      return rewriteImpl(gadget, content);
+      try {
+        return rewriteImpl(gadget, content);
+      } catch (GadgetException ge) {
+        // TODO: Rewriter interface needs to be modified to handle 
GadgetException or
+        // RewriterException or something along those lines.
+        throw new RuntimeException(ge);
+      }
     }
     return null;
   }
@@ -91,7 +108,8 @@
     return 
("true".equalsIgnoreCase(f.getParams().get(SERVER_TEMPLATING_PARAM)));
   }
 
-  private RewriterResults rewriteImpl(Gadget gadget, MutableContent content) {
+  private RewriterResults rewriteImpl(Gadget gadget, MutableContent content)
+      throws GadgetException {
     List<Element> tagList =
       DomUtil.getElementsByTagNameCaseInsensitive(content.getDocument(), TAGS);
     final Map<String, JSONObject> pipelinedData = content.getPipelinedData();
@@ -119,10 +137,17 @@
 
     TemplateContext templateContext = new TemplateContext(pipelinedData);
     GadgetELResolver globalGadgetVars = new 
GadgetELResolver(gadget.getContext());
+    
+    MessageBundle bundle = messageBundleFactory.getBundle(gadget.getSpec(),
+        gadget.getContext().getLocale(), gadget.getContext().getIgnoreCache());
+    MessageELResolver messageELResolver = new MessageELResolver(expressions, 
bundle);
+    CompositeELResolver resolvers = new CompositeELResolver();
+    resolvers.add(globalGadgetVars);
+    resolvers.add(messageELResolver);
 
     for (Element template : templates) {
       DocumentFragment result = processor.get().processTemplate(
-          template, templateContext, globalGadgetVars);
+          template, templateContext, resolvers);
       // Note: replaceNode errors when replacing Element with DocumentFragment
       template.getParentNode().insertBefore(result, template);
       // TODO: clients that need to update data that is initially available,

Added: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java?rev=751919&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java
 Tue Mar 10 00:19:40 2009
@@ -0,0 +1,138 @@
+/*
+ * 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.shindig.gadgets.templates;
+
+import org.apache.shindig.expressions.Expressions;
+import org.apache.shindig.gadgets.spec.MessageBundle;
+
+import java.beans.FeatureDescriptor;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.ELResolver;
+import javax.el.PropertyNotWritableException;
+
+import com.google.common.collect.Lists;
+
+/**
+ * ELResolver for the Msg property in templates.
+ */
+public class MessageELResolver extends ELResolver {
+  public static final String PROPERTY_MSG = "Msg";
+  private final MessageBundle bundle;
+  private final Expressions expressions;
+
+  public MessageELResolver(Expressions expressions, MessageBundle bundle) {
+    this.expressions = expressions;
+    this.bundle = bundle;
+  }
+  
+  @Override
+  public Class<?> getCommonPropertyType(ELContext context, Object base) {
+    if (base == null) {
+      return String.class;
+    }
+    
+    return null;
+  }
+
+  @Override
+  public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context,
+      Object base) {
+    return null;
+  }
+
+  @Override
+  public Class<?> getType(ELContext context, Object base, Object property) {
+    // TODO: implement
+    return null;
+  }
+
+  @Override
+  public Object getValue(ELContext context, Object base, Object property) {
+    if ((base == null) && PROPERTY_MSG.equals(property)) {
+      context.setPropertyResolved(true);
+      return bundle;
+    } else if (base instanceof MessageBundle) {
+      String text = bundle.getMessages().get(property);
+      if (text == null) {
+        context.setPropertyResolved(true);
+        return null;
+      }
+      
+      List<Object> properties = null;
+      try {
+        properties = pushCurrentProperty(context, property);
+        context.setPropertyResolved(false);
+        return expressions.parse(text, Object.class).getValue(context);
+      } finally {
+        popProperty(properties);
+        context.setPropertyResolved(true);
+      }
+    }
+    
+    return null;
+  }
+
+  /**
+   * Track the set of message bundle properties being evaluated.  We allow
+   * recursion, but don't want to allow infinite self-recursion (though the
+   * stack overflows quickly).
+   */
+  private List<Object> pushCurrentProperty(ELContext context, Object property) 
{
+    @SuppressWarnings("unchecked")
+    List<Object> propertyList = (List<Object>) 
context.getContext(MessageELResolver.class);
+    if (propertyList == null) {
+      propertyList = Lists.newArrayList();
+      context.putContext(MessageELResolver.class, propertyList);
+    } else {
+      if (propertyList.contains(property)) {
+        throw new ELException("Recursive invocation of message bundle 
properties");
+      }
+    }
+    
+    propertyList.add(property);
+    return propertyList;
+  }
+
+  private void popProperty(List<Object> properties) {
+    if (properties != null) {
+      properties.remove(properties.size() - 1);
+    }
+  }
+
+  @Override
+  public boolean isReadOnly(ELContext context, Object base, Object property) {
+    if ((base == null) && PROPERTY_MSG.equals(property)) {
+      context.setPropertyResolved(true);
+      return true;
+    }
+    
+    return false;
+  }
+
+  @Override
+  public void setValue(ELContext context, Object base, Object property, Object 
value) {
+    if ((base == null) && PROPERTY_MSG.equals(property)) {
+      throw new PropertyNotWritableException();
+    }
+  }
+}

Propchange: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/MessageELResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/TemplateELResolver.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/TemplateELResolver.java?rev=751919&r1=751918&r2=751919&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/TemplateELResolver.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/main/java/org/apache/shindig/gadgets/templates/TemplateELResolver.java
 Tue Mar 10 00:19:40 2009
@@ -34,6 +34,8 @@
  * ELResolver used to process OpenSocial templates.  Provides three variables:
  * <ul>
  * <li>"Top": Global values </li>
+ * <li>"Cur": Current template variable</li>
+ * <li>"Context": Miscellaneous contextual information</li>
  */
 public class TemplateELResolver extends ELResolver {
   public static final String PROPERTY_TOP = "Top";

Added: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java?rev=751919&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java
 Tue Mar 10 00:19:40 2009
@@ -0,0 +1,39 @@
+/*
+ * 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.shindig.gadgets.render;
+
+import org.apache.shindig.gadgets.MessageBundleFactory;
+import org.apache.shindig.gadgets.spec.GadgetSpec;
+import org.apache.shindig.gadgets.spec.LocaleSpec;
+import org.apache.shindig.gadgets.spec.MessageBundle;
+
+import java.util.Locale;
+
+/**
+ * Simple message bundle factory -- only honors inline bundles.
+ */
+public class FakeMessageBundleFactory implements MessageBundleFactory {
+  public MessageBundle getBundle(GadgetSpec spec, Locale locale, boolean 
ignoreCache) {
+    LocaleSpec localeSpec = spec.getModulePrefs().getLocale(locale);
+    if (localeSpec == null) {
+      return MessageBundle.EMPTY;
+    }
+    return spec.getModulePrefs().getLocale(locale).getMessageBundle();
+  }
+}
\ No newline at end of file

Propchange: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/FakeMessageBundleFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java?rev=751919&r1=751918&r2=751919&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/render/RenderingContentRewriterTest.java
 Tue Mar 10 00:19:40 2009
@@ -35,7 +35,6 @@
 import org.apache.shindig.gadgets.GadgetFeature;
 import org.apache.shindig.gadgets.GadgetFeatureRegistry;
 import org.apache.shindig.gadgets.JsLibrary;
-import org.apache.shindig.gadgets.MessageBundleFactory;
 import org.apache.shindig.gadgets.UrlGenerator;
 import org.apache.shindig.gadgets.parse.GadgetHtmlParser;
 import org.apache.shindig.gadgets.parse.ParseModule;
@@ -43,8 +42,6 @@
 import org.apache.shindig.gadgets.preload.PreloadedData;
 import org.apache.shindig.gadgets.rewrite.MutableContent;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
-import org.apache.shindig.gadgets.spec.LocaleSpec;
-import org.apache.shindig.gadgets.spec.MessageBundle;
 import org.apache.shindig.gadgets.spec.View;
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -55,7 +52,6 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.List;
-import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.regex.Matcher;
@@ -737,22 +733,6 @@
     }
   }
 
-  /**
-   * Simple message bundle factory -- only honors inline bundles.
-   */
-  private static class FakeMessageBundleFactory implements 
MessageBundleFactory {
-    protected FakeMessageBundleFactory() {
-    }
-
-    public MessageBundle getBundle(GadgetSpec spec, Locale locale, boolean 
ignoreCache) {
-      LocaleSpec localeSpec = spec.getModulePrefs().getLocale(locale);
-      if (localeSpec == null) {
-        return MessageBundle.EMPTY;
-      }
-      return spec.getModulePrefs().getLocale(locale).getMessageBundle();
-    }
-  }
-
   private static class FakeUrlGenerator implements UrlGenerator {
     protected FakeUrlGenerator() {
     }

Modified: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/TemplateRewriterTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/TemplateRewriterTest.java?rev=751919&r1=751918&r2=751919&view=diff
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/TemplateRewriterTest.java
 (original)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/rewrite/TemplateRewriterTest.java
 Tue Mar 10 00:19:40 2009
@@ -26,6 +26,7 @@
 import org.apache.shindig.gadgets.GadgetContext;
 import org.apache.shindig.gadgets.parse.ParseModule;
 import org.apache.shindig.gadgets.parse.nekohtml.SocialMarkupHtmlParser;
+import org.apache.shindig.gadgets.render.FakeMessageBundleFactory;
 import org.apache.shindig.gadgets.spec.GadgetSpec;
 import org.apache.shindig.gadgets.spec.SpecParserException;
 import org.apache.shindig.gadgets.templates.DefaultTemplateProcessor;
@@ -57,6 +58,9 @@
   private static final String CONTENT_PLAIN =
     "<script type='text/os-template'>Hello, ${user.name}</script>";  
 
+  private static final String CONTENT_WITH_MESSAGE =
+    "<script type='text/os-template'>Hello, ${Msg.name}</script>";  
+
   private static final String CONTENT_REQUIRE =
     "<script type='text/os-template' require='user'>Hello, 
${user.name}</script>";  
   
@@ -79,7 +83,9 @@
             return new DefaultTemplateProcessor(Expressions.sharedInstance(), 
                 new TagRegistry(handlers));
           }
-        });
+        },
+        new FakeMessageBundleFactory(),
+        new Expressions());
   }
   
   @Test
@@ -118,6 +124,12 @@
     testExpectingNoTransform(getGadgetXml(CONTENT_WITH_TAG), "with @tag");
   }
    
+  @Test
+  public void templateUsingMessage() throws Exception {
+    // Render a simple template
+    testExpectingTransform(getGadgetXml(CONTENT_WITH_MESSAGE), "simple");
+  }
+  
   private void testExpectingTransform(String code, String condition) throws 
Exception {
     setupGadget(code);
     rewriter.rewrite(gadget, content);
@@ -162,7 +174,11 @@
         "  <Param name='" + TemplateRewriter.SERVER_TEMPLATING_PARAM + 
"'>true</Param>" +
         "</Require>" : "";
     return "<Module>" + "<ModulePrefs title='Title'>"
-        + feature + "</ModulePrefs>"
+        + feature
+        + "  <Locale>"
+        + "    <msg name='name'>John</msg>"
+        + "  </Locale>"
+        + "</ModulePrefs>"
         + "<Content>"
         + "    <![CDATA[" + content + "]]>"
         + "</Content></Module>";

Added: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java
URL: 
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java?rev=751919&view=auto
==============================================================================
--- 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java
 (added)
+++ 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java
 Tue Mar 10 00:19:40 2009
@@ -0,0 +1,91 @@
+/*
+ * 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.shindig.gadgets.templates;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.apache.shindig.common.xml.XmlUtil;
+import org.apache.shindig.expressions.Expressions;
+import org.apache.shindig.gadgets.spec.MessageBundle;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+
+public class MessageELResolverTest {
+  static private final String MESSAGE_BUNDLE =
+    "<messagebundle>" +
+      "<msg name='hello'>world</msg>" +
+      "<msg name='number'>${1+1}</msg>" +
+      "<msg name='concat'>${Msg.hello} ${Msg.number}</msg>" + 
+      "<msg name='multiLevel'>${Msg.concat} ${Msg.concat}</msg>" +
+      // Self-recursive EL, should fail
+      "<msg name='recurse'>${Msg.recurse}</msg>" +
+      // Mutually recursive EL, should fail
+      "<msg name='mutual1'>${Msg.mutual2}</msg>" +
+      "<msg name='mutual2'>${Msg.mutual1}</msg>" +
+    "</messagebundle>";
+  private MessageBundle messageBundle;
+  private Expressions expressions;
+  private ELContext context;
+  
+  @Before
+  public void setUp() throws Exception {
+    messageBundle = new MessageBundle(XmlUtil.parse(MESSAGE_BUNDLE));
+    expressions = new Expressions();
+    context = expressions.newELContext(new MessageELResolver(expressions, 
messageBundle));
+  }
+
+  @Test
+  public void basicExpression() {
+    assertEquals("world", expressions.parse("${Msg.hello}", 
String.class).getValue(context)); 
+  }
+  
+  @Test
+  public void nullForMissingProperty() {
+    assertNull(expressions.parse("${Msg.notThere}", 
Object.class).getValue(context)); 
+  }
+  
+  @Test
+  public void innerEvaluation() {
+    assertEquals(2, expressions.parse("${Msg.number}", 
Integer.class).getValue(context)); 
+  }
+
+  @Test
+  public void recursiveEvaluation() {
+    assertEquals("world 2", expressions.parse("${Msg.concat}", 
String.class).getValue(context)); 
+  }
+
+  @Test
+  public void multiLevelRecursiveEvaluation() {
+    assertEquals("world 2 world 2", expressions.parse("${Msg.multiLevel}", 
String.class).getValue(context)); 
+  }
+
+  @Test(expected = ELException.class)
+  public void failsInsteadOfInfiniteRecursion() {
+    expressions.parse("${Msg.recurse}", String.class).getValue(context); 
+  }
+
+  @Test(expected = ELException.class)
+  public void failsInsteadOfMutualInfiniteRecursion() {
+    expressions.parse("${Msg.mutual1}", String.class).getValue(context); 
+  }
+}

Propchange: 
incubator/shindig/trunk/java/gadgets/src/test/java/org/apache/shindig/gadgets/templates/MessageELResolverTest.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to