001/* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar 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 * Sonar 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 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020package org.sonar.api.resources; 021 022import com.google.common.collect.ImmutableList; 023import com.google.common.collect.Lists; 024import org.apache.commons.configuration.Configuration; 025import org.apache.commons.lang.StringUtils; 026import org.apache.commons.lang.builder.ToStringBuilder; 027import org.apache.maven.project.MavenProject; 028import org.sonar.api.CoreProperties; 029 030import java.util.ArrayList; 031import java.util.Date; 032import java.util.List; 033 034/** 035 * A class that manipulates Projects in the Sonar way. 036 * 037 * @since 1.10 038 */ 039public class Project extends Resource { 040 041 public static final String SCOPE = Scopes.PROJECT; 042 043 /** 044 * @deprecated since version 1.11. Constant moved to CoreProperties 045 */ 046 @Deprecated 047 public static final String PARAM_VERSION = CoreProperties.PROJECT_VERSION_PROPERTY; 048 049 /** 050 * @deprecated since version 1.11. Constant moved to CoreProperties 051 */ 052 @Deprecated 053 public static final String PARAM_DATE = CoreProperties.PROJECT_DATE_PROPERTY; 054 055 /** 056 * @deprecated since version 1.11. Constant moved to CoreProperties 057 */ 058 @Deprecated 059 public static final String PARAM_LANGUAGE = CoreProperties.PROJECT_LANGUAGE_PROPERTY; 060 061 /** 062 * @deprecated since version 1.11. Constant moved to CoreProperties 063 */ 064 @Deprecated 065 public static final String PARAM_DYNAMIC_ANALYSIS = CoreProperties.DYNAMIC_ANALYSIS_PROPERTY; 066 067 /** 068 * @deprecated since version 1.11. Constant moved to CoreProperties 069 */ 070 @Deprecated 071 public static final String PARAM_EXCLUSIONS = CoreProperties.PROJECT_EXCLUSIONS_PROPERTY; 072 073 /** 074 * @deprecated since version 1.11. Constant moved to CoreProperties 075 */ 076 @Deprecated 077 public static final String PARAM_REUSE_RULES_CONFIG = CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY; 078 079 /** 080 * Enumerates the type of possible analysis 081 */ 082 public enum AnalysisType { 083 STATIC, DYNAMIC, REUSE_REPORTS; 084 085 /** 086 * @param includeReuseReportMode whether to count report reuse as dynamic or not 087 * @return whether this a dynamic analysis 088 */ 089 public boolean isDynamic(boolean includeReuseReportMode) { 090 return equals(Project.AnalysisType.DYNAMIC) || 091 (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode); 092 } 093 } 094 095 private MavenProject pom; 096 private String branch; 097 private ProjectFileSystem fileSystem; 098 private Configuration configuration; 099 private String name; 100 private String description; 101 private String packaging; 102 private Language language; 103 private Date analysisDate; 104 private AnalysisType analysisType; 105 private String analysisVersion; 106 private boolean latestAnalysis; 107 108 // modules tree 109 private Project parent; 110 private List<Project> modules = new ArrayList<Project>(); 111 112 public Project(String key) { 113 setKey(key); 114 setEffectiveKey(key); 115 } 116 117 public Project(String key, String branch, String name) { 118 if (StringUtils.isNotBlank(branch)) { 119 setKey(String.format("%s:%s", key, branch)); 120 this.name = String.format("%s %s", name, branch); 121 } else { 122 setKey(key); 123 this.name = name; 124 } 125 setEffectiveKey(getKey()); 126 this.branch = branch; 127 } 128 129 public String getBranch() { 130 return branch; 131 } 132 133 /** 134 * For internal use only. 135 */ 136 public Project setBranch(String branch) { 137 this.branch = branch; 138 return this; 139 } 140 141 /** 142 * For internal use only. 143 */ 144 public final Project setPom(MavenProject pom) { 145 this.pom = pom; 146 return this; 147 } 148 149 /** 150 * @return the project's packaging 151 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 152 */ 153 @Deprecated 154 public String getPackaging() { 155 return packaging; 156 } 157 158 @Override 159 public String getName() { 160 return name; 161 } 162 163 @Override 164 public String getLongName() { 165 return name; 166 } 167 168 @Override 169 public String getDescription() { 170 return description; 171 } 172 173 /** 174 * For internal use only. 175 */ 176 public Project setName(String name) { 177 this.name = name; 178 return this; 179 } 180 181 /** 182 * For internal use only. 183 */ 184 public Project setDescription(String description) { 185 this.description = description; 186 return this; 187 } 188 189 /** 190 * For internal use only. 191 * 192 * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341 193 */ 194 @Deprecated 195 public Project setPackaging(String packaging) { 196 this.packaging = packaging; 197 return this; 198 } 199 200 /** 201 * @return whether the current project is root project 202 */ 203 public boolean isRoot() { 204 return getParent() == null; 205 } 206 207 public Project getRoot() { 208 return (parent == null ? this : parent.getRoot()); 209 } 210 211 /** 212 * @return whether the current project is a module 213 */ 214 public boolean isModule() { 215 return !isRoot(); 216 } 217 218 /** 219 * @return the type of analysis of the project 220 */ 221 public AnalysisType getAnalysisType() { 222 return analysisType; 223 } 224 225 public Project setAnalysisType(AnalysisType at) { 226 this.analysisType = at; 227 return this; 228 } 229 230 /** 231 * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision. 232 * 233 * @since 2.0 234 */ 235 public boolean isLatestAnalysis() { 236 return latestAnalysis; 237 } 238 239 /** 240 * For internal use only. 241 */ 242 public Project setLatestAnalysis(boolean b) { 243 this.latestAnalysis = b; 244 return this; 245 } 246 247 /** 248 * @return the project language 249 */ 250 @Override 251 public Language getLanguage() { 252 return language; 253 } 254 255 public Project setLanguage(Language language) { 256 this.language = language; 257 return this; 258 } 259 260 /** 261 * @return the language key 262 */ 263 public String getLanguageKey() { 264 return configuration.getString("sonar.language", Java.KEY); 265 } 266 267 /** 268 * For internal use only. 269 */ 270 public Project setAnalysisDate(Date analysisDate) { 271 this.analysisDate = analysisDate; 272 return this; 273 } 274 275 /** 276 * For internal use only. 277 */ 278 public Project setAnalysisVersion(String analysisVersion) { 279 this.analysisVersion = analysisVersion; 280 return this; 281 } 282 283 /** 284 * @return the scope of the current object 285 */ 286 @Override 287 public String getScope() { 288 return Scopes.PROJECT; 289 } 290 291 /** 292 * @return the qualifier of the current object 293 */ 294 @Override 295 public String getQualifier() { 296 return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE; 297 } 298 299 @Override 300 public boolean matchFilePattern(String antPattern) { 301 return false; 302 } 303 304 @Override 305 public Project getParent() { 306 return parent; 307 } 308 309 /** 310 * For internal use only. 311 */ 312 public Project setParent(Project parent) { 313 this.parent = parent; 314 if (parent != null) { 315 parent.modules.add(this); 316 } 317 return this; 318 } 319 320 /** 321 * For internal use only. 322 */ 323 public void removeFromParent() { 324 if (parent != null) { 325 parent.modules.remove(this); 326 } 327 } 328 329 /** 330 * @return the list of modules 331 */ 332 public List<Project> getModules() { 333 return modules; 334 } 335 336 /** 337 * @return whether to use external source for rules configuration 338 * @deprecated since 2.5. See discussion from http://jira.codehaus.org/browse/SONAR-1873 339 */ 340 @Deprecated 341 public boolean getReuseExistingRulesConfig() { 342 return (configuration != null && configuration.getBoolean(CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY, false)); 343 } 344 345 /** 346 * @return the current version of the project 347 */ 348 public String getAnalysisVersion() { 349 return analysisVersion; 350 } 351 352 /** 353 * @return the analysis date, i.e. the date that will be used to store the snapshot 354 */ 355 public Date getAnalysisDate() { 356 return analysisDate; 357 } 358 359 /** 360 * Patterns of resource exclusion as defined in project settings page. 361 * 362 * @since 3.3 also applies exclusions in general settings page and global exclusions. 363 */ 364 public String[] getExclusionPatterns() { 365 return trimExclusions(ImmutableList.<String> builder() 366 .add(configuration.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY)) 367 .add(configuration.getStringArray(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY)).build()); 368 } 369 370 /** 371 * Patterns of test exclusion as defined in project settings page. 372 * Also applies exclusions in general settings page and global exclusions. 373 * 374 * @since 3.3 375 */ 376 public String[] getTestExclusionPatterns() { 377 String[] globalTestExclusions = configuration.getStringArray(CoreProperties.GLOBAL_TEST_EXCLUSIONS_PROPERTY); 378 if (globalTestExclusions.length == 0) { 379 globalTestExclusions = new String[] {CoreProperties.GLOBAL_TEST_EXCLUSIONS_DEFAULT}; 380 } 381 382 return trimExclusions(ImmutableList.<String> builder() 383 .add(configuration.getStringArray(CoreProperties.PROJECT_TEST_EXCLUSIONS_PROPERTY)) 384 .add(globalTestExclusions).build()); 385 } 386 387 // http://jira.codehaus.org/browse/SONAR-2261 - exclusion must be trimmed 388 private static String[] trimExclusions(List<String> exclusions) { 389 List<String> trimmed = Lists.newArrayList(); 390 for (String exclusion : exclusions) { 391 trimmed.add(StringUtils.trim(exclusion)); 392 } 393 return trimmed.toArray(new String[trimmed.size()]); 394 } 395 396 /** 397 * Set exclusion patterns. Configuration is not saved, so this method must be used ONLY IN UNIT TESTS. 398 */ 399 public Project setExclusionPatterns(String[] s) { 400 configuration.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, StringUtils.join(s, ",")); 401 return this; 402 } 403 404 /** 405 * Note: it's better to get a reference on ProjectFileSystem as an IoC dependency (constructor parameter) 406 */ 407 public ProjectFileSystem getFileSystem() { 408 return fileSystem; 409 } 410 411 /** 412 * For internal use only. 413 * 414 * @deprecated since 2.6. See http://jira.codehaus.org/browse/SONAR-2126 415 */ 416 @Deprecated 417 public Project setFileSystem(ProjectFileSystem fs) { 418 this.fileSystem = fs; 419 return this; 420 } 421 422 /** 423 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 424 */ 425 @Deprecated 426 public String getGroupId() { 427 return pom.getGroupId(); 428 } 429 430 /** 431 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 432 */ 433 @Deprecated 434 public String getArtifactId() { 435 return pom.getArtifactId(); 436 } 437 438 /** 439 * @return the underlying Maven project 440 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 , 441 * MavenProject can be retrieved as an IoC dependency 442 */ 443 @Deprecated 444 public MavenProject getPom() { 445 return pom; 446 } 447 448 /** 449 * @return the project configuration 450 * @deprecated since 2.12. The component org.sonar.api.config.Settings must be used. 451 */ 452 @Deprecated 453 public Configuration getConfiguration() { 454 return configuration; 455 } 456 457 /** 458 * For internal use only. 459 */ 460 public final Project setConfiguration(Configuration configuration) { 461 this.configuration = configuration; 462 return this; 463 } 464 465 public Object getProperty(String key) { 466 return configuration != null ? configuration.getProperty(key) : null; 467 } 468 469 public static Project createFromMavenIds(String groupId, String artifactId) { 470 return new Project(String.format("%s:%s", groupId, artifactId)); 471 } 472 473 @Override 474 public String toString() { 475 return new ToStringBuilder(this) 476 .append("id", getId()) 477 .append("key", getKey()) 478 .append("qualifier", getQualifier()) 479 .toString(); 480 } 481}