1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.esigate.server;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileNotFoundException;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.security.ProtectionDomain;
24 import java.util.Properties;
25
26 import org.apache.commons.io.FileUtils;
27 import org.apache.commons.lang3.StringUtils;
28 import org.eclipse.jetty.server.Connector;
29 import org.eclipse.jetty.server.HttpConfiguration;
30 import org.eclipse.jetty.server.HttpConnectionFactory;
31 import org.eclipse.jetty.server.Server;
32 import org.eclipse.jetty.server.ServerConnector;
33 import org.eclipse.jetty.server.handler.HandlerCollection;
34 import org.eclipse.jetty.server.handler.HandlerList;
35 import org.eclipse.jetty.util.thread.QueuedThreadPool;
36 import org.eclipse.jetty.webapp.WebAppContext;
37 import org.esigate.server.metrics.InstrumentedServerConnector;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 import com.codahale.metrics.MetricRegistry;
42 import com.codahale.metrics.Timer;
43 import com.codahale.metrics.jetty9.InstrumentedConnectionFactory;
44 import com.codahale.metrics.jetty9.InstrumentedHandler;
45 import com.codahale.metrics.jetty9.InstrumentedQueuedThreadPool;
46
47
48
49
50
51
52
53
54
55
56
57 public final class EsigateServer {
58
59 private static final Logger LOG = LoggerFactory.getLogger(EsigateServer.class);
60
61 private static String contextPath;
62 private static int controlPort;
63 private static String extraClasspath;
64 private static long idleTimeout = 0;
65 private static int maxThreads = 0;
66 private static int minThreads = 0;
67 private static int outputBufferSize = 0;
68 private static int port;
69 private static String sessionCookieName;
70 private static final int PROPERTY_DEFAULT_CONTROL_PORT = 8081;
71 private static final int PROPERTY_DEFAULT_HTTP_PORT = 8080;
72 private static final String PROPERTY_PREFIX = "server.";
73 private static Server srv = null;
74
75 private EsigateServer() {
76
77 }
78
79
80
81
82
83
84
85
86
87 private static int getProperty(String prefix, String name, int defaultValue) {
88 int result = defaultValue;
89
90 try {
91 result = Integer.parseInt(System.getProperty(prefix + name));
92 } catch (NumberFormatException e) {
93 LOG.warn("Value for " + prefix + name + " must be an integer. Using default " + defaultValue);
94 }
95 return result;
96 }
97
98
99
100
101
102
103
104
105
106 private static String getProperty(String prefix, String name, String defaultValue) {
107 return System.getProperty(prefix + name, defaultValue);
108 }
109
110
111
112
113 public static void init() {
114
115
116
117
118 String configFile = null;
119 Properties serverProperties = new Properties();
120 try {
121 configFile = System.getProperty(PROPERTY_PREFIX + "config", "server.properties");
122 LOG.info("Loading server configuration from " + configFile);
123
124 try (InputStream is = new FileInputStream(configFile)) {
125 serverProperties.load(is);
126 }
127
128 } catch (FileNotFoundException e) {
129 LOG.warn(configFile + " not found.");
130 } catch (IOException e) {
131 LOG.error("Unexpected error reading " + configFile);
132 }
133
134 init(serverProperties);
135 }
136
137
138
139
140
141
142
143 public static void init(Properties configuration) {
144
145 for (Object prop : configuration.keySet()) {
146 String serverPropertyName = (String) prop;
147 System.setProperty(PROPERTY_PREFIX + serverPropertyName, configuration.getProperty(serverPropertyName));
148 }
149
150
151 LOG.info("Using configuration provided using '-D' parameter and/or default values");
152 EsigateServer.port = getProperty(PROPERTY_PREFIX, "port", PROPERTY_DEFAULT_HTTP_PORT);
153 EsigateServer.controlPort = getProperty(PROPERTY_PREFIX, "controlPort", PROPERTY_DEFAULT_CONTROL_PORT);
154 EsigateServer.contextPath = getProperty(PROPERTY_PREFIX, "contextPath", "/");
155 EsigateServer.extraClasspath = getProperty(PROPERTY_PREFIX, "extraClasspath", null);
156 EsigateServer.maxThreads = getProperty(PROPERTY_PREFIX, "maxThreads", 500);
157 EsigateServer.minThreads = getProperty(PROPERTY_PREFIX, "minThreads", 40);
158 EsigateServer.outputBufferSize = getProperty(PROPERTY_PREFIX, "outputBufferSize", 8 * 1024);
159 EsigateServer.idleTimeout = getProperty(PROPERTY_PREFIX, "idleTimeout", 30 * 1000);
160 EsigateServer.sessionCookieName = getProperty(PROPERTY_PREFIX, "sessionCookieName", null);
161 }
162
163
164
165
166
167
168 public static int getControlPort() {
169 return controlPort;
170 }
171
172
173
174
175
176
177
178
179
180 public static void main(String[] args) throws Exception {
181
182 if (args.length < 1) {
183 EsigateServer.usage();
184 return;
185 }
186
187 switch (args[0]) {
188 case "start":
189 EsigateServer.init();
190 EsigateServer.start();
191 break;
192
193 case "stop":
194 EsigateServer.stop();
195 break;
196
197 default:
198 EsigateServer.usage();
199 break;
200 }
201 }
202
203 private static File resetTempDirectory(String currentDir) throws IOException {
204 File workDir;
205
206
207
208
209 workDir = new File(currentDir, "work");
210
211 if (workDir.exists()) {
212 try {
213 FileUtils.cleanDirectory(workDir);
214 } catch (IllegalArgumentException e) {
215
216
217
218 LOG.info("Info: issue while deleting work directory, it was already deleted. Not a problem.");
219 }
220 }
221
222 return workDir;
223
224 }
225
226
227
228
229
230
231
232 public static void start() throws Exception {
233 MetricRegistry registry = new MetricRegistry();
234
235 QueuedThreadPool threadPool = new InstrumentedQueuedThreadPool(registry);
236 threadPool.setName("esigate");
237 threadPool.setMaxThreads(maxThreads);
238 threadPool.setMinThreads(minThreads);
239
240 srv = new Server(threadPool);
241 srv.setStopAtShutdown(true);
242 srv.setStopTimeout(5000);
243
244
245 HttpConfiguration httpConfig = new HttpConfiguration();
246 httpConfig.setOutputBufferSize(outputBufferSize);
247 httpConfig.setSendServerVersion(false);
248 Timer processTime = registry.timer("processTime");
249
250 try (ServerConnector connector =
251 new InstrumentedServerConnector("main", EsigateServer.port, srv, registry,
252 new InstrumentedConnectionFactory(new HttpConnectionFactory(httpConfig), processTime));
253 ServerConnector controlConnector = new ServerConnector(srv)) {
254
255
256 connector.setIdleTimeout(EsigateServer.idleTimeout);
257 connector.setSoLingerTime(-1);
258 connector.setName("main");
259 connector.setAcceptQueueSize(200);
260
261
262 controlConnector.setHost("127.0.0.1");
263 controlConnector.setPort(EsigateServer.controlPort);
264 controlConnector.setName("control");
265
266 srv.setConnectors(new Connector[] {connector, controlConnector});
267
268 ProtectionDomain protectionDomain = EsigateServer.class.getProtectionDomain();
269 String warFile = protectionDomain.getCodeSource().getLocation().toExternalForm();
270 String currentDir = new File(protectionDomain.getCodeSource().getLocation().getPath()).getParent();
271
272 File workDir = resetTempDirectory(currentDir);
273
274 WebAppContext context = new WebAppContext(warFile, EsigateServer.contextPath);
275 context.setServer(srv);
276 context.setTempDirectory(workDir);
277 if (StringUtils.isNoneEmpty(sessionCookieName)) {
278 context.getSessionHandler().setSessionCookie(sessionCookieName);
279 }
280
281 if (EsigateServer.extraClasspath != null) {
282 context.setExtraClasspath(EsigateServer.extraClasspath);
283 }
284
285
286 HandlerCollection handlers = new HandlerList();
287
288
289 handlers.addHandler(new ControlHandler(registry));
290 InstrumentedHandler ih = new InstrumentedHandler(registry);
291 ih.setName("main");
292 ih.setHandler(context);
293 handlers.addHandler(ih);
294
295 srv.setHandler(handlers);
296 srv.start();
297 srv.join();
298
299 }
300
301 }
302
303
304
305
306
307
308 public static boolean isStarted() {
309 return srv != null && srv.isStarted();
310 }
311
312
313
314
315 public static void stop() {
316 ControlHandler.shutdown(EsigateServer.controlPort);
317 }
318
319
320
321
322 private static void usage() {
323 StringBuilder usageText = new StringBuilder();
324 usageText.append("Usage: java -D").append(PROPERTY_PREFIX)
325 .append("config=esigate.properties -jar esigate-server.jar [start|stop]\n\t");
326 usageText.append("start Start the server (default)\n\t");
327 usageText.append("stop Stop the server gracefully\n\t");
328
329 System.out.println(usageText.toString());
330 System.exit(-1);
331 }
332 }