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     */
020    package org.sonar.api.resources;
021    
022    import org.apache.commons.configuration.Configuration;
023    import org.apache.commons.lang.StringUtils;
024    import org.apache.commons.lang.builder.ToStringBuilder;
025    import org.apache.maven.project.MavenProject;
026    import org.sonar.api.CoreProperties;
027    
028    import java.util.ArrayList;
029    import java.util.Date;
030    import java.util.List;
031    
032    /**
033     * A class that manipulates Projects in the Sonar way.
034     * 
035     * @since 1.10
036     */
037    public 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    }