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.batch;
021    
022    import com.google.common.collect.Lists;
023    import com.google.common.collect.Maps;
024    import org.apache.commons.lang.ObjectUtils;
025    import org.slf4j.LoggerFactory;
026    import org.sonar.api.batch.bootstrap.ProjectBuilder;
027    import org.sonar.api.batch.bootstrap.ProjectDefinition;
028    import org.sonar.api.batch.bootstrap.ProjectReactor;
029    import org.sonar.api.resources.Project;
030    import org.sonar.batch.bootstrap.ProjectFilter;
031    
032    import java.util.Iterator;
033    import java.util.List;
034    import java.util.Map;
035    
036    public 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    }