package org.exoplatform.portal.resource;
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;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.charset.Charset;
/** @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() throws IOException
{
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;
}
}