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 javax.annotation.concurrent.Immutable; 023 024import org.sonar.api.batch.ScannerSide; 025import org.sonar.api.batch.sensor.Sensor; 026import org.sonar.api.batch.sensor.SensorContext; 027import org.sonar.api.ce.ComputeEngineSide; 028import org.sonar.api.server.ServerSide; 029import org.sonar.api.utils.Version; 030import org.sonarsource.api.sonarlint.SonarLintSide; 031 032/** 033 * Information about runtime environment. 034 * 035 * <p> 036 * A usage for plugins is to benefit from new APIs 037 * while keeping backward-compatibility with previous versions of SonarQube 038 * or SonarLint. 039 * </p> 040 * 041 * <p> 042 * Example: a plugin extension wants to use a new feature of API 6.1 without 043 * breaking compatibility with version 6.0 at runtime. This new feature 044 * would be enabled only in 6.1 and greater runtimes. 045 * </p> 046 * <pre> 047 * // Component provided by sonar-plugin-api 048 * // @since 6.0 049 * public interface AnApi { 050 * // implicitly since 6.0 051 * public void foo(); 052 * 053 * // @since 6.1 054 * public void bar(); 055 * } 056 * 057 * // Plugin extension 058 * public class MyExtension { 059 * private final SonarRuntime sonarRuntime; 060 * private final AnApi api; 061 * 062 * public MyExtension(SonarRuntime sonarRuntime, AnApi api) { 063 * this.sonarRuntime = sonarRuntime; 064 * this.api = api; 065 * } 066 * 067 * public void doSomething() { 068 * // assume that minimal supported runtime is 6.0 069 * api.foo(); 070 * 071 * if (sonarRuntime.getApiVersion().isGreaterThanOrEqual(Version.create(6, 1))) { 072 * api.bar(); 073 * } 074 * } 075 * } 076 * </pre> 077 * 078 * 079 * <p> 080 * Note that {@link Sensor} extensions can directly get {@link SonarRuntime} through 081 * {@link SensorContext#runtime()}, without using constructor injection: 082 * </p> 083 * <pre> 084 * public class MySensor implements Sensor { 085 * 086 * public void execute(SensorContext context) { 087 * if (context.runtime().getApiVersion().isGreaterThanOrEqual(Version.create(6, 1)) { 088 * context.newMethodIntroducedIn6_0(); 089 * } 090 * } 091 * 092 * } 093 * </pre> 094 * 095 * <p> 096 * The minimal supported version of plugin API is verified at runtime. As plugin is built 097 * with sonar-plugin-api 6.1, we assume that the plugin requires v6.1 or greater at runtime. 098 * For this reason the plugin must override the minimal supported version 099 * in the configuration of sonar-packaging-maven-plugin 1.16+: 100 * <p> 101 * <pre> 102 * <packaging>sonar-plugin</packaging> 103 * 104 * <dependencies> 105 * <dependency> 106 * <groupId>org.sonarsource.sonarqube</groupId> 107 * <artifactId>sonar-plugin-api</artifactId> 108 * <version>6.1</version> 109 * <scope>provided</scope> 110 * </dependency> 111 * </dependencies> 112 * 113 * <build> 114 * <plugins> 115 * <plugin> 116 * <groupId>org.sonarsource.sonar-packaging-maven-plugin</groupId> 117 * <artifactId>sonar-packaging-maven-plugin</artifactId> 118 * <version>1.16</version> 119 * <extensions>true</extensions> 120 * <configuration> 121 * <!-- Override the default value 6.0 which is guessed from sonar-plugin-api dependency --> 122 * <sonarQubeMinVersion>6.0</sonarQubeMinVersion> 123 * </configuration> 124 * </plugin> 125 * </plugins> 126 * </build> 127 * </pre> 128 * 129 * <p> 130 * As this component was introduced in version 6.0, the pattern described above can't be 131 * exactly applied when plugin must support version 5.6 Long Term Support. In this case plugin 132 * should use {@link SonarQubeVersion}, for example through {@link Plugin.Context#getSonarQubeVersion()} or 133 * {@link SensorContext#getSonarQubeVersion()}. 134 * </p> 135 * 136 * <p> 137 * Unit tests of plugin extensions can create instances of {@link SonarRuntime} 138 * via {@link org.sonar.api.internal.SonarRuntimeImpl}. 139 * </p> 140 * @since 6.0 141 */ 142@ScannerSide 143@ServerSide 144@ComputeEngineSide 145@SonarLintSide 146@Immutable 147public interface SonarRuntime { 148 149 /** 150 * Version of API (sonar-plugin-api artifact) at runtime. 151 * It can be helpful to call some API classes/methods without checking their availability at 152 * runtime by using reflection. 153 * <br/> 154 * Since 6.3, the returned version includes the build number in the fourth field, for 155 * example {@code "6.3.0.12345"}. 156 */ 157 Version getApiVersion(); 158 159 /** 160 * The product being executed at runtime. It targets analysers so that they can implement 161 * different behaviours in SonarQube and SonarLint. 162 */ 163 SonarProduct getProduct(); 164 165 /** 166 * The SonarQube stack being executed at runtime. 167 * @throws UnsupportedOperationException if {@link #getProduct()} is not equal to {@link SonarProduct#SONARQUBE} 168 */ 169 SonarQubeSide getSonarQubeSide(); 170 171}