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 com.google.common.collect.ImmutableList; 023 import com.google.common.collect.Lists; 024 import org.apache.commons.configuration.Configuration; 025 import org.apache.commons.lang.StringUtils; 026 import org.apache.commons.lang.builder.ToStringBuilder; 027 import org.apache.maven.project.MavenProject; 028 import org.sonar.api.CoreProperties; 029 import org.sonar.api.component.Component; 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 private 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 * @deprecated since version 1.11. Constant moved to CoreProperties 059 */ 060 @Deprecated 061 public static final String PARAM_REUSE_RULES_CONFIG = CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY; 062 063 /** 064 * Enumerates the type of possible analysis 065 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 066 */ 067 @Deprecated 068 public enum AnalysisType { 069 STATIC, DYNAMIC, REUSE_REPORTS; 070 071 /** 072 * @param includeReuseReportMode whether to count report reuse as dynamic or not 073 * @return whether this a dynamic analysis 074 */ 075 public boolean isDynamic(boolean includeReuseReportMode) { 076 return equals(Project.AnalysisType.DYNAMIC) || 077 (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode); 078 } 079 } 080 081 private MavenProject pom; 082 private String branch; 083 private ProjectFileSystem fileSystem; 084 private Configuration configuration; 085 private String name; 086 private String description; 087 private String packaging; 088 private Language language; 089 private Date analysisDate; 090 private AnalysisType analysisType; 091 private String analysisVersion; 092 093 // modules tree 094 private Project parent; 095 private List<Project> modules = new ArrayList<Project>(); 096 097 public Project(String key) { 098 setKey(key); 099 setDeprecatedKey(key); 100 setEffectiveKey(key); 101 } 102 103 public Project(String key, String branch, String name) { 104 if (StringUtils.isNotBlank(branch)) { 105 setKey(String.format(BRANCH_KEY_FORMAT, key, branch)); 106 this.name = String.format("%s %s", name, branch); 107 } else { 108 setKey(key); 109 this.name = name; 110 } 111 setDeprecatedKey(getKey()); 112 setEffectiveKey(getKey()); 113 this.branch = branch; 114 } 115 116 public String getBranch() { 117 return branch; 118 } 119 120 /** 121 * For internal use only. 122 */ 123 public Project setBranch(String branch) { 124 this.branch = branch; 125 return this; 126 } 127 128 /** 129 * For internal use only. 130 */ 131 public final Project setPom(MavenProject pom) { 132 this.pom = pom; 133 return this; 134 } 135 136 /** 137 * @return the project's packaging 138 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 139 */ 140 @Deprecated 141 public String getPackaging() { 142 return packaging; 143 } 144 145 @Override 146 public String getName() { 147 return name; 148 } 149 150 @Override 151 public String getLongName() { 152 return name; 153 } 154 155 @Override 156 public String getDescription() { 157 return description; 158 } 159 160 /** 161 * For internal use only. 162 */ 163 public Project setName(String name) { 164 this.name = name; 165 return this; 166 } 167 168 /** 169 * For internal use only. 170 */ 171 public Project setDescription(String description) { 172 this.description = description; 173 return this; 174 } 175 176 /** 177 * For internal use only. 178 * 179 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 180 */ 181 @Deprecated 182 public Project setPackaging(String packaging) { 183 this.packaging = packaging; 184 return this; 185 } 186 187 /** 188 * @return whether the current project is root project 189 */ 190 public boolean isRoot() { 191 return getParent() == null; 192 } 193 194 public Project getRoot() { 195 return parent == null ? this : parent.getRoot(); 196 } 197 198 /** 199 * @return whether the current project is a module 200 */ 201 public boolean isModule() { 202 return !isRoot(); 203 } 204 205 /** 206 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 207 */ 208 @Deprecated 209 public AnalysisType getAnalysisType() { 210 return analysisType; 211 } 212 213 /** 214 * @deprecated since 4.4 Since 4.3 SQ will no more run tests. So basically it's always reuse report. 215 */ 216 @Deprecated 217 public Project setAnalysisType(AnalysisType at) { 218 this.analysisType = at; 219 return this; 220 } 221 222 /** 223 * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision. 224 * 225 * @since 2.0 226 * @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 227 */ 228 @Deprecated 229 public boolean isLatestAnalysis() { 230 return true; 231 } 232 233 /** 234 * For internal use only. 235 * 236 * @deprecated in 3.6. It's not possible to analyze a project before the latest known quality snapshot. 237 * See http://jira.codehaus.org/browse/SONAR-4334 238 */ 239 @Deprecated 240 public Project setLatestAnalysis(boolean b) { 241 if (!b) { 242 throw new UnsupportedOperationException("The analysis is always the latest one. " + 243 "Past analysis must be done in a chronological order."); 244 } 245 return this; 246 } 247 248 /** 249 * @return the project language when there is only one language 250 * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()} 251 */ 252 @Deprecated 253 @Override 254 public Language getLanguage() { 255 return language; 256 } 257 258 /** 259 * Internal use 260 */ 261 public Project setLanguage(Language language) { 262 this.language = language; 263 return this; 264 } 265 266 /** 267 * @return the language key or empty if no language is specified 268 * @deprecated since 4.2 use {@link org.sonar.api.batch.fs.FileSystem#languages()} 269 */ 270 @Deprecated 271 public String getLanguageKey() { 272 return configuration.getString(CoreProperties.PROJECT_LANGUAGE_PROPERTY, ""); 273 } 274 275 /** 276 * For internal use only. 277 */ 278 public Project setAnalysisDate(Date analysisDate) { 279 this.analysisDate = analysisDate; 280 return this; 281 } 282 283 /** 284 * For internal use only. 285 */ 286 public Project setAnalysisVersion(String analysisVersion) { 287 this.analysisVersion = analysisVersion; 288 return this; 289 } 290 291 /** 292 * @return the scope of the current object 293 */ 294 @Override 295 public String getScope() { 296 return Scopes.PROJECT; 297 } 298 299 /** 300 * @return the qualifier of the current object 301 */ 302 @Override 303 public String getQualifier() { 304 return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE; 305 } 306 307 @Override 308 public boolean matchFilePattern(String antPattern) { 309 return false; 310 } 311 312 @Override 313 public Project getParent() { 314 return parent; 315 } 316 317 /** 318 * For internal use only. 319 */ 320 public Project setParent(Project parent) { 321 this.parent = parent; 322 if (parent != null) { 323 parent.modules.add(this); 324 } 325 return this; 326 } 327 328 /** 329 * For internal use only. 330 */ 331 public void removeFromParent() { 332 if (parent != null) { 333 parent.modules.remove(this); 334 } 335 } 336 337 /** 338 * @return the list of modules 339 */ 340 public List<Project> getModules() { 341 return modules; 342 } 343 344 /** 345 * @return whether to use external source for rules configuration 346 * @deprecated since 2.5. See discussion from http://jira.codehaus.org/browse/SONAR-1873 347 */ 348 @Deprecated 349 public boolean getReuseExistingRulesConfig() { 350 return configuration != null && configuration.getBoolean(CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY, false); 351 } 352 353 /** 354 * @return the current version of the project 355 */ 356 public String getAnalysisVersion() { 357 return analysisVersion; 358 } 359 360 /** 361 * @return the analysis date, i.e. the date that will be used to store the snapshot 362 */ 363 public Date getAnalysisDate() { 364 return analysisDate; 365 } 366 367 /** 368 * Patterns of resource exclusion as defined in project settings page. 369 * 370 * @since 3.3 also applies exclusions in general settings page and global exclusions. 371 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5 372 */ 373 @Deprecated 374 public String[] getExclusionPatterns() { 375 return trimExclusions(ImmutableList.<String>builder() 376 .add(configuration.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY)) 377 .add(configuration.getStringArray(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY)).build()); 378 } 379 380 /** 381 * Patterns of test exclusion as defined in project settings page. 382 * Also applies exclusions in general settings page and global exclusions. 383 * 384 * @since 3.3 385 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5 386 */ 387 @Deprecated 388 public String[] getTestExclusionPatterns() { 389 return trimExclusions(ImmutableList.<String>builder() 390 .add(configuration.getStringArray(CoreProperties.PROJECT_TEST_EXCLUSIONS_PROPERTY)) 391 .add(configuration.getStringArray(CoreProperties.GLOBAL_TEST_EXCLUSIONS_PROPERTY)).build()); 392 } 393 394 // http://jira.codehaus.org/browse/SONAR-2261 - exclusion must be trimmed 395 private static String[] trimExclusions(List<String> exclusions) { 396 List<String> trimmed = Lists.newArrayList(); 397 for (String exclusion : exclusions) { 398 trimmed.add(StringUtils.trim(exclusion)); 399 } 400 return trimmed.toArray(new String[trimmed.size()]); 401 } 402 403 /** 404 * Set exclusion patterns. Configuration is not saved, so this method must be used ONLY IN UNIT TESTS. 405 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5 406 */ 407 @Deprecated 408 public Project setExclusionPatterns(String[] s) { 409 throw new UnsupportedOperationException("deprecated in 3.5"); 410 } 411 412 /** 413 * Note: it's better to get a reference on ProjectFileSystem as an IoC dependency (constructor parameter) 414 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem} in 3.5 415 */ 416 @Deprecated 417 public ProjectFileSystem getFileSystem() { 418 return fileSystem; 419 } 420 421 /** 422 * For internal use only. 423 * 424 * @deprecated since 2.6. See http://jira.codehaus.org/browse/SONAR-2126 425 */ 426 @Deprecated 427 public Project setFileSystem(ProjectFileSystem fs) { 428 this.fileSystem = fs; 429 return this; 430 } 431 432 /** 433 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 434 */ 435 @Deprecated 436 public String getGroupId() { 437 return pom.getGroupId(); 438 } 439 440 /** 441 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 442 */ 443 @Deprecated 444 public String getArtifactId() { 445 return pom.getArtifactId(); 446 } 447 448 /** 449 * @return the underlying Maven project 450 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 , 451 * MavenProject can be retrieved as an IoC dependency 452 */ 453 @Deprecated 454 public MavenProject getPom() { 455 return pom; 456 } 457 458 /** 459 * @return the project configuration 460 * @deprecated since 2.12. The component org.sonar.api.config.Settings must be used. 461 */ 462 @Deprecated 463 public Configuration getConfiguration() { 464 return configuration; 465 } 466 467 /** 468 * For internal use only. 469 */ 470 public final Project setConfiguration(Configuration configuration) { 471 this.configuration = configuration; 472 return this; 473 } 474 475 /** 476 * @deprecated since 3.6. Replaced by {@link org.sonar.api.config.Settings}. 477 */ 478 @Deprecated 479 public Object getProperty(String key) { 480 return configuration != null ? configuration.getProperty(key) : null; 481 } 482 483 public static Project createFromMavenIds(String groupId, String artifactId) { 484 return new Project(String.format(MAVEN_KEY_FORMAT, groupId, artifactId)); 485 } 486 487 @Override 488 public String toString() { 489 return new ToStringBuilder(this) 490 .append("id", getId()) 491 .append("key", getKey()) 492 .append("qualifier", getQualifier()) 493 .toString(); 494 } 495 496 @Override 497 public String key() { 498 return getKey(); 499 } 500 501 @Override 502 public String name() { 503 return getName(); 504 } 505 506 @Override 507 public String path() { 508 return getPath(); 509 } 510 511 @Override 512 public String longName() { 513 return getLongName(); 514 } 515 516 @Override 517 public String qualifier() { 518 return getQualifier(); 519 } 520 }