Author: hermanns Date: Wed Apr 22 13:37:01 2009 New Revision: 767518 URL: http://svn.apache.org/viewvc?rev=767518&view=rev Log: WW-3009 Extensibility Improvements to javatemplates plugin - patch (project scope) submitted by Eric Chijioke
Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/Attributes.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/DefaultTheme.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/JavaTemplateEngine.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/XHTMLTagSerializer.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/DivHandler.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/HeadHandler.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SelectHandler.java struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java struts/struts2/trunk/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/HeadTest.java Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/Attributes.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/Attributes.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/Attributes.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/Attributes.java Wed Apr 22 13:37:01 2009 @@ -30,6 +30,8 @@ */ public class Attributes extends LinkedHashMap<String, String> { + private static final long serialVersionUID = 4103241472140545630L; + public Attributes add(String key, String value) { return add(key, value, true); } Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/DefaultTheme.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/DefaultTheme.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/DefaultTheme.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/DefaultTheme.java Wed Apr 22 13:37:01 2009 @@ -38,7 +38,7 @@ private static final Logger LOG = LoggerFactory.getLogger(DefaultTheme.class); private String name; - private Map<String, List<TagHandlerFactory>> handlerFactories; + protected Map<String, List<TagHandlerFactory>> handlerFactories; protected void setName(String name) { this.name = name; @@ -48,6 +48,47 @@ this.handlerFactories = handlers; } + + /** + * Set (replace if exists) the tag handler factories for specific tag + * + * @param tagName + * @param handlers + */ + protected void setTagHandlerFactories(String tagName, List<TagHandlerFactory> handlers) { + if (tagName != null && handlers != null && this.handlerFactories != null) { + handlerFactories.put(tagName, handlers); + } + } + + /** + * Insert a new tag handler into a sequence of tag handlers for a specific tag + * TODO: Need to take care of serializers, if handler specified is not a TagSerializer it should never + * be placed after the serializer, but if it is not a TagSerializer, it should never + * + * @param tagName + * @param sequence + * @param factory + */ + protected void insertTagHandlerFactory(String tagName, int sequence, TagHandlerFactory factory) { + + if (tagName != null && factory != null && this.handlerFactories != null) { + + List<TagHandlerFactory> tagHandlerFactories = handlerFactories.get(tagName); + + if (tagHandlerFactories == null) { + tagHandlerFactories = new ArrayList<TagHandlerFactory>(); //TODO: Could use public FactoryList here + } + + if (sequence > tagHandlerFactories.size()) { + sequence = tagHandlerFactories.size(); + } + + //TODO, need to account for TagHandlers vs. TagSerializers here + tagHandlerFactories.add(sequence, factory); + } + } + public String getName() { return name; } @@ -70,7 +111,7 @@ handlers.add(0, prev); } - TagSerializer ser = (TagSerializer) handlers.get(handlers.size() - 1); + // TagSerializer ser = (TagSerializer) handlers.get(handlers.size() - 1); TagGenerator gen = (TagGenerator) handlers.get(0); try { Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/JavaTemplateEngine.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/JavaTemplateEngine.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/JavaTemplateEngine.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/JavaTemplateEngine.java Wed Apr 22 13:37:01 2009 @@ -27,12 +27,20 @@ import org.apache.struts2.views.java.simple.SimpleTheme; import java.util.HashMap; +import java.util.StringTokenizer; + +import com.opensymphony.xwork2.util.logging.LoggerFactory; +import com.opensymphony.xwork2.util.logging.Logger; +import com.opensymphony.xwork2.util.ClassLoaderUtil; +import com.opensymphony.xwork2.inject.Inject; /** * Template engine that renders tags using java implementations */ public class JavaTemplateEngine extends BaseTemplateEngine { + private static final Logger LOG = LoggerFactory.getLogger(JavaTemplateEngine.class); + private Themes themes = new Themes() {{ add(new SimpleTheme()); }}; @@ -64,4 +72,34 @@ } } + /** + * Allows for providing custom theme classes (implementations of the org.apache.struts2.views.java.Theme) interface + * for custom rendering of tags using the javatemplates engine + * + * @param themeClasses a comma delimited list of custom theme class names + */ + @Inject("struts.javatemplates.customThemes") + public void setThemeClasses(String themeClasses) { + + StringTokenizer customThemes = new StringTokenizer(themeClasses, ","); + + while (customThemes.hasMoreTokens()) { + String themeClass = customThemes.nextToken().trim(); + try { + LOG.info("Registering custom theme '" + themeClass + "' to javatemplates engine"); + + + //FIXME: This means Themes must have no-arg constructor - should use object factory here + //ObjectFactory.getObjectFactory().buildBean(ClassLoaderUtil.loadClass(themeClass, getClass()), null); + themes.add((Theme) ClassLoaderUtil.loadClass(themeClass, getClass()).newInstance()); + + } catch (ClassCastException cce) { + LOG.error("Invalid java them class '" + themeClass + "'. Class does not implement 'org.apache.struts2.views.java.Theme' interface"); + } catch (ClassNotFoundException cnf) { + LOG.error("Invalid java theme class '" + themeClass + "'. Class not found"); + } catch (Exception e) { + LOG.error("Could not find messages file " + themeClass + ".properties. Skipping"); + } + } + } } Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/XHTMLTagSerializer.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/XHTMLTagSerializer.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/XHTMLTagSerializer.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/XHTMLTagSerializer.java Wed Apr 22 13:37:01 2009 @@ -32,7 +32,7 @@ */ public class XHTMLTagSerializer implements TagSerializer { - private Writer writer; + protected Writer writer; public void characters(String text) throws IOException { characters(text, true); Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/DivHandler.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/DivHandler.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/DivHandler.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/DivHandler.java Wed Apr 22 13:37:01 2009 @@ -35,7 +35,7 @@ .addIfExists("class", params.get("cssClass")) .addIfExists("style", params.get("cssStyle")) .addIfExists("title", params.get("title")); - start("div", attrs); + super.start("div", attrs); } public static class CloseHandler extends AbstractTagHandler implements TagGenerator { Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/HeadHandler.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/HeadHandler.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/HeadHandler.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/HeadHandler.java Wed Apr 22 13:37:01 2009 @@ -37,9 +37,13 @@ attrs.put("type", "text/javascript"); String base = ServletActionContext.getRequest().getContextPath(); + attrs.put("base", base); + StringBuilder sb = new StringBuilder(); - if (base != null) + if (base != null) { sb.append(base); + } + sb.append("/struts/utils.js"); attrs.put("src", sb.toString()); Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SelectHandler.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SelectHandler.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SelectHandler.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SelectHandler.java Wed Apr 22 13:37:01 2009 @@ -76,10 +76,10 @@ //key Object itemKey = findValue(listKey != null ? listKey : "top"); - String itemKeyStr = StringUtils.defaultString(itemKey.toString()); + String itemKeyStr = StringUtils.defaultString(itemKey == null ? null : itemKey.toString()); //value Object itemValue = findValue(listValue != null ? listValue : "top"); - String itemValueStr = StringUtils.defaultString(itemValue.toString()); + String itemValueStr = StringUtils.defaultString(itemValue == null ? null : itemValue.toString()); boolean selected = ContainUtil.contains(value, itemKey); writeOption(itemKeyStr, itemValueStr, selected); Modified: struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/main/java/org/apache/struts2/views/java/simple/SimpleTheme.java Wed Apr 22 13:37:01 2009 @@ -32,36 +32,41 @@ public class SimpleTheme extends DefaultTheme { public SimpleTheme() { - setHandlerFactories(new HashMap<String, List<TagHandlerFactory>>() {{ - put("text", new FactoryList(TextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("textfield", new FactoryList(TextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("select", new FactoryList(SelectHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("form", new FactoryList(FormHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("form-close", new FactoryList(FormHandler.CloseHandler.class)); - put("a", new FactoryList(AnchorHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("a-close", new FactoryList(AnchorHandler.CloseHandler.class)); - put("checkbox", new FactoryList(CheckboxHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("file", new FactoryList(FileHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("password", new FactoryList(PasswordHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("label", new FactoryList(LabelHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("reset", new FactoryList(ResetHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("submit", new FactoryList(SubmitHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("submit-close", new FactoryList(SubmitHandler.CloseHandler.class)); - put("textarea", new FactoryList(TextAreaHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("actionerror", new FactoryList(ActionErrorHandler.class)); - put("token", new FactoryList(TokenHandler.class)); - put("actionmessage", new FactoryList(ActionMessageHandler.class)); - put("head", new FactoryList(HeadHandler.class)); - put("hidden", new FactoryList(HiddenHandler.class)); - put("fielderror", new FactoryList(FieldErrorHandler.class)); - put("div", new FactoryList(DivHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); - put("div-close", new FactoryList(DivHandler.CloseHandler.class)); - put("empty", new FactoryList(EmptyHandler.class)); - }}); + setHandlerFactories(new HashMap<String, List<TagHandlerFactory>>() { + { + put("text", new FactoryList(TextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("textfield", new FactoryList(TextFieldHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("select", new FactoryList(SelectHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("form", new FactoryList(FormHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("form-close", new FactoryList(FormHandler.CloseHandler.class)); + put("a", new FactoryList(AnchorHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("a-close", new FactoryList(AnchorHandler.CloseHandler.class)); + put("checkbox", new FactoryList(CheckboxHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("file", new FactoryList(FileHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("password", new FactoryList(PasswordHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("label", new FactoryList(LabelHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("reset", new FactoryList(ResetHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("submit", new FactoryList(SubmitHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("submit-close", new FactoryList(SubmitHandler.CloseHandler.class)); + put("textarea", new FactoryList(TextAreaHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("actionerror", new FactoryList(ActionErrorHandler.class)); + put("token", new FactoryList(TokenHandler.class)); + put("actionmessage", new FactoryList(ActionMessageHandler.class)); + put("head", new FactoryList(HeadHandler.class)); + put("hidden", new FactoryList(HiddenHandler.class)); + put("fielderror", new FactoryList(FieldErrorHandler.class)); + put("div", new FactoryList(DivHandler.class, ScriptingEventsHandler.class, CommonAttributesHandler.class)); + put("div-close", new FactoryList(DivHandler.CloseHandler.class)); + put("empty", new FactoryList(EmptyHandler.class)); + } + }); setName("simple"); } private class FactoryList extends ArrayList<TagHandlerFactory> { + + private static final long serialVersionUID = -1551895041394434032L; + public FactoryList(Class... classes) { super(); for (Class cls : classes) { Modified: struts/struts2/trunk/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/HeadTest.java URL: http://svn.apache.org/viewvc/struts/struts2/trunk/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/HeadTest.java?rev=767518&r1=767517&r2=767518&view=diff ============================================================================== --- struts/struts2/trunk/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/HeadTest.java (original) +++ struts/struts2/trunk/plugins/javatemplates/src/test/java/org/apache/struts2/views/java/simple/HeadTest.java Wed Apr 22 13:37:01 2009 @@ -31,7 +31,7 @@ map.putAll(tag.getParameters()); theme.renderTag(getTagName(), context); String output = writer.getBuffer().toString(); - String expected = s("<script type='text/javascript' src='/some/path/struts/utils.js'></script>"); + String expected = s("<script type='text/javascript' base='/some/path' src='/some/path/struts/utils.js'></script>"); assertEquals(expected, output); }