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.

Platform.java 7.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * SonarQube, open source software quality management tool.
  3. * Copyright (C) 2008-2014 SonarSource
  4. * mailto:contact AT sonarsource DOT com
  5. *
  6. * SonarQube is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 3 of the License, or (at your option) any later version.
  10. *
  11. * SonarQube is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public License
  17. * along with this program; if not, write to the Free Software Foundation,
  18. * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  19. */
  20. package org.sonar.server.platform;
  21. import org.sonar.core.platform.ComponentContainer;
  22. import org.sonar.api.platform.Server;
  23. import org.sonar.api.utils.log.Logger;
  24. import org.sonar.api.utils.log.Loggers;
  25. import org.sonar.core.persistence.DatabaseVersion;
  26. import javax.annotation.CheckForNull;
  27. import javax.servlet.ServletContext;
  28. import java.util.Collection;
  29. import java.util.Properties;
  30. /**
  31. * @since 2.2
  32. */
  33. public class Platform {
  34. private static final Logger LOGGER = Loggers.get(Platform.class);
  35. private static final Platform INSTANCE = new Platform();
  36. private ServerComponents serverComponents;
  37. private ComponentContainer level1Container, level2Container, safeModeContainer, level3Container, level4Container;
  38. private ComponentContainer currentContainer;
  39. private boolean dbConnected = false;
  40. private boolean started = false;
  41. public Platform() {
  42. }
  43. public static Platform getInstance() {
  44. return INSTANCE;
  45. }
  46. /**
  47. * shortcut for ruby code
  48. */
  49. public static Server getServer() {
  50. return (Server) getInstance().getComponent(Server.class);
  51. }
  52. /**
  53. * Used by ruby code
  54. */
  55. @CheckForNull
  56. public static <T> T component(Class<T> type) {
  57. if (INSTANCE.started) {
  58. return INSTANCE.getContainer().getComponentByType(type);
  59. }
  60. return null;
  61. }
  62. public void init(Properties properties, ServletContext servletContext) {
  63. serverComponents = new ServerComponents(this, properties, servletContext);
  64. if (!dbConnected) {
  65. startLevel1Container();
  66. startLevel2Container();
  67. currentContainer = level2Container;
  68. dbConnected = true;
  69. }
  70. }
  71. // Platform is injected in Pico, so do not rename this method "start"
  72. public void doStart() {
  73. if (started && !isInSafeMode()) {
  74. return;
  75. }
  76. if (requireSafeMode()) {
  77. LOGGER.info("DB needs migration, entering safe mode");
  78. startSafeModeContainer();
  79. currentContainer = safeModeContainer;
  80. started = true;
  81. } else {
  82. startLevel34Containers();
  83. executeStartupTasks();
  84. // switch current container last to avoid giving access to a partially initialized container
  85. currentContainer = level4Container;
  86. started = true;
  87. // stop safemode container if it existed
  88. stopSafeModeContainer();
  89. }
  90. }
  91. public void restart() {
  92. // switch currentContainer on level1 now to avoid exposing a container in the process of stopping
  93. currentContainer = level1Container;
  94. // stop containers
  95. stopSafeModeContainer();
  96. stopLevel234Containers();
  97. // no need to initialize database connection, so level 1 is skipped
  98. startLevel2Container();
  99. startLevel34Containers();
  100. executeStartupTasks();
  101. currentContainer = level4Container;
  102. }
  103. private boolean requireSafeMode() {
  104. return getDatabaseStatus() != DatabaseVersion.Status.UP_TO_DATE;
  105. }
  106. public boolean isStarted() {
  107. return started && !isInSafeMode();
  108. }
  109. public boolean isInSafeMode() {
  110. return started && safeModeContainer != null && currentContainer == safeModeContainer;
  111. }
  112. /**
  113. * Starts level 1
  114. */
  115. private void startLevel1Container() {
  116. level1Container = new ComponentContainer();
  117. level1Container.addSingletons(serverComponents.level1Components());
  118. level1Container.startComponents();
  119. }
  120. /**
  121. * Starts level 2
  122. */
  123. private void startLevel2Container() {
  124. level2Container = level1Container.createChild();
  125. level2Container.addSingletons(serverComponents.level2Components());
  126. level2Container.startComponents();
  127. }
  128. /**
  129. * Starts level 3 and 4
  130. */
  131. private void startLevel34Containers() {
  132. level3Container = level2Container.createChild();
  133. level3Container.addSingletons(serverComponents.level3Components());
  134. level3Container.startComponents();
  135. level4Container = level3Container.createChild();
  136. serverComponents.startLevel4Components(level4Container);
  137. }
  138. public void executeStartupTasks() {
  139. serverComponents.executeStartupTasks(level4Container);
  140. }
  141. private void startSafeModeContainer() {
  142. safeModeContainer = level2Container.createChild();
  143. safeModeContainer.addSingletons(serverComponents.safeModeComponents());
  144. safeModeContainer.startComponents();
  145. }
  146. /**
  147. * Stops level 1
  148. */
  149. private void stopLevel1Container() {
  150. if (level1Container != null) {
  151. level1Container.stopComponents();
  152. level1Container = null;
  153. }
  154. }
  155. /**
  156. * Stops level 2, 3 and 3 containers cleanly if they exists.
  157. * Call this method before {@link #startLevel1Container()} to avoid duplicate attempt to stop safemode container
  158. * components (since calling stop on a container calls stop on its children too, see
  159. * {@link ComponentContainer#stopComponents()}).
  160. */
  161. private void stopLevel234Containers() {
  162. if (level2Container != null) {
  163. level2Container.stopComponents();
  164. level2Container = null;
  165. level3Container = null;
  166. level4Container = null;
  167. }
  168. }
  169. /**
  170. * Stops safemode container cleanly if it exists.
  171. * Call this method before {@link #stopLevel234Containers()} and {@link #stopLevel1Container()} to avoid duplicate
  172. * attempt to stop safemode container components (since calling stop on a container calls stops on its children too,
  173. * see {@link ComponentContainer#stopComponents()}).
  174. */
  175. private void stopSafeModeContainer() {
  176. if (safeModeContainer != null) {
  177. safeModeContainer.stopComponents();
  178. safeModeContainer = null;
  179. }
  180. }
  181. private DatabaseVersion.Status getDatabaseStatus() {
  182. DatabaseVersion version = getContainer().getComponentByType(DatabaseVersion.class);
  183. return version.getStatus();
  184. }
  185. // Do not rename "stop"
  186. public void doStop() {
  187. try {
  188. stopSafeModeContainer();
  189. stopLevel234Containers();
  190. stopLevel1Container();
  191. currentContainer = null;
  192. dbConnected = false;
  193. started = false;
  194. } catch (Exception e) {
  195. LOGGER.debug("Fail to stop server - ignored", e);
  196. }
  197. }
  198. public void addComponents(Collection components) {
  199. serverComponents.addComponents(components);
  200. }
  201. public ComponentContainer getContainer() {
  202. return currentContainer;
  203. }
  204. public Object getComponent(Object key) {
  205. return getContainer().getComponentByKey(key);
  206. }
  207. }