package com.hastybox.lesscss.compileservice.controller.spring;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.servlet.mvc.Controller;
import org.springframework.web.servlet.mvc.LastModified;
import com.hastybox.lesscss.compileservice.LessCompileService;
/**
* Abstract class containing common functions to SpringLessControllers
* @author psy
*
*/
abstract public class AbstractSpringLessController implements Controller,
LastModified, ResourceLoaderAware {
/**
* logger
*/
private static final Logger LOGGER;
static {
LOGGER = LoggerFactory.getLogger(AbstractSpringLessController.class);
}
/**
* resource loader to load LESS files
*/
protected ResourceLoader resourceLoader;
/**
* compile service to do the compilation
*/
protected LessCompileService compileService;
/**
* base path of all LESS files
*/
protected String basePath;
/**
* relative value (from now) to set to LastModified header.
*/
private Long relativeLastModified;
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
/**
* @param compileService
* the compileService to set
*/
public void setCompileService(LessCompileService compileService) {
this.compileService = compileService;
}
/**
* Relative value (from now) to set to LastModified Header. {@code null}
* will always return Jan. 1st, 1970 in header. A positive value will set
* the LastModied to be {@code relativeLastModified} milliseconds in the
* past. A negative value will always trigger a generation of the content.
*
*
* @param relativeLastModified
* the relativeLastModified to set
*/
public void setRelativeLastModified(Long relativeLastModified) {
this.relativeLastModified = relativeLastModified;
}
/**
* Base path to all LESS files. Be aware that a
* {@link org.springframework.core.io.ResourceLoader} is used to access LESS
* files (e.g. "WEB-INF/less/", beware closing "/").
*
* @param basePath
* the basePath
*/
public void setBasePath(String basePath) {
this.basePath = basePath;
}
public long getLastModified(HttpServletRequest request) {
if (relativeLastModified == null) {
return 0;
}
if (relativeLastModified < 0L) {
return -1;
}
return System.currentTimeMillis() - relativeLastModified;
}
/**
* Compiles CSS code from given file in {@code resourcePath} and writes it
* into the given {@code response} object. If the file was not found a 404
* response is triggered.
*
*
* @param resourcePath
* path to file to compile
* @param response
* response to write to
* @throws IOException
*/
protected void compileLess(String resourcePath, HttpServletResponse response)
throws IOException {
LOGGER.debug("Compiling LESS from {}", resourcePath);
String cssCode;
// TODO add caching here to prevent file system lookup
try {
// try to compile file
cssCode = compileLess(resourcePath);
} catch (FileNotFoundException e) {
// file not found. Set ressponse to 404
LOGGER.info("LESS file at {} not found. Returning 404.",
resourcePath);
response.sendError(404);
return;
}
// write to response
response.getWriter().write(cssCode);
response.setContentType("text/css");
}
/**
* compiles CCS code from given file in {@code resourcePath}
*
* @param resourcePath
* path to LESS file
* @return compiles CSS code
* @throws IOException
*/
protected String compileLess(String resourcePath) throws IOException {
// load LESS file
Resource resource = resourceLoader.getResource(basePath + resourcePath);
if (!resource.exists()) {
throw new FileNotFoundException("Resource at " + resourcePath
+ " does not exist");
}
File lessFile = resourceLoader.getResource(basePath + resourcePath)
.getFile();
// compile
return compileService.compileCode(lessFile);
}
}