package com.google.sitebricks.compiler.template.jsp;
import java.io.IOException;
import java.util.List;
import java.util.Set;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.sitebricks.Renderable;
import com.google.sitebricks.Respond;
import com.google.sitebricks.Template;
import com.google.sitebricks.compiler.TemplateCompiler;
/**
* Class that delegates the JSP compilation to the provided WEB container compiler
* and let the {@link RequestDispatcher} write the result into the response.
*
* The {@link Respond} is not used to write the result.
*
* An pageFlow attribute is added to the request so the accessors available in the
* page object can be used from the JSP page.
*/
@Singleton
public class JspTemplateCompiler implements TemplateCompiler {
public static final String PAGE_FLOW_REQUEST_ATTRIBUTE_NAME = "pageFlow";
public static final String PAGE_FLOW_ERRORS_REQUEST_ATTRIBUTE_NAME = "pageFlowErrors";
@Inject
private Provider<HttpServletRequest> httpServletRequestProvider;
@Inject
private Provider<HttpServletResponse> httpServletResponseProvider;
public Renderable compile(Class<?> page, final Template template) {
Renderable renderable = new Renderable() {
@Override
public void render(Object bound, Respond respond) {
HttpServletRequest httpRequest = httpServletRequestProvider.get();
HttpServletResponse httpresponse = httpServletResponseProvider.get();
httpRequest.setAttribute(PAGE_FLOW_REQUEST_ATTRIBUTE_NAME, bound);
List<String> errors = respond.getErrors();
Object obj = httpRequest.getAttribute(PAGE_FLOW_ERRORS_REQUEST_ATTRIBUTE_NAME);
if (obj != null) {
errors.addAll((List<String>) obj);
}
httpRequest.setAttribute(PAGE_FLOW_ERRORS_REQUEST_ATTRIBUTE_NAME, errors);
RequestDispatcher requestDispatcher = httpRequest.getRequestDispatcher(template.getName());
try {
requestDispatcher.include(httpRequest, httpresponse);
} catch (ServletException e) {
throw new RuntimeException("Could not include the JSP response for path=" + template.getName(), e);
} catch (IOException e) {
throw new RuntimeException("Could not include the JSP response for path=" + template.getName(), e);
}
}
@Override
public <T extends Renderable> Set<T> collect(Class<T> clazz) {
throw new IllegalStateException(
"The collect method should not be called while rendering a JSP template.");
}
};
return renderable;
}
}