diff --git a/pom.xml b/pom.xml
index 09ae23d0a..4c701e8b4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -796,6 +796,11 @@
groovy-all
2.2.2
+
+ com.github.detro
+ phantomjsdriver
+ 1.2.0
+
junit
diff --git a/src/main/java/jp/sf/fess/action/IndexAction.java b/src/main/java/jp/sf/fess/action/IndexAction.java
index e9d5fa915..6aa6f76ac 100644
--- a/src/main/java/jp/sf/fess/action/IndexAction.java
+++ b/src/main/java/jp/sf/fess/action/IndexAction.java
@@ -531,10 +531,11 @@ public class IndexAction {
}
final File screenShotFile = screenShotManager.getScreenShotFile(
- indexForm.queryId, url);
+ indexForm.queryId, indexForm.docId);
if (screenShotFile == null) {
// 404
response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ screenShotManager.generate(doc);
return null;
}
diff --git a/src/main/java/jp/sf/fess/helper/QueryHelper.java b/src/main/java/jp/sf/fess/helper/QueryHelper.java
index 0c8e01d4a..3d02338be 100644
--- a/src/main/java/jp/sf/fess/helper/QueryHelper.java
+++ b/src/main/java/jp/sf/fess/helper/QueryHelper.java
@@ -103,14 +103,14 @@ public class QueryHelper implements Serializable {
protected String[] responseFields = new String[] { "id", "docId", "score",
"boost", "contentLength", "host", "site", "lastModified",
"mimetype", "filetype_s", "created", TITLE_FIELD, "digest", "url",
- "clickCount_l_x_dv", "favoriteCount_l_x_dv", "screenshot_s_s",
- "cid_s_s", "lang_s", "hasCache_s_s" };
+ "clickCount_l_x_dv", "favoriteCount_l_x_dv", "cid_s_s", "lang_s",
+ "hasCache_s_s" };
protected String[] cacheResponseFields = new String[] { "id", "docId",
"score", "boost", "contentLength", "host", "site", "lastModified",
"mimetype", "filetype_s", "created", TITLE_FIELD, "digest", "url",
- "clickCount_l_x_dv", "favoriteCount_l_x_dv", "screenshot_s_s",
- "cid_s_s", "lang_s", "cache" };
+ "clickCount_l_x_dv", "favoriteCount_l_x_dv", "cid_s_s", "lang_s",
+ "cache" };
protected String[] responseDocValuesFields = new String[] {
"clickCount_l_x_dv", "favoriteCount_l_x_dv" };
diff --git a/src/main/java/jp/sf/fess/helper/SystemHelper.java b/src/main/java/jp/sf/fess/helper/SystemHelper.java
index 10d82b857..5a51c33b2 100644
--- a/src/main/java/jp/sf/fess/helper/SystemHelper.java
+++ b/src/main/java/jp/sf/fess/helper/SystemHelper.java
@@ -121,8 +121,6 @@ public class SystemHelper implements Serializable {
public String clickCountField = "clickCount_l_x_dv";
- public String screenshotField = "screenshot_s_s";
-
public String configIdField = "cid_s_s";
public String expiresField = "expires_dt";
diff --git a/src/main/java/jp/sf/fess/screenshot/ScreenShotGenerator.java b/src/main/java/jp/sf/fess/screenshot/ScreenShotGenerator.java
index 8f12803f3..a1f482cbb 100644
--- a/src/main/java/jp/sf/fess/screenshot/ScreenShotGenerator.java
+++ b/src/main/java/jp/sf/fess/screenshot/ScreenShotGenerator.java
@@ -21,8 +21,6 @@ import java.util.Map;
public interface ScreenShotGenerator {
- String getPath(Map docMap);
-
void generate(String url, File outputFile);
boolean isTarget(Map docMap);
diff --git a/src/main/java/jp/sf/fess/screenshot/ScreenShotManager.java b/src/main/java/jp/sf/fess/screenshot/ScreenShotManager.java
index cb45f42f8..79ef38133 100644
--- a/src/main/java/jp/sf/fess/screenshot/ScreenShotManager.java
+++ b/src/main/java/jp/sf/fess/screenshot/ScreenShotManager.java
@@ -17,14 +17,12 @@
package jp.sf.fess.screenshot;
import java.io.File;
-import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
import javax.annotation.Resource;
import javax.servlet.ServletContext;
@@ -35,8 +33,8 @@ import jp.sf.fess.FessSystemException;
import jp.sf.fess.helper.SystemHelper;
import jp.sf.fess.util.ComponentUtil;
-import org.apache.commons.io.FileUtils;
import org.codelibs.core.util.StringUtil;
+import org.seasar.framework.container.annotation.tiger.DestroyMethod;
import org.seasar.framework.container.annotation.tiger.InitMethod;
import org.seasar.robot.util.LruHashMap;
import org.seasar.struts.util.RequestUtil;
@@ -54,20 +52,24 @@ public class ScreenShotManager {
public File baseDir;
- public int threadNum = 10;
-
public long shutdownTimeout = 5 * 60 * 1000; // 5min
public int screenShotPathCacheSize = 10;
private final List generatorList = new ArrayList();
- private ExecutorService executorService;
+ public String imageExtention = "png";
+
+ public int splitSize = 5;
+
+ private BlockingQueue screenShotTaskQueue = new LinkedBlockingQueue();
+
+ private boolean generating;
+
+ private Thread screenshotGeneratorThread;
@InitMethod
public void init() {
- executorService = Executors.newFixedThreadPool(threadNum);
-
if (baseDir == null) {
final String path = application.getRealPath(DEFAULT_SCREENSHOT_DIR);
if (StringUtil.isNotBlank(path)) {
@@ -87,35 +89,71 @@ public class ScreenShotManager {
if (logger.isDebugEnabled()) {
logger.debug("ScreenShot Directory: " + baseDir.getAbsolutePath());
}
+
+ generating = true;
+ screenshotGeneratorThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ while (generating) {
+ try {
+ screenShotTaskQueue.take().generate();
+ } catch (InterruptedException e) {
+ logger.debug("Interupted task.", e);
+ } catch (Exception e) {
+ logger.warn("Failed to generage a screenshot.", e);
+ }
+ }
+ }
+ }, "ScreenShotGenerator");
+ screenshotGeneratorThread.start();
+ }
+
+ @DestroyMethod
+ public void destroy() {
+ generating = false;
+ screenshotGeneratorThread.interrupt();
}
public void generate(final Map docMap) {
- final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
for (final ScreenShotGenerator generator : generatorList) {
if (generator.isTarget(docMap)) {
- final String segment = (String) docMap.get("segment");
final String url = (String) docMap.get("url");
- final String path = segment + "/" + generator.getPath(docMap);
- docMap.put(systemHelper.screenshotField, path);
- executorService.execute(new GenerateTask(url, new File(baseDir,
- path), generator));
+ final String path = getImageFilename(docMap);
+ if (!screenShotTaskQueue.offer((new ScreenShotTask(url,
+ new File(baseDir, path), generator)))) {
+ logger.warn("Failed to offer a screenshot task: " + url
+ + " -> " + path);
+ }
break;
}
}
}
+ protected String getImageFilename(final Map docMap) {
+ StringBuilder buf = new StringBuilder(50);
+ final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
+ final String docid = (String) docMap.get(systemHelper.docIdField);
+ for (int i = 0; i < docid.length(); i++) {
+ if (i > 0 && i % splitSize == 0) {
+ buf.append('/');
+ }
+ buf.append(docid.charAt(i));
+ }
+ buf.append('.').append(imageExtention);
+ return buf.toString();
+ }
+
public void storeRequest(final String queryId,
final List