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