001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube 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 * SonarQube 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 */ 020 package org.sonar.api.resources; 021 022 import org.apache.commons.lang.StringUtils; 023 import org.apache.commons.lang.builder.ToStringBuilder; 024 import org.apache.maven.project.MavenProject; 025 import org.sonar.api.CoreProperties; 026 import org.sonar.api.component.Component; 027 import org.sonar.api.config.Settings; 028 029 import javax.annotation.Nullable; 030 031 import java.util.ArrayList; 032 import java.util.Date; 033 import java.util.List; 034 035 /** 036 * A class that manipulates Projects in the Sonar way. 037 * 038 * @since 1.10 039 */ 040 public class Project extends Resource implements Component { 041 042 /** 043 * Internal use 044 */ 045 public static final Language NONE_LANGUAGE = new AbstractLanguage("none", "None") { 046 @Override 047 public String[] getFileSuffixes() { 048 return new String[0]; 049 } 050 }; 051 052 static final String MAVEN_KEY_FORMAT = "%s:%s"; 053 private static final String BRANCH_KEY_FORMAT = "%s:%s"; 054 055 public static final String SCOPE = Scopes.PROJECT; 056 057 /** 058 * Enumerates the type of possible analysis 059 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 060 */ 061 @Deprecated 062 public enum AnalysisType { 063 STATIC, DYNAMIC, REUSE_REPORTS; 064 065 /** 066 * @param includeReuseReportMode whether to count report reuse as dynamic or not 067 * @return whether this a dynamic analysis 068 */ 069 public boolean isDynamic(boolean includeReuseReportMode) { 070 return equals(Project.AnalysisType.DYNAMIC) || 071 (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode); 072 } 073 } 074 075 private MavenProject pom; 076 private String branch; 077 private ProjectFileSystem fileSystem; 078 private String name; 079 private String description; 080 private String packaging; 081 private Language language; 082 private Date analysisDate; 083 private AnalysisType analysisType; 084 private String analysisVersion; 085 private Settings settings; 086 087 // modules tree 088 private Project parent; 089 private List<Project> modules = new ArrayList<Project>(); 090 091 public Project(String key) { 092 setKey(key); 093 setDeprecatedKey(key); 094 setEffectiveKey(key); 095 } 096 097 public Project(String key, String branch, String name) { 098 if (StringUtils.isNotBlank(branch)) { 099 setKey(String.format(BRANCH_KEY_FORMAT, key, branch)); 100 this.name = String.format("%s %s", name, branch); 101 } else { 102 setKey(key); 103 this.name = name; 104 } 105 setDeprecatedKey(getKey()); 106 setEffectiveKey(getKey()); 107 this.branch = branch; 108 } 109 110 public String getBranch() { 111 return branch; 112 } 113 114 /** 115 * For internal use only. 116 */ 117 public Project setBranch(String branch) { 118 this.branch = branch; 119 return this; 120 } 121 122 /** 123 * For internal use only. 124 */ 125 public final Project setPom(MavenProject pom) { 126 this.pom = pom; 127 return this; 128 } 129 130 /** 131 * @return the project's packaging 132 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 133 */ 134 @Deprecated 135 public String getPackaging() { 136 return packaging; 137 } 138 139 @Override 140 public String getName() { 141 return name; 142 } 143 144 @Override 145 public String getLongName() { 146 return name; 147 } 148 149 @Override 150 public String getDescription() { 151 return description; 152 } 153 154 /** 155 * For internal use only. 156 */ 157 public Project setName(String name) { 158 this.name = name; 159 return this; 160 } 161 162 /** 163 * For internal use only. 164 */ 165 public Project setDescription(String description) { 166 this.description = description; 167 return this; 168 } 169 170 /** 171 * For internal use only. 172 * 173 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 174 */ 175 @Deprecated 176 public Project setPackaging(String packaging) { 177 this.packaging = packaging; 178 return this; 179 } 180 181 /** 182 * @return whether the current project is root project 183 */ 184 public boolean isRoot() { 185 return getParent() == null; 186 } 187 188 public Project getRoot() { 189 return parent == null ? this : parent.getRoot(); 190 } 191 192 /** 193 * @return whether the current project is a module 194 */ 195 public boolean isModule() { 196 return !isRoot(); 197 } 198 199 /** 200 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 201 */ 202 @Deprecated 203 public AnalysisType getAnalysisType() { 204 return analysisType; 205 } 206 207 /** 208 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 209 */ 210 @Deprecated 211 public Project setAnalysisType(AnalysisType at) { 212 this.analysisType = at; 213 return this; 214 } 215 216 /** 217 * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision. 218 * 219 * @since 2.0 220 * @deprecated in 3.6. The analysis is now always the latest one (past analysis must be done in a chronological order). See http://jira.codehaus.org/browse/SONAR-4334 221 */ 222 @Deprecated 223 public boolean isLatestAnalysis() { 224 return true; 225 } 226 227 /** 228 * For internal use only. 229 * 230 * @deprecated in 3.6. It's not possible to analyze a project before the latest known quality snapshot. 231 * See http://jira.codehaus.org/browse/SONAR-4334 232 */ 233 @Deprecated 234 public Project setLatestAnalysis(boolean b) { 235 if (!b) { 236 throw new UnsupportedOperationException("The analysis is always the latest one. " + 237 "Past analysis must be done in a chronological order."); 238 } 239 return this; 240 } 241 242 /** 243 * @return the project language when there is only one language 244 * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()} 245 */ 246 @Deprecated 247 @Override 248 public Language getLanguage() { 249 return language; 250 } 251 252 /** 253 * Internal use 254 */ 255 public Project setLanguage(Language language) { 256 this.language = language; 257 return this; 258 } 259 260 /** 261 * @return the language key or empty if no language is specified 262 * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()} 263 */ 264 @Deprecated 265 public String getLanguageKey() { 266 if (settings == null) { 267 throw new IllegalStateException("Project is not yet initialized"); 268 } 269 return StringUtils.defaultIfEmpty(settings.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY), ""); 270 } 271 272 /** 273 * Internal use 274 */ 275 public Project setSettings(Settings settings) { 276 this.settings = settings; 277 return this; 278 } 279 280 /** 281 * Internal use for backward compatibility. Settings should be retrieved as an IoC dependency. 282 * @deprecated since 5.0 283 */ 284 @Deprecated 285 public Settings getSettings() { 286 return settings; 287 } 288 289 /** 290 * For internal use only. 291 */ 292 public Project setAnalysisDate(Date analysisDate) { 293 this.analysisDate = analysisDate; 294 return this; 295 } 296 297 /** 298 * For internal use only. 299 */ 300 public Project setAnalysisVersion(String analysisVersion) { 301 this.analysisVersion = analysisVersion; 302 return this; 303 } 304 305 /** 306 * @return the scope of the current object 307 */ 308 @Override 309 public String getScope() { 310 return Scopes.PROJECT; 311 } 312 313 /** 314 * @return the qualifier of the current object 315 */ 316 @Override 317 public String getQualifier() { 318 return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE; 319 } 320 321 @Override 322 public boolean matchFilePattern(String antPattern) { 323 return false; 324 } 325 326 @Override 327 public Project getParent() { 328 return parent; 329 } 330 331 /** 332 * For internal use only. 333 */ 334 public Project setParent(Project parent) { 335 this.parent = parent; 336 if (parent != null) { 337 parent.modules.add(this); 338 } 339 return this; 340 } 341 342 /** 343 * For internal use only. 344 */ 345 public void removeFromParent() { 346 if (parent != null) { 347 parent.modules.remove(this); 348 } 349 } 350 351 /** 352 * @return the list of modules 353 */ 354 public List<Project> getModules() { 355 return modules; 356 } 357 358 /** 359 * @return the current version of the project 360 */ 361 public String getAnalysisVersion() { 362 return analysisVersion; 363 } 364 365 /** 366 * @return the analysis date, i.e. the date that will be used to store the snapshot 367 */ 368 public Date getAnalysisDate() { 369 return analysisDate; 370 } 371 372 /** 373 * Note: it's better to get a reference on ProjectFileSystem as an IoC dependency (constructor parameter) 374 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem} in 3.5 375 */ 376 @Deprecated 377 public ProjectFileSystem getFileSystem() { 378 return fileSystem; 379 } 380 381 /** 382 * For internal use only. 383 * 384 * @deprecated since 2.6. See http://jira.codehaus.org/browse/SONAR-2126 385 */ 386 @Deprecated 387 public Project setFileSystem(ProjectFileSystem fs) { 388 this.fileSystem = fs; 389 return this; 390 } 391 392 /** 393 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 394 */ 395 @Deprecated 396 public String getGroupId() { 397 return pom.getGroupId(); 398 } 399 400 /** 401 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 402 */ 403 @Deprecated 404 public String getArtifactId() { 405 return pom.getArtifactId(); 406 } 407 408 /** 409 * @return the underlying Maven project 410 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 , 411 * MavenProject can be retrieved as an IoC dependency 412 */ 413 @Deprecated 414 public MavenProject getPom() { 415 return pom; 416 } 417 418 public static Project createFromMavenIds(String groupId, String artifactId) { 419 return createFromMavenIds(groupId, artifactId, null); 420 } 421 422 public static Project createFromMavenIds(String groupId, String artifactId, @Nullable String branch) { 423 return new Project(String.format(MAVEN_KEY_FORMAT, groupId, artifactId), branch, ""); 424 } 425 426 @Override 427 public String toString() { 428 return new ToStringBuilder(this) 429 .append("id", getId()) 430 .append("key", getKey()) 431 .append("qualifier", getQualifier()) 432 .toString(); 433 } 434 435 @Override 436 public String key() { 437 return getKey(); 438 } 439 440 @Override 441 public String name() { 442 return getName(); 443 } 444 445 @Override 446 public String path() { 447 return getPath(); 448 } 449 450 @Override 451 public String longName() { 452 return getLongName(); 453 } 454 455 @Override 456 public String qualifier() { 457 return getQualifier(); 458 } 459 }