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