Shinsuke Sugaya преди 11 години
родител
ревизия
17b76c9cf5

+ 5 - 1
src/main/java/jp/sf/fess/action/admin/CrawlingSessionAction.java

@@ -24,6 +24,7 @@ import javax.annotation.Resource;
 import jp.sf.fess.crud.action.admin.BsCrawlingSessionAction;
 import jp.sf.fess.crud.action.admin.BsCrawlingSessionAction;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.db.exentity.CrawlingSessionInfo;
 import jp.sf.fess.db.exentity.CrawlingSessionInfo;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 
 
 import org.seasar.struts.annotation.Execute;
 import org.seasar.struts.annotation.Execute;
@@ -35,6 +36,9 @@ public class CrawlingSessionAction extends BsCrawlingSessionAction {
     @Resource
     @Resource
     protected SystemHelper systemHelper;
     protected SystemHelper systemHelper;
 
 
+    @Resource
+    protected JobHelper jobHelper;
+
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("crawlingSession");
         return systemHelper.getHelpLink("crawlingSession");
     }
     }
@@ -49,7 +53,7 @@ public class CrawlingSessionAction extends BsCrawlingSessionAction {
 
 
     @Execute(validator = false, input = "error.jsp")
     @Execute(validator = false, input = "error.jsp")
     public String deleteall() {
     public String deleteall() {
-        crawlingSessionService.deleteOldSessions(systemHelper
+        crawlingSessionService.deleteOldSessions(jobHelper
                 .getRunningSessionIdSet());
                 .getRunningSessionIdSet());
         SAStrutsUtil.addSessionMessage("success.crawling_session_delete_all");
         SAStrutsUtil.addSessionMessage("success.crawling_session_delete_all");
         return displayList(true);
         return displayList(true);

+ 12 - 8
src/main/java/jp/sf/fess/action/admin/DocumentAction.java

@@ -28,6 +28,7 @@ import javax.annotation.Resource;
 import jp.sf.fess.Constants;
 import jp.sf.fess.Constants;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.form.admin.DocumentForm;
 import jp.sf.fess.form.admin.DocumentForm;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.WebManagementHelper;
 import jp.sf.fess.helper.WebManagementHelper;
 
 
@@ -73,6 +74,9 @@ public class DocumentAction implements Serializable {
     @Resource
     @Resource
     protected SystemHelper systemHelper;
     protected SystemHelper systemHelper;
 
 
+    @Resource
+    protected JobHelper jobHelper;
+
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("document");
         return systemHelper.getHelpLink("document");
     }
     }
@@ -157,7 +161,7 @@ public class DocumentAction implements Serializable {
     @Token(save = false, validate = true)
     @Token(save = false, validate = true)
     @Execute(validator = true, input = "index")
     @Execute(validator = true, input = "index")
     public String commit() {
     public String commit() {
-        if (systemHelper.isCrawlProcessRunning()) {
+        if (jobHelper.isCrawlProcessRunning()) {
             throw new SSCActionMessagesException(
             throw new SSCActionMessagesException(
                     "errors.failed_to_start_solr_process_because_of_running");
                     "errors.failed_to_start_solr_process_because_of_running");
         }
         }
@@ -170,7 +174,7 @@ public class DocumentAction implements Serializable {
             final Thread thread = new Thread(new Runnable() {
             final Thread thread = new Thread(new Runnable() {
                 @Override
                 @Override
                 public void run() {
                 public void run() {
-                    if (!systemHelper.isCrawlProcessRunning()) {
+                    if (!jobHelper.isCrawlProcessRunning()) {
                         final long execTime = System.currentTimeMillis();
                         final long execTime = System.currentTimeMillis();
                         try {
                         try {
                             systemHelper.updateStatus(solrGroup, QueryType.ADD);
                             systemHelper.updateStatus(solrGroup, QueryType.ADD);
@@ -203,7 +207,7 @@ public class DocumentAction implements Serializable {
     @Token(save = false, validate = true)
     @Token(save = false, validate = true)
     @Execute(validator = true, input = "index")
     @Execute(validator = true, input = "index")
     public String optimize() {
     public String optimize() {
-        if (systemHelper.isCrawlProcessRunning()) {
+        if (jobHelper.isCrawlProcessRunning()) {
             throw new SSCActionMessagesException(
             throw new SSCActionMessagesException(
                     "errors.failed_to_start_solr_process_because_of_running");
                     "errors.failed_to_start_solr_process_because_of_running");
         }
         }
@@ -216,7 +220,7 @@ public class DocumentAction implements Serializable {
             final Thread thread = new Thread(new Runnable() {
             final Thread thread = new Thread(new Runnable() {
                 @Override
                 @Override
                 public void run() {
                 public void run() {
-                    if (!systemHelper.isCrawlProcessRunning()) {
+                    if (!jobHelper.isCrawlProcessRunning()) {
                         final long execTime = System.currentTimeMillis();
                         final long execTime = System.currentTimeMillis();
                         try {
                         try {
                             systemHelper.updateStatus(solrGroup, QueryType.ADD);
                             systemHelper.updateStatus(solrGroup, QueryType.ADD);
@@ -274,7 +278,7 @@ public class DocumentAction implements Serializable {
     }
     }
 
 
     private String deleteByQuery(final String deleteQuery) {
     private String deleteByQuery(final String deleteQuery) {
-        if (systemHelper.isCrawlProcessRunning()) {
+        if (jobHelper.isCrawlProcessRunning()) {
             throw new SSCActionMessagesException(
             throw new SSCActionMessagesException(
                     "errors.failed_to_start_solr_process_because_of_running");
                     "errors.failed_to_start_solr_process_because_of_running");
         }
         }
@@ -287,7 +291,7 @@ public class DocumentAction implements Serializable {
             final Thread thread = new Thread(new Runnable() {
             final Thread thread = new Thread(new Runnable() {
                 @Override
                 @Override
                 public void run() {
                 public void run() {
-                    if (!systemHelper.isCrawlProcessRunning()) {
+                    if (!jobHelper.isCrawlProcessRunning()) {
                         final long execTime = System.currentTimeMillis();
                         final long execTime = System.currentTimeMillis();
                         try {
                         try {
                             systemHelper.updateStatus(solrGroup,
                             systemHelper.updateStatus(solrGroup,
@@ -377,11 +381,11 @@ public class DocumentAction implements Serializable {
     }
     }
 
 
     public boolean isSolrProcessRunning() {
     public boolean isSolrProcessRunning() {
-        return systemHelper.isCrawlProcessRunning();
+        return jobHelper.isCrawlProcessRunning();
     }
     }
 
 
     public Set<String> getRunningSessionIdSet() {
     public Set<String> getRunningSessionIdSet() {
-        return systemHelper.getRunningSessionIdSet();
+        return jobHelper.getRunningSessionIdSet();
     }
     }
 
 
     private static class SessionIdList<E> extends ArrayList<E> {
     private static class SessionIdList<E> extends ArrayList<E> {

+ 52 - 16
src/main/java/jp/sf/fess/action/admin/ScheduledJobAction.java

@@ -28,6 +28,7 @@ import jp.sf.fess.crud.action.admin.BsScheduledJobAction;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.db.exentity.RoleType;
 import jp.sf.fess.db.exentity.RoleType;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.ScheduledJob;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.service.RoleTypeService;
 import jp.sf.fess.service.RoleTypeService;
 import jp.sf.fess.util.FessBeans;
 import jp.sf.fess.util.FessBeans;
@@ -50,6 +51,11 @@ public class ScheduledJobAction extends BsScheduledJobAction {
     @Resource
     @Resource
     protected SystemHelper systemHelper;
     protected SystemHelper systemHelper;
 
 
+    @Resource
+    protected JobHelper jobHelper;
+
+    public boolean running = false;
+
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("scheduledJob");
         return systemHelper.getHelpLink("scheduledJob");
     }
     }
@@ -57,14 +63,7 @@ public class ScheduledJobAction extends BsScheduledJobAction {
     @Override
     @Override
     protected void loadScheduledJob() {
     protected void loadScheduledJob() {
 
 
-        final ScheduledJob scheduledJob = scheduledJobService
-                .getScheduledJob(createKeyMap());
-        if (scheduledJob == null) {
-            // throw an exception
-            throw new SSCActionMessagesException(
-                    "errors.crud_could_not_find_crud_table",
-                    new Object[] { scheduledJobForm.id });
-        }
+        final ScheduledJob scheduledJob = getScheduledJob();
 
 
         FessBeans.copy(scheduledJob, scheduledJobForm)
         FessBeans.copy(scheduledJob, scheduledJobForm)
                 .commonColumnDateConverter()
                 .commonColumnDateConverter()
@@ -75,6 +74,7 @@ public class ScheduledJobAction extends BsScheduledJobAction {
                 : null;
                 : null;
         scheduledJobForm.available = scheduledJob.isEnabled() ? Constants.ON
         scheduledJobForm.available = scheduledJob.isEnabled() ? Constants.ON
                 : null;
                 : null;
+        running = scheduledJob.isRunning();
     }
     }
 
 
     @Override
     @Override
@@ -122,14 +122,7 @@ public class ScheduledJobAction extends BsScheduledJobAction {
         }
         }
 
 
         try {
         try {
-            final ScheduledJob scheduledJob = scheduledJobService
-                    .getScheduledJob(createKeyMap());
-            if (scheduledJob == null) {
-                // throw an exception
-                throw new SSCActionMessagesException(
-                        "errors.crud_could_not_find_crud_table",
-                        new Object[] { scheduledJobForm.id });
-            }
+            final ScheduledJob scheduledJob = getScheduledJob();
 
 
             final String username = systemHelper.getUsername();
             final String username = systemHelper.getUsername();
             final Timestamp timestamp = systemHelper.getCurrentTimestamp();
             final Timestamp timestamp = systemHelper.getCurrentTimestamp();
@@ -153,7 +146,50 @@ public class ScheduledJobAction extends BsScheduledJobAction {
         }
         }
     }
     }
 
 
+    @Execute(validator = false, input = "error.jsp")
+    public String start() {
+        final ScheduledJob scheduledJob = getScheduledJob();
+        try {
+            scheduledJob.start();
+            SAStrutsUtil.addSessionMessage("success.job_started",
+                    scheduledJob.getName());
+            return displayList(true);
+        } catch (final Exception e) {
+            log.error(e.getMessage(), e);
+            throw new SSCActionMessagesException(e,
+                    "errors.failed_to_start_job", scheduledJob.getName());
+        }
+
+    }
+
+    @Execute(validator = false, input = "error.jsp")
+    public String stop() {
+        final ScheduledJob scheduledJob = getScheduledJob();
+        try {
+            jobHelper.getJobExecutoer(scheduledJob.getId());
+            SAStrutsUtil.addSessionMessage("success.job_stopped",
+                    scheduledJob.getName());
+            return displayList(true);
+        } catch (final Exception e) {
+            log.error(e.getMessage(), e);
+            throw new SSCActionMessagesException(e,
+                    "errors.failed_to_stop_job", scheduledJob.getName());
+        }
+    }
+
     public List<RoleType> getRoleTypeItems() {
     public List<RoleType> getRoleTypeItems() {
         return roleTypeService.getRoleTypeList();
         return roleTypeService.getRoleTypeList();
     }
     }
+
+    protected ScheduledJob getScheduledJob() {
+        final ScheduledJob scheduledJob = scheduledJobService
+                .getScheduledJob(createKeyMap());
+        if (scheduledJob == null) {
+            // throw an exception
+            throw new SSCActionMessagesException(
+                    "errors.crud_could_not_find_crud_table",
+                    new Object[] { scheduledJobForm.id });
+        }
+        return scheduledJob;
+    }
 }
 }

+ 10 - 6
src/main/java/jp/sf/fess/action/admin/SearchListAction.java

@@ -28,6 +28,7 @@ import jp.sf.fess.InvalidQueryException;
 import jp.sf.fess.ResultOffsetExceededException;
 import jp.sf.fess.ResultOffsetExceededException;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.form.admin.SearchListForm;
 import jp.sf.fess.form.admin.SearchListForm;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.service.SearchService;
 import jp.sf.fess.service.SearchService;
 import jp.sf.fess.util.QueryResponseList;
 import jp.sf.fess.util.QueryResponseList;
@@ -73,6 +74,12 @@ public class SearchListAction implements Serializable {
     @Resource
     @Resource
     protected HttpServletRequest request;
     protected HttpServletRequest request;
 
 
+    @Resource
+    protected SystemHelper systemHelper;
+
+    @Resource
+    protected JobHelper jobHelper;
+
     public List<Map<String, Object>> documentItems;
     public List<Map<String, Object>> documentItems;
 
 
     public String pageSize;
     public String pageSize;
@@ -95,9 +102,6 @@ public class SearchListAction implements Serializable {
 
 
     public String execTime;
     public String execTime;
 
 
-    @Resource
-    protected SystemHelper systemHelper;
-
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("searchList");
         return systemHelper.getHelpLink("searchList");
     }
     }
@@ -247,7 +251,7 @@ public class SearchListAction implements Serializable {
     }
     }
 
 
     private String deleteByQuery(final String deleteId) {
     private String deleteByQuery(final String deleteId) {
-        if (systemHelper.isCrawlProcessRunning()) {
+        if (jobHelper.isCrawlProcessRunning()) {
             throw new SSCActionMessagesException(
             throw new SSCActionMessagesException(
                     "errors.failed_to_start_solr_process_because_of_running");
                     "errors.failed_to_start_solr_process_because_of_running");
         }
         }
@@ -260,7 +264,7 @@ public class SearchListAction implements Serializable {
             final Thread thread = new Thread(new Runnable() {
             final Thread thread = new Thread(new Runnable() {
                 @Override
                 @Override
                 public void run() {
                 public void run() {
-                    if (!systemHelper.isCrawlProcessRunning()) {
+                    if (!jobHelper.isCrawlProcessRunning()) {
                         final long time = System.currentTimeMillis();
                         final long time = System.currentTimeMillis();
                         try {
                         try {
                             solrGroup.deleteById(deleteId);
                             solrGroup.deleteById(deleteId);
@@ -290,6 +294,6 @@ public class SearchListAction implements Serializable {
     }
     }
 
 
     public boolean isSolrProcessRunning() {
     public boolean isSolrProcessRunning() {
-        return systemHelper.isCrawlProcessRunning();
+        return jobHelper.isCrawlProcessRunning();
     }
     }
 }
 }

+ 11 - 7
src/main/java/jp/sf/fess/action/admin/SystemAction.java

@@ -29,6 +29,7 @@ import jp.sf.fess.Constants;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.crud.util.SAStrutsUtil;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.form.admin.SystemForm;
 import jp.sf.fess.form.admin.SystemForm;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.WebManagementHelper;
 import jp.sf.fess.helper.WebManagementHelper;
 import jp.sf.fess.service.ScheduledJobService;
 import jp.sf.fess.service.ScheduledJobService;
@@ -70,6 +71,9 @@ public class SystemAction implements Serializable {
     @Resource
     @Resource
     protected SystemHelper systemHelper;
     protected SystemHelper systemHelper;
 
 
+    @Resource
+    protected JobHelper jobHelper;
+
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("system");
         return systemHelper.getHelpLink("system");
     }
     }
@@ -214,7 +218,7 @@ public class SystemAction implements Serializable {
                 .getProperty(SolrLibConstants.UPDATE_GROUP);
                 .getProperty(SolrLibConstants.UPDATE_GROUP);
         final SolrGroup solrGroup = solrGroupManager.getSolrGroup(groupName);
         final SolrGroup solrGroup = solrGroupManager.getSolrGroup(groupName);
         if (solrGroup != null) {
         if (solrGroup != null) {
-            if (!systemHelper.isCrawlProcessRunning()) {
+            if (!jobHelper.isCrawlProcessRunning()) {
                 final ScheduledJobService scheduledJobService = SingletonS2Container
                 final ScheduledJobService scheduledJobService = SingletonS2Container
                         .getComponent(ScheduledJobService.class);
                         .getComponent(ScheduledJobService.class);
                 final List<ScheduledJob> scheduledJobList = scheduledJobService
                 final List<ScheduledJob> scheduledJobList = scheduledJobService
@@ -237,13 +241,13 @@ public class SystemAction implements Serializable {
     @Token(save = false, validate = true)
     @Token(save = false, validate = true)
     @Execute(validator = true, input = "index")
     @Execute(validator = true, input = "index")
     public String stop() {
     public String stop() {
-        if (systemHelper.isCrawlProcessRunning()) {
+        if (jobHelper.isCrawlProcessRunning()) {
             if (StringUtil.isNotBlank(systemForm.sessionId)) {
             if (StringUtil.isNotBlank(systemForm.sessionId)) {
-                systemHelper.destroyCrawlerProcess(systemForm.sessionId);
+                jobHelper.destroyCrawlerProcess(systemForm.sessionId);
             } else {
             } else {
-                for (final String sessionId : systemHelper
+                for (final String sessionId : jobHelper
                         .getRunningSessionIdSet()) {
                         .getRunningSessionIdSet()) {
-                    systemHelper.destroyCrawlerProcess(sessionId);
+                    jobHelper.destroyCrawlerProcess(sessionId);
                 }
                 }
             }
             }
             SAStrutsUtil.addSessionMessage("success.stopping_crawl_process");
             SAStrutsUtil.addSessionMessage("success.stopping_crawl_process");
@@ -312,11 +316,11 @@ public class SystemAction implements Serializable {
     }
     }
 
 
     public boolean isCrawlerRunning() {
     public boolean isCrawlerRunning() {
-        return systemHelper.isCrawlProcessRunning();
+        return jobHelper.isCrawlProcessRunning();
     }
     }
 
 
     public String[] getRunningSessionIds() {
     public String[] getRunningSessionIds() {
-        final Set<String> idSet = systemHelper.getRunningSessionIdSet();
+        final Set<String> idSet = jobHelper.getRunningSessionIdSet();
         return idSet.toArray(new String[idSet.size()]);
         return idSet.toArray(new String[idSet.size()]);
     }
     }
 
 

+ 5 - 1
src/main/java/jp/sf/fess/action/admin/WizardAction.java

@@ -33,6 +33,7 @@ import jp.sf.fess.db.exentity.FileCrawlingConfig;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.WebCrawlingConfig;
 import jp.sf.fess.db.exentity.WebCrawlingConfig;
 import jp.sf.fess.form.admin.WizardForm;
 import jp.sf.fess.form.admin.WizardForm;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.job.TriggeredJob;
 import jp.sf.fess.job.TriggeredJob;
 import jp.sf.fess.service.BrowserTypeService;
 import jp.sf.fess.service.BrowserTypeService;
@@ -77,6 +78,9 @@ public class WizardAction implements Serializable {
     @Resource
     @Resource
     protected SystemHelper systemHelper;
     protected SystemHelper systemHelper;
 
 
+    @Resource
+    protected JobHelper jobHelper;
+
     public String getHelpLink() {
     public String getHelpLink() {
         return systemHelper.getHelpLink("wizard");
         return systemHelper.getHelpLink("wizard");
     }
     }
@@ -324,7 +328,7 @@ public class WizardAction implements Serializable {
     @Token(save = false, validate = true)
     @Token(save = false, validate = true)
     @Execute(validator = false)
     @Execute(validator = false)
     public String startCrawling() {
     public String startCrawling() {
-        if (!systemHelper.isCrawlProcessRunning()) {
+        if (!jobHelper.isCrawlProcessRunning()) {
             final ScheduledJobService scheduledJobService = SingletonS2Container
             final ScheduledJobService scheduledJobService = SingletonS2Container
                     .getComponent(ScheduledJobService.class);
                     .getComponent(ScheduledJobService.class);
             final List<ScheduledJob> scheduledJobList = scheduledJobService
             final List<ScheduledJob> scheduledJobList = scheduledJobService

+ 2 - 2
src/main/java/jp/sf/fess/db/exentity/ScheduledJob.java

@@ -18,7 +18,7 @@ package jp.sf.fess.db.exentity;
 
 
 import jp.sf.fess.Constants;
 import jp.sf.fess.Constants;
 import jp.sf.fess.db.bsentity.BsScheduledJob;
 import jp.sf.fess.db.bsentity.BsScheduledJob;
-import jp.sf.fess.helper.SystemHelper;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.job.TriggeredJob;
 import jp.sf.fess.job.TriggeredJob;
 
 
 import org.seasar.framework.container.SingletonS2Container;
 import org.seasar.framework.container.SingletonS2Container;
@@ -49,7 +49,7 @@ public class ScheduledJob extends BsScheduledJob {
     }
     }
 
 
     public boolean isRunning() {
     public boolean isRunning() {
-        return SingletonS2Container.getComponent(SystemHelper.class)
+        return SingletonS2Container.getComponent(JobHelper.class)
                 .getJobExecutoer(getId()) != null;
                 .getJobExecutoer(getId()) != null;
     }
     }
 
 

+ 85 - 0
src/main/java/jp/sf/fess/helper/JobHelper.java

@@ -0,0 +1,85 @@
+package jp.sf.fess.helper;
+
+import java.io.IOException;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import jp.sf.fess.FessSystemException;
+import jp.sf.fess.job.JobExecutor;
+
+import org.apache.commons.io.IOUtils;
+import org.seasar.framework.container.annotation.tiger.DestroyMethod;
+
+public class JobHelper {
+    private final ConcurrentHashMap<String, Process> runningProcessMap = new ConcurrentHashMap<String, Process>();
+
+    private final ConcurrentHashMap<Long, JobExecutor> runningJobExecutorMap = new ConcurrentHashMap<Long, JobExecutor>();
+
+    @DestroyMethod
+    public void destroy() {
+        for (final String sessionId : runningProcessMap.keySet()) {
+            destroyCrawlerProcess(sessionId);
+        }
+    }
+
+    public Process startCrawlerProcess(final String sessionId,
+            final ProcessBuilder processBuilder) {
+        destroyCrawlerProcess(sessionId);
+        Process currentProcess;
+        try {
+            currentProcess = processBuilder.start();
+            destroyCrawlerProcess(runningProcessMap.putIfAbsent(sessionId,
+                    currentProcess));
+            return currentProcess;
+        } catch (final IOException e) {
+            throw new FessSystemException("Crawler Process terminated.", e);
+        }
+    }
+
+    public void destroyCrawlerProcess(final String sessionId) {
+        final Process process = runningProcessMap.remove(sessionId);
+        destroyCrawlerProcess(process);
+    }
+
+    public boolean isCrawlProcessRunning() {
+        return !runningProcessMap.isEmpty();
+    }
+
+    protected void destroyCrawlerProcess(final Process process) {
+        if (process != null) {
+            try {
+                IOUtils.closeQuietly(process.getInputStream());
+            } catch (final Exception e) {
+            }
+            try {
+                IOUtils.closeQuietly(process.getErrorStream());
+            } catch (final Exception e) {
+            }
+            try {
+                IOUtils.closeQuietly(process.getOutputStream());
+            } catch (final Exception e) {
+            }
+            try {
+                process.destroy();
+            } catch (final Exception e) {
+            }
+        }
+    }
+
+    public Set<String> getRunningSessionIdSet() {
+        return runningProcessMap.keySet();
+    }
+
+    public JobExecutor startJobExecutoer(final Long id,
+            final JobExecutor jobExecutor) {
+        return runningJobExecutorMap.putIfAbsent(id, jobExecutor);
+    }
+
+    public void finishJobExecutoer(final Long id) {
+        runningJobExecutorMap.remove(id);
+    }
+
+    public JobExecutor getJobExecutoer(final Long id) {
+        return runningJobExecutorMap.get(id);
+    }
+}

+ 0 - 78
src/main/java/jp/sf/fess/helper/SystemHelper.java

@@ -18,7 +18,6 @@ package jp.sf.fess.helper;
 
 
 import java.io.File;
 import java.io.File;
 import java.io.FilenameFilter;
 import java.io.FilenameFilter;
-import java.io.IOException;
 import java.io.Serializable;
 import java.io.Serializable;
 import java.io.UnsupportedEncodingException;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.net.URLEncoder;
@@ -28,25 +27,20 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.List;
 import java.util.Locale;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map;
-import java.util.Set;
 import java.util.UUID;
 import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 
 import jp.sf.fess.Constants;
 import jp.sf.fess.Constants;
 import jp.sf.fess.FessSystemException;
 import jp.sf.fess.FessSystemException;
 import jp.sf.fess.db.exentity.RoleType;
 import jp.sf.fess.db.exentity.RoleType;
-import jp.sf.fess.job.JobExecutor;
 import jp.sf.fess.service.RoleTypeService;
 import jp.sf.fess.service.RoleTypeService;
 import jp.sf.fess.util.ResourceUtil;
 import jp.sf.fess.util.ResourceUtil;
 
 
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.StringUtils;
 import org.codelibs.solr.lib.SolrGroup;
 import org.codelibs.solr.lib.SolrGroup;
 import org.codelibs.solr.lib.policy.QueryType;
 import org.codelibs.solr.lib.policy.QueryType;
 import org.codelibs.solr.lib.policy.StatusPolicy;
 import org.codelibs.solr.lib.policy.StatusPolicy;
 import org.seasar.framework.container.SingletonS2Container;
 import org.seasar.framework.container.SingletonS2Container;
-import org.seasar.framework.container.annotation.tiger.DestroyMethod;
 import org.seasar.framework.container.annotation.tiger.InitMethod;
 import org.seasar.framework.container.annotation.tiger.InitMethod;
 import org.seasar.framework.util.FileUtil;
 import org.seasar.framework.util.FileUtil;
 import org.seasar.framework.util.StringUtil;
 import org.seasar.framework.util.StringUtil;
@@ -63,10 +57,6 @@ public class SystemHelper implements Serializable {
     private static final Logger logger = LoggerFactory
     private static final Logger logger = LoggerFactory
             .getLogger(SystemHelper.class);
             .getLogger(SystemHelper.class);
 
 
-    private final ConcurrentHashMap<String, Process> runningProcessMap = new ConcurrentHashMap<String, Process>();
-
-    private final ConcurrentHashMap<Long, JobExecutor> runningJobExecutorMap = new ConcurrentHashMap<Long, JobExecutor>();
-
     private String adminRole = "fess";
     private String adminRole = "fess";
 
 
     private String[] crawlerJavaOptions = new String[] {
     private String[] crawlerJavaOptions = new String[] {
@@ -168,53 +158,6 @@ public class SystemHelper implements Serializable {
         }
         }
     }
     }
 
 
-    @DestroyMethod
-    public void destroy() {
-        for (final String sessionId : runningProcessMap.keySet()) {
-            destroyCrawlerProcess(sessionId);
-        }
-    }
-
-    public Process startCrawlerProcess(final String sessionId,
-            final ProcessBuilder processBuilder) {
-        destroyCrawlerProcess(sessionId);
-        Process currentProcess;
-        try {
-            currentProcess = processBuilder.start();
-            destroyCrawlerProcess(runningProcessMap.putIfAbsent(sessionId,
-                    currentProcess));
-            return currentProcess;
-        } catch (final IOException e) {
-            throw new FessSystemException("Crawler Process terminated.", e);
-        }
-    }
-
-    public void destroyCrawlerProcess(final String sessionId) {
-        final Process process = runningProcessMap.remove(sessionId);
-        destroyCrawlerProcess(process);
-    }
-
-    protected void destroyCrawlerProcess(final Process process) {
-        if (process != null) {
-            try {
-                IOUtils.closeQuietly(process.getInputStream());
-            } catch (final Exception e) {
-            }
-            try {
-                IOUtils.closeQuietly(process.getErrorStream());
-            } catch (final Exception e) {
-            }
-            try {
-                IOUtils.closeQuietly(process.getOutputStream());
-            } catch (final Exception e) {
-            }
-            try {
-                process.destroy();
-            } catch (final Exception e) {
-            }
-        }
-    }
-
     public String getUsername() {
     public String getUsername() {
         String username = RequestUtil.getRequest().getRemoteUser();
         String username = RequestUtil.getRequest().getRemoteUser();
         if (StringUtil.isBlank(username)) {
         if (StringUtil.isBlank(username)) {
@@ -227,10 +170,6 @@ public class SystemHelper implements Serializable {
         return new Timestamp(System.currentTimeMillis());
         return new Timestamp(System.currentTimeMillis());
     }
     }
 
 
-    public boolean isCrawlProcessRunning() {
-        return !runningProcessMap.isEmpty();
-    }
-
     public String getLogFilePath() {
     public String getLogFilePath() {
         return logFilePath;
         return logFilePath;
     }
     }
@@ -451,10 +390,6 @@ public class SystemHelper implements Serializable {
 
 
     }
     }
 
 
-    public Set<String> getRunningSessionIdSet() {
-        return runningProcessMap.keySet();
-    }
-
     public boolean isForceStop() {
     public boolean isForceStop() {
         return forceStop.get();
         return forceStop.get();
     }
     }
@@ -463,19 +398,6 @@ public class SystemHelper implements Serializable {
         forceStop.set(true);
         forceStop.set(true);
     }
     }
 
 
-    public JobExecutor startJobExecutoer(final Long id,
-            final JobExecutor jobExecutor) {
-        return runningJobExecutorMap.putIfAbsent(id, jobExecutor);
-    }
-
-    public void finishJobExecutoer(final Long id) {
-        runningJobExecutorMap.remove(id);
-    }
-
-    public JobExecutor getJobExecutoer(final Long id) {
-        return runningJobExecutorMap.get(id);
-    }
-
     public String generateDocId(final Map<String, Object> map) {
     public String generateDocId(final Map<String, Object> map) {
         return UUID.randomUUID().toString().replace("-", "");
         return UUID.randomUUID().toString().replace("-", "");
     }
     }

+ 6 - 3
src/main/java/jp/sf/fess/job/CrawlJob.java

@@ -28,6 +28,7 @@ import javax.servlet.ServletContext;
 import jp.sf.fess.Constants;
 import jp.sf.fess.Constants;
 import jp.sf.fess.FessSystemException;
 import jp.sf.fess.FessSystemException;
 import jp.sf.fess.exec.Crawler;
 import jp.sf.fess.exec.Crawler;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.job.JobExecutor.ShutdownListener;
 import jp.sf.fess.job.JobExecutor.ShutdownListener;
 import jp.sf.fess.util.InputStreamThread;
 import jp.sf.fess.util.InputStreamThread;
@@ -185,7 +186,7 @@ public class CrawlJob {
             jobExecutor.addShutdownListener(new ShutdownListener() {
             jobExecutor.addShutdownListener(new ShutdownListener() {
                 @Override
                 @Override
                 public void onShutdown() {
                 public void onShutdown() {
-                    SingletonS2Container.getComponent(SystemHelper.class)
+                    SingletonS2Container.getComponent(JobHelper.class)
                             .destroyCrawlerProcess(sessionId);
                             .destroyCrawlerProcess(sessionId);
                 }
                 }
             });
             });
@@ -210,6 +211,8 @@ public class CrawlJob {
                 .getComponent(ServletContext.class);
                 .getComponent(ServletContext.class);
         final SystemHelper systemHelper = SingletonS2Container
         final SystemHelper systemHelper = SingletonS2Container
                 .getComponent(SystemHelper.class);
                 .getComponent(SystemHelper.class);
+        final JobHelper jobHelper = SingletonS2Container
+                .getComponent(JobHelper.class);
 
 
         crawlerCmdList.add(systemHelper.getJavaCommandPath());
         crawlerCmdList.add(systemHelper.getJavaCommandPath());
 
 
@@ -302,7 +305,7 @@ public class CrawlJob {
         pb.redirectErrorStream(true);
         pb.redirectErrorStream(true);
 
 
         try {
         try {
-            final Process currentProcess = systemHelper.startCrawlerProcess(
+            final Process currentProcess = jobHelper.startCrawlerProcess(
                     sessionId, pb);
                     sessionId, pb);
 
 
             final InputStreamThread it = new InputStreamThread(
             final InputStreamThread it = new InputStreamThread(
@@ -329,7 +332,7 @@ public class CrawlJob {
         } catch (final Exception e) {
         } catch (final Exception e) {
             throw new FessSystemException("Crawler Process terminated.", e);
             throw new FessSystemException("Crawler Process terminated.", e);
         } finally {
         } finally {
-            systemHelper.destroyCrawlerProcess(sessionId);
+            jobHelper.destroyCrawlerProcess(sessionId);
             if (ownTmpDir != null && !ownTmpDir.delete()) {
             if (ownTmpDir != null && !ownTmpDir.delete()) {
                 logger.warn("Could not delete a temp dir: "
                 logger.warn("Could not delete a temp dir: "
                         + ownTmpDir.getAbsolutePath());
                         + ownTmpDir.getAbsolutePath());

+ 5 - 5
src/main/java/jp/sf/fess/job/JobScheduler.java

@@ -28,7 +28,7 @@ import jp.sf.fess.Constants;
 import jp.sf.fess.db.cbean.ScheduledJobCB;
 import jp.sf.fess.db.cbean.ScheduledJobCB;
 import jp.sf.fess.db.exbhv.ScheduledJobBhv;
 import jp.sf.fess.db.exbhv.ScheduledJobBhv;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.ScheduledJob;
-import jp.sf.fess.helper.SystemHelper;
+import jp.sf.fess.helper.JobHelper;
 
 
 import org.quartz.Job;
 import org.quartz.Job;
 import org.quartz.JobDataMap;
 import org.quartz.JobDataMap;
@@ -84,10 +84,10 @@ public class JobScheduler {
 
 
     @DestroyMethod
     @DestroyMethod
     public void destroy() {
     public void destroy() {
-        final SystemHelper systemHelper = SingletonS2Container
-                .getComponent(SystemHelper.class);
-        for (final String sessionId : systemHelper.getRunningSessionIdSet()) {
-            systemHelper.destroyCrawlerProcess(sessionId);
+        final JobHelper jobHelper = SingletonS2Container
+                .getComponent(JobHelper.class);
+        for (final String sessionId : jobHelper.getRunningSessionIdSet()) {
+            jobHelper.destroyCrawlerProcess(sessionId);
         }
         }
         try {
         try {
             scheduler.shutdown(true);
             scheduler.shutdown(true);

+ 5 - 2
src/main/java/jp/sf/fess/job/TriggeredJob.java

@@ -21,6 +21,7 @@ import java.sql.Timestamp;
 import jp.sf.fess.Constants;
 import jp.sf.fess.Constants;
 import jp.sf.fess.db.exentity.JobLog;
 import jp.sf.fess.db.exentity.JobLog;
 import jp.sf.fess.db.exentity.ScheduledJob;
 import jp.sf.fess.db.exentity.ScheduledJob;
+import jp.sf.fess.helper.JobHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.helper.SystemHelper;
 import jp.sf.fess.service.JobLogService;
 import jp.sf.fess.service.JobLogService;
 
 
@@ -51,6 +52,8 @@ public class TriggeredJob implements Job {
     public void execute(final ScheduledJob scheduledJob) {
     public void execute(final ScheduledJob scheduledJob) {
         final SystemHelper systemHelper = SingletonS2Container
         final SystemHelper systemHelper = SingletonS2Container
                 .getComponent(SystemHelper.class);
                 .getComponent(SystemHelper.class);
+        final JobHelper jobHelper = SingletonS2Container
+                .getComponent(JobHelper.class);
         final JobLog jobLog = new JobLog(scheduledJob);
         final JobLog jobLog = new JobLog(scheduledJob);
         final String scriptType = scheduledJob.getScriptType();
         final String scriptType = scheduledJob.getScriptType();
         final String script = scheduledJob.getScriptData();
         final String script = scheduledJob.getScriptData();
@@ -63,7 +66,7 @@ public class TriggeredJob implements Job {
                     + JOB_EXECUTOR_SUFFIX);
                     + JOB_EXECUTOR_SUFFIX);
         }
         }
 
 
-        if (systemHelper.startJobExecutoer(id, jobExecutor) != null) {
+        if (jobHelper.startJobExecutoer(id, jobExecutor) != null) {
             if (logger.isDebugEnabled()) {
             if (logger.isDebugEnabled()) {
                 logger.debug(jobId + " is running.");
                 logger.debug(jobId + " is running.");
             }
             }
@@ -102,7 +105,7 @@ public class TriggeredJob implements Job {
             jobLog.setScriptResult(systemHelper.abbreviateLongText(e
             jobLog.setScriptResult(systemHelper.abbreviateLongText(e
                     .getLocalizedMessage()));
                     .getLocalizedMessage()));
         } finally {
         } finally {
-            systemHelper.finishJobExecutoer(id);
+            jobHelper.finishJobExecutoer(id);
             jobLog.setEndTime(new Timestamp(System.currentTimeMillis()));
             jobLog.setEndTime(new Timestamp(System.currentTimeMillis()));
             if (logger.isDebugEnabled()) {
             if (logger.isDebugEnabled()) {
                 logger.debug("jobLog: " + jobLog);
                 logger.debug("jobLog: " + jobLog);

+ 6 - 0
src/main/resources/application.properties

@@ -69,6 +69,8 @@ errors.unsupported_encoding={0} is not supported as encoding.
 errors.docid_not_found=Not found Doc ID:{0}
 errors.docid_not_found=Not found Doc ID:{0}
 errors.document_not_found=Not found URL of Doc ID:{0}
 errors.document_not_found=Not found URL of Doc ID:{0}
 errors.not_load_from_server=Could not load from this server: {0}
 errors.not_load_from_server=Could not load from this server: {0}
+errors.failed_to_start_job=Failed to start job {0}.
+errors.failed_to_stop_job=Failed to stop job {0}.
 
 
 errors.invalid_query_unknown=The given query is invalid.
 errors.invalid_query_unknown=The given query is invalid.
 errors.invalid_query_quoted=An invalid quote character is used.
 errors.invalid_query_quoted=An invalid quote character is used.
@@ -99,6 +101,8 @@ success.search_log_delete_all=Deleted search logs.
 success.failure_url_delete_all=Deleted failure urls.
 success.failure_url_delete_all=Deleted failure urls.
 success.delete_file=Deleted {0} file.
 success.delete_file=Deleted {0} file.
 success.user_info_delete_all=Deleted user information.
 success.user_info_delete_all=Deleted user information.
+success.job_started=Started job {0}.
+success.job_stopped=Stopped job {0}.
 
 
 # labels
 # labels
 labels.authRealm=Realm
 labels.authRealm=Realm
@@ -1279,6 +1283,8 @@ labels.scheduledjob_button_back=Back
 labels.scheduledjob_button_update=Update
 labels.scheduledjob_button_update=Update
 labels.scheduledjob_button_delete=Delete
 labels.scheduledjob_button_delete=Delete
 labels.scheduledjob_button_edit=Edit
 labels.scheduledjob_button_edit=Edit
+labels.scheduledjob_button_start=Start
+labels.scheduledjob_button_stop=Stop
 
 
 # view/admin/scheduledjob/index.jsp
 # view/admin/scheduledjob/index.jsp
 labels.scheduledjob_link_create_new=Create New
 labels.scheduledjob_link_create_new=Create New

+ 6 - 0
src/main/resources/application_ja.properties

@@ -69,6 +69,8 @@ errors.unsupported_encoding={0}\u306f\u30b5\u30dd\u30fc\u30c8\u3055\u308c\u3066\
 errors.docid_not_found=ID:{0}\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002
 errors.docid_not_found=ID:{0}\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002
 errors.document_not_found=ID:{0}\u306eURL\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002
 errors.document_not_found=ID:{0}\u306eURL\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3002
 errors.not_load_from_server=\u3053\u306e\u30b5\u30fc\u30d0\u304b\u3089\u30ed\u30fc\u30c9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f: {0}
 errors.not_load_from_server=\u3053\u306e\u30b5\u30fc\u30d0\u304b\u3089\u30ed\u30fc\u30c9\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f: {0}
+errors.failed_to_start_job=\u30b8\u30e7\u30d6 {0} \u306e\u958b\u59cb\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
+errors.failed_to_stop_job=\u30b8\u30e7\u30d6 {0} \u306e\u958b\u59cb\u306b\u5931\u6557\u3057\u307e\u3057\u305f\u3002
 
 
 errors.invalid_query_unknown=\u691c\u7d22\u30af\u30a8\u30ea\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
 errors.invalid_query_unknown=\u691c\u7d22\u30af\u30a8\u30ea\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
 errors.invalid_query_quoted=\u30af\u30aa\u30fc\u30c8\u6587\u5b57(")\u306e\u5229\u7528\u65b9\u6cd5\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
 errors.invalid_query_quoted=\u30af\u30aa\u30fc\u30c8\u6587\u5b57(")\u306e\u5229\u7528\u65b9\u6cd5\u304c\u6b63\u3057\u304f\u3042\u308a\u307e\u305b\u3093\u3002
@@ -99,6 +101,8 @@ success.search_log_delete_all=\u691c\u7d22\u30ed\u30b0\u3092\u524a\u9664\u3057\u
 success.failure_url_delete_all=\u969c\u5bb3URL\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.failure_url_delete_all=\u969c\u5bb3URL\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.delete_file=\u30d5\u30a1\u30a4\u30eb {0} \u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.delete_file=\u30d5\u30a1\u30a4\u30eb {0} \u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.user_info_delete_all= \u5229\u7528\u8005\u60c5\u5831\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
 success.user_info_delete_all= \u5229\u7528\u8005\u60c5\u5831\u3092\u524a\u9664\u3057\u307e\u3057\u305f\u3002
+success.job_started=\u30b8\u30e7\u30d6 {0} \u3092\u958b\u59cb\u3057\u307e\u3057\u305f\u3002
+success.job_stopped=\u30b8\u30e7\u30d6 {0} \u3092\u505c\u6b62\u3057\u307e\u3057\u305f\u3002
 
 
 # labels
 # labels
 labels.authRealm=\u8a8d\u8a3c\u30ec\u30eb\u30e0
 labels.authRealm=\u8a8d\u8a3c\u30ec\u30eb\u30e0
@@ -1277,6 +1281,8 @@ labels.scheduledjob_button_back=\u623b\u308b
 labels.scheduledjob_button_update=\u66f4\u65b0
 labels.scheduledjob_button_update=\u66f4\u65b0
 labels.scheduledjob_button_delete=\u524a\u9664
 labels.scheduledjob_button_delete=\u524a\u9664
 labels.scheduledjob_button_edit=\u7de8\u96c6
 labels.scheduledjob_button_edit=\u7de8\u96c6
+labels.scheduledjob_button_start=\u958b\u59cb
+labels.scheduledjob_button_stop=\u505c\u6b62
 
 
 # view/admin/scheduledjob/index.jsp
 # view/admin/scheduledjob/index.jsp
 labels.scheduledjob_link_create_new=\u65b0\u898f\u4f5c\u6210
 labels.scheduledjob_link_create_new=\u65b0\u898f\u4f5c\u6210

+ 2 - 0
src/main/resources/fess.dicon

@@ -22,6 +22,8 @@
 	</component>
 	</component>
     <component name="pathMappingHelper" class="jp.sf.fess.helper.PathMappingHelper">
     <component name="pathMappingHelper" class="jp.sf.fess.helper.PathMappingHelper">
     </component>
     </component>
+	<component name="jobHelper" class="jp.sf.fess.helper.JobHelper">
+	</component>
 	<component name="systemHelper" class="jp.sf.fess.helper.SystemHelper">
 	<component name="systemHelper" class="jp.sf.fess.helper.SystemHelper">
 		<!--
 		<!--
 		<property name="adminRole">"fess"</property>
 		<property name="adminRole">"fess"</property>

+ 8 - 0
src/main/webapp/WEB-INF/view/admin/scheduledJob/confirm.jsp

@@ -132,6 +132,14 @@
 										value="<bean:message key="labels.scheduledjob_button_edit"/>" />
 										value="<bean:message key="labels.scheduledjob_button_edit"/>" />
 									<input type="submit" class="btn mini" name="deletefromconfirm"
 									<input type="submit" class="btn mini" name="deletefromconfirm"
 										value="<bean:message key="labels.scheduledjob_button_delete"/>" />
 										value="<bean:message key="labels.scheduledjob_button_delete"/>" />
+									<c:if test="${running}">
+									<input type="submit" class="btn mini" name="stop"
+										value="<bean:message key="labels.scheduledjob_button_stop"/>" />
+									</c:if>
+									<c:if test="${!running}">
+									<input type="submit" class="btn mini" name="start"
+										value="<bean:message key="labels.scheduledjob_button_start"/>" />
+									</c:if>
 								</c:if></td>
 								</c:if></td>
 						</tr>
 						</tr>
 					</tfoot>
 					</tfoot>