package org.exoplatform.portal.resource;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.charset.Charset;
import javax.servlet.http.HttpServletResponse;
import org.exoplatform.commons.utils.BinaryOutput;
import org.exoplatform.commons.utils.PropertyManager;
import org.exoplatform.web.ControllerContext;
import org.exoplatform.web.WebRequestHandler;
import org.gatein.common.logging.Logger;
import org.gatein.common.logging.LoggerFactory;
import org.gatein.portal.controller.resource.ResourceRequestHandler;
/** @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */
public class SkinResourceRequestHandler extends WebRequestHandler {
/** . */
private final Logger log = LoggerFactory.getLogger(getClass());
/** . */
private static final Charset UTF_8 = Charset.forName("UTF-8");
/** . */
public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
/** . */
public static final String LAST_MODIFIED = "Last-Modified";
/** . */
private final SkinService skinService;
public SkinResourceRequestHandler(SkinService skinService) {
this.skinService = skinService;
}
@Override
public String getHandlerName() {
return "skin";
}
@Override
public boolean execute(final ControllerContext context) throws Exception {
String compressParam = context.getParameter(ResourceRequestHandler.COMPRESS_QN);
boolean compress = "min".equals(compressParam);
//
final HttpServletResponse response = context.getResponse();
// Check if cached resource has not been modifed, return 304 code
long ifModifiedSince = context.getRequest().getDateHeader(IF_MODIFIED_SINCE);
long cssLastModified = skinService.getLastModified(context);
if (isNotModified(ifModifiedSince, cssLastModified)) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return true;
} else {
//
response.setContentType("text/css; charset=UTF-8");
final OutputStream out = response.getOutputStream();
final BinaryOutput output = new BinaryOutput() {
public Charset getCharset() {
return UTF_8;
}
public void write(byte b) throws IOException {
out.write(b);
}
public void write(byte[] bytes) throws IOException {
out.write(bytes);
}
public void write(byte[] bytes, int off, int len) throws IOException {
out.write(bytes, off, len);
}
};
ResourceRenderer renderer = new ResourceRenderer() {
public BinaryOutput getOutput() {
return output;
}
public void setExpiration(long seconds) {
if (seconds > 0) {
response.addHeader("Cache-Control", "max-age=" + seconds + ",s-maxage=" + seconds);
} else {
response.setHeader("Cache-Control", "no-cache");
}
long lastModified = skinService.getLastModified(context);
response.setDateHeader(LAST_MODIFIED, lastModified);
}
};
//
final String resource = "/" + context.getParameter(ResourceRequestHandler.RESOURCE_QN) + ".css";
try {
if (skinService.renderCSS(context, renderer, compress)) {
// Ok we did the job
return true;
} else {
log.warn("CSS " + resource + " not found");
return false;
}
} catch (Exception e) {
if (e instanceof SocketException) {
// Should we print something/somewhere exception message
} else {
log.error("Could not render css " + resource, e);
}
return false;
}
}
}
/**
* If cached resource has not changed since date in http header (If_Modified_Since), return true otherwise return false.
*/
private boolean isNotModified(long ifModifedSince, long lastModified) {
if (!PropertyManager.isDevelopping()) {
if (ifModifedSince >= lastModified) {
return true;
}
}
return false;
}
@Override
protected boolean getRequiresLifeCycle() {
return false;
}
}