blob: dea448c787e406b819a25c246ff2817169de074e [file] [log] [blame]
/*
* 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.struts2.views.java;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.inject.Inject;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.struts2.StrutsException;
import org.apache.struts2.components.template.BaseTemplateEngine;
import org.apache.struts2.components.template.Template;
import org.apache.struts2.components.template.TemplateEngine;
import org.apache.struts2.components.template.TemplateEngineManager;
import org.apache.struts2.components.template.TemplateRenderingContext;
import org.apache.struts2.views.java.simple.SimpleTheme;
import java.util.HashMap;
import java.util.StringTokenizer;
/**
* Template engine that renders tags using java implementations
*/
public class JavaTemplateEngine extends BaseTemplateEngine {
private static final Logger LOG = LogManager.getLogger(JavaTemplateEngine.class);
// The struts template engine manager
protected TemplateEngineManager templateEngineManager;
// The struts default template type. If struts ever changes this will need updating.
private String defaultTemplateType = "ftl";
@Inject
public void setTemplateEngineManager(TemplateEngineManager mgr) {
this.templateEngineManager = mgr;
}
private Themes themes = new Themes() {
{
add(new SimpleTheme());
}
};
@Override
protected String getSuffix() {
return "java";
}
public void renderTemplate(TemplateRenderingContext templateContext) throws Exception {
Template t = templateContext.getTemplate();
Theme theme = themes.get(t.getTheme());
if (theme == null) {
// Theme not supported, so do what struts would have done if we were not here.
LOG.debug("Theme not found [{}] trying default template engine using template type [{}]", t.getTheme(), defaultTemplateType);
final TemplateEngine engine = templateEngineManager.getTemplateEngine(templateContext.getTemplate(), defaultTemplateType);
if (engine == null) {
// May be the default template has changed?
throw new ConfigurationException("Unable to find a TemplateEngine for template type '" + defaultTemplateType
+ "' whilst trying to render template " + templateContext.getTemplate());
} else {
try {
// Retry render
engine.renderTemplate(templateContext);
} catch (Exception e) {
// Give up and throw a new StrutsException(e);
throw new StrutsException("Cannot render tag [" + t.getName() + "] because theme ["
+ t.getTheme() + "] was not found.", e);
}
}
} else {
// Render our template
theme.renderTag(t.getName(), templateContext);
}
}
private static class Themes {
private HashMap<String, Theme> themes = new HashMap<String, Theme>();
public void add(Theme theme) {
themes.put(theme.getName(), theme);
}
public Theme get(String name) {
return themes.get(name);
}
}
/**
* 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(value = JavaTemplateConstants.STRUTS_JAVATEMPLATES_CUSTOM_THEMES, required = false)
public void setThemeClasses(String themeClasses) {
StringTokenizer customThemes = new StringTokenizer(themeClasses, ",");
while (customThemes.hasMoreTokens()) {
String themeClass = customThemes.nextToken().trim();
try {
LOG.info("Registering custom theme [{}] to javatemplates engine", themeClass);
ObjectFactory factory = ActionContext.getContext().getContainer().getInstance(ObjectFactory.class);
Theme theme = (Theme) factory.buildBean(themeClass, new HashMap<String, Object>());
themes.add(theme);
} catch (ClassCastException cce) {
LOG.error("Invalid java them class [{}]. Class does not implement 'org.apache.struts2.views.java.Theme' interface", themeClass, cce);
} catch (ClassNotFoundException cnf) {
LOG.error("Invalid java theme class [{}]. Class not found!", themeClass, cnf);
} catch (Exception e) {
LOG.error("Could not find messages file [{}].properties. Skipping!", themeClass, e);
}
}
}
/**
* Allows for providing an alternative default struts theme. Will default to "ftl" otherwise.
*
* @param defaultTemplateTheme the struts default theme
*/
@Inject(value = JavaTemplateConstants.STRUTS_JAVATEMPLATES_DEFAULT_TEMPLATE_TYPE, required = false)
public void setDefaultTemplateType(String defaultTemplateTheme) {
// Make sure we don't set ourself as default for race condition
if (defaultTemplateTheme != null && !defaultTemplateTheme.equalsIgnoreCase(getSuffix())) {
this.defaultTemplateType = defaultTemplateTheme.toLowerCase();
} else {
LOG.error("Invalid struts.javatemplates.defaultTemplateType value. Cannot be [{}]!", getSuffix());
}
}
}