package ddth.dasp.framework.springmvc;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.activation.MimetypesFileTypeMap;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import ddth.dasp.common.rp.IRequestParser;
import ddth.dasp.framework.resource.IResourceLoader;
/**
* This controller serves bundle's static content over the web.
*
* @author NBThanh <btnguyen2k@gmail.com>
* @version since v0.1.0
*/
public class BundleStaticResourceController extends BaseAnnotationController {
private String encoding = "utf-8";
private String resourcePrefix = "";
private IResourceLoader resourceLoader;
private Map<String, String> mimetypes = new HashMap<String, String>();
public BundleStaticResourceController() {
mimetypes.put(".bmp", "image/bmp");
mimetypes.put(".css", "text/css");
mimetypes.put(".gif", "image/gif");
mimetypes.put(".ico", "image/x-icon");
mimetypes.put(".jpg", "image/jpeg");
mimetypes.put(".js", "text/javascript");
mimetypes.put(".png", "image/png");
}
protected Map<String, String> getMimetypes() {
return mimetypes;
}
public void setMimetypes(Map<String, String> mimetypes) {
this.mimetypes = mimetypes;
}
protected String getEncoding() {
return encoding;
}
public void setEncoding(String encoding) {
this.encoding = encoding;
}
protected String getResourcePrefix() {
return resourcePrefix;
}
public void setResourcePrefix(String resourcePrefix) {
this.resourcePrefix = resourcePrefix;
if (resourcePrefix.endsWith("/")) {
resourcePrefix.replaceAll("\\/+$", "/");
} else {
resourcePrefix += "/";
}
}
protected IResourceLoader getResourceLoader() {
return resourceLoader;
}
public void setResourceLoader(IResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@RequestMapping
public void handle(HttpServletRequest request, HttpServletResponse response) throws IOException {
IRequestParser rp = getRequestParser(request);
String requestUri = rp.getRequestUri();
if (requestUri.startsWith("/")) {
requestUri = requestUri.replaceAll("^\\/+", "");
}
String resourceUri = resourcePrefix != null ? resourcePrefix + requestUri : requestUri;
if (serveStaticResource(resourceUri, request, response)) {
return;
}
String requestAction = getRequestAction(request);
if (!StringUtils.isBlank(requestAction)) {
if (requestAction.length() + 1 < requestUri.length()) {
requestUri = requestUri.substring(requestAction.length() + 1);
resourceUri = resourcePrefix != null ? resourcePrefix + requestUri : requestUri;
if (serveStaticResource(resourceUri, request, response)) {
return;
}
}
}
response.sendError(HttpServletResponse.SC_NOT_FOUND);
}
protected String deltectMimetype(String resourceUri) {
int index = resourceUri.lastIndexOf('.');
String resourceExt = index < 0 ? "" : resourceUri.substring(index);
String mimetype = mimetypes.get(resourceExt);
if (StringUtils.isBlank(mimetype)) {
mimetype = MimetypesFileTypeMap.getDefaultFileTypeMap().getContentType(resourceUri);
}
return !StringUtils.isBlank(mimetype) ? mimetype : "application/octet-stream";
}
protected boolean serveStaticResource(String resourceUri, HttpServletRequest request,
HttpServletResponse response) throws IOException {
if (!resourceLoader.resourceExists(resourceUri)) {
return false;
}
// return some HTTP headers first
if (!StringUtils.isBlank(encoding)) {
response.setCharacterEncoding(encoding);
}
String mimetype = deltectMimetype(resourceUri);
response.setContentType(mimetype);
byte[] content = resourceLoader.loadResourceAsBinary(resourceUri);
response.setContentLength(content.length);
String etag = DigestUtils.md5Hex(content);
response.setHeader("ETag", etag);
response.setHeader("Cache-control", "private");
// 1 hour in seconds
response.setIntHeader("Max-Age", 3600 * 1);
long resourceTimestamp = resourceLoader.getLastModified(resourceUri);
if (resourceTimestamp > 0) {
response.setDateHeader("Last-Modified", resourceTimestamp);
// 1 hour in millisecs
response.setDateHeader("Expires", System.currentTimeMillis() + 1 * 3600000L);
}
String headerIfNoneMatch = request.getHeader("If-None-Match");
if (headerIfNoneMatch != null) {
if (headerIfNoneMatch.equals(etag)) {
response.setStatus(304);
return true;
}
}
if (request.getMethod().equals("HEAD")) {
return true;
}
// and then the content
OutputStream os = response.getOutputStream();
os.write(content);
os.flush();
// InputStream is = resourceLoader.loadResource(resourceUri);
// try {
// OutputStream os = response.getOutputStream();
// byte[] buffer = new byte[1024];
// int bytesRead = is.read(buffer);
// while (bytesRead != -1) {
// os.write(buffer, 0, bytesRead);
// bytesRead = is.read(buffer);
// }
// os.flush();
// } finally {
// is.close();
// }
return true;
}
}