diff --git a/etc/ehcache-1.5.0.xsd b/etc/ehcache-1.5.0.xsd
new file mode 100644
index 0000000..dd47ef8
--- /dev/null
+++ b/etc/ehcache-1.5.0.xsd
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/etc/ehcache.xml b/etc/ehcache.xml
new file mode 100644
index 0000000..b2c8fc6
--- /dev/null
+++ b/etc/ehcache.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index eea6a79..e4cb460 100644
--- a/pom.xml
+++ b/pom.xml
@@ -108,6 +108,11 @@
2.4
provided
+
+ net.sf.ehcache
+ ehcache
+ 1.5.0
+
diff --git a/src/org/forkalsrud/album/web/AlbumServlet.java b/src/org/forkalsrud/album/web/AlbumServlet.java
index d6ed452..0d9893e 100644
--- a/src/org/forkalsrud/album/web/AlbumServlet.java
+++ b/src/org/forkalsrud/album/web/AlbumServlet.java
@@ -4,6 +4,7 @@ import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Iterator;
@@ -22,6 +23,10 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.PropertyConfigurator;
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Element;
+
import org.forkalsrud.album.exif.Dimension;
import org.forkalsrud.album.exif.DirectoryEntry;
import org.forkalsrud.album.exif.Entry;
@@ -33,6 +38,7 @@ public class AlbumServlet
{
File base;
String basePrefix;
+ Cache imageCache;
@Override
public void init()
@@ -44,6 +50,8 @@ public class AlbumServlet
PropertyConfigurator.configure("log4j.properties");
LogFactory.getFactory().setAttribute("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.Log4JLogger");
+ CacheManager cacheManager = new CacheManager();
+ imageCache = cacheManager.getCache("imageCache");
}
@Override
@@ -80,16 +88,18 @@ public class AlbumServlet
return;
}
- if (req.getParameter("size") != null) {
+ String size = req.getParameter("size");
+ if (size != null) {
try {
res.setContentType("image/jpeg");
FileEntry e = (FileEntry)DirectoryEntry.getEntry(file);
- scaleImage(req, res, file, e.getThumbnail(), req.getParameter("size"));
+ scaleImage(req, res, file, e.getThumbnail(), size);
+ res.setStatus(HttpServletResponse.SC_OK);
+ return;
} catch (Exception e) {
throw new RuntimeException("sadness", e);
}
- return;
}
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
}
@@ -132,15 +142,46 @@ public class AlbumServlet
return false;
}
- synchronized void scaleImage(HttpServletRequest req, HttpServletResponse res, File file, Thumbnail thumbnail, String size) throws IOException {
+ boolean notModified(HttpServletRequest req, File f) {
+ long reqDate = req.getDateHeader("If-Modified-Since");
+ long fDate = f.lastModified();
+ return reqDate > 0 && fDate > 0 && fDate <= reqDate;
+ }
+ void scaleImage(HttpServletRequest req, HttpServletResponse res, File file, Thumbnail thumbnail, String size) throws IOException {
+
+ if (notModified(req, file)) {
+ res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ System.out.println(file.getName() + " not modified (based on date)");
+ return;
+ }
String fileEtag = thumbnail.getEtag() + "-" + size;
if (etagMatches(req, fileEtag)) {
res.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ System.out.println(file.getName() + " not modified (based on etag)");
return;
}
+ res.setDateHeader("Last-Modified", file.lastModified());
res.setHeader("ETag", fileEtag);
+
+ String key = file.getPath() + ":" + size;
+ Element element = imageCache.get(key);
+ if (element != null) {
+ CachedImage cimg = (CachedImage) element.getObjectValue();
+ if (cimg.lastModified == file.lastModified()) {
+ System.out.println("cache hit on " + key);
+ //res.setContentType(cimg.mimeType);
+ res.setContentLength(cimg.bits.length);
+ res.getOutputStream().write(cimg.bits);
+ return;
+ } else {
+ System.out.println(" " + key + " has changed so cache entry wil be refreshed");
+ imageCache.remove(key);
+ }
+ }
+
+ synchronized (this) {
Dimension orig = thumbnail.getSize();
Dimension outd;
if (size.endsWith("h")) {
@@ -210,13 +251,26 @@ public class AlbumServlet
Iterator writers = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = writers.next();
-// ImageWriteParam wParam = writer.getDefaultWriteParam();
-// wParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
-// wParam.setCompressionQuality(1.0f);
- ImageOutputStream ios = ImageIO.createImageOutputStream(res.getOutputStream());
+
+ ByteArrayOutputStream bits = new ByteArrayOutputStream();
+
+ ImageOutputStream ios = ImageIO.createImageOutputStream(bits);
writer.setOutput(ios);
-// writer.write(null, new IIOImage(buf2, null, null), wParam);
writer.write(buf2);
+ ios.flush();
+
+ CachedImage cimg = new CachedImage();
+ cimg.lastModified = file.lastModified();
+ cimg.mimeType = "image/jpeg";
+ cimg.bits = bits.toByteArray();
+ imageCache.put(new Element(key, cimg));
+
+ System.out.println(" " + key + " added to the cache with size " + cimg.bits.length + " -- now " + imageCache.getSize() + " entries");
+
+ //res.setContentType(cimg.mimeType);
+ res.setContentLength(cimg.bits.length);
+ res.getOutputStream().write(cimg.bits);
+ }
}
@@ -262,6 +316,12 @@ public class AlbumServlet
}
}
}
+
+ static class CachedImage {
+ long lastModified;
+ String mimeType;
+ byte[] bits;
+ }
}
// eof