Author: phuong_vu
Date: 2010-11-23 07:03:39 -0500 (Tue, 23 Nov 2010)
New Revision: 5217
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
portal/branches/branch-GTNPORTAL-1643/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java
Log:
GTNPORTAL-1455 CSS file are not cached (in the browser)
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/Image.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -19,6 +19,8 @@
package org.exoplatform.portal.application;
+import java.util.Date;
+
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
* @version $Revision$
@@ -29,10 +31,19 @@
final ImageType type;
final byte[] bytes;
+
+ final long lastModified;
public Image(ImageType type, byte[] bytes)
{
this.type = type;
this.bytes = bytes;
+// Remove miliseconds because string of date retrieve from Http header doesn't have
miliseconds
+ lastModified = (new Date().getTime() / 1000) * 1000;
}
+
+ public long getLastModified()
+ {
+ return lastModified;
+ }
}
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/application/ResourceRequestFilter.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -36,6 +36,7 @@
import java.io.OutputStream;
import java.net.URLDecoder;
import java.nio.charset.Charset;
+import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -64,6 +65,10 @@
private ConcurrentMap<String, FutureTask<Image>> mirroredImageCache = new
ConcurrentHashMap<String, FutureTask<Image>>();
+ public static final String IF_MODIFIED_SINCE = "If-Modified-Since";
+
+ public static final String LAST_MODIFIED = "Last-Modified";
+
public void afterInit(FilterConfig filterConfig)
{
cfg = filterConfig;
@@ -77,11 +82,19 @@
final String uri = URLDecoder.decode(httpRequest.getRequestURI(),
"UTF-8");
final HttpServletResponse httpResponse = (HttpServletResponse)response;
ExoContainer portalContainer = getContainer();
- SkinService skinService =
(SkinService)portalContainer.getComponentInstanceOfType(SkinService.class);
+ final SkinService skinService = (SkinService)
portalContainer.getComponentInstanceOfType(SkinService.class);
+ long ifModifiedSince = httpRequest.getDateHeader(IF_MODIFIED_SINCE);
//
if (uri.endsWith(".css"))
{
+// Check if cached resource has not been modifed, return 304 code
+ long cssLastModified = skinService.getLastModified(uri);
+ if (isNotModified(ifModifiedSince, cssLastModified)) {
+ httpResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+
final OutputStream out = response.getOutputStream();
final BinaryOutput output = new BinaryOutput()
{
@@ -118,6 +131,9 @@
{
httpResponse.setHeader("Cache-Control",
"no-cache");
}
+
+ long lastModified = skinService.getLastModified(uri);
+ processIfModified(lastModified, httpResponse);
}
};
@@ -192,8 +208,16 @@
Image img = futureImg.get();
if (img != null)
{
+ //Check if cached resource has not been modifed, return 304 code
+ long imgLastModified = img.getLastModified();
+ if (isNotModified(ifModifiedSince, imgLastModified)) {
+ httpResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
httpResponse.setContentType(img.type.getMimeType());
httpResponse.setContentLength(img.bytes.length);
+ processIfModified(imgLastModified, httpResponse);
+
OutputStream out = httpResponse.getOutputStream();
out.write(img.bytes);
out.close();
@@ -238,6 +262,30 @@
}
}
+ /**
+ * Add Last-Modified Http header to HttpServetResponse
+ */
+ public void processIfModified(long lastModified, HttpServletResponse httpResponse) {
+ httpResponse.setDateHeader(ResourceRequestFilter.LAST_MODIFIED, lastModified);
+ }
+
+ /**
+ * If cached resource has not changed since date in http header (If_Modified_Since),
return true
+ * Else return false;
+ * @param ifModifedSince - String, and HttpHeader element
+ * @param lastModified
+ * @param httpResponse
+ * @return
+ */
+ public boolean isNotModified(long ifModifedSince, long lastModified) {
+ if (!PropertyManager.isDevelopping()) {
+ if (ifModifedSince >= lastModified) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public void destroy()
{
}
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/CachedStylesheet.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -24,6 +24,7 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
+import java.util.Date;
/**
* @author <a href="mailto:julien.viet@exoplatform.com">Julien
Viet</a>
@@ -40,6 +41,8 @@
/** . */
private final byte[] bytes;
+
+ private long lastModified;
public CachedStylesheet(String text)
{
@@ -59,11 +62,18 @@
//
this.text = text;
this.bytes = bytes;
+// Remove miliseconds because string of date retrieve from Http header doesn't have
miliseconds
+ lastModified = (new Date().getTime() / 1000) * 1000;
}
public String getText()
{
return text;
+ }
+
+ public long getLastModified()
+ {
+ return lastModified;
}
public void writeTo(BinaryOutput output) throws IOException
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/portal/resource/SkinService.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -51,6 +51,7 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.HashSet;
@@ -455,6 +456,9 @@
// Try cache first
if (!PropertyManager.isDevelopping())
{
+ //
+ FutureExoCache<String, CachedStylesheet, Orientation> cache = orientation
== Orientation.LT ? ltCache : rtCache;
+ CachedStylesheet cachedCss = cache.get(orientation, path);
if (path.startsWith("/" + portalContainerName +
"/resource"))
{
@@ -464,11 +468,7 @@
{
renderer.setExpiration(ONE_HOUR);
}
-
- //
- FutureExoCache<String, CachedStylesheet, Orientation> cache = orientation
== Orientation.LT ? ltCache : rtCache;
- CachedStylesheet cachedCss = cache.get(orientation, path);
-
+
cachedCss.writeTo(renderer.getOutput());
}
else
@@ -546,6 +546,41 @@
}
/**
+ * Return last modifed date of cached css
+ * Return null if cached css can not be found
+ * @param path - path must not be null
+ */
+ public long getLastModified(String path)
+ {
+ if (path == null)
+ {
+ throw new IllegalArgumentException("path must not be null");
+ }
+
+ FutureExoCache<String, CachedStylesheet, Orientation> cache = ltCache;
+ Orientation orientation = Orientation.LT;
+ if (path.endsWith("-lt.css"))
+ {
+ path = path.substring(0, path.length() - "-lt.css".length()) +
".css";
+ }
+ else if (path.endsWith("-rt.css"))
+ {
+ path = path.substring(0, path.length() - "-rt.css".length()) +
".css";
+ orientation = Orientation.RT;
+ }
+
+ CachedStylesheet cachedCSS = cache.get(orientation, path);
+ if (cachedCSS == null)
+ {
+ return Long.MAX_VALUE;
+ }
+ else
+ {
+ return cachedCSS.getLastModified();
+ }
+ }
+
+ /**
* Remove SkinConfig from Portal Skin Configs by module and skin name
* @param module
* @param skinName
Modified:
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/component/web/resources/src/main/java/org/exoplatform/web/application/javascript/JavascriptConfigService.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -40,6 +40,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
+import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -64,6 +65,8 @@
private HashMap<String, String> extendedJavascripts;
private byte[] jsBytes = null;
+
+ private long lastModified = Long.MAX_VALUE;
/** . */
private JavascriptDeployer deployer;
@@ -278,6 +281,18 @@
*/
public void writeMergedJavascript(OutputStream out) throws IOException
{
+ jsBytes = getMergedJavascript();
+
+ //
+ out.write(jsBytes);
+ }
+
+ /**
+ * Return merged javascript in byte array
+ * @return byte[]
+ */
+ public byte[] getMergedJavascript()
+ {
if (jsBytes == null)
{
// Generate javascript in a buffer
@@ -314,10 +329,15 @@
log.error("Error when generating minified javascript, will use normal
javascript instead", e);
jsBytes = bytes;
}
+// Remove miliseconds because string of date retrieve from Http header
doesn't have miliseconds
+ lastModified = (new Date().getTime() / 1000) * 1000;
}
+ return jsBytes;
+ }
- //
- out.write(jsBytes);
+ public long getLastModified()
+ {
+ return lastModified;
}
/**
@@ -374,4 +394,4 @@
DefaultServletContainerFactory.getInstance().getServletContainer().removeWebAppListener(removal);
}
-}
\ No newline at end of file
+}
Modified:
portal/branches/branch-GTNPORTAL-1643/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java
===================================================================
---
portal/branches/branch-GTNPORTAL-1643/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java 2010-11-23
11:40:36 UTC (rev 5216)
+++
portal/branches/branch-GTNPORTAL-1643/webui/portal/src/main/java/org/exoplatform/portal/webui/javascript/JavascriptServlet.java 2010-11-23
12:03:39 UTC (rev 5217)
@@ -19,10 +19,14 @@
package org.exoplatform.portal.webui.javascript;
+import org.exoplatform.commons.utils.PropertyManager;
import org.exoplatform.container.ExoContainerContext;
+import org.exoplatform.portal.application.ResourceRequestFilter;
import org.exoplatform.web.application.javascript.JavascriptConfigService;
import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
@@ -55,14 +59,23 @@
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException,
IOException
{
- JavascriptConfigService service =
+ final JavascriptConfigService service =
(JavascriptConfigService)ExoContainerContext.getCurrentContainer().getComponentInstanceOfType(
JavascriptConfigService.class);
-
+ long lastModified = service.getLastModified();
+ long ifModifiedSince =
request.getDateHeader(ResourceRequestFilter.IF_MODIFIED_SINCE);
+
// Julien: should we also set charset along with the content type ?
response.setContentType("application/x-javascript");
- ServletOutputStream stream = response.getOutputStream();
- service.writeMergedJavascript(stream);
+ if (!PropertyManager.isDevelopping()) {
+ if (ifModifiedSince >= lastModified) {
+ response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+ }
+
+ byte[] jsBytes = service.getMergedJavascript();
+ response.setDateHeader(ResourceRequestFilter.LAST_MODIFIED, lastModified);
+ response.getOutputStream().write(jsBytes);
}
-
}