]> source.dussan.org Git - sonarqube.git/commitdiff
Merge remote-tracking branch 'origin/branch-4.5'
authorJulien HENRY <julien.henry@sonarsource.com>
Wed, 8 Oct 2014 15:10:38 +0000 (17:10 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Wed, 8 Oct 2014 15:10:38 +0000 (17:10 +0200)
1  2 
sonar-batch/src/main/java/org/sonar/batch/design/MavenDependenciesSensor.java
sonar-batch/src/main/java/org/sonar/batch/referential/DefaultProjectReferentialsLoader.java
sonar-core/src/main/resources/org/sonar/l10n/core.properties
sonar-plugin-api/src/main/java/org/sonar/api/resources/Project.java

index 0f2e7157b22d6c2130b0574f0767a1b614d92eb4,0000000000000000000000000000000000000000..67f92b40e5594198e63d07860fdef963e1388f66
mode 100644,000000..100644
--- /dev/null
@@@ -1,265 -1,0 +1,265 @@@
-             saveDependency(node, context);
 +/*
 + * SonarQube, open source software quality management tool.
 + * Copyright (C) 2008-2014 SonarSource
 + * mailto:contact AT sonarsource DOT com
 + *
 + * SonarQube 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.
 + *
 + * SonarQube 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 this program; if not, write to the Free Software Foundation,
 + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 + */
 +package org.sonar.batch.design;
 +
 +import com.google.gson.Gson;
 +import com.google.gson.GsonBuilder;
 +import com.google.gson.JsonArray;
 +import com.google.gson.JsonDeserializationContext;
 +import com.google.gson.JsonDeserializer;
 +import com.google.gson.JsonElement;
 +import com.google.gson.JsonObject;
 +import com.google.gson.reflect.TypeToken;
 +import org.apache.maven.artifact.Artifact;
 +import org.apache.maven.artifact.factory.ArtifactFactory;
 +import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 +import org.apache.maven.artifact.repository.ArtifactRepository;
 +import org.apache.maven.artifact.resolver.ArtifactCollector;
 +import org.apache.maven.shared.dependency.tree.DependencyNode;
 +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
 +import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
 +import org.apache.maven.shared.dependency.tree.filter.AncestorOrSelfDependencyNodeFilter;
 +import org.apache.maven.shared.dependency.tree.filter.DependencyNodeFilter;
 +import org.apache.maven.shared.dependency.tree.filter.StateDependencyNodeFilter;
 +import org.apache.maven.shared.dependency.tree.traversal.BuildingDependencyNodeVisitor;
 +import org.apache.maven.shared.dependency.tree.traversal.CollectingDependencyNodeVisitor;
 +import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor;
 +import org.apache.maven.shared.dependency.tree.traversal.FilteringDependencyNodeVisitor;
 +import org.slf4j.Logger;
 +import org.slf4j.LoggerFactory;
 +import org.sonar.api.batch.Sensor;
 +import org.sonar.api.batch.SensorContext;
 +import org.sonar.api.batch.SonarIndex;
 +import org.sonar.api.batch.SupportedEnvironment;
 +import org.sonar.api.config.Settings;
 +import org.sonar.api.design.Dependency;
 +import org.sonar.api.resources.Library;
 +import org.sonar.api.resources.Project;
 +import org.sonar.api.resources.Resource;
 +import org.sonar.api.utils.SonarException;
 +
 +import java.lang.reflect.Type;
 +import java.util.ArrayList;
 +import java.util.Collection;
 +import java.util.List;
 +
 +@SupportedEnvironment("maven")
 +public class MavenDependenciesSensor implements Sensor {
 +
 +  private static final String SONAR_MAVEN_PROJECT_DEPENDENCY = "sonar.maven.projectDependencies";
 +
 +  private static final Logger LOG = LoggerFactory.getLogger(MavenDependenciesSensor.class);
 +
 +  private ArtifactRepository localRepository;
 +  private ArtifactFactory artifactFactory;
 +  private ArtifactMetadataSource artifactMetadataSource;
 +  private ArtifactCollector artifactCollector;
 +  private DependencyTreeBuilder treeBuilder;
 +  private SonarIndex index;
 +  private Settings settings;
 +
 +  public MavenDependenciesSensor(Settings settings, ArtifactRepository localRepository, ArtifactFactory artifactFactory, ArtifactMetadataSource artifactMetadataSource,
 +    ArtifactCollector artifactCollector, DependencyTreeBuilder treeBuilder, SonarIndex index) {
 +    this.settings = settings;
 +    this.localRepository = localRepository;
 +    this.artifactFactory = artifactFactory;
 +    this.artifactMetadataSource = artifactMetadataSource;
 +    this.artifactCollector = artifactCollector;
 +    this.index = index;
 +    this.treeBuilder = treeBuilder;
 +  }
 +
 +  /**
 +   * Used with SQ Maven plugin 2.5+
 +   */
 +  public MavenDependenciesSensor(Settings settings, SonarIndex index) {
 +    this.settings = settings;
 +    this.index = index;
 +  }
 +
 +  public boolean shouldExecuteOnProject(Project project) {
 +    return true;
 +  }
 +
 +  private static class InputDependency {
 +
 +    private final String key;
 +
 +    private final String version;
 +
 +    private String scope;
 +
 +    List<InputDependency> dependencies = new ArrayList<InputDependency>();
 +
 +    public InputDependency(String key, String version) {
 +      this.key = key;
 +      this.version = version;
 +    }
 +
 +    public String key() {
 +      return key;
 +    }
 +
 +    public String version() {
 +      return version;
 +    }
 +
 +    public String scope() {
 +      return scope;
 +    }
 +
 +    public InputDependency setScope(String scope) {
 +      this.scope = scope;
 +      return this;
 +    }
 +
 +    public List<InputDependency> dependencies() {
 +      return dependencies;
 +    }
 +  }
 +
 +  private static class DependencyDeserializer implements JsonDeserializer<InputDependency> {
 +
 +    @Override
 +    public InputDependency deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
 +
 +      JsonObject dep = json.getAsJsonObject();
 +      String key = dep.get("k").getAsString();
 +      String version = dep.get("v").getAsString();
 +      InputDependency result = new InputDependency(key, version);
 +      result.setScope(dep.get("s").getAsString());
 +      JsonElement subDeps = dep.get("d");
 +      if (subDeps != null) {
 +        JsonArray arrayOfSubDeps = subDeps.getAsJsonArray();
 +        for (JsonElement e : arrayOfSubDeps) {
 +          result.dependencies().add(deserialize(e, typeOfT, context));
 +        }
 +      }
 +      return result;
 +    }
 +
 +  }
 +
 +  public void analyse(final Project project, final SensorContext context) {
 +    if (settings.hasKey(SONAR_MAVEN_PROJECT_DEPENDENCY)) {
 +      LOG.debug("Using dependency provided by property " + SONAR_MAVEN_PROJECT_DEPENDENCY);
 +      String depsAsJson = settings.getString(SONAR_MAVEN_PROJECT_DEPENDENCY);
 +      Collection<InputDependency> deps;
 +      try {
 +        GsonBuilder gsonBuilder = new GsonBuilder();
 +        gsonBuilder.registerTypeAdapter(InputDependency.class, new DependencyDeserializer());
 +        Gson gson = gsonBuilder.create();
 +
 +        Type collectionType = new TypeToken<Collection<InputDependency>>() {
 +        }.getType();
 +        deps = gson.fromJson(depsAsJson, collectionType);
 +        saveDependencies(project, deps, context);
 +      } catch (Exception e) {
 +        throw new IllegalStateException("Unable to deserialize dependency information: " + depsAsJson, e);
 +      }
 +    } else if (treeBuilder != null) {
 +      computeDependencyTree(project, context);
 +    }
 +  }
 +
 +  private void computeDependencyTree(final Project project, final SensorContext context) {
 +    LOG.warn("Computation of Maven dependencies by SonarQube is deprecated. Please update the version of SonarQube Maven plugin to 2.5+");
 +    try {
 +      DependencyNode root = treeBuilder.buildDependencyTree(project.getPom(), localRepository, artifactFactory, artifactMetadataSource, null, artifactCollector);
 +
 +      DependencyNodeVisitor visitor = new BuildingDependencyNodeVisitor(new DependencyNodeVisitor() {
 +        public boolean visit(DependencyNode node) {
 +          return true;
 +        }
 +
 +        public boolean endVisit(DependencyNode node) {
 +          if (node.getParent() != null && node.getParent() != node) {
-   protected void saveDependency(DependencyNode node, SensorContext context) {
-     Resource from = (node.getParent().getParent() == null) ? index.getProject() : toResource(node.getParent().getArtifact(), context);
-     Resource to = toResource(node.getArtifact(), context);
++            saveDependency(project, node, context);
 +          }
 +          return true;
 +        }
 +      });
 +
 +      // mode verbose OFF : do not show the same lib many times
 +      DependencyNodeFilter filter = StateDependencyNodeFilter.INCLUDED;
 +
 +      CollectingDependencyNodeVisitor collectingVisitor = new CollectingDependencyNodeVisitor();
 +      DependencyNodeVisitor firstPassVisitor = new FilteringDependencyNodeVisitor(collectingVisitor, filter);
 +      root.accept(firstPassVisitor);
 +
 +      DependencyNodeFilter secondPassFilter = new AncestorOrSelfDependencyNodeFilter(collectingVisitor.getNodes());
 +      visitor = new FilteringDependencyNodeVisitor(visitor, secondPassFilter);
 +
 +      root.accept(visitor);
 +
 +    } catch (DependencyTreeBuilderException e) {
 +      throw new SonarException("Can not load the graph of dependencies of the project " + project.getKey(), e);
 +    }
 +  }
 +
 +  private void saveDependencies(Resource from, Collection<InputDependency> deps, SensorContext context) {
 +    for (InputDependency inputDep : deps) {
 +      Resource to = toResource(inputDep, context);
 +      Dependency dependency = new Dependency(from, to);
 +      dependency.setUsage(inputDep.scope());
 +      dependency.setWeight(1);
 +      context.saveDependency(dependency);
 +      if (!inputDep.dependencies().isEmpty()) {
 +        saveDependencies(to, inputDep.dependencies(), context);
 +      }
 +    }
 +  }
 +
 +  private Resource toResource(InputDependency dependency, SensorContext context) {
 +    Project project = new Project(dependency.key());
 +    Resource result = context.getResource(project);
 +    if (result == null || !((Project) result).getAnalysisVersion().equals(dependency.version())) {
 +      Library lib = new Library(project.getKey(), dependency.version());
 +      context.saveResource(lib);
 +      result = context.getResource(lib);
 +    }
 +    return result;
 +  }
 +
-   protected static Resource toResource(Artifact artifact, SensorContext context) {
-     Project project = Project.createFromMavenIds(artifact.getGroupId(), artifact.getArtifactId());
-     Resource result = context.getResource(project);
++  protected void saveDependency(final Project project, DependencyNode node, SensorContext context) {
++    Resource from = (node.getParent().getParent() == null) ? index.getProject() : toResource(project, node.getParent().getArtifact(), context);
++    Resource to = toResource(project, node.getArtifact(), context);
 +    Dependency dependency = new Dependency(from, to);
 +    dependency.setUsage(node.getArtifact().getScope());
 +    dependency.setWeight(1);
 +    context.saveDependency(dependency);
 +  }
 +
-       Library lib = new Library(project.getKey(), artifact.getBaseVersion());
++  protected static Resource toResource(final Project project, Artifact artifact, SensorContext context) {
++    Project depWithBranch = Project.createFromMavenIds(artifact.getGroupId(), artifact.getArtifactId(), project.getBranch());
++    Resource result = context.getResource(depWithBranch);
 +    if (result == null || !((Project) result).getAnalysisVersion().equals(artifact.getBaseVersion())) {
++      Library lib = Library.createFromMavenIds(artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion());
 +      context.saveResource(lib);
 +      result = context.getResource(lib);
 +    }
 +    return result;
 +  }
 +
 +  @Override
 +  public String toString() {
 +    return "Maven dependencies";
 +  }
 +}
index eeb1853de7702f52221b7f4ec644e48f09bdd957,8340c63a6813b24003144be9ad72826340aff096..b86dd4e1cf7f91f8b8e5efdeb31001785e2246da
   */
  package org.sonar.batch.referential;
  
 +import com.google.common.collect.Maps;
+ import org.slf4j.Logger;
+ import org.slf4j.LoggerFactory;
 +import org.sonar.api.batch.bootstrap.ProjectDefinition;
  import org.sonar.api.batch.bootstrap.ProjectReactor;
 +import org.sonar.api.database.DatabaseSession;
 +import org.sonar.api.database.model.MeasureModel;
 +import org.sonar.api.database.model.ResourceModel;
 +import org.sonar.api.database.model.Snapshot;
 +import org.sonar.api.measures.CoreMetrics;
 +import org.sonar.api.measures.Metric;
 +import org.sonar.api.resources.Qualifiers;
 +import org.sonar.api.utils.KeyValueFormat;
  import org.sonar.batch.bootstrap.AnalysisMode;
  import org.sonar.batch.bootstrap.ServerClient;
  import org.sonar.batch.bootstrap.TaskProperties;
@@@ -68,9 -47,10 +72,11 @@@ public class DefaultProjectReferentials
  
    @Override
    public ProjectReferentials load(ProjectReactor reactor, TaskProperties taskProperties) {
 -    String url = BATCH_PROJECT_URL + "?key=" + reactor.getRoot().getKeyWithBranch();
 +    String projectKey = reactor.getRoot().getKeyWithBranch();
 +    String url = BATCH_PROJECT_URL + "?key=" + projectKey;
      if (taskProperties.properties().containsKey(ModuleQProfiles.SONAR_PROFILE_PROP)) {
+       LOG.warn("Ability to set quality profile from command line using '" + ModuleQProfiles.SONAR_PROFILE_PROP
+         + "' is deprecated and will be dropped in a future SonarQube version. Please configure quality profile used by your project on SonarQube server.");
        try {
          url += "&profile=" + URLEncoder.encode(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP), "UTF-8");
        } catch (UnsupportedEncodingException e) {
index 65f6dc39d45e02d5c42999f27601f4eb54a86c07,64be7f80a54d25a7aef618703ad9108fb4a16035..bc866693f9b83a62e8fe12c160856bdc28b1d10f
@@@ -24,8 -27,9 +24,10 @@@ import org.apache.commons.lang.builder.
  import org.apache.maven.project.MavenProject;
  import org.sonar.api.CoreProperties;
  import org.sonar.api.component.Component;
 +import org.sonar.api.config.Settings;
  
+ import javax.annotation.Nullable;
  import java.util.ArrayList;
  import java.util.Date;
  import java.util.List;
@@@ -413,8 -457,37 +415,12 @@@ public class Project extends Resource i
      return pom;
    }
  
 -  /**
 -   * @return the project configuration
 -   * @deprecated since 2.12. The component org.sonar.api.config.Settings must be used.
 -   */
 -  @Deprecated
 -  public Configuration getConfiguration() {
 -    return configuration;
 -  }
 -
 -  /**
 -   * For internal use only.
 -   */
 -  public final Project setConfiguration(Configuration configuration) {
 -    this.configuration = configuration;
 -    return this;
 -  }
 -
 -  /**
 -   * @deprecated since 3.6. Replaced by {@link org.sonar.api.config.Settings}.
 -   */
 -  @Deprecated
 -  public Object getProperty(String key) {
 -    return configuration != null ? configuration.getProperty(key) : null;
 -  }
 -
    public static Project createFromMavenIds(String groupId, String artifactId) {
-     return new Project(String.format(MAVEN_KEY_FORMAT, groupId, artifactId));
+     return createFromMavenIds(groupId, artifactId, null);
+   }
+   public static Project createFromMavenIds(String groupId, String artifactId, @Nullable String branch) {
+     return new Project(String.format(MAVEN_KEY_FORMAT, groupId, artifactId), branch, "");
    }
  
    @Override