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;
023import org.sonar.api.batch.ScannerSide;
024import org.sonar.api.batch.sensor.Sensor;
025import org.sonar.api.batch.sensor.SensorContext;
026import org.sonar.api.ce.ComputeEngineSide;
027import org.sonar.api.server.ServerSide;
028import org.sonar.api.utils.Version;
029
030import static java.util.Objects.requireNonNull;
031
032/**
033 * Version of SonarQube at runtime, but not at compilation time.
034 * This component can be injected as a dependency of plugin extensions.
035 * The main usage for a plugin is to benefit from new APIs
036 * while keeping backward-compatibility with previous versions of API.
037 *
038 * <p>
039 * Example: a plugin extension needs a new feature of API 6.0 without
040 * breaking compatibility with version 5.6 at runtime. This new feature
041 * would be disabled when plugin is executed within SonarQube 5.6.
042 * </p>
043 * <pre>
044 * // Component provided by sonar-plugin-api
045 * // @since 5.6
046 * public interface AnApi {
047 *   // implicitly since 5.6
048 *   public void foo();
049 *
050 *   // @since 6.0
051 *   public void bar();
052 * }
053 *
054 * // Component provided by plugin
055 * public class MyExtension {
056 *   private final SonarQubeVersion sonarQubeVersion;
057 *   private final AnApi api;
058 *
059 *   public MyExtension(SonarQubeVersion sonarQubeVersion, AnApi api) {
060 *     this.sonarQubeVersion = sonarQubeVersion;
061 *     this.api = api;
062 *   }
063 *
064 *   public void doSomething() {
065 *     // assume that runtime is 5.6+
066 *     api.foo();
067 *
068 *     if (sonarQubeVersion.isGreaterThanOrEqual(Version.create(6, 0))) {
069 *       api.bar();
070 *     }
071 *   }
072 * }
073 * </pre>
074 *
075 * <p>
076 *   Note that {@link Sensor} extensions can directly get {@link SonarQubeVersion} through
077 * {@link SensorContext#getSonarQubeVersion()}, without using constructor injection:
078 * </p>
079 * <pre>
080 * public class MySensor implements Sensor {
081 *
082 *   public void execute(SensorContext context) {
083 *     if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(6, 0)) {
084 *       context.newMethodIntroducedIn6_0();
085 *     }
086 *   }
087 *
088 * }
089 * </pre>
090 * <p>
091 * The minimal supported version of SonarQube is verified at runtime. As plugin is built
092 * with sonar-plugin-api 6.0, we assume that the plugin requires v6.0 or greater at runtime.
093 * As the plugin codebase is compatible with 5.6, the plugin must define what is the
094 * effective minimal supported version through the configuration of sonar-packaging-maven-plugin 1.16+:
095 * <p>
096 * <pre>
097 * &lt;packaging&gt;sonar-plugin&lt;/packaging&gt;
098 *
099 * &lt;dependencies&gt;
100 *   &lt;dependency&gt;
101 *     &lt;groupId&gt;org.sonarsource.sonarqube&lt;/groupId&gt;
102 *     &lt;artifactId&gt;sonar-plugin-api&lt;/artifactId&gt;
103 *     &lt;version&gt;6.0&lt;/version&gt;
104 *     &lt;scope&gt;provided&lt;/scope&gt;
105 *   &lt;/dependency&gt;
106 * &lt;/dependencies&gt;
107 *
108 * &lt;build&gt;
109 *  &lt;plugins&gt;
110 *    &lt;plugin&gt;
111 *      &lt;groupId&gt;org.sonarsource.sonar-packaging-maven-plugin&lt;/groupId&gt;
112 *      &lt;artifactId&gt;sonar-packaging-maven-plugin&lt;/artifactId&gt;
113 *      &lt;version&gt;1.16&lt;/version&gt;
114 *      &lt;extensions&gt;true&lt;/extensions&gt;
115 *      &lt;configuration&gt;
116 *        &lt;!-- Override the default value 6.0 which is guessed from sonar-plugin-api dependency --&gt;
117 *        &lt;sonarQubeMinVersion&gt;5.6&lt;/sonarQubeMinVersion&gt;
118 *      &lt;/configuration&gt;
119 *    &lt;/plugin&gt;
120 *  &lt;/plugins&gt;
121 * &lt;/build&gt;
122 * </pre>
123 *
124 * <p>
125 * The component {@link SonarRuntime}, introduced in version 6.0, is more complete.
126 * It is preferred over {@link SonarQubeVersion} if compatibility with version 5.6 Long Term Support
127 * is not required.
128 * </p>
129 *
130 * @see SonarRuntime
131 * @since 5.5
132 */
133@ScannerSide
134@ServerSide
135@ComputeEngineSide
136@Immutable
137public class SonarQubeVersion {
138  /**
139   * Constant for version 5.5
140   * @deprecated in 6.0. Please define your own constants.
141   */
142  @Deprecated
143  public static final Version V5_5 = Version.create(5, 5);
144
145  /**
146   * Constant for version 5.6
147   * @deprecated in 6.0. Please define your own constants.
148   */
149  @Deprecated
150  public static final Version V5_6 = Version.create(5, 6);
151
152  private final Version version;
153
154  public SonarQubeVersion(Version version) {
155    requireNonNull(version);
156    this.version = version;
157  }
158
159  public Version get() {
160    return this.version;
161  }
162
163  public boolean isGreaterThanOrEqual(Version than) {
164    return this.version.isGreaterThanOrEqual(than);
165  }
166}