1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.job;
17
18 import static org.codelibs.core.stream.StreamUtil.stream;
19
20 import java.io.File;
21 import java.util.ArrayList;
22 import java.util.List;
23
24 import javax.servlet.ServletContext;
25
26 import org.apache.commons.lang3.RandomStringUtils;
27 import org.apache.commons.lang3.SystemUtils;
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.codelibs.core.lang.StringUtil;
31 import org.codelibs.core.timer.TimeoutTask;
32 import org.codelibs.fess.Constants;
33 import org.codelibs.fess.exception.JobProcessingException;
34 import org.codelibs.fess.exec.SuggestCreator;
35 import org.codelibs.fess.helper.ProcessHelper;
36 import org.codelibs.fess.mylasta.direction.FessConfig;
37 import org.codelibs.fess.util.ComponentUtil;
38 import org.codelibs.fess.util.InputStreamThread;
39 import org.codelibs.fess.util.JobProcess;
40 import org.codelibs.fess.util.ResourceUtil;
41
42 public class SuggestJob extends ExecJob {
43
44 private static final Logger logger = LogManager.getLogger(SuggestJob.class);
45
46 @Override
47 public String execute() {
48 final StringBuilder resultBuf = new StringBuilder();
49
50 if (sessionId == null) {
51 sessionId = RandomStringUtils.randomAlphabetic(15);
52 }
53 resultBuf.append("Session Id: ").append(sessionId).append("\n");
54 if (jobExecutor != null) {
55 jobExecutor.addShutdownListener(() -> ComponentUtil.getProcessHelper().destroyProcess(sessionId));
56 }
57
58 final TimeoutTask timeoutTask = createTimeoutTask();
59 try {
60 executeSuggestCreator();
61 } catch (final Exception e) {
62 logger.warn("Failed to create suggest data.", e);
63 resultBuf.append(e.getMessage()).append("\n");
64 } finally {
65 if (timeoutTask != null && !timeoutTask.isCanceled()) {
66 timeoutTask.cancel();
67 }
68 }
69
70 return resultBuf.toString();
71
72 }
73
74 protected void executeSuggestCreator() {
75 final List<String> cmdList = new ArrayList<>();
76 final String cpSeparator = SystemUtils.IS_OS_WINDOWS ? ";" : ":";
77 final ServletContext servletContext = ComponentUtil.getComponent(ServletContext.class);
78 final ProcessHelper processHelper = ComponentUtil.getProcessHelper();
79 final FessConfig fessConfig = ComponentUtil.getFessConfig();
80
81 cmdList.add(fessConfig.getJavaCommandPath());
82
83
84 cmdList.add("-cp");
85 final StringBuilder buf = new StringBuilder(100);
86 ResourceUtil.getOverrideConfPath().ifPresent(p -> {
87 buf.append(p);
88 buf.append(cpSeparator);
89 });
90 final String confPath = System.getProperty(Constants.FESS_CONF_PATH);
91 if (StringUtil.isNotBlank(confPath)) {
92 buf.append(confPath);
93 buf.append(cpSeparator);
94 }
95
96 buf.append("WEB-INF");
97 buf.append(File.separator);
98 buf.append("env");
99 buf.append(File.separator);
100 buf.append(getExecuteType());
101 buf.append(File.separator);
102 buf.append("resources");
103 buf.append(cpSeparator);
104
105 buf.append("WEB-INF");
106 buf.append(File.separator);
107 buf.append("classes");
108
109 final String userDir = System.getProperty("user.dir");
110 final File targetDir = new File(userDir, "target");
111 final File targetClassesDir = new File(targetDir, "classes");
112 if (targetClassesDir.isDirectory()) {
113 buf.append(cpSeparator);
114 buf.append(targetClassesDir.getAbsolutePath());
115 }
116
117 appendJarFile(cpSeparator, buf, new File(servletContext.getRealPath("/WEB-INF/lib")),
118 "WEB-INF" + File.separator + "lib" + File.separator);
119
120 appendJarFile(cpSeparator, buf, new File(servletContext.getRealPath("/WEB-INF/env/" + getExecuteType() + "/lib")),
121 "WEB-INF" + File.separator + "env" + File.separator + getExecuteType() + File.separator + "lib" + File.separator);
122
123 appendJarFile(cpSeparator, buf, new File(servletContext.getRealPath("/WEB-INF/plugin")),
124 "WEB-INF" + File.separator + "plugin" + File.separator);
125 final File targetLibDir = new File(targetDir, "fess" + File.separator + "WEB-INF" + File.separator + "lib");
126 if (targetLibDir.isDirectory()) {
127 appendJarFile(cpSeparator, buf, targetLibDir, targetLibDir.getAbsolutePath() + File.separator);
128 }
129 cmdList.add(buf.toString());
130
131 if (useLocalFesen) {
132 final String httpAddress = System.getProperty(Constants.FESS_ES_HTTP_ADDRESS);
133 if (StringUtil.isNotBlank(httpAddress)) {
134 cmdList.add("-D" + Constants.FESS_ES_HTTP_ADDRESS + "=" + httpAddress);
135 }
136 }
137
138 final String systemLastaEnv = System.getProperty("lasta.env");
139 if (StringUtil.isNotBlank(systemLastaEnv)) {
140 if ("web".equals(systemLastaEnv)) {
141 cmdList.add("-Dlasta.env=" + getExecuteType());
142 } else {
143 cmdList.add("-Dlasta.env=" + systemLastaEnv);
144 }
145 } else if (StringUtil.isNotBlank(lastaEnv)) {
146 cmdList.add("-Dlasta.env=" + lastaEnv);
147 } else {
148 cmdList.add("-Dlasta.env=" + getExecuteType());
149 }
150
151 addFessConfigProperties(cmdList);
152 addFessSystemProperties(cmdList);
153 addSystemProperty(cmdList, Constants.FESS_CONF_PATH, null, null);
154 cmdList.add("-Dfess." + getExecuteType() + ".process=true");
155 if (logFilePath == null) {
156 final String value = System.getProperty("fess.log.path");
157 logFilePath = value != null ? value : new File(targetDir, "logs").getAbsolutePath();
158 }
159 cmdList.add("-Dfess.log.path=" + logFilePath);
160 addSystemProperty(cmdList, "fess.log.name", "fess-" + getExecuteType(), "-" + getExecuteType());
161 if (logLevel == null) {
162 addSystemProperty(cmdList, "fess.log.level", null, null);
163 } else {
164 cmdList.add("-Dfess.log.level=" + logLevel);
165 }
166 stream(fessConfig.getJvmSuggestOptionsAsArray())
167 .of(stream -> stream.filter(StringUtil::isNotBlank).forEach(value -> cmdList.add(value)));
168
169 File ownTmpDir = null;
170 final String tmpDir = System.getProperty("java.io.tmpdir");
171 if (fessConfig.isUseOwnTmpDir() && StringUtil.isNotBlank(tmpDir)) {
172 ownTmpDir = new File(tmpDir, "fessTmpDir_" + sessionId);
173 if (ownTmpDir.mkdirs()) {
174 cmdList.add("-Djava.io.tmpdir=" + ownTmpDir.getAbsolutePath());
175 } else {
176 ownTmpDir = null;
177 }
178 }
179
180 if (!jvmOptions.isEmpty()) {
181 jvmOptions.stream().filter(StringUtil::isNotBlank).forEach(cmdList::add);
182 }
183
184 cmdList.add(SuggestCreator.class.getCanonicalName());
185
186 cmdList.add("--sessionId");
187 cmdList.add(sessionId);
188
189 final File propFile = ComponentUtil.getSystemHelper().createTempFile(getExecuteType() + "_", ".properties");
190 try {
191 cmdList.add("-p");
192 cmdList.add(propFile.getAbsolutePath());
193 createSystemProperties(cmdList, propFile);
194
195 final File baseDir = new File(servletContext.getRealPath("/WEB-INF")).getParentFile();
196
197 if (logger.isInfoEnabled()) {
198 logger.info("SuggestCreator: \nDirectory={}\nOptions={}", baseDir, cmdList);
199 }
200
201 final JobProcess jobProcess = processHelper.startProcess(sessionId, cmdList, pb -> {
202 pb.directory(baseDir);
203 pb.redirectErrorStream(true);
204 });
205
206 final InputStreamThread it = jobProcess.getInputStreamThread();
207 it.start();
208
209 final Process currentProcess = jobProcess.getProcess();
210 currentProcess.waitFor();
211 it.join(5000);
212
213 final int exitValue = currentProcess.exitValue();
214
215 if (logger.isInfoEnabled()) {
216 logger.info("SuggestCreator: Exit Code={} - Process Output:\n{}", exitValue, it.getOutput());
217 }
218 if (exitValue != 0) {
219 final StringBuilder out = new StringBuilder();
220 if (processTimeout) {
221 out.append("Process is terminated due to ").append(timeout).append(" second exceeded.\n");
222 }
223 out.append("Exit Code: ").append(exitValue).append("\nOutput:\n").append(it.getOutput());
224 throw new JobProcessingException(out.toString());
225 }
226 ComponentUtil.getPopularWordHelper().clearCache();
227 } catch (final JobProcessingException e) {
228 throw e;
229 } catch (final Exception e) {
230 throw new JobProcessingException("SuggestCreator Process terminated.", e);
231 } finally {
232 try {
233 processHelper.destroyProcess(sessionId);
234 } finally {
235 if (propFile != null && !propFile.delete()) {
236 logger.warn("Failed to delete {}.", propFile.getAbsolutePath());
237 }
238 deleteTempDir(ownTmpDir);
239 }
240 }
241 }
242
243 @Override
244 protected String getExecuteType() {
245 return Constants.EXECUTE_TYPE_SUGGEST;
246 }
247
248 }