001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2011 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      public String getName() {
158        return name;
159      }
160    
161      public String getLongName() {
162        return name;
163      }
164    
165      public String getDescription() {
166        return description;
167      }
168    
169      /**
170       * For internal use only.
171       */
172      public Project setName(String name) {
173        this.name = name;
174        return this;
175      }
176    
177      /**
178       * For internal use only.
179       */
180      public Project setDescription(String description) {
181        this.description = description;
182        return this;
183      }
184    
185      /**
186       * For internal use only.
187       * 
188       * @deprecated in 2.8. See http://jira.codehaus.org/browse/SONAR-2341
189       */
190      @Deprecated
191      public Project setPackaging(String packaging) {
192        this.packaging = packaging;
193        return this;
194      }
195    
196      /**
197       * @return whether the current project is root project
198       */
199      public boolean isRoot() {
200        return getParent() == null;
201      }
202    
203      public Project getRoot() {
204        return (parent == null ? this : parent.getRoot());
205      }
206    
207      /**
208       * @return whether the current project is a module
209       */
210      public boolean isModule() {
211        return !isRoot();
212      }
213    
214      /**
215       * @return the type of analysis of the project
216       */
217      public AnalysisType getAnalysisType() {
218        return analysisType;
219      }
220    
221      public Project setAnalysisType(AnalysisType at) {
222        this.analysisType = at;
223        return this;
224      }
225    
226      /**
227       * whether it's the latest analysis done on this project (displayed in sonar dashboard) or an analysis on a past revision.
228       * 
229       * @since 2.0
230       */
231      public boolean isLatestAnalysis() {
232        return latestAnalysis;
233      }
234    
235      /**
236       * For internal use only.
237       */
238      public Project setLatestAnalysis(boolean b) {
239        this.latestAnalysis = b;
240        return this;
241      }
242    
243      /**
244       * @return the project language
245       */
246      public Language getLanguage() {
247        return language;
248      }
249    
250      public Project setLanguage(Language language) {
251        this.language = language;
252        return this;
253      }
254    
255      /**
256       * @return the language key
257       */
258      public String getLanguageKey() {
259        return languageKey;
260      }
261    
262      /**
263       * For internal use only.
264       */
265      public Project setLanguageKey(String languageKey) {
266        this.languageKey = languageKey;
267        return this;
268      }
269    
270      /**
271       * For internal use only.
272       */
273      public Project setAnalysisDate(Date analysisDate) {
274        this.analysisDate = analysisDate;
275        return this;
276      }
277    
278      /**
279       * For internal use only.
280       */
281      public Project setAnalysisVersion(String analysisVersion) {
282        this.analysisVersion = analysisVersion;
283        return this;
284      }
285    
286      /**
287       * @return the scope of the current object
288       */
289      public String getScope() {
290        return Scopes.PROJECT;
291      }
292    
293      /**
294       * @return the qualifier of the current object
295       */
296      public String getQualifier() {
297        return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE;
298      }
299    
300      @Override
301      public boolean matchFilePattern(String antPattern) {
302        return false;
303      }
304    
305      public Project getParent() {
306        return parent;
307      }
308    
309    
310    
311      /**
312       * For internal use only.
313       */
314      public Project setParent(Project parent) {
315        this.parent = parent;
316        if (parent != null) {
317          parent.modules.add(this);
318        }
319        return this;
320      }
321    
322      /**
323       * For internal use only.
324       */
325      public void removeFromParent() {
326        if (parent != null) {
327          parent.modules.remove(this);
328        }
329      }
330    
331      /**
332       * @return the list of modules
333       */
334      public List<Project> getModules() {
335        return modules;
336      }
337    
338      /**
339       * @return whether to use external source for rules configuration
340       * @deprecated since 2.5. See discussion from http://jira.codehaus.org/browse/SONAR-1873
341       */
342      @Deprecated
343      public boolean getReuseExistingRulesConfig() {
344        return (configuration != null && configuration.getBoolean(CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY, false));
345      }
346    
347      /**
348       * @return the current version of the project
349       */
350      public String getAnalysisVersion() {
351        return analysisVersion;
352      }
353    
354      /**
355       * @return the analysis date, i.e. the date that will be used to store the snapshot
356       */
357      public Date getAnalysisDate() {
358        return analysisDate;
359      }
360    
361      /**
362       * Patterns of resource exclusion as defined in project settings page.
363       */
364      public String[] getExclusionPatterns() {
365        String[] exclusions = configuration.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY);
366        for (int index=0 ; index<exclusions.length ; index++) {
367          // http://jira.codehaus.org/browse/SONAR-2261 - exclusion must be trimmed
368          exclusions[index]=StringUtils.trim(exclusions[index]);
369        }
370        return exclusions;
371      }
372    
373      /**
374       * Set exclusion patterns. Configuration is not saved, so this method must be used ONLY IN UNIT TESTS.
375       */
376      public Project setExclusionPatterns(String[] s) {
377        configuration.setProperty(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY, StringUtils.join(s, ","));
378        return this;
379      }
380    
381      /**
382       * Note: it's better to get a reference on ProjectFileSystem as an IoC dependency (constructor parameter)
383       */
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    }