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.

Plugin.java 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. /*
  2. * SonarQube
  3. * Copyright (C) 2009-2019 SonarSource SA
  4. * mailto:info AT sonarsource DOT com
  5. *
  6. * This program 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. * This program 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.api;
  21. import java.util.ArrayList;
  22. import java.util.Collection;
  23. import java.util.List;
  24. import org.sonar.api.config.Configuration;
  25. import org.sonar.api.utils.Version;
  26. import static java.util.Arrays.asList;
  27. import static java.util.Objects.requireNonNull;
  28. /**
  29. * Entry-point for plugins to inject extensions into SonarQube.
  30. * <p>The JAR manifest must declare the name of the implementation class in the property <code>Plugin-Class</code>.
  31. * This property is automatically set by sonar-packaging-maven-plugin when building plugin.
  32. * <p>Example of implementation
  33. * <pre>
  34. * public class MyPlugin implements Plugin {
  35. * {@literal @}Override
  36. * public void define(Context context) {
  37. * context.addExtensions(MySensor.class, MyRules.class);
  38. * if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(6, 0))) {
  39. * // Extension which supports only versions 6.0 and greater
  40. * // See org.sonar.api.SonarRuntime for more details.
  41. * context.addExtension(MyNewExtension.class);
  42. * }
  43. * }
  44. * }
  45. * </pre>
  46. *
  47. * <p>Example of pom.xml
  48. * <pre>
  49. * &lt;project&gt;
  50. * ...
  51. * &lt;packaging&gt;sonar-plugin&lt;/packaging&gt;
  52. *
  53. * &lt;build&gt;
  54. * &lt;plugins&gt;
  55. * &lt;plugin&gt;
  56. * &lt;groupId&gt;org.sonarsource.sonar-packaging-maven-plugin&lt;/groupId&gt;
  57. * &lt;artifactId&gt;sonar-packaging-maven-plugin&lt;/artifactId&gt;
  58. * &lt;extensions&gt;true&lt;/extensions&gt;
  59. * &lt;configuration&gt;
  60. * &lt;pluginClass&gt;com.mycompany.sonarqube.MyPlugin&lt;/pluginClass&gt;
  61. * &lt;/configuration&gt;
  62. * &lt;/plugin&gt;
  63. * &lt;/plugins&gt;
  64. * &lt;/build&gt;
  65. * &lt;/project&gt;
  66. * </pre>
  67. *
  68. * <p>Example of Test
  69. * <pre>
  70. *{@literal @}Test
  71. * public void test_plugin_extensions_compatible_with_5_6() {
  72. * SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(5, 6), SonarQubeSide.SCANNER);
  73. * Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build();
  74. * MyPlugin underTest = new MyPlugin();
  75. *
  76. * underTest.define(context);
  77. *
  78. * assertThat(context.getExtensions()).hasSize(4);
  79. * }
  80. * </pre>
  81. *
  82. * @since 5.5
  83. * @see org.sonar.api.internal.PluginContextImpl for unit tests
  84. */
  85. public interface Plugin {
  86. class Context {
  87. private final SonarRuntime sonarRuntime;
  88. private final List extensions = new ArrayList();
  89. /**
  90. * For unit tests only. It's recommended to use {@link org.sonar.api.internal.PluginContextImpl.Builder}
  91. * to create instances of {@link Plugin.Context}.
  92. * The configuration returned by {@see #getBootConfiguration()} is empty.
  93. */
  94. public Context(SonarRuntime sonarRuntime) {
  95. this.sonarRuntime = requireNonNull(sonarRuntime, "sonarRuntime is null");
  96. }
  97. /**
  98. * Shortcut on {@code getRuntime().getApiVersion()} since version 6.0.
  99. *
  100. * @see #getRuntime()
  101. * @since 5.5
  102. * @return the version of SonarQube API at runtime, not at compilation time
  103. */
  104. public Version getSonarQubeVersion() {
  105. return sonarRuntime.getApiVersion();
  106. }
  107. /**
  108. * Runtime environment. Can be use to add some extensions only on some conditions.
  109. * @since 6.0
  110. */
  111. public SonarRuntime getRuntime() {
  112. return sonarRuntime;
  113. }
  114. /**
  115. * Add an extension as :
  116. * <ul>
  117. * <li>a Class that is annotated with {@link org.sonar.api.scanner.ScannerSide}, {@link org.sonar.api.server.ServerSide}
  118. * or {@link org.sonar.api.ce.ComputeEngineSide}. The extension will be instantiated once. Its dependencies are
  119. * injected through constructor parameters.</li>
  120. * <li>an instance that is annotated with {@link org.sonar.api.scanner.ScannerSide}, {@link org.sonar.api.server.ServerSide}
  121. * or {@link org.sonar.api.ce.ComputeEngineSide}.</li>
  122. * </ul>
  123. * Only a single component can be registered for a class. It's not allowed for example to register:
  124. * <ul>
  125. * <li>two MyExtension.class</li>
  126. * <li>MyExtension.class and new MyExtension()</li>
  127. * </ul>
  128. */
  129. public Context addExtension(Object extension) {
  130. requireNonNull(extension);
  131. this.extensions.add(extension);
  132. return this;
  133. }
  134. /**
  135. * @see #addExtension(Object)
  136. */
  137. public Context addExtensions(Collection extensions) {
  138. this.extensions.addAll(extensions);
  139. return this;
  140. }
  141. /**
  142. * @see #addExtension(Object)
  143. */
  144. public Context addExtensions(Object first, Object second, Object... others) {
  145. addExtension(first);
  146. addExtension(second);
  147. addExtensions(asList(others));
  148. return this;
  149. }
  150. public List getExtensions() {
  151. return extensions;
  152. }
  153. /**
  154. * The configuration that contains only the few properties required to bootstrap the process, for example:
  155. * - conf/sonar.properties and persisted properties on web server and Compute Engine sides. The default values
  156. * defined by plugins are ignored.
  157. * - command-line arguments on scanner side. Default values or properties persisted in server are ignored.
  158. *
  159. * @since 7.1
  160. */
  161. public Configuration getBootConfiguration() {
  162. throw new UnsupportedOperationException("Unit tests should create Plugin.Context with org.sonar.api.internal.PluginContextImpl#Builder");
  163. }
  164. }
  165. /**
  166. * This method is executed at runtime when:
  167. * <ul>
  168. * <li>Web Server starts</li>
  169. * <li>Compute Engine starts</li>
  170. * <li>Scanner starts</li>
  171. * </ul>
  172. */
  173. void define(Context context);
  174. }