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