1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.codelibs.fess.exec;
17
18 import java.io.File;
19 import java.lang.management.ManagementFactory;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Executors;
22 import java.util.concurrent.TimeUnit;
23
24 import javax.annotation.Resource;
25
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.misc.DynamicProperties;
30 import org.codelibs.core.timer.TimeoutManager;
31 import org.codelibs.core.timer.TimeoutTask;
32 import org.codelibs.fesen.monitor.jvm.JvmInfo;
33 import org.codelibs.fesen.monitor.os.OsProbe;
34 import org.codelibs.fesen.monitor.process.ProcessProbe;
35 import org.codelibs.fess.Constants;
36 import org.codelibs.fess.crawler.client.FesenClient;
37 import org.codelibs.fess.es.client.SearchEngineClient;
38 import org.codelibs.fess.exception.ContainerNotAvailableException;
39 import org.codelibs.fess.timer.SystemMonitorTarget;
40 import org.codelibs.fess.util.ComponentUtil;
41 import org.kohsuke.args4j.CmdLineException;
42 import org.kohsuke.args4j.CmdLineParser;
43 import org.kohsuke.args4j.Option;
44 import org.lastaflute.di.core.external.GenericExternalContext;
45 import org.lastaflute.di.core.external.GenericExternalContextComponentDefRegister;
46 import org.lastaflute.di.core.factory.SingletonLaContainerFactory;
47
48 public class ThumbnailGenerator {
49
50 private static final Logger logger = LogManager.getLogger(ThumbnailGenerator.class);
51
52 @Resource
53 public SearchEngineClient searchEngineClient;
54
55 protected static class Options {
56 @Option(name = "-s", aliases = "--sessionId", metaVar = "sessionId", usage = "Session ID")
57 protected String sessionId;
58
59 @Option(name = "-n", aliases = "--name", metaVar = "name", usage = "Name")
60 protected String name;
61
62 @Option(name = "-p", aliases = "--properties", metaVar = "properties", usage = "Properties File")
63 protected String propertiesPath;
64
65 @Option(name = "-t", aliases = "--numOfThreads", metaVar = "numOfThreads", usage = "The number of threads")
66 protected int numOfThreads = 1;
67
68 @Option(name = "-c", aliases = "--cleanup", usage = "Clean-Up mode")
69 protected boolean cleanup;
70
71 protected Options() {
72
73 }
74
75 @Override
76 public String toString() {
77 return "Options [sessionId=" + sessionId + ", name=" + name + ", propertiesPath=" + propertiesPath + ", numOfThreads="
78 + numOfThreads + "]";
79 }
80
81 }
82
83 static void initializeProbes() {
84
85 ProcessProbe.getInstance();
86 OsProbe.getInstance();
87 JvmInfo.jvmInfo();
88 }
89
90 public static void main(final String[] args) {
91 final Options options = new Options();
92
93 final CmdLineParser parser = new CmdLineParser(options);
94 try {
95 parser.parseArgument(args);
96 } catch (final CmdLineException e) {
97 System.err.println(e.getMessage());
98 System.err.println("java " + ThumbnailGenerator.class.getCanonicalName() + " [options...] arguments...");
99 parser.printUsage(System.err);
100 return;
101 }
102
103 if (logger.isDebugEnabled()) {
104 try {
105 ManagementFactory.getRuntimeMXBean().getInputArguments().stream().forEach(s -> logger.debug("Parameter: {}", s));
106 System.getProperties().entrySet().stream().forEach(e -> logger.debug("Property: {}={}", e.getKey(), e.getValue()));
107 System.getenv().entrySet().forEach(e -> logger.debug("Env: {}={}", e.getKey(), e.getValue()));
108 logger.debug("Option: {}", options);
109 } catch (final Exception e) {
110
111 }
112 }
113
114 final String httpAddress = System.getProperty(Constants.FESS_ES_HTTP_ADDRESS);
115 if (StringUtil.isNotBlank(httpAddress)) {
116 System.setProperty(FesenClient.HTTP_ADDRESS, httpAddress);
117 }
118
119 TimeoutTask systemMonitorTask = null;
120 int exitCode;
121 try {
122 SingletonLaContainerFactory.setConfigPath("app.xml");
123 SingletonLaContainerFactory.setExternalContext(new GenericExternalContext());
124 SingletonLaContainerFactory.setExternalContextComponentDefRegister(new GenericExternalContextComponentDefRegister());
125 SingletonLaContainerFactory.init();
126
127 final Thread shutdownCallback = new Thread("ShutdownHook") {
128 @Override
129 public void run() {
130 if (logger.isDebugEnabled()) {
131 logger.debug("Destroying LaContainer..");
132 }
133 destroyContainer();
134 }
135 };
136 Runtime.getRuntime().addShutdownHook(shutdownCallback);
137
138 systemMonitorTask = TimeoutManager.getInstance().addTimeoutTarget(new SystemMonitorTarget(),
139 ComponentUtil.getFessConfig().getThumbnailSystemMonitorIntervalAsInteger(), true);
140
141 final int totalCount = process(options);
142 if (totalCount != 0) {
143 logger.info("Created {} thumbnail files.", totalCount);
144 } else {
145 logger.info("No new thumbnails found.");
146 }
147 exitCode = 0;
148 } catch (final ContainerNotAvailableException e) {
149 if (logger.isDebugEnabled()) {
150 logger.debug("ThumbnailGenerator is stopped.", e);
151 } else if (logger.isInfoEnabled()) {
152 logger.info("ThumbnailGenerator is stopped.");
153 }
154 exitCode = Constants.EXIT_FAIL;
155 } catch (final Throwable t) {
156 logger.error("ThumbnailGenerator does not work correctly.", t);
157 exitCode = Constants.EXIT_FAIL;
158 } finally {
159 if (systemMonitorTask != null) {
160 systemMonitorTask.cancel();
161 }
162 destroyContainer();
163 }
164
165 System.exit(exitCode);
166 }
167
168 private static void destroyContainer() {
169 TimeoutManager.getInstance().stop();
170 synchronized (SingletonLaContainerFactory.class) {
171 SingletonLaContainerFactory.destroy();
172 }
173 }
174
175 private static int process(final Options options) {
176 final DynamicProperties systemProperties = ComponentUtil.getSystemProperties();
177
178 if (StringUtil.isNotBlank(options.propertiesPath)) {
179 systemProperties.reload(options.propertiesPath);
180 } else {
181 try {
182 final File propFile = ComponentUtil.getSystemHelper().createTempFile("thumbnail_", ".properties");
183 if (propFile.delete() && logger.isDebugEnabled()) {
184 logger.debug("Deleted a temp file: {}", propFile.getAbsolutePath());
185 }
186 systemProperties.reload(propFile.getAbsolutePath());
187 propFile.deleteOnExit();
188 } catch (final Exception e) {
189 logger.warn("Failed to create system properties file.", e);
190 }
191 }
192
193 int totalCount = 0;
194 int count = 1;
195 final ExecutorService executorService = Executors.newFixedThreadPool(options.numOfThreads);
196 try {
197 while (count != 0) {
198 count = ComponentUtil.getThumbnailManager().generate(executorService, options.cleanup);
199 totalCount += count;
200 }
201 executorService.shutdown();
202 executorService.awaitTermination(60, TimeUnit.SECONDS);
203 } catch (final InterruptedException e) {
204 if (logger.isDebugEnabled()) {
205 logger.debug("Interrupted.", e);
206 }
207 } finally {
208 executorService.shutdownNow();
209 }
210 return totalCount;
211 }
212 }