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.batch;
021
022import com.google.common.collect.Lists;
023import com.google.common.collect.Maps;
024import org.apache.commons.lang.ObjectUtils;
025import org.slf4j.LoggerFactory;
026import org.sonar.api.batch.bootstrap.ProjectBuilder;
027import org.sonar.api.batch.bootstrap.ProjectDefinition;
028import org.sonar.api.batch.bootstrap.ProjectReactor;
029import org.sonar.api.resources.Project;
030import org.sonar.batch.bootstrap.ProjectFilter;
031
032import java.util.Iterator;
033import java.util.List;
034import java.util.Map;
035
036public class ProjectTree {
037
038  private final ProjectConfigurator configurator;
039  private ProjectReactor projectReactor;
040
041  private List<Project> projects;
042  private Map<ProjectDefinition, Project> projectsByDef;
043  private ProjectFilter projectFilter;
044
045  public ProjectTree(ProjectReactor projectReactor, // NOSONAR the unused parameter 'builders' is used for the startup order of components
046      ProjectConfigurator projectConfigurator,
047      ProjectFilter projectFilter,
048      /* Must be executed after ProjectBuilders */ProjectBuilder[] builders) {
049    this(projectReactor, projectConfigurator, projectFilter);
050  }
051
052  public ProjectTree(ProjectReactor projectReactor, // NOSONAR the unused parameter 'builders' is used for the startup order of components
053      ProjectConfigurator projectConfigurator,
054      ProjectFilter projectFilter) {
055    this.projectReactor = projectReactor;
056    this.configurator = projectConfigurator;
057    this.projectFilter = projectFilter;
058  }
059
060  ProjectTree(ProjectConfigurator configurator) {
061    this.configurator = configurator;
062  }
063
064  public void start() {
065    doStart(projectReactor.getProjects());
066  }
067
068  void doStart(List<ProjectDefinition> definitions) {
069    projects = Lists.newArrayList();
070    projectsByDef = Maps.newHashMap();
071
072    for (ProjectDefinition def : definitions) {
073      Project project = configurator.create(def);
074      projectsByDef.put(def, project);
075      projects.add(project);
076    }
077
078    for (Map.Entry<ProjectDefinition, Project> entry : projectsByDef.entrySet()) {
079      ProjectDefinition def = entry.getKey();
080      Project project = entry.getValue();
081      for (ProjectDefinition module : def.getSubProjects()) {
082        projectsByDef.get(module).setParent(project);
083      }
084    }
085
086    // Configure
087    for (Project project : projects) {
088      configurator.configure(project);
089    }
090
091    applyExclusions();
092  }
093
094  void applyExclusions() {
095    for (Iterator<Project> it = projects.iterator(); it.hasNext();) {
096      Project project = it.next();
097      if (projectFilter.isExcluded(project)) {
098        project.setExcluded(true);
099        LoggerFactory.getLogger(getClass()).info("Project {} excluded", project.getName());
100        project.removeFromParent();
101        it.remove();
102      }
103    }
104  }
105
106  public List<Project> getProjects() {
107    return projects;
108  }
109
110  public Project getRootProject() {
111    for (Project project : projects) {
112      if (project.getParent() == null) {
113        return project;
114      }
115    }
116    throw new IllegalStateException("Can not find the root project from the list of Maven modules");
117  }
118
119  public ProjectDefinition getProjectDefinition(Project project) {
120    for (Map.Entry<ProjectDefinition, Project> entry : projectsByDef.entrySet()) {
121      if (ObjectUtils.equals(entry.getValue(), project)) {
122        return entry.getKey();
123      }
124    }
125    throw new IllegalStateException("Can not find ProjectDefinition for " + project);
126  }
127}