package org.smartly.packages.cms.impl.handlers.filters;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.util.resource.Resource;
import org.smartly.commons.logging.Level;
import org.smartly.commons.logging.Logger;
import org.smartly.commons.util.DateUtils;
import org.smartly.commons.util.ExceptionUtils;
import org.smartly.commons.util.FormatUtils;
import org.smartly.commons.util.StringUtils;
import org.smartly.packages.cms.SmartlyHttpCms;
import org.smartly.packages.cms.impl.cms.endpoint.CMSRouter;
import org.smartly.packages.cms.impl.cms.endpoint.CMSEndPointPage;
import org.smartly.packages.http.impl.util.ServletUtils;
import org.smartly.packages.http.impl.util.vtool.Cookies;
import org.smartly.packages.http.impl.util.vtool.Req;
import org.smartly.packages.velocity.impl.VLCManager;
import org.smartly.packages.velocity.impl.vtools.toolbox.VLCToolbox;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
/**
* Servlet for site file parsing.
*/
public class SmartlyCMSFilter
implements Filter {
public static String PATH = "/*";
private static final String MIME_HTML = "text/html";
private Resource _baseResource;
public SmartlyCMSFilter() {
}
public SmartlyCMSFilter(final Object params) {
}
public void setBaseResource(final Resource base) {
_baseResource = base;
}
public void setResourceBase(final String resourceBase) {
try {
this.setBaseResource(Resource.newResource(resourceBase));
} catch (Exception e) {
this.getLogger().warning(e.toString());
throw new IllegalArgumentException(resourceBase);
}
}
@Override
public void init(final FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(final ServletRequest request,
final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
boolean handled = false;
if (request instanceof HttpServletRequest && response instanceof HttpServletResponse) {
handled = this.handle((HttpServletRequest) request, (HttpServletResponse) response);
}
if (!handled) {
chain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
// ------------------------------------------------------------------------
// p r i v a t e
// ------------------------------------------------------------------------
private Logger getLogger() {
return SmartlyHttpCms.getCMSLogger();
}
private boolean handle(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException, IOException {
final String resourcePath = ServletUtils.getResourcePath(request);
final CMSRouter cms = SmartlyHttpCms.getCMS();
if (cms.contains(resourcePath)) {
final CMSEndPointPage page = cms.getPage(resourcePath);
final String template = cms.getPageTemplate(resourcePath);
if (null == page || !StringUtils.hasText(template)) {
response.sendError(HttpStatus.NOT_FOUND_404);
return true;
}
// eval template
final byte[] output = this.merge(template, page, request, response);
// write body
ServletUtils.writeResponse(response, DateUtils.now().getTime(), MIME_HTML, output);
return true;
} else {
return false;
}
}
private byte[] merge(final String templateText,
final CMSEndPointPage page,
final HttpServletRequest request,
final HttpServletResponse response) {
try {
// session context
final HttpSession session = request.getSession(true);
if (session.isNew()) {
session.setAttribute("velocity-context", new HashMap<String, Object>());
}
final Map<String, Object> sessionContext = (Map<String, Object>) session.getAttribute("velocity-context");
final VelocityEngine engine = getEngine();
// execution context
final VelocityContext context = new VelocityContext(sessionContext, this.createInnerContext(page.getUrl(), request, response));
// creates new context page
final CMSEndPointPage ctxPage = new CMSEndPointPage(page, engine, context);
context.put(CMSEndPointPage.NAME, ctxPage);
//-- eval velocity template --//
final String result;
if (null != engine) {
result = VLCManager.getInstance().evaluateText(engine, ctxPage.getUrl(), templateText, context);
} else {
result = VLCManager.getInstance().evaluateText(ctxPage.getUrl(), templateText, context);
}
if (StringUtils.hasText(result)) {
return result.getBytes();
}
} catch (Throwable t) {
this.getLogger().log(Level.SEVERE, FormatUtils.format(
"ERROR MERGING TEMPLATE FOR RESOURCE '{0}': {1}",
page.getUrl(), ExceptionUtils.getRealMessage(t)), t);
}
return new byte[0];
}
private VelocityContext createInnerContext(final String url,
final HttpServletRequest request,
final HttpServletResponse response) {
final VelocityContext result = new VelocityContext(VLCToolbox.getInstance().getToolsContext());
//-- "$req" tool --//
result.put(Req.NAME, new Req(url, request));
//-- "$cookies" tool --//
result.put(Cookies.NAME, new Cookies(request, response));
return result;
}
// --------------------------------------------------------------------
// S T A T I C
// --------------------------------------------------------------------
private static VelocityEngine __engine;
private static VelocityEngine getEngine() throws Exception {
if (null == __engine) {
__engine = VLCManager.getInstance().getEngine().getNativeEngine();
}
return __engine;
}
}