You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 11 година
пре 13 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 11 година
пре 13 година
пре 13 година
пре 11 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  1. /*
  2. * Copyright 2011 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit;
  17. import java.io.BufferedReader;
  18. import java.io.BufferedWriter;
  19. import java.io.File;
  20. import java.io.FileWriter;
  21. import java.io.IOException;
  22. import java.io.InputStreamReader;
  23. import java.io.OutputStream;
  24. import java.net.InetAddress;
  25. import java.net.ServerSocket;
  26. import java.net.Socket;
  27. import java.net.URI;
  28. import java.net.URL;
  29. import java.net.UnknownHostException;
  30. import java.security.ProtectionDomain;
  31. import java.text.MessageFormat;
  32. import java.util.ArrayList;
  33. import java.util.Date;
  34. import java.util.List;
  35. import java.util.Scanner;
  36. import org.eclipse.jetty.ajp.Ajp13SocketConnector;
  37. import org.eclipse.jetty.security.ConstraintMapping;
  38. import org.eclipse.jetty.security.ConstraintSecurityHandler;
  39. import org.eclipse.jetty.server.Connector;
  40. import org.eclipse.jetty.server.Server;
  41. import org.eclipse.jetty.server.bio.SocketConnector;
  42. import org.eclipse.jetty.server.nio.SelectChannelConnector;
  43. import org.eclipse.jetty.server.session.HashSessionManager;
  44. import org.eclipse.jetty.server.ssl.SslConnector;
  45. import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
  46. import org.eclipse.jetty.server.ssl.SslSocketConnector;
  47. import org.eclipse.jetty.util.security.Constraint;
  48. import org.eclipse.jetty.util.thread.QueuedThreadPool;
  49. import org.eclipse.jetty.webapp.WebAppContext;
  50. import org.eclipse.jgit.storage.file.FileBasedConfig;
  51. import org.eclipse.jgit.util.FS;
  52. import org.eclipse.jgit.util.FileUtils;
  53. import org.slf4j.Logger;
  54. import org.slf4j.LoggerFactory;
  55. import com.beust.jcommander.JCommander;
  56. import com.beust.jcommander.Parameter;
  57. import com.beust.jcommander.ParameterException;
  58. import com.beust.jcommander.Parameters;
  59. import com.gitblit.authority.GitblitAuthority;
  60. import com.gitblit.authority.NewCertificateConfig;
  61. import com.gitblit.utils.StringUtils;
  62. import com.gitblit.utils.TimeUtils;
  63. import com.gitblit.utils.X509Utils;
  64. import com.gitblit.utils.X509Utils.X509Log;
  65. import com.gitblit.utils.X509Utils.X509Metadata;
  66. import com.unboundid.ldap.listener.InMemoryDirectoryServer;
  67. import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
  68. import com.unboundid.ldap.listener.InMemoryListenerConfig;
  69. import com.unboundid.ldif.LDIFReader;
  70. /**
  71. * GitBlitServer is the embedded Jetty server for Gitblit GO. This class starts
  72. * and stops an instance of Jetty that is configured from a combination of the
  73. * gitblit.properties file and command line parameters. JCommander is used to
  74. * simplify command line parameter processing. This class also automatically
  75. * generates a self-signed certificate for localhost, if the keystore does not
  76. * already exist.
  77. *
  78. * @author James Moger
  79. *
  80. */
  81. public class GitBlitServer {
  82. private static Logger logger;
  83. public static void main(String... args) {
  84. GitBlitServer server = new GitBlitServer();
  85. // filter out the baseFolder parameter
  86. List<String> filtered = new ArrayList<String>();
  87. String folder = "data";
  88. for (int i = 0; i< args.length; i++) {
  89. String arg = args[i];
  90. if (arg.equals("--baseFolder")) {
  91. if (i + 1 == args.length) {
  92. System.out.println("Invalid --baseFolder parameter!");
  93. System.exit(-1);
  94. } else if (!".".equals(args[i + 1])) {
  95. folder = args[i + 1];
  96. }
  97. i = i + 1;
  98. } else {
  99. filtered.add(arg);
  100. }
  101. }
  102. Params.baseFolder = folder;
  103. Params params = new Params();
  104. JCommander jc = new JCommander(params);
  105. try {
  106. jc.parse(filtered.toArray(new String[filtered.size()]));
  107. if (params.help) {
  108. server.usage(jc, null);
  109. }
  110. } catch (ParameterException t) {
  111. server.usage(jc, t);
  112. }
  113. if (params.stop) {
  114. server.stop(params);
  115. } else {
  116. server.start(params);
  117. }
  118. }
  119. /**
  120. * Display the command line usage of Gitblit GO.
  121. *
  122. * @param jc
  123. * @param t
  124. */
  125. protected final void usage(JCommander jc, ParameterException t) {
  126. System.out.println(Constants.BORDER);
  127. System.out.println(Constants.getGitBlitVersion());
  128. System.out.println(Constants.BORDER);
  129. System.out.println();
  130. if (t != null) {
  131. System.out.println(t.getMessage());
  132. System.out.println();
  133. }
  134. if (jc != null) {
  135. jc.usage();
  136. System.out
  137. .println("\nExample:\n java -server -Xmx1024M -jar gitblit.jar --repositoriesFolder c:\\git --httpPort 80 --httpsPort 443");
  138. }
  139. System.exit(0);
  140. }
  141. /**
  142. * Stop Gitblt GO.
  143. */
  144. public void stop(Params params) {
  145. try {
  146. Socket s = new Socket(InetAddress.getByName("127.0.0.1"), params.shutdownPort);
  147. OutputStream out = s.getOutputStream();
  148. System.out.println("Sending Shutdown Request to " + Constants.NAME);
  149. out.write("\r\n".getBytes());
  150. out.flush();
  151. s.close();
  152. } catch (UnknownHostException e) {
  153. e.printStackTrace();
  154. } catch (IOException e) {
  155. e.printStackTrace();
  156. }
  157. }
  158. /**
  159. * Start Gitblit GO.
  160. */
  161. protected final void start(Params params) {
  162. final File baseFolder = new File(Params.baseFolder).getAbsoluteFile();
  163. FileSettings settings = params.FILESETTINGS;
  164. if (!StringUtils.isEmpty(params.settingsfile)) {
  165. if (new File(params.settingsfile).exists()) {
  166. settings = new FileSettings(params.settingsfile);
  167. }
  168. }
  169. logger = LoggerFactory.getLogger(GitBlitServer.class);
  170. logger.info(Constants.BORDER);
  171. logger.info(" _____ _ _ _ _ _ _");
  172. logger.info(" | __ \\(_)| | | | | |(_)| |");
  173. logger.info(" | | \\/ _ | |_ | |__ | | _ | |_");
  174. logger.info(" | | __ | || __|| '_ \\ | || || __|");
  175. logger.info(" | |_\\ \\| || |_ | |_) || || || |_");
  176. logger.info(" \\____/|_| \\__||_.__/ |_||_| \\__|");
  177. int spacing = (Constants.BORDER.length() - Constants.getGitBlitVersion().length()) / 2;
  178. StringBuilder sb = new StringBuilder();
  179. while (spacing > 0) {
  180. spacing--;
  181. sb.append(' ');
  182. }
  183. logger.info(sb.toString() + Constants.getGitBlitVersion());
  184. logger.info("");
  185. logger.info(Constants.BORDER);
  186. System.setProperty("java.awt.headless", "true");
  187. String osname = System.getProperty("os.name");
  188. String osversion = System.getProperty("os.version");
  189. logger.info("Running on " + osname + " (" + osversion + ")");
  190. List<Connector> connectors = new ArrayList<Connector>();
  191. // conditionally configure the http connector
  192. if (params.port > 0) {
  193. Connector httpConnector = createConnector(params.useNIO, params.port, settings.getInteger(Keys.server.threadPoolSize, 50));
  194. String bindInterface = settings.getString(Keys.server.httpBindInterface, null);
  195. if (!StringUtils.isEmpty(bindInterface)) {
  196. logger.warn(MessageFormat.format("Binding connector on port {0,number,0} to {1}",
  197. params.port, bindInterface));
  198. httpConnector.setHost(bindInterface);
  199. }
  200. if (params.port < 1024 && !isWindows()) {
  201. logger.warn("Gitblit needs to run with ROOT permissions for ports < 1024!");
  202. }
  203. if (params.port > 0 && params.securePort > 0 && settings.getBoolean(Keys.server.redirectToHttpsPort, true)) {
  204. // redirect HTTP requests to HTTPS
  205. if (httpConnector instanceof SelectChannelConnector) {
  206. ((SelectChannelConnector) httpConnector).setConfidentialPort(params.securePort);
  207. } else {
  208. ((SocketConnector) httpConnector).setConfidentialPort(params.securePort);
  209. }
  210. }
  211. connectors.add(httpConnector);
  212. }
  213. // conditionally configure the https connector
  214. if (params.securePort > 0) {
  215. File certificatesConf = new File(baseFolder, X509Utils.CA_CONFIG);
  216. File serverKeyStore = new File(baseFolder, X509Utils.SERVER_KEY_STORE);
  217. File serverTrustStore = new File(baseFolder, X509Utils.SERVER_TRUST_STORE);
  218. File caRevocationList = new File(baseFolder, X509Utils.CA_REVOCATION_LIST);
  219. // generate CA & web certificates, create certificate stores
  220. X509Metadata metadata = new X509Metadata("localhost", params.storePassword);
  221. // set default certificate values from config file
  222. if (certificatesConf.exists()) {
  223. FileBasedConfig config = new FileBasedConfig(certificatesConf, FS.detect());
  224. try {
  225. config.load();
  226. } catch (Exception e) {
  227. logger.error("Error parsing " + certificatesConf, e);
  228. }
  229. NewCertificateConfig certificateConfig = NewCertificateConfig.KEY.parse(config);
  230. certificateConfig.update(metadata);
  231. }
  232. metadata.notAfter = new Date(System.currentTimeMillis() + 10*TimeUtils.ONEYEAR);
  233. X509Utils.prepareX509Infrastructure(metadata, baseFolder, new X509Log() {
  234. @Override
  235. public void log(String message) {
  236. BufferedWriter writer = null;
  237. try {
  238. writer = new BufferedWriter(new FileWriter(new File(baseFolder, X509Utils.CERTS + File.separator + "log.txt"), true));
  239. writer.write(MessageFormat.format("{0,date,yyyy-MM-dd HH:mm}: {1}", new Date(), message));
  240. writer.newLine();
  241. writer.flush();
  242. } catch (Exception e) {
  243. LoggerFactory.getLogger(GitblitAuthority.class).error("Failed to append log entry!", e);
  244. } finally {
  245. if (writer != null) {
  246. try {
  247. writer.close();
  248. } catch (IOException e) {
  249. }
  250. }
  251. }
  252. }
  253. });
  254. if (serverKeyStore.exists()) {
  255. Connector secureConnector = createSSLConnector(params.alias, serverKeyStore, serverTrustStore, params.storePassword,
  256. caRevocationList, params.useNIO, params.securePort, settings.getInteger(Keys.server.threadPoolSize, 50), params.requireClientCertificates);
  257. String bindInterface = settings.getString(Keys.server.httpsBindInterface, null);
  258. if (!StringUtils.isEmpty(bindInterface)) {
  259. logger.warn(MessageFormat.format(
  260. "Binding ssl connector on port {0,number,0} to {1}", params.securePort,
  261. bindInterface));
  262. secureConnector.setHost(bindInterface);
  263. }
  264. if (params.securePort < 1024 && !isWindows()) {
  265. logger.warn("Gitblit needs to run with ROOT permissions for ports < 1024!");
  266. }
  267. connectors.add(secureConnector);
  268. } else {
  269. logger.warn("Failed to find or load Keystore?");
  270. logger.warn("SSL connector DISABLED.");
  271. }
  272. }
  273. // conditionally configure the ajp connector
  274. if (params.ajpPort > 0) {
  275. Connector ajpConnector = createAJPConnector(params.ajpPort);
  276. String bindInterface = settings.getString(Keys.server.ajpBindInterface, null);
  277. if (!StringUtils.isEmpty(bindInterface)) {
  278. logger.warn(MessageFormat.format("Binding connector on port {0,number,0} to {1}",
  279. params.ajpPort, bindInterface));
  280. ajpConnector.setHost(bindInterface);
  281. }
  282. if (params.ajpPort < 1024 && !isWindows()) {
  283. logger.warn("Gitblit needs to run with ROOT permissions for ports < 1024!");
  284. }
  285. connectors.add(ajpConnector);
  286. }
  287. // tempDir is where the embedded Gitblit web application is expanded and
  288. // where Jetty creates any necessary temporary files
  289. File tempDir = com.gitblit.utils.FileUtils.resolveParameter(Constants.baseFolder$, baseFolder, params.temp);
  290. if (tempDir.exists()) {
  291. try {
  292. FileUtils.delete(tempDir, FileUtils.RECURSIVE | FileUtils.RETRY);
  293. } catch (IOException x) {
  294. logger.warn("Failed to delete temp dir " + tempDir.getAbsolutePath(), x);
  295. }
  296. }
  297. if (!tempDir.mkdirs()) {
  298. logger.warn("Failed to create temp dir " + tempDir.getAbsolutePath());
  299. }
  300. Server server = new Server();
  301. server.setStopAtShutdown(true);
  302. server.setConnectors(connectors.toArray(new Connector[connectors.size()]));
  303. // Get the execution path of this class
  304. // We use this to set the WAR path.
  305. ProtectionDomain protectionDomain = GitBlitServer.class.getProtectionDomain();
  306. URL location = protectionDomain.getCodeSource().getLocation();
  307. // Root WebApp Context
  308. WebAppContext rootContext = new WebAppContext();
  309. rootContext.setContextPath(settings.getString(Keys.server.contextPath, "/"));
  310. rootContext.setServer(server);
  311. rootContext.setWar(location.toExternalForm());
  312. rootContext.setTempDirectory(tempDir);
  313. // Set cookies HttpOnly so they are not accessible to JavaScript engines
  314. HashSessionManager sessionManager = new HashSessionManager();
  315. sessionManager.setHttpOnly(true);
  316. // Use secure cookies if only serving https
  317. sessionManager.setSecureCookies(params.port <= 0 && params.securePort > 0);
  318. rootContext.getSessionHandler().setSessionManager(sessionManager);
  319. // Ensure there is a defined User Service
  320. String realmUsers = params.userService;
  321. if (StringUtils.isEmpty(realmUsers)) {
  322. logger.error(MessageFormat.format("PLEASE SPECIFY {0}!!", Keys.realm.userService));
  323. return;
  324. }
  325. // Override settings from the command-line
  326. settings.overrideSetting(Keys.realm.userService, params.userService);
  327. settings.overrideSetting(Keys.git.repositoriesFolder, params.repositoriesFolder);
  328. settings.overrideSetting(Keys.git.daemonPort, params.gitPort);
  329. // Start up an in-memory LDAP server, if configured
  330. try {
  331. if (!StringUtils.isEmpty(params.ldapLdifFile)) {
  332. File ldifFile = new File(params.ldapLdifFile);
  333. if (ldifFile != null && ldifFile.exists()) {
  334. URI ldapUrl = new URI(settings.getRequiredString(Keys.realm.ldap.server));
  335. String firstLine = new Scanner(ldifFile).nextLine();
  336. String rootDN = firstLine.substring(4);
  337. String bindUserName = settings.getString(Keys.realm.ldap.username, "");
  338. String bindPassword = settings.getString(Keys.realm.ldap.password, "");
  339. // Get the port
  340. int port = ldapUrl.getPort();
  341. if (port == -1)
  342. port = 389;
  343. InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(rootDN);
  344. config.addAdditionalBindCredentials(bindUserName, bindPassword);
  345. config.setListenerConfigs(InMemoryListenerConfig.createLDAPConfig("default", port));
  346. config.setSchema(null);
  347. InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
  348. ds.importFromLDIF(true, new LDIFReader(ldifFile));
  349. ds.startListening();
  350. logger.info("LDAP Server started at ldap://localhost:" + port);
  351. }
  352. }
  353. } catch (Exception e) {
  354. // Completely optional, just show a warning
  355. logger.warn("Unable to start LDAP server", e);
  356. }
  357. // Set the server's contexts
  358. server.setHandler(rootContext);
  359. // redirect HTTP requests to HTTPS
  360. if (params.port > 0 && params.securePort > 0 && settings.getBoolean(Keys.server.redirectToHttpsPort, true)) {
  361. logger.info(String.format("Configuring automatic http(%1$s) -> https(%2$s) redirects", params.port, params.securePort));
  362. // Create the internal mechanisms to handle secure connections and redirects
  363. Constraint constraint = new Constraint();
  364. constraint.setDataConstraint(Constraint.DC_CONFIDENTIAL);
  365. ConstraintMapping cm = new ConstraintMapping();
  366. cm.setConstraint(constraint);
  367. cm.setPathSpec("/*");
  368. ConstraintSecurityHandler sh = new ConstraintSecurityHandler();
  369. sh.setConstraintMappings(new ConstraintMapping[] { cm });
  370. // Configure this context to use the Security Handler defined before
  371. rootContext.setHandler(sh);
  372. }
  373. // Setup the GitBlit context
  374. GitBlit gitblit = getGitBlitInstance();
  375. gitblit.configureContext(settings, baseFolder, true);
  376. rootContext.addEventListener(gitblit);
  377. try {
  378. // start the shutdown monitor
  379. if (params.shutdownPort > 0) {
  380. Thread shutdownMonitor = new ShutdownMonitorThread(server, params);
  381. shutdownMonitor.start();
  382. }
  383. // start Jetty
  384. server.start();
  385. server.join();
  386. } catch (Exception e) {
  387. e.printStackTrace();
  388. System.exit(100);
  389. }
  390. }
  391. protected GitBlit getGitBlitInstance() {
  392. return GitBlit.self();
  393. }
  394. /**
  395. * Creates an http connector.
  396. *
  397. * @param useNIO
  398. * @param port
  399. * @param threadPoolSize
  400. * @return an http connector
  401. */
  402. private Connector createConnector(boolean useNIO, int port, int threadPoolSize) {
  403. Connector connector;
  404. if (useNIO) {
  405. logger.info("Setting up NIO SelectChannelConnector on port " + port);
  406. SelectChannelConnector nioconn = new SelectChannelConnector();
  407. nioconn.setSoLingerTime(-1);
  408. if (threadPoolSize > 0) {
  409. nioconn.setThreadPool(new QueuedThreadPool(threadPoolSize));
  410. }
  411. connector = nioconn;
  412. } else {
  413. logger.info("Setting up SocketConnector on port " + port);
  414. SocketConnector sockconn = new SocketConnector();
  415. if (threadPoolSize > 0) {
  416. sockconn.setThreadPool(new QueuedThreadPool(threadPoolSize));
  417. }
  418. connector = sockconn;
  419. }
  420. connector.setPort(port);
  421. connector.setMaxIdleTime(30000);
  422. return connector;
  423. }
  424. /**
  425. * Creates an https connector.
  426. *
  427. * SSL renegotiation will be enabled if the JVM is 1.6.0_22 or later.
  428. * oracle.com/technetwork/java/javase/documentation/tlsreadme2-176330.html
  429. *
  430. * @param certAlias
  431. * @param keyStore
  432. * @param clientTrustStore
  433. * @param storePassword
  434. * @param caRevocationList
  435. * @param useNIO
  436. * @param port
  437. * @param threadPoolSize
  438. * @param requireClientCertificates
  439. * @return an https connector
  440. */
  441. private Connector createSSLConnector(String certAlias, File keyStore, File clientTrustStore,
  442. String storePassword, File caRevocationList, boolean useNIO, int port, int threadPoolSize,
  443. boolean requireClientCertificates) {
  444. GitblitSslContextFactory factory = new GitblitSslContextFactory(certAlias,
  445. keyStore, clientTrustStore, storePassword, caRevocationList);
  446. SslConnector connector;
  447. if (useNIO) {
  448. logger.info("Setting up NIO SslSelectChannelConnector on port " + port);
  449. SslSelectChannelConnector ssl = new SslSelectChannelConnector(factory);
  450. ssl.setSoLingerTime(-1);
  451. if (requireClientCertificates) {
  452. factory.setNeedClientAuth(true);
  453. } else {
  454. factory.setWantClientAuth(true);
  455. }
  456. if (threadPoolSize > 0) {
  457. ssl.setThreadPool(new QueuedThreadPool(threadPoolSize));
  458. }
  459. connector = ssl;
  460. } else {
  461. logger.info("Setting up NIO SslSocketConnector on port " + port);
  462. SslSocketConnector ssl = new SslSocketConnector(factory);
  463. if (threadPoolSize > 0) {
  464. ssl.setThreadPool(new QueuedThreadPool(threadPoolSize));
  465. }
  466. connector = ssl;
  467. }
  468. connector.setPort(port);
  469. connector.setMaxIdleTime(30000);
  470. return connector;
  471. }
  472. /**
  473. * Creates an ajp connector.
  474. *
  475. * @param port
  476. * @return an ajp connector
  477. */
  478. private Connector createAJPConnector(int port) {
  479. logger.info("Setting up AJP Connector on port " + port);
  480. Ajp13SocketConnector ajp = new Ajp13SocketConnector();
  481. ajp.setPort(port);
  482. if (port < 1024 && !isWindows()) {
  483. logger.warn("Gitblit needs to run with ROOT permissions for ports < 1024!");
  484. }
  485. return ajp;
  486. }
  487. /**
  488. * Tests to see if the operating system is Windows.
  489. *
  490. * @return true if this is a windows machine
  491. */
  492. private boolean isWindows() {
  493. return System.getProperty("os.name").toLowerCase().indexOf("windows") > -1;
  494. }
  495. /**
  496. * The ShutdownMonitorThread opens a socket on a specified port and waits
  497. * for an incoming connection. When that connection is accepted a shutdown
  498. * message is issued to the running Jetty server.
  499. *
  500. * @author James Moger
  501. *
  502. */
  503. private static class ShutdownMonitorThread extends Thread {
  504. private final ServerSocket socket;
  505. private final Server server;
  506. private final Logger logger = LoggerFactory.getLogger(ShutdownMonitorThread.class);
  507. public ShutdownMonitorThread(Server server, Params params) {
  508. this.server = server;
  509. setDaemon(true);
  510. setName(Constants.NAME + " Shutdown Monitor");
  511. ServerSocket skt = null;
  512. try {
  513. skt = new ServerSocket(params.shutdownPort, 1, InetAddress.getByName("127.0.0.1"));
  514. } catch (Exception e) {
  515. logger.warn("Could not open shutdown monitor on port " + params.shutdownPort, e);
  516. }
  517. socket = skt;
  518. }
  519. @Override
  520. public void run() {
  521. logger.info("Shutdown Monitor listening on port " + socket.getLocalPort());
  522. Socket accept;
  523. try {
  524. accept = socket.accept();
  525. BufferedReader reader = new BufferedReader(new InputStreamReader(
  526. accept.getInputStream()));
  527. reader.readLine();
  528. logger.info(Constants.BORDER);
  529. logger.info("Stopping " + Constants.NAME);
  530. logger.info(Constants.BORDER);
  531. server.stop();
  532. server.setStopAtShutdown(false);
  533. accept.close();
  534. socket.close();
  535. } catch (Exception e) {
  536. logger.warn("Failed to shutdown Jetty", e);
  537. }
  538. }
  539. }
  540. /**
  541. * JCommander Parameters class for GitBlitServer.
  542. */
  543. @Parameters(separators = " ")
  544. public static class Params {
  545. public static String baseFolder;
  546. private final FileSettings FILESETTINGS = new FileSettings(new File(baseFolder, Constants.PROPERTIES_FILE).getAbsolutePath());
  547. /*
  548. * Server parameters
  549. */
  550. @Parameter(names = { "-h", "--help" }, description = "Show this help")
  551. public Boolean help = false;
  552. @Parameter(names = { "--stop" }, description = "Stop Server")
  553. public Boolean stop = false;
  554. @Parameter(names = { "--tempFolder" }, description = "Folder for server to extract built-in webapp")
  555. public String temp = FILESETTINGS.getString(Keys.server.tempFolder, "temp");
  556. /*
  557. * GIT Servlet Parameters
  558. */
  559. @Parameter(names = { "--repositoriesFolder" }, description = "Git Repositories Folder")
  560. public String repositoriesFolder = FILESETTINGS.getString(Keys.git.repositoriesFolder,
  561. "git");
  562. /*
  563. * Authentication Parameters
  564. */
  565. @Parameter(names = { "--userService" }, description = "Authentication and Authorization Service (filename or fully qualified classname)")
  566. public String userService = FILESETTINGS.getString(Keys.realm.userService,
  567. "users.conf");
  568. /*
  569. * JETTY Parameters
  570. */
  571. @Parameter(names = { "--useNio" }, description = "Use NIO Connector else use Socket Connector.")
  572. public Boolean useNIO = FILESETTINGS.getBoolean(Keys.server.useNio, true);
  573. @Parameter(names = "--httpPort", description = "HTTP port for to serve. (port <= 0 will disable this connector)")
  574. public Integer port = FILESETTINGS.getInteger(Keys.server.httpPort, 0);
  575. @Parameter(names = "--httpsPort", description = "HTTPS port to serve. (port <= 0 will disable this connector)")
  576. public Integer securePort = FILESETTINGS.getInteger(Keys.server.httpsPort, 8443);
  577. @Parameter(names = "--ajpPort", description = "AJP port to serve. (port <= 0 will disable this connector)")
  578. public Integer ajpPort = FILESETTINGS.getInteger(Keys.server.ajpPort, 0);
  579. @Parameter(names = "--gitPort", description = "Git Daemon port to serve. (port <= 0 will disable this connector)")
  580. public Integer gitPort = FILESETTINGS.getInteger(Keys.git.daemonPort, 9418);
  581. @Parameter(names = "--alias", description = "Alias of SSL certificate in keystore for serving https.")
  582. public String alias = FILESETTINGS.getString(Keys.server.certificateAlias, "");
  583. @Parameter(names = "--storePassword", description = "Password for SSL (https) keystore.")
  584. public String storePassword = FILESETTINGS.getString(Keys.server.storePassword, "");
  585. @Parameter(names = "--shutdownPort", description = "Port for Shutdown Monitor to listen on. (port <= 0 will disable this monitor)")
  586. public Integer shutdownPort = FILESETTINGS.getInteger(Keys.server.shutdownPort, 8081);
  587. @Parameter(names = "--requireClientCertificates", description = "Require client X509 certificates for https connections.")
  588. public Boolean requireClientCertificates = FILESETTINGS.getBoolean(Keys.server.requireClientCertificates, false);
  589. /*
  590. * Setting overrides
  591. */
  592. @Parameter(names = { "--settings" }, description = "Path to alternative settings")
  593. public String settingsfile;
  594. @Parameter(names = { "--ldapLdifFile" }, description = "Path to LDIF file. This will cause an in-memory LDAP server to be started according to gitblit settings")
  595. public String ldapLdifFile;
  596. }
  597. }