|
@@ -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<ScreenShotGenerator> generatorList = new ArrayList<ScreenShotGenerator>();
|
|
|
|
|
|
- private ExecutorService executorService;
|
|
|
+ public String imageExtention = "png";
|
|
|
+
|
|
|
+ public int splitSize = 5;
|
|
|
+
|
|
|
+ private BlockingQueue<ScreenShotTask> screenShotTaskQueue = new LinkedBlockingQueue<ScreenShotTask>();
|
|
|
+
|
|
|
+ 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<String, Object> 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<String, Object> 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<Map<String, Object>> documentItems) {
|
|
|
final SystemHelper systemHelper = ComponentUtil.getSystemHelper();
|
|
|
final Map<String, String> dataMap = new HashMap<String, String>(
|
|
|
documentItems.size());
|
|
|
for (final Map<String, Object> docMap : documentItems) {
|
|
|
- final String url = (String) docMap.get("url");
|
|
|
- final String screenShotPath = (String) docMap
|
|
|
- .get(systemHelper.screenshotField);
|
|
|
- if (StringUtil.isNotBlank(url)
|
|
|
+ final String docid = (String) docMap.get(systemHelper.docIdField);
|
|
|
+ final String screenShotPath = getImageFilename(docMap);
|
|
|
+ if (StringUtil.isNotBlank(docid)
|
|
|
&& StringUtil.isNotBlank(screenShotPath)) {
|
|
|
- dataMap.put(url, screenShotPath);
|
|
|
+ dataMap.put(docid, screenShotPath);
|
|
|
}
|
|
|
}
|
|
|
final Map<String, Map<String, String>> screenShotPathCache = getScreenShotPathCache(RequestUtil
|
|
@@ -123,14 +161,14 @@ public class ScreenShotManager {
|
|
|
screenShotPathCache.put(queryId, dataMap);
|
|
|
}
|
|
|
|
|
|
- public File getScreenShotFile(final String queryId, final String url) {
|
|
|
+ public File getScreenShotFile(final String queryId, final String docId) {
|
|
|
final HttpSession session = RequestUtil.getRequest().getSession(false);
|
|
|
if (session != null) {
|
|
|
final Map<String, Map<String, String>> screenShotPathCache = getScreenShotPathCache(session);
|
|
|
final Map<String, String> dataMap = screenShotPathCache
|
|
|
.get(queryId);
|
|
|
if (dataMap != null) {
|
|
|
- final String path = dataMap.get(url);
|
|
|
+ final String path = dataMap.get(docId);
|
|
|
final File file = new File(baseDir, path);
|
|
|
if (file.isFile()) {
|
|
|
return file;
|
|
@@ -142,6 +180,7 @@ public class ScreenShotManager {
|
|
|
|
|
|
private Map<String, Map<String, String>> getScreenShotPathCache(
|
|
|
final HttpSession session) {
|
|
|
+ @SuppressWarnings("unchecked")
|
|
|
Map<String, Map<String, String>> screenShotPathCache = (Map<String, Map<String, String>>) session
|
|
|
.getAttribute(Constants.SCREEN_SHOT_PATH_CACHE);
|
|
|
if (screenShotPathCache == null) {
|
|
@@ -153,56 +192,60 @@ public class ScreenShotManager {
|
|
|
return screenShotPathCache;
|
|
|
}
|
|
|
|
|
|
- public void delete(final String expiredSessionId) {
|
|
|
- final File screenShotDir = new File(baseDir, expiredSessionId);
|
|
|
- if (screenShotDir.isDirectory()) {
|
|
|
- logger.info("Deleted: " + screenShotDir.getAbsolutePath());
|
|
|
- try {
|
|
|
- FileUtils.deleteDirectory(screenShotDir);
|
|
|
- } catch (final IOException e) {
|
|
|
- logger.warn(
|
|
|
- "Failed to delete " + screenShotDir.getAbsolutePath(),
|
|
|
- e);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void shutdown() {
|
|
|
- executorService.shutdown();
|
|
|
- try {
|
|
|
- if (!executorService.awaitTermination(shutdownTimeout,
|
|
|
- TimeUnit.MILLISECONDS)) {
|
|
|
- logger.warn("Forced to shutdown processes. Modify shutdownTimeout if needed.");
|
|
|
- executorService.shutdownNow();
|
|
|
- }
|
|
|
- } catch (final InterruptedException e) {
|
|
|
- logger.warn("Interrupted shutdown processes.", e);
|
|
|
- executorService.shutdownNow();
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
public void add(final ScreenShotGenerator generator) {
|
|
|
generatorList.add(generator);
|
|
|
}
|
|
|
|
|
|
- protected static class GenerateTask implements Runnable {
|
|
|
+ protected static class ScreenShotTask {
|
|
|
String url;
|
|
|
|
|
|
File outputFile;
|
|
|
|
|
|
ScreenShotGenerator generator;
|
|
|
|
|
|
- protected GenerateTask(final String url, final File outputFile,
|
|
|
+ protected ScreenShotTask(final String url, final File outputFile,
|
|
|
final ScreenShotGenerator generator) {
|
|
|
this.url = url;
|
|
|
this.outputFile = outputFile;
|
|
|
this.generator = generator;
|
|
|
}
|
|
|
|
|
|
- @Override
|
|
|
- public void run() {
|
|
|
+ public void generate() {
|
|
|
generator.generate(url, outputFile);
|
|
|
}
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public int hashCode() {
|
|
|
+ final int prime = 31;
|
|
|
+ int result = 1;
|
|
|
+ result = prime * result
|
|
|
+ + ((outputFile == null) ? 0 : outputFile.hashCode());
|
|
|
+ result = prime * result + ((url == null) ? 0 : url.hashCode());
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public boolean equals(Object obj) {
|
|
|
+ if (this == obj)
|
|
|
+ return true;
|
|
|
+ if (obj == null)
|
|
|
+ return false;
|
|
|
+ if (getClass() != obj.getClass())
|
|
|
+ return false;
|
|
|
+ ScreenShotTask other = (ScreenShotTask) obj;
|
|
|
+ if (outputFile == null) {
|
|
|
+ if (other.outputFile != null)
|
|
|
+ return false;
|
|
|
+ } else if (!outputFile.equals(other.outputFile))
|
|
|
+ return false;
|
|
|
+ if (url == null) {
|
|
|
+ if (other.url != null)
|
|
|
+ return false;
|
|
|
+ } else if (!url.equals(other.url))
|
|
|
+ return false;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|