package com.twitter.common.net.http.handlers;
import com.google.common.base.Preconditions;
import com.google.inject.BindingAnnotation;
import com.twitter.common.base.Closure;
import com.twitter.common.base.MorePreconditions;
import com.twitter.common.util.templating.StringTemplateHelper;
import com.twitter.common.util.templating.StringTemplateHelper.TemplateException;
import org.antlr.stringtemplate.StringTemplate;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A base class for servlets that render using the string template templating system. Subclasses
* can call one of the {@link #writeTemplate} methods to render their content with the associated
* template.
*/
public abstract class StringTemplateServlet extends HttpServlet {
private static final String CONTENT_TYPE_TEXT_HTML = "text/html";
/**
* A {@literal @BindingAnnotation} that allows configuration of whether or not
* StringTemplateServlets should cache their templates.
*/
@BindingAnnotation
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
public @interface CacheTemplates {}
private static final Logger LOG = Logger.getLogger(StringTemplateServlet.class.getName());
private final StringTemplateHelper templateHelper;
/**
* Creates a new StringTemplateServlet that expects to find its template located in the same
* package on the classpath at '{@code templateName}.st'.
*
* @param templateName The name of the string template to use.
* @param cacheTemplates {@code true} to re-use loaded templates, {@code false} to reload the
* template for each request.
*/
protected StringTemplateServlet(String templateName, boolean cacheTemplates) {
templateHelper = new StringTemplateHelper(getClass(), templateName, cacheTemplates);
}
protected final void writeTemplate(
HttpServletResponse response,
Closure<StringTemplate> parameterSetter) throws IOException {
writeTemplate(response, CONTENT_TYPE_TEXT_HTML, HttpServletResponse.SC_OK, parameterSetter);
}
protected final void writeTemplate(
HttpServletResponse response,
String contentType,
int status,
Closure<StringTemplate> parameterSetter) throws IOException {
Preconditions.checkNotNull(response);
MorePreconditions.checkNotBlank(contentType);
Preconditions.checkArgument(status > 0);
Preconditions.checkNotNull(parameterSetter);
try {
templateHelper.writeTemplate(response.getWriter(), parameterSetter);
response.setStatus(status);
response.setContentType(contentType);
} catch (TemplateException e) {
LOG.log(Level.SEVERE, "Unknown exception.", e);
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}