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