]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2967 extract the new component ProjectFilter from ProjectTree
authorsimonbrandhof <simon.brandhof@gmail.com>
Fri, 4 Nov 2011 09:16:50 +0000 (10:16 +0100)
committersimonbrandhof <simon.brandhof@gmail.com>
Fri, 4 Nov 2011 09:17:18 +0000 (10:17 +0100)
sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectFilter.java [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java
sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectFilterTest.java [new file with mode: 0644]
sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java [new file with mode: 0644]

index 06ec2bd23fde90470200bc5a79f614202e8e84c3..34916a1e38a32fdc4e97e4a6df62698be0daf236 100644 (file)
@@ -21,18 +21,18 @@ package org.sonar.batch;
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
 import org.apache.commons.lang.ObjectUtils;
-import org.apache.commons.lang.StringUtils;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.batch.bootstrap.ProjectBuilder;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Project;
+import org.sonar.batch.bootstrap.ProjectFilter;
 
 import java.io.IOException;
-import java.util.*;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 public class ProjectTree {
 
@@ -41,21 +41,21 @@ public class ProjectTree {
 
   private List<Project> projects;
   private Map<ProjectDefinition, Project> projectsByDef;
-  private Settings settings;
+  private ProjectFilter projectFilter;
 
   public ProjectTree(ProjectReactor projectReactor, //NOSONAR the unused parameter 'builders' is used for the startup order of components
                      ProjectConfigurator projectConfigurator,
-                     Settings settings,
+                     ProjectFilter projectFilter,
                      /* Must be executed after ProjectBuilders */ ProjectBuilder[] builders) {
-    this(projectReactor, projectConfigurator, settings);
+    this(projectReactor, projectConfigurator, projectFilter);
   }
 
   public ProjectTree(ProjectReactor projectReactor, //NOSONAR the unused parameter 'builders' is used for the startup order of components
                      ProjectConfigurator projectConfigurator,
-                     Settings settings) {
+                     ProjectFilter projectFilter) {
     this.projectReactor = projectReactor;
     this.configurator = projectConfigurator;
-    this.settings = settings;
+    this.projectFilter = projectFilter;
   }
 
   ProjectTree(ProjectConfigurator configurator) {
@@ -93,78 +93,21 @@ public class ProjectTree {
   }
 
   void applyExclusions() {
-    for (Project project : projects) {
-      String[] excludedArtifactIds = settings.getStringArray("sonar.skippedModules");
-      String[] includedArtifactIds = settings.getStringArray("sonar.includedModules");
-
-      Set<String> includedModulesIdSet = Sets.newHashSet();
-      Set<String> excludedModulesIdSet = Sets.newHashSet();
-
-      if (includedArtifactIds != null) {
-        includedModulesIdSet.addAll(Arrays.asList(includedArtifactIds));
-      }
-
-      if (excludedArtifactIds != null) {
-        excludedModulesIdSet.addAll(Arrays.asList(excludedArtifactIds));
-        includedModulesIdSet.removeAll(excludedModulesIdSet);
-      }
-
-      if (!includedModulesIdSet.isEmpty()) {
-        for (Project currentProject : projects) {
-          if (!includedModulesIdSet.contains(getArtifactId(currentProject))) {
-            exclude(currentProject);
-          }
-        }
-      } else {
-        for (String excludedArtifactId : excludedModulesIdSet) {
-          Project excludedProject = getProjectByArtifactId(excludedArtifactId);
-          exclude(excludedProject);
-        }
-      }
-    }
-
     for (Iterator<Project> it = projects.iterator(); it.hasNext(); ) {
       Project project = it.next();
-      if (project.isExcluded()) {
-        LoggerFactory.getLogger(getClass()).info("Module {} is excluded from analysis", project.getName());
+      if (projectFilter.isExcluded(project)) {
+        project.setExcluded(true);
+        LoggerFactory.getLogger(getClass()).info("Project {} excluded", project.getName());
         project.removeFromParent();
         it.remove();
       }
     }
   }
 
-  private void exclude(Project project) {
-    if (project != null) {
-      project.setExcluded(true);
-      for (Project module : project.getModules()) {
-        exclude(module);
-      }
-    }
-  }
-
   public List<Project> getProjects() {
     return projects;
   }
 
-  private String getArtifactId(Project project) {
-    String key = project.getKey();
-    if (StringUtils.isNotBlank(project.getBranch())) {
-      // remove branch part
-      key = StringUtils.removeEnd(project.getKey(), ":" + project.getBranch());
-    }
-    return StringUtils.substringAfterLast(key, ":");
-  }
-
-  public Project getProjectByArtifactId(String artifactId) {
-    for (Project project : projects) {
-      // TODO see http://jira.codehaus.org/browse/SONAR-2324
-      if (StringUtils.equals(getArtifactId(project), artifactId)) {
-        return project;
-      }
-    }
-    return null;
-  }
-
   public Project getRootProject() {
     for (Project project : projects) {
       if (project.getParent() == null) {
index 822d6ca7a8d94ced466c5069b358e44a55648f55..0dbe5c95b97669c9846ddf09e8cac2157702b83e 100644 (file)
@@ -49,6 +49,7 @@ public class BatchModule extends Module {
   @Override
   protected void configure() {
     addCoreSingleton(ProjectTree.class);
+    addCoreSingleton(ProjectFilter.class);
     addCoreSingleton(ProjectConfigurator.class);
     addCoreSingleton(DefaultResourceCreationLock.class);
     addCoreSingleton(DefaultIndex.class);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectFilter.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectFilter.java
new file mode 100644 (file)
index 0000000..5ecf660
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Project;
+
+/**
+ * Filter projects to analyze by using the properties sonar.skippedModules and sonar.includedModules
+ *
+ * @since 2.12
+ */
+public class ProjectFilter {
+
+  private Settings settings;
+
+  public ProjectFilter(Settings settings) {
+    this.settings = settings;
+  }
+
+  public boolean isExcluded(Project project) {
+    Project p = project;
+    while (p != null) {
+      if (isExcluded(getArtifactId(p))) {
+        return true;
+      }
+      p = p.getParent();
+    }
+    return false;
+  }
+
+  private boolean isExcluded(String artifactId) {
+    String[] includedArtifactIds = settings.getStringArray("sonar.includedModules");
+
+    if (includedArtifactIds.length > 0) {
+      return !ArrayUtils.contains(includedArtifactIds, artifactId);
+    }
+    String[] excludedArtifactIds = settings.getStringArray("sonar.skippedModules");
+    return ArrayUtils.contains(excludedArtifactIds, artifactId);
+  }
+
+  // TODO see http://jira.codehaus.org/browse/SONAR-2324
+  static String getArtifactId(Project project) {
+    String key = project.getKey();
+    if (StringUtils.isNotBlank(project.getBranch())) {
+      // remove branch part
+      key = StringUtils.removeEnd(project.getKey(), ":" + project.getBranch());
+    }
+    if (key.contains(":")) {
+      return StringUtils.substringAfter(key, ":");
+    }
+    return key;
+  }
+}
index b8fc2a60b84c83665fe023ef8c910b5a616331d6..7a7fb5a1886449c33560898c2da9b1bd49eab45c 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.batch.config;
 
+import com.google.common.collect.Lists;
 import org.apache.commons.configuration.Configuration;
 import org.sonar.api.batch.bootstrap.ProjectDefinition;
 import org.sonar.api.config.PropertyDefinitions;
@@ -49,11 +50,11 @@ public class ProjectSettings extends Settings {
 
   public ProjectSettings load() {
     clear();
-    
+
     // order is important -> bottom-up. The last one overrides all the others.
     loadDatabaseGlobalSettings();
     loadDatabaseProjectSettings(projectDefinition);
-    addProperties(projectDefinition.getProperties());
+    loadBuildProperties();
     addEnvironmentVariables();
     addSystemProperties();
 
@@ -62,6 +63,13 @@ public class ProjectSettings extends Settings {
     return this;
   }
 
+  private void loadBuildProperties() {
+    List<ProjectDefinition> orderedProjects = getOrderedProjects(projectDefinition);
+    for (ProjectDefinition p : orderedProjects) {
+      addProperties(p.getProperties());
+    }
+  }
+
   private void loadDatabaseProjectSettings(ProjectDefinition projectDef) {
     if (projectDef.getParent() != null) {
       loadDatabaseProjectSettings(projectDef.getParent());
@@ -83,4 +91,16 @@ public class ProjectSettings extends Settings {
     ConfigurationUtils.copyToCommonsConfiguration(properties, deprecatedCommonsConf);
   }
 
+  /**
+   * From root to module
+   */
+  static List<ProjectDefinition> getOrderedProjects(ProjectDefinition project) {
+    List<ProjectDefinition> result = Lists.newArrayList();
+    ProjectDefinition pd = project;
+    while (pd != null) {
+      result.add(0, pd);
+      pd = pd.getParent();
+    }
+    return result;
+  }
 }
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectFilterTest.java
new file mode 100644 (file)
index 0000000..d01f515
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.bootstrap;
+
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Project;
+import org.sonar.batch.config.ProjectSettings;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+public class ProjectFilterTest {
+
+  @Test
+  public void testSkippedModule() {
+    Settings settings = new Settings();
+    settings.setProperty("sonar.skippedModules", "foo,bar");
+
+    ProjectFilter filter = new ProjectFilter(settings);
+    assertTrue(filter.isExcluded(new Project("my:foo")));
+  }
+
+  @Test
+  public void testNotExcluded() {
+    Settings settings = new Settings();
+    settings.setProperty("sonar.skippedModules", "foo,bar");
+
+    ProjectFilter filter = new ProjectFilter(settings);
+    assertFalse(filter.isExcluded(new Project("my:other")));
+  }
+
+  @Test
+  public void testNoSkippedModules() {
+    Settings settings = new Settings();
+
+    ProjectFilter filter = new ProjectFilter(settings);
+    assertFalse(filter.isExcluded(new Project("my:other")));
+  }
+
+  @Test
+  public void testIncludedModules() {
+    Settings settings = new Settings();
+    settings.setProperty("sonar.includedModules", "foo");
+
+    ProjectFilter filter = new ProjectFilter(settings);
+    assertFalse(filter.isExcluded(new Project("my:foo")));
+
+    filter = new ProjectFilter(settings);
+    assertTrue(filter.isExcluded(new Project("my:bar")));
+  }
+
+  @Test
+  public void shouldBeExcludedIfParentIsExcluded() {
+    Settings settings = new Settings();
+    settings.setProperty("sonar.skippedModules", "parent");
+
+    Project parent = new Project("my:parent");
+    Project child = new Project("my:child");
+    child.setParent(parent);
+
+    ProjectFilter filter = new ProjectFilter(settings);
+    assertTrue(filter.isExcluded(child));
+  }
+
+  @Test
+  public void testGetArtifactId() {
+    assertThat(ProjectFilter.getArtifactId(new Project("org:foo")), is("foo"));
+    assertThat(ProjectFilter.getArtifactId(new Project("foo")), is("foo"));
+    assertThat(ProjectFilter.getArtifactId(new Project("org:foo:1.x").setBranch("1.x")), is("foo"));
+  }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java
new file mode 100644 (file)
index 0000000..0cd4f31
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+ */
+package org.sonar.batch.config;
+
+import org.hamcrest.core.Is;
+import org.junit.Test;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+
+public class ProjectSettingsTest {
+
+  @Test
+  public void testOrderedProjects() {
+    ProjectDefinition grandParent = ProjectDefinition.create();
+    ProjectDefinition parent = ProjectDefinition.create();
+    ProjectDefinition child = ProjectDefinition.create();
+    grandParent.addSubProject(parent);
+    parent.addSubProject(child);
+
+    List<ProjectDefinition> hierarchy = ProjectSettings.getOrderedProjects(child);
+    assertThat(hierarchy.get(0), Is.is(grandParent));
+    assertThat(hierarchy.get(1), Is.is(parent));
+    assertThat(hierarchy.get(2), Is.is(child));
+
+  }
+}