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.

ServicesManager.java 7.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. /*
  2. * Copyright 2013 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.manager;
  17. import java.io.IOException;
  18. import java.text.MessageFormat;
  19. import java.util.Arrays;
  20. import java.util.Date;
  21. import java.util.List;
  22. import java.util.concurrent.Executors;
  23. import java.util.concurrent.ScheduledExecutorService;
  24. import java.util.concurrent.TimeUnit;
  25. import javax.servlet.http.HttpServletRequest;
  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;
  28. import com.gitblit.Constants.AccessPermission;
  29. import com.gitblit.Constants.AccessRestrictionType;
  30. import com.gitblit.Constants.FederationToken;
  31. import com.gitblit.IStoredSettings;
  32. import com.gitblit.Keys;
  33. import com.gitblit.fanout.FanoutNioService;
  34. import com.gitblit.fanout.FanoutService;
  35. import com.gitblit.fanout.FanoutSocketService;
  36. import com.gitblit.git.GitDaemon;
  37. import com.gitblit.models.FederationModel;
  38. import com.gitblit.models.RepositoryModel;
  39. import com.gitblit.models.UserModel;
  40. import com.gitblit.service.FederationPullService;
  41. import com.gitblit.utils.StringUtils;
  42. import com.gitblit.utils.TimeUtils;
  43. /**
  44. * Services manager manages long-running services/processes that either have no
  45. * direct relation to other managers OR require really high-level manager
  46. * integration (i.e. a Gitblit instance).
  47. *
  48. * @author James Moger
  49. *
  50. */
  51. public class ServicesManager implements IManager {
  52. private final Logger logger = LoggerFactory.getLogger(getClass());
  53. private final ScheduledExecutorService scheduledExecutor = Executors.newScheduledThreadPool(5);
  54. private final IStoredSettings settings;
  55. private final IGitblit gitblit;
  56. private FanoutService fanoutService;
  57. private GitDaemon gitDaemon;
  58. public ServicesManager(IGitblit gitblit) {
  59. this.settings = gitblit.getSettings();
  60. this.gitblit = gitblit;
  61. }
  62. @Override
  63. public ServicesManager start() {
  64. configureFederation();
  65. configureFanout();
  66. configureGitDaemon();
  67. return this;
  68. }
  69. @Override
  70. public ServicesManager stop() {
  71. scheduledExecutor.shutdownNow();
  72. if (fanoutService != null) {
  73. fanoutService.stop();
  74. }
  75. if (gitDaemon != null) {
  76. gitDaemon.stop();
  77. }
  78. return this;
  79. }
  80. protected void configureFederation() {
  81. boolean validPassphrase = true;
  82. String passphrase = settings.getString(Keys.federation.passphrase, "");
  83. if (StringUtils.isEmpty(passphrase)) {
  84. logger.info("Federation passphrase is blank! This server can not be PULLED from.");
  85. validPassphrase = false;
  86. }
  87. if (validPassphrase) {
  88. // standard tokens
  89. for (FederationToken tokenType : FederationToken.values()) {
  90. logger.info(MessageFormat.format("Federation {0} token = {1}", tokenType.name(),
  91. gitblit.getFederationToken(tokenType)));
  92. }
  93. // federation set tokens
  94. for (String set : settings.getStrings(Keys.federation.sets)) {
  95. logger.info(MessageFormat.format("Federation Set {0} token = {1}", set,
  96. gitblit.getFederationToken(set)));
  97. }
  98. }
  99. // Schedule or run the federation executor
  100. List<FederationModel> registrations = gitblit.getFederationRegistrations();
  101. if (registrations.size() > 0) {
  102. FederationPuller executor = new FederationPuller(registrations);
  103. scheduledExecutor.schedule(executor, 1, TimeUnit.MINUTES);
  104. }
  105. }
  106. protected void configureGitDaemon() {
  107. int port = settings.getInteger(Keys.git.daemonPort, 0);
  108. String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost");
  109. if (port > 0) {
  110. try {
  111. gitDaemon = new GitDaemon(gitblit);
  112. gitDaemon.start();
  113. } catch (IOException e) {
  114. gitDaemon = null;
  115. logger.error(MessageFormat.format("Failed to start Git Daemon on {0}:{1,number,0}", bindInterface, port), e);
  116. }
  117. } else {
  118. logger.info("Git Daemon is disabled.");
  119. }
  120. }
  121. protected void configureFanout() {
  122. // startup Fanout PubSub service
  123. if (settings.getInteger(Keys.fanout.port, 0) > 0) {
  124. String bindInterface = settings.getString(Keys.fanout.bindInterface, null);
  125. int port = settings.getInteger(Keys.fanout.port, FanoutService.DEFAULT_PORT);
  126. boolean useNio = settings.getBoolean(Keys.fanout.useNio, true);
  127. int limit = settings.getInteger(Keys.fanout.connectionLimit, 0);
  128. if (useNio) {
  129. if (StringUtils.isEmpty(bindInterface)) {
  130. fanoutService = new FanoutNioService(port);
  131. } else {
  132. fanoutService = new FanoutNioService(bindInterface, port);
  133. }
  134. } else {
  135. if (StringUtils.isEmpty(bindInterface)) {
  136. fanoutService = new FanoutSocketService(port);
  137. } else {
  138. fanoutService = new FanoutSocketService(bindInterface, port);
  139. }
  140. }
  141. fanoutService.setConcurrentConnectionLimit(limit);
  142. fanoutService.setAllowAllChannelAnnouncements(false);
  143. fanoutService.start();
  144. } else {
  145. logger.info("Fanout PubSub service is disabled.");
  146. }
  147. }
  148. public String getGitDaemonUrl(HttpServletRequest request, UserModel user, RepositoryModel repository) {
  149. if (gitDaemon != null) {
  150. String bindInterface = settings.getString(Keys.git.daemonBindInterface, "localhost");
  151. if (bindInterface.equals("localhost")
  152. && (!request.getServerName().equals("localhost") && !request.getServerName().equals("127.0.0.1"))) {
  153. // git daemon is bound to localhost and the request is from elsewhere
  154. return null;
  155. }
  156. if (user.canClone(repository)) {
  157. String servername = request.getServerName();
  158. String url = gitDaemon.formatUrl(servername, repository.name);
  159. return url;
  160. }
  161. }
  162. return null;
  163. }
  164. public AccessPermission getGitDaemonAccessPermission(UserModel user, RepositoryModel repository) {
  165. if (gitDaemon != null && user.canClone(repository)) {
  166. AccessPermission gitDaemonPermission = user.getRepositoryPermission(repository).permission;
  167. if (gitDaemonPermission.atLeast(AccessPermission.CLONE)) {
  168. if (repository.accessRestriction.atLeast(AccessRestrictionType.CLONE)) {
  169. // can not authenticate clone via anonymous git protocol
  170. gitDaemonPermission = AccessPermission.NONE;
  171. } else if (repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
  172. // can not authenticate push via anonymous git protocol
  173. gitDaemonPermission = AccessPermission.CLONE;
  174. } else {
  175. // normal user permission
  176. }
  177. }
  178. return gitDaemonPermission;
  179. }
  180. return AccessPermission.NONE;
  181. }
  182. private class FederationPuller extends FederationPullService {
  183. public FederationPuller(FederationModel registration) {
  184. super(gitblit, Arrays.asList(registration));
  185. }
  186. public FederationPuller(List<FederationModel> registrations) {
  187. super(gitblit, registrations);
  188. }
  189. @Override
  190. public void reschedule(FederationModel registration) {
  191. // schedule the next pull
  192. int mins = TimeUtils.convertFrequencyToMinutes(registration.frequency);
  193. registration.nextPull = new Date(System.currentTimeMillis() + (mins * 60 * 1000L));
  194. scheduledExecutor.schedule(new FederationPuller(registration), mins, TimeUnit.MINUTES);
  195. logger.info(MessageFormat.format(
  196. "Next pull of {0} @ {1} scheduled for {2,date,yyyy-MM-dd HH:mm}",
  197. registration.name, registration.url, registration.nextPull));
  198. }
  199. }
  200. }