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