001/*
002 * SonarQube
003 * Copyright (C) 2009-2017 SonarSource SA
004 * mailto:info AT sonarsource DOT com
005 *
006 * This program is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * This program is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
019 */
020package org.sonar.api;
021
022import org.sonar.api.batch.ScannerSide;
023import org.sonar.api.batch.sensor.Sensor;
024import org.sonar.api.batch.sensor.SensorContext;
025import org.sonar.api.ce.ComputeEngineSide;
026import org.sonar.api.server.ServerSide;
027import org.sonar.api.utils.Version;
028import org.sonarsource.api.sonarlint.SonarLintSide;
029
030/**
031 * Information about runtime environment.
032 *
033 * <p>
034 * A usage for plugins is to benefit from new APIs
035 * while keeping backward-compatibility with previous versions of SonarQube
036 * or SonarLint.
037 * </p>
038 *
039 * <p>
040 * Example: a plugin extension wants to use a new feature of API 6.1 without
041 * breaking compatibility with version 6.0 at runtime. This new feature
042 * would be enabled only in 6.1 and greater runtimes.
043 * </p>
044 * <pre>
045 * // Component provided by sonar-plugin-api
046 * // @since 6.0
047 * public interface AnApi {
048 *   // implicitly since 6.0
049 *   public void foo();
050 *
051 *   // @since 6.1
052 *   public void bar();
053 * }
054 * 
055 * // Plugin extension
056 * public class MyExtension {
057 *   private final SonarRuntime sonarRuntime;
058 *   private final AnApi api;
059 *
060 *   public MyExtension(SonarRuntime sonarRuntime, AnApi api) {
061 *     this.sonarRuntime = sonarRuntime;
062 *     this.api = api;
063 *   }
064 *
065 *   public void doSomething() {
066 *     // assume that minimal supported runtime is 6.0
067 *     api.foo();
068 *
069 *     if (sonarRuntime.getApiVersion().isGreaterThanOrEqual(Version.create(6, 1))) {
070 *       api.bar();
071 *     }
072 *   }
073 * }
074 * </pre>
075 *
076 *
077 * <p>
078 *   Note that {@link Sensor} extensions can directly get {@link SonarRuntime} through
079 * {@link SensorContext#runtime()}, without using constructor injection:
080 * </p>
081 * <pre>
082 * public class MySensor implements Sensor {
083 *
084 *   public void execute(SensorContext context) {
085 *     if (context.runtime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 1)) {
086 *       context.newMethodIntroducedIn6_0();
087 *     }
088 *   }
089 *
090 * }
091 * </pre>
092 *
093 * <p>
094 * The minimal supported version of plugin API is verified at runtime. As plugin is built
095 * with sonar-plugin-api 6.1, we assume that the plugin requires v6.1 or greater at runtime.
096 * For this reason the plugin must override the minimal supported version
097 * in the configuration of sonar-packaging-maven-plugin 1.16+:
098 * <p>
099 * <pre>
100 * &lt;packaging&gt;sonar-plugin&lt;/packaging&gt;
101 *
102 * &lt;dependencies&gt;
103 *   &lt;dependency&gt;
104 *     &lt;groupId&gt;org.sonarsource.sonarqube&lt;/groupId&gt;
105 *     &lt;artifactId&gt;sonar-plugin-api&lt;/artifactId&gt;
106 *     &lt;version&gt;6.1&lt;/version&gt;
107 *     &lt;scope&gt;provided&lt;/scope&gt;
108 *   &lt;/dependency&gt;
109 * &lt;/dependencies&gt;
110 *
111 * &lt;build&gt;
112 *  &lt;plugins&gt;
113 *    &lt;plugin&gt;
114 *      &lt;groupId&gt;org.sonarsource.sonar-packaging-maven-plugin&lt;/groupId&gt;
115 *      &lt;artifactId&gt;sonar-packaging-maven-plugin&lt;/artifactId&gt;
116 *      &lt;version&gt;1.16&lt;/version&gt;
117 *      &lt;extensions&gt;true&lt;/extensions&gt;
118 *      &lt;configuration&gt;
119 *        &lt;!-- Override the default value 6.0 which is guessed from sonar-plugin-api dependency --&gt;
120 *        &lt;sonarQubeMinVersion&gt;6.0&lt;/sonarQubeMinVersion&gt;
121 *      &lt;/configuration&gt;
122 *    &lt;/plugin&gt;
123 *  &lt;/plugins&gt;
124 * &lt;/build&gt;
125 * </pre>
126 *
127 * <p>
128 *   As this component was introduced in version 6.0, the pattern described above can't be
129 *   exactly applied when plugin must support version 5.6 Long Term Support. In this case plugin
130 *   should use {@link SonarQubeVersion}, for example through {@link Plugin.Context#getSonarQubeVersion()} or
131 *   {@link SensorContext#getSonarQubeVersion()}.
132 * </p>
133 *
134 * <p>
135 * Unit tests of plugin extensions can create instances of {@link SonarRuntime}
136 * via {@link org.sonar.api.internal.SonarRuntimeImpl}.
137 * </p>
138 * @since 6.0
139 */
140@ScannerSide
141@ServerSide
142@ComputeEngineSide
143@SonarLintSide
144public interface SonarRuntime {
145
146  /**
147   * Version of API (sonar-plugin-api artifact) at runtime.
148   * It can be helpful to call some API classes/methods without checking their availability at
149   * runtime by using reflection.
150   * <br/>
151   * Since 6.3, the returned version includes the build number in the fourth field, for
152   * example {@code "6.3.0.12345"}.
153  */
154  Version getApiVersion();
155
156  /**
157   * The product being executed at runtime. It targets analysers so that they can implement
158   * different behaviours in SonarQube and SonarLint.
159   */
160  SonarProduct getProduct();
161
162  /**
163   * The SonarQube stack being executed at runtime.
164   * @throws UnsupportedOperationException if {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE}
165   */
166  SonarQubeSide getSonarQubeSide();
167
168}