001 /*
002 * SonarQube, open source software quality management tool.
003 * Copyright (C) 2008-2013 SonarSource
004 * mailto:contact AT sonarsource DOT com
005 *
006 * SonarQube 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 * SonarQube 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 License
017 * along with this program; if not, write to the Free Software Foundation,
018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
019 */
020 package org.sonar.api.resources;
021
022 import com.google.common.collect.ImmutableList;
023 import com.google.common.collect.Lists;
024 import org.apache.commons.configuration.Configuration;
025 import org.apache.commons.lang.StringUtils;
026 import org.apache.commons.lang.builder.ToStringBuilder;
027 import org.apache.maven.project.MavenProject;
028 import org.sonar.api.CoreProperties;
029 import org.sonar.api.component.Component;
030
031 import java.util.ArrayList;
032 import java.util.Date;
033 import java.util.List;
034
035 /**
036 * A class that manipulates Projects in the Sonar way.
037 *
038 * @since 1.10
039 */
040 public class Project extends Resource implements Component {
041
042 public static final String SCOPE = Scopes.PROJECT;
043
044 /**
045 * @deprecated since version 1.11. Constant moved to CoreProperties
046 */
047 @Deprecated
048 public static final String PARAM_REUSE_RULES_CONFIG = CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY;
049
050 /**
051 * Enumerates the type of possible analysis
052 */
053 public enum AnalysisType {
054 STATIC, DYNAMIC, REUSE_REPORTS;
055
056 /**
057 * @param includeReuseReportMode whether to count report reuse as dynamic or not
058 * @return whether this a dynamic analysis
059 */
060 public boolean isDynamic(boolean includeReuseReportMode) {
061 return equals(Project.AnalysisType.DYNAMIC) ||
062 (equals(Project.AnalysisType.REUSE_REPORTS) && includeReuseReportMode);
063 }
064 }
065
066 private MavenProject pom;
067 private String branch;
068 private ProjectFileSystem fileSystem;
069 private Configuration configuration;
070 private String name;
071 private String description;
072 private String packaging;
073 private Language language;
074 private Date analysisDate;
075 private AnalysisType analysisType;
076 private String analysisVersion;
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 * @deprecated in 3.6. The analysis is now always the latest one (past analysis must be done in a chronological order). See http://jira.codehaus.org/browse/SONAR-4334
205 */
206 @Deprecated
207 public boolean isLatestAnalysis() {
208 return true;
209 }
210
211 /**
212 * For internal use only.
213 *
214 * @deprecated in 3.6. It's not possible to analyze a project before the latest known quality snapshot.
215 * See http://jira.codehaus.org/browse/SONAR-4334
216 */
217 @Deprecated
218 public Project setLatestAnalysis(boolean b) {
219 if (!b) {
220 throw new UnsupportedOperationException("The analysis is always the latest one. " +
221 "Past analysis must be done in a chronological order.");
222 }
223 return this;
224 }
225
226 /**
227 * @return the project language
228 */
229 @Override
230 public Language getLanguage() {
231 return language;
232 }
233
234 public Project setLanguage(Language language) {
235 this.language = language;
236 return this;
237 }
238
239 /**
240 * @return the language key
241 */
242 public String getLanguageKey() {
243 return configuration.getString("sonar.language", Java.KEY);
244 }
245
246 /**
247 * For internal use only.
248 */
249 public Project setAnalysisDate(Date analysisDate) {
250 this.analysisDate = analysisDate;
251 return this;
252 }
253
254 /**
255 * For internal use only.
256 */
257 public Project setAnalysisVersion(String analysisVersion) {
258 this.analysisVersion = analysisVersion;
259 return this;
260 }
261
262 /**
263 * @return the scope of the current object
264 */
265 @Override
266 public String getScope() {
267 return Scopes.PROJECT;
268 }
269
270 /**
271 * @return the qualifier of the current object
272 */
273 @Override
274 public String getQualifier() {
275 return isRoot() ? Qualifiers.PROJECT : Qualifiers.MODULE;
276 }
277
278 @Override
279 public boolean matchFilePattern(String antPattern) {
280 return false;
281 }
282
283 @Override
284 public Project getParent() {
285 return parent;
286 }
287
288 /**
289 * For internal use only.
290 */
291 public Project setParent(Project parent) {
292 this.parent = parent;
293 if (parent != null) {
294 parent.modules.add(this);
295 }
296 return this;
297 }
298
299 /**
300 * For internal use only.
301 */
302 public void removeFromParent() {
303 if (parent != null) {
304 parent.modules.remove(this);
305 }
306 }
307
308 /**
309 * @return the list of modules
310 */
311 public List<Project> getModules() {
312 return modules;
313 }
314
315 /**
316 * @return whether to use external source for rules configuration
317 * @deprecated since 2.5. See discussion from http://jira.codehaus.org/browse/SONAR-1873
318 */
319 @Deprecated
320 public boolean getReuseExistingRulesConfig() {
321 return (configuration != null && configuration.getBoolean(CoreProperties.REUSE_RULES_CONFIGURATION_PROPERTY, false));
322 }
323
324 /**
325 * @return the current version of the project
326 */
327 public String getAnalysisVersion() {
328 return analysisVersion;
329 }
330
331 /**
332 * @return the analysis date, i.e. the date that will be used to store the snapshot
333 */
334 public Date getAnalysisDate() {
335 return analysisDate;
336 }
337
338 /**
339 * Patterns of resource exclusion as defined in project settings page.
340 *
341 * @since 3.3 also applies exclusions in general settings page and global exclusions.
342 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5
343 */
344 @Deprecated
345 public String[] getExclusionPatterns() {
346 return trimExclusions(ImmutableList.<String> builder()
347 .add(configuration.getStringArray(CoreProperties.PROJECT_EXCLUSIONS_PROPERTY))
348 .add(configuration.getStringArray(CoreProperties.GLOBAL_EXCLUSIONS_PROPERTY)).build());
349 }
350
351 /**
352 * Patterns of test exclusion as defined in project settings page.
353 * Also applies exclusions in general settings page and global exclusions.
354 *
355 * @since 3.3
356 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5
357 */
358 @Deprecated
359 public String[] getTestExclusionPatterns() {
360 String[] globalTestExclusions = configuration.getStringArray(CoreProperties.GLOBAL_TEST_EXCLUSIONS_PROPERTY);
361 if (globalTestExclusions.length == 0) {
362 globalTestExclusions = new String[] {CoreProperties.GLOBAL_TEST_EXCLUSIONS_DEFAULT};
363 }
364
365 return trimExclusions(ImmutableList.<String> builder()
366 .add(configuration.getStringArray(CoreProperties.PROJECT_TEST_EXCLUSIONS_PROPERTY))
367 .add(globalTestExclusions).build());
368 }
369
370 // http://jira.codehaus.org/browse/SONAR-2261 - exclusion must be trimmed
371 private static String[] trimExclusions(List<String> exclusions) {
372 List<String> trimmed = Lists.newArrayList();
373 for (String exclusion : exclusions) {
374 trimmed.add(StringUtils.trim(exclusion));
375 }
376 return trimmed.toArray(new String[trimmed.size()]);
377 }
378
379 /**
380 * Set exclusion patterns. Configuration is not saved, so this method must be used ONLY IN UNIT TESTS.
381 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.FileExclusions} in version 3.5
382 */
383 @Deprecated
384 public Project setExclusionPatterns(String[] s) {
385 throw new UnsupportedOperationException("deprecated in 3.5");
386 }
387
388 /**
389 * Note: it's better to get a reference on ProjectFileSystem as an IoC dependency (constructor parameter)
390 * @deprecated replaced by {@link org.sonar.api.scan.filesystem.ModuleFileSystem} in 3.5
391 */
392 @Deprecated
393 public ProjectFileSystem getFileSystem() {
394 return fileSystem;
395 }
396
397 /**
398 * For internal use only.
399 *
400 * @deprecated since 2.6. See http://jira.codehaus.org/browse/SONAR-2126
401 */
402 @Deprecated
403 public Project setFileSystem(ProjectFileSystem fs) {
404 this.fileSystem = fs;
405 return this;
406 }
407
408 /**
409 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011
410 */
411 @Deprecated
412 public String getGroupId() {
413 return pom.getGroupId();
414 }
415
416 /**
417 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011
418 */
419 @Deprecated
420 public String getArtifactId() {
421 return pom.getArtifactId();
422 }
423
424 /**
425 * @return the underlying Maven project
426 * @deprecated since 2.5. See http://jira.codehaus.org/browse/SONAR-2011 ,
427 * MavenProject can be retrieved as an IoC dependency
428 */
429 @Deprecated
430 public MavenProject getPom() {
431 return pom;
432 }
433
434 /**
435 * @return the project configuration
436 * @deprecated since 2.12. The component org.sonar.api.config.Settings must be used.
437 */
438 @Deprecated
439 public Configuration getConfiguration() {
440 return configuration;
441 }
442
443 /**
444 * For internal use only.
445 */
446 public final Project setConfiguration(Configuration configuration) {
447 this.configuration = configuration;
448 return this;
449 }
450
451 /**
452 * @deprecated since 3.6. Replaced by {@link org.sonar.api.config.Settings}.
453 */
454 @Deprecated
455 public Object getProperty(String key) {
456 return configuration != null ? configuration.getProperty(key) : null;
457 }
458
459 public static Project createFromMavenIds(String groupId, String artifactId) {
460 return new Project(String.format("%s:%s", groupId, artifactId));
461 }
462
463 @Override
464 public String toString() {
465 return new ToStringBuilder(this)
466 .append("id", getId())
467 .append("key", getKey())
468 .append("qualifier", getQualifier())
469 .toString();
470 }
471
472 @Override
473 public String key() {
474 return getKey();
475 }
476
477 @Override
478 public String name() {
479 return getName();
480 }
481
482 @Override
483 public String longName() {
484 return getLongName();
485 }
486
487 @Override
488 public String qualifier() {
489 return getQualifier();
490 }
491 }