]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6823 WS batch/project with protobuf and new behaviors
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Thu, 17 Sep 2015 08:41:56 +0000 (10:41 +0200)
committerDuarte Meneses <duarte.meneses@sonarsource.com>
Wed, 30 Sep 2015 14:27:12 +0000 (16:27 +0200)
21 files changed:
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectAction.java
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectDataLoader.java
server/sonar-server/src/main/java/org/sonar/server/batch/ProjectDataQuery.java
server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectActionTest.java
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectDataLoaderMediumTest.java
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/FileData.java
sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java
sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java [deleted file]
sonar-batch-protocol/src/test/resources/org/sonar/batch/protocol/input/ProjectRepositoriesTest/testToJson.json
sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java
sonar-batch/src/test/java/org/sonar/batch/mediumtest/scm/ScmMediumTest.java
sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectSettingsLoaderTest.java
sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
sonar-db/src/main/java/org/sonar/db/component/FilePathWithHashDto.java
sonar-db/src/main/resources/org/sonar/db/component/ComponentMapper.xml
sonar-db/src/test/java/org/sonar/db/component/ComponentDaoTest.java
sonar-db/src/test/resources/org/sonar/db/component/ComponentDaoTest/select_module_files_tree.xml
sonar-ws/src/main/gen-java/org/sonarqube/ws/WsBatch.java [new file with mode: 0644]
sonar-ws/src/main/protobuf/ws-batch.proto [new file with mode: 0644]

index 646f8662423d68c6a3021342bb240299ebd9a9eb..df43571ca8b95b07dcb47689ee058acb6ac8eed5 100644 (file)
 
 package org.sonar.server.batch;
 
-import org.apache.commons.io.IOUtils;
+import java.util.HashMap;
+import java.util.Map;
 import org.sonar.api.server.ws.Request;
 import org.sonar.api.server.ws.Response;
 import org.sonar.api.server.ws.WebService;
+import org.sonar.batch.protocol.input.FileData;
 import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.server.plugins.MimeTypes;
+import org.sonarqube.ws.WsBatch.WsProjectResponse;
+
+import static org.sonar.server.ws.WsUtils.writeProtobuf;
 
 public class ProjectAction implements BatchWsAction {
 
@@ -66,13 +70,85 @@ public class ProjectAction implements BatchWsAction {
   }
 
   @Override
-  public void handle(Request request, Response response) throws Exception {
+  public void handle(Request wsRequest, Response wsResponse) throws Exception {
     ProjectRepositories data = projectDataLoader.load(ProjectDataQuery.create()
-      .setModuleKey(request.mandatoryParam(PARAM_KEY))
-      .setProfileName(request.param(PARAM_PROFILE))
-      .setPreview(request.mandatoryParamAsBoolean(PARAM_PREVIEW)));
-    response.stream().setMediaType(MimeTypes.JSON);
-    IOUtils.write(data.toJson(), response.stream().output());
+      .setModuleKey(wsRequest.mandatoryParam(PARAM_KEY))
+      .setProfileName(wsRequest.param(PARAM_PROFILE))
+      .setIssuesMode(wsRequest.mandatoryParamAsBoolean(PARAM_PREVIEW)));
+
+    WsProjectResponse projectResponse = buildResponse(data);
+    writeProtobuf(projectResponse, wsRequest, wsResponse);
+  }
+
+  private static WsProjectResponse buildResponse(ProjectRepositories data) {
+    WsProjectResponse.Builder response = WsProjectResponse.newBuilder();
+    setLastAnalysisDate(response, data);
+    response.setTimestamp(data.timestamp());
+    response.getMutableFileDataByModuleAndPatch()
+      .putAll(buildFileDataByModuleAndPatch(data));
+    response.getMutableSettingsByModule()
+      .putAll(buildSettingsByModule(data));
+
+    return response.build();
+  }
+
+  private static void setLastAnalysisDate(WsProjectResponse.Builder response, ProjectRepositories data) {
+    if (data.lastAnalysisDate() != null) {
+      response.setLastAnalysisDate(data.lastAnalysisDate().getTime());
+    }
+  }
+
+  private static Map<String, WsProjectResponse.FileDataByPath> buildFileDataByModuleAndPatch(ProjectRepositories data) {
+    Map<String, WsProjectResponse.FileDataByPath> fileDataByModuleAndPathResponse = new HashMap<>();
+    for (Map.Entry<String, Map<String, FileData>> moduleAndFileDataByPathEntry : data.fileDataByModuleAndPath().entrySet()) {
+      fileDataByModuleAndPathResponse.put(
+        moduleAndFileDataByPathEntry.getKey(),
+        buildFileDataByPath(moduleAndFileDataByPathEntry.getValue()));
+    }
+
+    return fileDataByModuleAndPathResponse;
+  }
+
+  private static WsProjectResponse.FileDataByPath buildFileDataByPath(Map<String, FileData> fileDataByPath) {
+    WsProjectResponse.FileDataByPath.Builder response = WsProjectResponse.FileDataByPath.newBuilder();
+    Map<String, WsProjectResponse.FileData> fileDataByPathResponse = response.getMutableFileDataByPath();
+
+    for (Map.Entry<String, FileData> pathFileDataEntry : fileDataByPath.entrySet()) {
+      fileDataByPathResponse.put(
+        pathFileDataEntry.getKey(),
+        toFileDataResponse(pathFileDataEntry.getValue()));
+    }
+
+    return response.build();
+  }
+
+  private static Map<String, WsProjectResponse.Settings> buildSettingsByModule(ProjectRepositories data) {
+    Map<String, WsProjectResponse.Settings> settingsByModuleResponse = new HashMap<>();
+    for (Map.Entry<String, Map<String, String>> moduleSettingsEntry : data.settings().entrySet()) {
+      settingsByModuleResponse.put(
+        moduleSettingsEntry.getKey(),
+        toSettingsResponse(moduleSettingsEntry.getValue())
+        );
+    }
+
+    return settingsByModuleResponse;
+  }
+
+  private static WsProjectResponse.Settings toSettingsResponse(Map<String, String> settings) {
+    WsProjectResponse.Settings.Builder settingsResponse = WsProjectResponse.Settings
+      .newBuilder();
+    settingsResponse
+      .getMutableSettings()
+      .putAll(settings);
+
+    return settingsResponse.build();
+  }
+
+  private static WsProjectResponse.FileData toFileDataResponse(FileData fileData) {
+    return WsProjectResponse.FileData.newBuilder()
+      .setHash(fileData.hash())
+      .setRevision(fileData.revision())
+      .build();
   }
 
 }
index bf543ceb2658ce3aee2cfa1dbddf513cbf21686d..2a0ccdd956239d8849c1d02a7a7b21d9c9d8f49a 100644 (file)
 
 package org.sonar.server.batch;
 
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
 import com.google.common.collect.ArrayListMultimap;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import java.util.Collections;
 import java.util.Date;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import javax.annotation.Nullable;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.ServerSide;
 import org.sonar.api.utils.log.Logger;
 import org.sonar.api.utils.log.Loggers;
@@ -41,28 +34,19 @@ import org.sonar.api.web.UserRole;
 import org.sonar.batch.protocol.input.FileData;
 import org.sonar.batch.protocol.input.ProjectRepositories;
 import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.util.UtcDateUtils;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
 import org.sonar.db.MyBatis;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.FilePathWithHashDto;
 import org.sonar.db.property.PropertyDto;
-import org.sonar.db.qualityprofile.QualityProfileDto;
 import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.qualityprofile.ActiveRule;
-import org.sonar.server.qualityprofile.QProfileFactory;
-import org.sonar.server.qualityprofile.QProfileLoader;
-import org.sonar.server.rule.Rule;
-import org.sonar.server.rule.RuleService;
-import org.sonar.server.rule.index.RuleNormalizer;
-import org.sonar.server.rule.index.RuleQuery;
-import org.sonar.server.search.QueryContext;
-import org.sonar.server.search.Result;
 import org.sonar.server.user.UserSession;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Maps.newHashMap;
+import static java.lang.String.format;
+import static org.sonar.server.ws.WsUtils.checkFound;
 
 @ServerSide
 public class ProjectDataLoader {
@@ -70,73 +54,60 @@ public class ProjectDataLoader {
   private static final Logger LOG = Loggers.get(ProjectDataLoader.class);
 
   private final DbClient dbClient;
-  private final QProfileFactory qProfileFactory;
-  private final QProfileLoader qProfileLoader;
-  private final RuleService ruleService;
-  private final Languages languages;
   private final UserSession userSession;
 
-  public ProjectDataLoader(DbClient dbClient, QProfileFactory qProfileFactory, QProfileLoader qProfileLoader, RuleService ruleService,
-                           Languages languages, UserSession userSession) {
+  public ProjectDataLoader(DbClient dbClient, UserSession userSession) {
     this.dbClient = dbClient;
-    this.qProfileFactory = qProfileFactory;
-    this.qProfileLoader = qProfileLoader;
-    this.ruleService = ruleService;
-    this.languages = languages;
     this.userSession = userSession;
   }
 
   public ProjectRepositories load(ProjectDataQuery query) {
     boolean hasScanPerm = userSession.hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION);
-    checkPermission(query.isPreview());
+    checkPermission(query.isIssuesMode());
 
     DbSession session = dbClient.openSession(false);
     try {
-      ProjectRepositories ref = new ProjectRepositories();
-      String projectKey = query.getModuleKey();
-      Optional<ComponentDto> moduleOptional = dbClient.componentDao().selectByKey(session, query.getModuleKey());
-      // Current project/module can be null when analysing a new project
-      if (moduleOptional.isPresent()) {
-        ComponentDto module = moduleOptional.get();
-        // Scan permission is enough to analyze all projects but preview permission is limited to projects user can access
-        if (query.isPreview() && !userSession.hasProjectPermissionByUuid(UserRole.USER, module.projectUuid())) {
-          throw new ForbiddenException("You're not authorized to access to project '" + module.name() + "', please contact your SonarQube administrator.");
-        }
+      ProjectRepositories data = new ProjectRepositories();
+      ComponentDto module = checkFound(dbClient.componentDao().selectByKey(session, query.getModuleKey()),
+        format("Project or module with key '%s' is not found", query.getModuleKey()));
 
-        ComponentDto project = getProject(module, session);
-        if (!project.key().equals(module.key())) {
-          addSettings(ref, module.getKey(), getSettingsFromParents(module, hasScanPerm, session));
-          projectKey = project.key();
-        }
+      // Scan permission is enough to analyze all projects but preview permission is limited to projects user can access
+      if (query.isIssuesMode() && !userSession.hasProjectPermissionByUuid(UserRole.USER, module.projectUuid())) {
+        throw new ForbiddenException("You're not authorized to access to project '" + module.name() + "', please contact your SonarQube administrator.");
+      }
+
+      ComponentDto project = getProject(module, session);
+      if (!project.key().equals(module.key())) {
+        addSettings(data, module.getKey(), getSettingsFromParents(module, hasScanPerm, session));
+      }
 
-        List<ComponentDto> modulesTree = dbClient.componentDao().selectEnabledDescendantModules(session, module.uuid());
-        Map<String, String> moduleUuidsByKey = moduleUuidsByKey(module, modulesTree);
-        Map<String, Long> moduleIdsByKey = moduleIdsByKey(module, modulesTree);
+      List<ComponentDto> modulesTree = dbClient.componentDao().selectEnabledDescendantModules(session, module.uuid());
+      Map<String, String> moduleUuidsByKey = moduleUuidsByKey(modulesTree);
+      Map<String, Long> moduleIdsByKey = moduleIdsByKey(modulesTree);
 
-        List<PropertyDto> modulesTreeSettings = dbClient.propertiesDao().selectEnabledDescendantModuleProperties(module.uuid(), session);
-        TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings, module);
+      List<PropertyDto> modulesTreeSettings = dbClient.propertiesDao().selectEnabledDescendantModuleProperties(module.uuid(), session);
+      TreeModuleSettings treeModuleSettings = new TreeModuleSettings(moduleUuidsByKey, moduleIdsByKey, modulesTree, modulesTreeSettings);
 
-        addSettingsToChildrenModules(ref, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm, session);
-        List<FilePathWithHashDto> files = module.isRootProject() ? dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid())
-          : dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid());
-        addFileData(session, ref, modulesTree, files);
+      addSettingsToChildrenModules(data, query.getModuleKey(), Maps.<String, String>newHashMap(), treeModuleSettings, hasScanPerm);
+      List<FilePathWithHashDto> files = searchFilesWithHashAndRevision(session, module);
+      addFileData(data, modulesTree, files);
 
-        // FIXME need real value but actually only used to know if there is a previous analysis in local issue tracking mode so any value is
-        // ok
-        ref.setLastAnalysisDate(new Date());
-      } else {
-        ref.setLastAnalysisDate(null);
-      }
+      // FIXME need real value but actually only used to know if there is a previous analysis in local issue tracking mode so any value is
+      // ok
+      data.setLastAnalysisDate(new Date());
 
-      addProfiles(ref, projectKey, query.getProfileName(), session);
-      addActiveRules(ref);
-      addManualRules(ref);
-      return ref;
+      return data;
     } finally {
       MyBatis.closeQuietly(session);
     }
   }
 
+  private List<FilePathWithHashDto> searchFilesWithHashAndRevision(DbSession session, ComponentDto module) {
+    return module.isRootProject() ?
+      dbClient.componentDao().selectEnabledFilesFromProject(session, module.uuid())
+      : dbClient.componentDao().selectEnabledDescendantFiles(session, module.uuid());
+  }
+
   private ComponentDto getProject(ComponentDto module, DbSession session) {
     if (!module.isRootProject()) {
       return dbClient.componentDao().selectOrFailByUuid(session, module.projectUuid());
@@ -169,7 +140,7 @@ public class ProjectDataLoader {
   }
 
   private void addSettingsToChildrenModules(ProjectRepositories ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings,
-    boolean hasScanPerm, DbSession session) {
+    boolean hasScanPerm) {
     Map<String, String> currentParentProperties = newHashMap();
     currentParentProperties.putAll(parentProperties);
     currentParentProperties.putAll(getPropertiesMap(treeModuleSettings.findModuleSettings(moduleKey), hasScanPerm));
@@ -177,7 +148,7 @@ public class ProjectDataLoader {
 
     for (ComponentDto childModule : treeModuleSettings.findChildrenModule(moduleKey)) {
       addSettings(ref, childModule.getKey(), currentParentProperties);
-      addSettingsToChildrenModules(ref, childModule.getKey(), currentParentProperties, treeModuleSettings, hasScanPerm, session);
+      addSettingsToChildrenModules(ref, childModule.getKey(), currentParentProperties, treeModuleSettings, hasScanPerm);
     }
   }
 
@@ -203,99 +174,15 @@ public class ProjectDataLoader {
     return !key.contains(".secured") || hasScanPerm;
   }
 
-  private void addProfiles(ProjectRepositories ref, @Nullable String projectKey, @Nullable String profileName, DbSession session) {
-    for (Language language : languages.all()) {
-      String languageKey = language.getKey();
-      QualityProfileDto qualityProfileDto = getProfile(languageKey, projectKey, profileName, session);
-      ref.addQProfile(new org.sonar.batch.protocol.input.QProfile(
-        qualityProfileDto.getKey(),
-        qualityProfileDto.getName(),
-        qualityProfileDto.getLanguage(),
-        UtcDateUtils.parseDateTime(qualityProfileDto.getRulesUpdatedAt())));
-    }
-  }
-
-  /**
-   * First try to find a quality profile matching the given name (if provided) and current language
-   * If no profile found, try to find the quality profile set on the project (if provided)
-   * If still no profile found, try to find the default profile of the language
-   * <p/>
-   * Never return null because a default profile should always be set on each language
-   */
-  private QualityProfileDto getProfile(String languageKey, @Nullable String projectKey, @Nullable String profileName, DbSession session) {
-    QualityProfileDto qualityProfileDto = profileName != null ? qProfileFactory.getByNameAndLanguage(session, profileName, languageKey) : null;
-    if (qualityProfileDto == null && projectKey != null) {
-      qualityProfileDto = qProfileFactory.getByProjectAndLanguage(session, projectKey, languageKey);
-    }
-    qualityProfileDto = qualityProfileDto != null ? qualityProfileDto : qProfileFactory.getDefault(session, languageKey);
-    if (qualityProfileDto != null) {
-      return qualityProfileDto;
-    } else {
-      throw new IllegalStateException(String.format("No quality profile can been found on language '%s' for project '%s'", languageKey, projectKey));
-    }
-  }
-
-  private void addActiveRules(ProjectRepositories ref) {
-    for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) {
-      // Load all rules of the profile language (only needed fields are loaded)
-      Map<RuleKey, Rule> languageRules = ruleByRuleKey(ruleService.search(new RuleQuery().setLanguages(newArrayList(qProfile.language())),
-        new QueryContext(userSession).setLimit(100).setFieldsToReturn(newArrayList(
-          RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field(), RuleNormalizer.RuleField.INTERNAL_KEY.field(),
-          RuleNormalizer.RuleField.TEMPLATE_KEY.field())).setScroll(true))
-        .scroll());
-      for (Iterator<ActiveRule> activeRuleIterator = qProfileLoader.findActiveRulesByProfile(qProfile.key()); activeRuleIterator.hasNext();) {
-        ActiveRule activeRule = activeRuleIterator.next();
-        Rule rule = languageRules.get(activeRule.key().ruleKey());
-        if (rule == null) {
-          // It should never happen, but we need some log in case it happens
-          LOG.warn("Rule could not be found on active rule '{}'", activeRule.key());
-        } else {
-          RuleKey templateKey = rule.templateKey();
-          org.sonar.batch.protocol.input.ActiveRule inputActiveRule = new org.sonar.batch.protocol.input.ActiveRule(
-            activeRule.key().ruleKey().repository(),
-            activeRule.key().ruleKey().rule(),
-            templateKey != null ? templateKey.rule() : null,
-            rule.name(),
-            activeRule.severity(),
-            rule.internalKey(),
-            qProfile.language());
-          for (Map.Entry<String, String> entry : activeRule.params().entrySet()) {
-            inputActiveRule.addParam(entry.getKey(), entry.getValue());
-          }
-          ref.addActiveRule(inputActiveRule);
-        }
-      }
-    }
-  }
-
-  private Map<RuleKey, Rule> ruleByRuleKey(Iterator<Rule> rules) {
-    return Maps.uniqueIndex(rules, MatchRuleKey.INSTANCE);
-  }
-
-  private void addManualRules(ProjectRepositories ref) {
-    Result<Rule> ruleSearchResult = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleKey.MANUAL_REPOSITORY_KEY)), new QueryContext(userSession).setScroll(true)
-      .setFieldsToReturn(newArrayList(RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field())));
-    Iterator<Rule> rules = ruleSearchResult.scroll();
-    while (rules.hasNext()) {
-      Rule rule = rules.next();
-      ref.addActiveRule(new org.sonar.batch.protocol.input.ActiveRule(
-        RuleKey.MANUAL_REPOSITORY_KEY,
-        rule.key().rule(),
-        null, rule.name(),
-        null, null, null));
-    }
-  }
-
-  private static void addFileData(DbSession session, ProjectRepositories ref, List<ComponentDto> moduleChildren, List<FilePathWithHashDto> files) {
+  private static void addFileData(ProjectRepositories data, List<ComponentDto> moduleChildren, List<FilePathWithHashDto> files) {
     Map<String, String> moduleKeysByUuid = newHashMap();
     for (ComponentDto module : moduleChildren) {
       moduleKeysByUuid.put(module.uuid(), module.key());
     }
 
     for (FilePathWithHashDto file : files) {
-      // TODO should query E/S to know if blame is missing on this file
-      FileData fileData = new FileData(file.getSrcHash(), true);
-      ref.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData);
+      FileData fileData = new FileData(file.getSrcHash(), file.getRevision());
+      data.addFileData(moduleKeysByUuid.get(file.getModuleUuid()), file.getPath(), fileData);
     }
   }
 
@@ -314,7 +201,7 @@ public class ProjectDataLoader {
     }
   }
 
-  private static Map<String, String> moduleUuidsByKey(ComponentDto module, List<ComponentDto> moduleChildren) {
+  private static Map<String, String> moduleUuidsByKey(List<ComponentDto> moduleChildren) {
     Map<String, String> moduleUuidsByKey = newHashMap();
     for (ComponentDto componentDto : moduleChildren) {
       moduleUuidsByKey.put(componentDto.key(), componentDto.uuid());
@@ -322,7 +209,7 @@ public class ProjectDataLoader {
     return moduleUuidsByKey;
   }
 
-  private static Map<String, Long> moduleIdsByKey(ComponentDto module, List<ComponentDto> moduleChildren) {
+  private static Map<String, Long> moduleIdsByKey(List<ComponentDto> moduleChildren) {
     Map<String, Long> moduleIdsByKey = newHashMap();
     for (ComponentDto componentDto : moduleChildren) {
       moduleIdsByKey.put(componentDto.key(), componentDto.getId());
@@ -338,7 +225,7 @@ public class ProjectDataLoader {
     private Multimap<String, ComponentDto> moduleChildrenByModuleUuid;
 
     private TreeModuleSettings(Map<String, String> moduleUuidsByKey, Map<String, Long> moduleIdsByKey, List<ComponentDto> moduleChildren,
-      List<PropertyDto> moduleChildrenSettings, ComponentDto module) {
+      List<PropertyDto> moduleChildrenSettings) {
       this.moduleIdsByKey = moduleIdsByKey;
       this.moduleUuidsByKey = moduleUuidsByKey;
       propertiesByModuleId = ArrayListMultimap.create();
@@ -366,13 +253,4 @@ public class ProjectDataLoader {
       return newArrayList(moduleChildrenByModuleUuid.get(moduleUuid));
     }
   }
-
-  private enum MatchRuleKey implements Function<Rule, RuleKey> {
-    INSTANCE;
-
-    @Override
-    public RuleKey apply(@Nullable Rule input) {
-      return input != null ? input.key() : null;
-    }
-  }
 }
index 794887c24ce8d6cc72e3b8962a582325dcd7e384..fa3e8246d6fe5d23f06ff7d07255cbccea6a73f7 100644 (file)
@@ -27,18 +27,18 @@ public class ProjectDataQuery {
 
   private String projectOrModuleKey;
   private String profileName;
-  private boolean preview;
+  private boolean issuesMode;
 
   private ProjectDataQuery() {
     // No direct call
   }
 
-  public boolean isPreview() {
-    return preview;
+  public boolean isIssuesMode() {
+    return issuesMode;
   }
 
-  public ProjectDataQuery setPreview(boolean preview) {
-    this.preview = preview;
+  public ProjectDataQuery setIssuesMode(boolean issuesMode) {
+    this.issuesMode = issuesMode;
     return this;
   }
 
index b96a67b7235cb298e191a4d4fad401e3293aaf2a..25a8400f61c131ebc48666dd4ed2026a8c1bfca4 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.server.ws;
 
+import com.google.common.base.Optional;
 import com.google.protobuf.Message;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -74,4 +75,16 @@ public class WsUtils {
 
     return value;
   }
+
+  /**
+   * @throws NotFoundException if the value is not present
+   * @return the value
+   */
+  public static <T> T checkFound(Optional<T> value, String message) {
+    if (!value.isPresent()) {
+      throw new NotFoundException(message);
+    }
+
+    return value.get();
+  }
 }
index 5e0afe0995a91b1d07e60dba1b6693451e35190d..372118eba96bb128f1c69855e392573c0b8e3eea 100644 (file)
@@ -59,7 +59,7 @@ public class ProjectActionTest {
 
     assertThat(queryArgumentCaptor.getValue().getModuleKey()).isEqualTo(projectKey);
     assertThat(queryArgumentCaptor.getValue().getProfileName()).isEqualTo("Default");
-    assertThat(queryArgumentCaptor.getValue().isPreview()).isFalse();
+    assertThat(queryArgumentCaptor.getValue().isIssuesMode()).isFalse();
   }
 
 }
index c6b42e7dc98ac1a54ff10b987a4057e35b458d2b..8498f3fc3dbba58544e5e6638631ec0a6732f81f 100644 (file)
@@ -22,43 +22,30 @@ package org.sonar.server.batch;
 
 import com.google.common.collect.ImmutableMap;
 import java.util.Date;
-import java.util.List;
 import java.util.Map;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
 import org.junit.Rule;
 import org.junit.Test;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.rule.Severity;
-import org.sonar.api.server.rule.RuleParamType;
-import org.sonar.api.utils.DateUtils;
 import org.sonar.api.web.UserRole;
-import org.sonar.batch.protocol.input.ActiveRule;
 import org.sonar.batch.protocol.input.FileData;
 import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.batch.protocol.input.QProfile;
 import org.sonar.core.permission.GlobalPermissions;
 import org.sonar.db.DbSession;
 import org.sonar.db.component.ComponentDto;
 import org.sonar.db.component.ComponentTesting;
 import org.sonar.db.property.PropertyDto;
 import org.sonar.db.qualityprofile.QualityProfileDto;
-import org.sonar.db.rule.RuleDto;
-import org.sonar.db.rule.RuleParamDto;
-import org.sonar.db.rule.RuleTesting;
 import org.sonar.db.source.FileSourceDao;
 import org.sonar.db.source.FileSourceDto;
 import org.sonar.db.source.FileSourceDto.Type;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.exceptions.ForbiddenException;
 import org.sonar.server.qualityprofile.QProfileName;
-import org.sonar.server.qualityprofile.RuleActivation;
-import org.sonar.server.qualityprofile.RuleActivator;
 import org.sonar.server.tester.ServerTester;
 import org.sonar.server.tester.UserSessionRule;
 
-import static com.google.common.collect.Lists.newArrayList;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
 import static org.sonar.api.utils.DateUtils.formatDateTime;
@@ -98,10 +85,10 @@ public class ProjectDataLoaderMediumTest {
     // Project properties
     tester.get(DbClient.class).propertiesDao().insertProperty(
       dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId())
-    );
+      );
     tester.get(DbClient.class).propertiesDao().insertProperty(
       dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId())
-    );
+      );
     dbSession.commit();
 
     ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
@@ -109,7 +96,7 @@ public class ProjectDataLoaderMediumTest {
     assertThat(projectSettings).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
   }
 
   @Test
@@ -122,17 +109,17 @@ public class ProjectDataLoaderMediumTest {
     // Project properties
     tester.get(DbClient.class).propertiesDao().insertProperty(
       dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId())
-    );
+      );
     tester.get(DbClient.class).propertiesDao().insertProperty(
       dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId())
-    );
+      );
     dbSession.commit();
 
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setPreview(true));
+    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setIssuesMode(true));
     Map<String, String> projectSettings = ref.settings(project.key());
     assertThat(projectSettings).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR"
-    ));
+      ));
   }
 
   @Test
@@ -163,12 +150,12 @@ public class ProjectDataLoaderMediumTest {
     assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
     assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR-SERVER",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
   }
 
   @Test
@@ -195,11 +182,11 @@ public class ProjectDataLoaderMediumTest {
     assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
     assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
   }
 
   @Test
@@ -237,17 +224,17 @@ public class ProjectDataLoaderMediumTest {
     assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
     assertThat(ref.settings(module.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR-SERVER",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
     assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR-SERVER-DAO",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
   }
 
   @Test
@@ -265,9 +252,11 @@ public class ProjectDataLoaderMediumTest {
     tester.get(DbClient.class).componentDao().insert(dbSession, module1);
 
     // Module 1 properties
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR-SERVER").setResourceId(module1.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR-SERVER").setResourceId(module1.getId()));
     // This property should not be found on the other module
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(module1.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(module1.getId()));
 
     ComponentDto module2 = ComponentTesting.newModuleDto(project);
     tester.get(DbClient.class).componentDao().insert(dbSession, module2);
@@ -282,16 +271,16 @@ public class ProjectDataLoaderMediumTest {
     assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
     assertThat(ref.settings(module1.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR-SERVER",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
     assertThat(ref.settings(module2.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR-APPLICATION",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
   }
 
   @Test
@@ -312,7 +301,7 @@ public class ProjectDataLoaderMediumTest {
     assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of(
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john"
-    ));
+      ));
   }
 
   @Test
@@ -334,7 +323,8 @@ public class ProjectDataLoaderMediumTest {
     // Sub module properties
     tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(subModule.getId()));
     tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(subModule.getId()));
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId()));
 
     dbSession.commit();
 
@@ -345,7 +335,7 @@ public class ProjectDataLoaderMediumTest {
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
   }
 
   @Test
@@ -368,7 +358,8 @@ public class ProjectDataLoaderMediumTest {
     tester.get(DbClient.class).componentDao().insert(dbSession, subModule);
 
     // Sub module properties
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(subModule.getId()));
 
     dbSession.commit();
 
@@ -379,7 +370,7 @@ public class ProjectDataLoaderMediumTest {
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
   }
 
   @Test
@@ -391,7 +382,8 @@ public class ProjectDataLoaderMediumTest {
     // Project properties
     tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId()));
     tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()));
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId()));
 
     ComponentDto module = ComponentTesting.newModuleDto(project);
     tester.get(DbClient.class).componentDao().insert(dbSession, module);
@@ -411,7 +403,7 @@ public class ProjectDataLoaderMediumTest {
       "sonar.jira.project.key", "SONAR",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
+      ));
   }
 
   @Test
@@ -422,7 +414,8 @@ public class ProjectDataLoaderMediumTest {
 
     // Project properties
     tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()));
-    tester.get(DbClient.class).propertiesDao().insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId()));
+    tester.get(DbClient.class).propertiesDao()
+      .insertProperty(dbSession, new PropertyDto().setKey("sonar.coverage.exclusions").setValue("**/*.java").setResourceId(project.getId()));
 
     ComponentDto module = ComponentTesting.newModuleDto(project);
     tester.get(DbClient.class).componentDao().insert(dbSession, module);
@@ -444,285 +437,7 @@ public class ProjectDataLoaderMediumTest {
       "sonar.jira.project.key", "SONAR-SERVER",
       "sonar.jira.login.secured", "john",
       "sonar.coverage.exclusions", "**/*.java"
-    ));
-  }
-
-  @Test
-  public void return_quality_profile_from_project_profile() {
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt));
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-    tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto.getKee(), dbSession);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<QProfile> profiles = newArrayList(ref.qProfiles());
-    assertThat(profiles).hasSize(1);
-    assertThat(profiles.get(0).key()).isEqualTo("abcd");
-    assertThat(profiles.get(0).name()).isEqualTo("SonarQube way");
-    assertThat(profiles.get(0).language()).isEqualTo("xoo");
-    assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt);
-  }
-
-  @Test
-  public void return_quality_profile_from_default_profile() {
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt)).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<QProfile> profiles = newArrayList(ref.qProfiles());
-    assertThat(profiles).hasSize(1);
-    assertThat(profiles.get(0).key()).isEqualTo("abcd");
-    assertThat(profiles.get(0).name()).isEqualTo("SonarQube way");
-    assertThat(profiles.get(0).language()).isEqualTo("xoo");
-    assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt);
-  }
-
-  @Test
-  public void return_quality_profile_from_given_profile_name() {
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt)).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setProfileName("SonarQube way"));
-    List<QProfile> profiles = newArrayList(ref.qProfiles());
-    assertThat(profiles).hasSize(1);
-    assertThat(profiles.get(0).key()).isEqualTo("abcd");
-    assertThat(profiles.get(0).name()).isEqualTo("SonarQube way");
-    assertThat(profiles.get(0).language()).isEqualTo("xoo");
-    assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt);
-  }
-
-  @Test
-  public void return_quality_profiles_even_when_project_does_not_exists() {
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt)).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey("project"));
-    List<QProfile> profiles = newArrayList(ref.qProfiles());
-    assertThat(profiles).hasSize(1);
-    assertThat(profiles.get(0).key()).isEqualTo("abcd");
-    assertThat(profiles.get(0).name()).isEqualTo("SonarQube way");
-    assertThat(profiles.get(0).language()).isEqualTo("xoo");
-    assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt);
-  }
-
-  @Test
-  public void return_provisioned_project_profile() {
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    // No snapshot attached on the project -> provisioned project
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt));
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-    tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto.getKee(), dbSession);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<QProfile> profiles = newArrayList(ref.qProfiles());
-    assertThat(profiles).hasSize(1);
-    assertThat(profiles.get(0).key()).isEqualTo("abcd");
-    assertThat(profiles.get(0).name()).isEqualTo("SonarQube way");
-    assertThat(profiles.get(0).language()).isEqualTo("xoo");
-    assertThat(profiles.get(0).rulesUpdatedAt()).isEqualTo(ruleUpdatedAt);
-  }
-
-  @Test
-  public void fail_when_no_quality_profile_for_a_language() {
-    ComponentDto project = ComponentTesting.newProjectDto().setKey("org.codehaus.sonar:sonar");
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-    dbSession.commit();
-
-    try {
-      loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-      fail();
-    } catch (Exception e) {
-      assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("No quality profile can been found on language 'xoo' for project 'org.codehaus.sonar:sonar'");
-    }
-  }
-
-  @Test
-  public void return_active_rules() {
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(DateUtils.parseDateTime("2014-01-14T13:00:00+0100"))).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    RuleKey ruleKey = RuleKey.of("squid", "AvoidCycle");
-    RuleDto rule = RuleTesting.newDto(ruleKey).setName("Avoid Cycle").setConfigKey("squid-1").setLanguage(ServerTester.Xoo.KEY);
-    tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, rule);
-    tester.get(DbClient.class).deprecatedRuleDao().insertRuleParam(dbSession, rule, RuleParamDto.createFor(rule)
-      .setName("max").setDefaultValue("10").setType(RuleParamType.INTEGER.type()));
-
-    RuleActivation activation = new RuleActivation(ruleKey);
-    activation.setSeverity(Severity.MINOR);
-    activation.setParameter("max", "2");
-    tester.get(RuleActivator.class).activate(dbSession, activation, profileDto.getKey());
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<ActiveRule> activeRules = newArrayList(ref.activeRules());
-    assertThat(activeRules).hasSize(1);
-    assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid");
-    assertThat(activeRules.get(0).ruleKey()).isEqualTo("AvoidCycle");
-    assertThat(activeRules.get(0).name()).isEqualTo("Avoid Cycle");
-    assertThat(activeRules.get(0).language()).isEqualTo("xoo");
-    assertThat(activeRules.get(0).severity()).isEqualTo("MINOR");
-    assertThat(activeRules.get(0).internalKey()).isEqualTo("squid-1");
-    assertThat(activeRules.get(0).params()).isEqualTo(ImmutableMap.of("max", "2"));
-  }
-
-  @Test
-  public void return_only_active_rules_from_project_profile() {
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    RuleKey ruleKey1 = RuleKey.of("squid", "AvoidCycle");
-    RuleKey ruleKey2 = RuleKey.of("squid", "AvoidNPE");
-    tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession,
-      RuleTesting.newDto(ruleKey1).setName("Avoid Cycle").setLanguage(ServerTester.Xoo.KEY),
-      RuleTesting.newDto(ruleKey2).setName("Avoid NPE").setLanguage(ServerTester.Xoo.KEY)
-    );
-
-    QualityProfileDto profileDto1 = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd");
-    QualityProfileDto profileDto2 = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "Another profile"), "efgh");
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto1, profileDto2);
-
-    // The first profile is the profile used but the project
-    tester.get(DbClient.class).qualityProfileDao().insertProjectProfileAssociation(project.uuid(), profileDto1.getKee(), dbSession);
-
-    tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey1).setSeverity(Severity.MINOR), profileDto1.getKey());
-
-    // Active rule from 2nd profile
-    tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey1).setSeverity(Severity.BLOCKER), profileDto2.getKey());
-    tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey2).setSeverity(Severity.BLOCKER), profileDto2.getKey());
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<ActiveRule> activeRules = newArrayList(ref.activeRules());
-    assertThat(activeRules).hasSize(1);
-    assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid");
-    assertThat(activeRules.get(0).ruleKey()).isEqualTo("AvoidCycle");
-    assertThat(activeRules.get(0).name()).isEqualTo("Avoid Cycle");
-    assertThat(activeRules.get(0).language()).isEqualTo("xoo");
-    assertThat(activeRules.get(0).severity()).isEqualTo("MINOR");
-  }
-
-  @Test
-  public void return_more_than_10_active_rules() {
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd")
-      .setRulesUpdatedAt(formatDateTime(DateUtils.parseDateTime("2014-01-14T13:00:00+0100"))).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    for (int i = 0; i < 20; i++) {
-      RuleKey ruleKey = RuleKey.of("squid", "Rule" + i);
-      tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, RuleTesting.newDto(ruleKey).setName("Rule" + i).setLanguage(ServerTester.Xoo.KEY));
-      tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(ruleKey).setSeverity(Severity.MINOR), profileDto.getKey());
-    }
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    assertThat(ref.activeRules()).hasSize(20);
-  }
-
-  @Test
-  public void return_custom_rule() {
-    Date ruleUpdatedAt = DateUtils.parseDateTime("2014-01-14T13:00:00+0100");
-
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-
-    QualityProfileDto profileDto = newQProfileDto(QProfileName.createFor(ServerTester.Xoo.KEY, "SonarQube way"), "abcd").setRulesUpdatedAt(
-      formatDateTime(ruleUpdatedAt)).setDefault(true);
-    tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
-
-    RuleKey ruleKey = RuleKey.of("squid", "ArchitecturalConstraint");
-    RuleDto templateRule = RuleTesting.newTemplateRule(ruleKey).setName("Architectural Constraint").setLanguage(ServerTester.Xoo.KEY);
-    tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, templateRule);
-
-    RuleDto customRule = RuleTesting.newCustomRule(templateRule);
-    tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, customRule);
-    tester.get(RuleActivator.class).activate(dbSession, new RuleActivation(customRule.getKey()).setSeverity(Severity.MINOR), profileDto.getKey());
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<ActiveRule> activeRules = newArrayList(ref.activeRules());
-    assertThat(activeRules).hasSize(1);
-    assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid");
-    assertThat(activeRules.get(0).ruleKey()).startsWith("ArchitecturalConstraint_");
-    assertThat(activeRules.get(0).templateRuleKey()).isEqualTo("ArchitecturalConstraint");
-    assertThat(activeRules.get(0).language()).isEqualTo("xoo");
-    assertThat(activeRules.get(0).severity()).isEqualTo("MINOR");
-  }
-
-  @Test
-  public void return_manual_rules() {
-    ComponentDto project = ComponentTesting.newProjectDto();
-    userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
-    tester.get(DbClient.class).componentDao().insert(dbSession, project);
-    addDefaultProfile();
-
-    RuleDto rule = RuleTesting.newManualRule("manualRuleKey").setName("Name manualRuleKey");
-    tester.get(DbClient.class).deprecatedRuleDao().insert(dbSession, rule);
-
-    dbSession.commit();
-
-    ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(project.key()));
-    List<ActiveRule> activeRules = newArrayList(ref.activeRules());
-    assertThat(activeRules).extracting("repositoryKey").containsOnly(RuleKey.MANUAL_REPOSITORY_KEY);
-    assertThat(activeRules).extracting("ruleKey").containsOnly("manualRuleKey");
-    assertThat(activeRules).extracting("name").containsOnly("Name manualRuleKey");
-    assertThat(activeRules).extracting("language").containsNull();
-    assertThat(activeRules).extracting("severity").containsNull();
+      ));
   }
 
   @Test
@@ -750,7 +465,7 @@ public class ProjectDataLoaderMediumTest {
     dbSession.commit();
 
     try {
-      loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setPreview(false));
+      loader.load(ProjectDataQuery.create().setModuleKey(project.key()).setIssuesMode(false));
       fail();
     } catch (Exception e) {
       assertThat(e).isInstanceOf(ForbiddenException.class).hasMessage(
@@ -814,7 +529,7 @@ public class ProjectDataLoaderMediumTest {
     // File on project
     ComponentDto projectFile = ComponentTesting.newFileDto(project, "projectFile");
     tester.get(DbClient.class).componentDao().insert(dbSession, projectFile);
-    tester.get(FileSourceDao.class).insert(newFileSourceDto(projectFile).setSrcHash("123456"));
+    tester.get(FileSourceDao.class).insert(newFileSourceDto(projectFile).setSrcHash("123456").setRevision("987654321"));
 
     ComponentDto module = ComponentTesting.newModuleDto(project);
     userSessionRule.login("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);
@@ -823,12 +538,13 @@ public class ProjectDataLoaderMediumTest {
     // File on module
     ComponentDto moduleFile = ComponentTesting.newFileDto(module, "moduleFile");
     tester.get(DbClient.class).componentDao().insert(dbSession, moduleFile);
-    tester.get(FileSourceDao.class).insert(newFileSourceDto(moduleFile).setSrcHash("789456"));
+    tester.get(FileSourceDao.class).insert(newFileSourceDto(moduleFile).setSrcHash("789456").setRevision("123456789"));
 
     dbSession.commit();
 
     ProjectRepositories ref = loader.load(ProjectDataQuery.create().setModuleKey(module.key()));
     assertThat(ref.fileData(module.key(), moduleFile.path()).hash()).isEqualTo("789456");
+    assertThat(ref.fileData(module.key(), moduleFile.path()).revision()).isEqualTo("123456789");
     assertThat(ref.fileData(project.key(), projectFile.path())).isNull();
   }
 
@@ -838,16 +554,17 @@ public class ProjectDataLoaderMediumTest {
     tester.get(DbClient.class).qualityProfileDao().insert(dbSession, profileDto);
   }
 
-  private FileSourceDto newFileSourceDto(ComponentDto file) {
+  private static FileSourceDto newFileSourceDto(ComponentDto file) {
     return new FileSourceDto()
       .setFileUuid(file.uuid())
       .setProjectUuid(file.projectUuid())
-        //.setSourceData(",,,,,,,,,,,,,,,unchanged&#13;&#10;,,,,,,,,,,,,,,,content&#13;&#10;")
+      // .setSourceData(",,,,,,,,,,,,,,,unchanged&#13;&#10;,,,,,,,,,,,,,,,content&#13;&#10;")
       .setDataHash("0263047cd758c68c27683625f072f010")
       .setLineHashes("8d7b3d6b83c0a517eac07e1aac94b773")
       .setCreatedAt(System.currentTimeMillis())
       .setUpdatedAt(System.currentTimeMillis())
       .setDataType(Type.SOURCE)
+      .setRevision("123456789")
       .setSrcHash("123456");
   }
 
index 28b8083c0e264fba023959aeb563c84cd108569c..6fb54002ab05fe9108461d1a5a1409e4ca47d6f0 100644 (file)
@@ -25,11 +25,11 @@ import javax.annotation.Nullable;
 public class FileData {
 
   private final String hash;
-  private final boolean needBlame;
+  private final String revision;
 
-  public FileData(@Nullable String hash, boolean needBlame) {
+  public FileData(@Nullable String hash, @Nullable String revision) {
     this.hash = hash;
-    this.needBlame = needBlame;
+    this.revision = revision;
   }
 
   @CheckForNull
@@ -37,8 +37,12 @@ public class FileData {
     return hash;
   }
 
-  public boolean needBlame() {
-    return needBlame;
+  @CheckForNull
+  public String revision() {
+    return revision;
   }
 
+  public boolean needBlame() {
+    return false;
+  }
 }
index 862a21152d8cc7e2afae0f27200d0483c53e8ba4..fdcfb0fe3f692689554057daf5aea0f18795f698 100644 (file)
@@ -36,8 +36,6 @@ import org.sonar.batch.protocol.GsonHelper;
 public class ProjectRepositories {
 
   private long timestamp;
-  private Map<String, QProfile> qprofilesByLanguage = new HashMap<>();
-  private Collection<ActiveRule> activeRules = new ArrayList<>();
   private Map<String, Map<String, String>> settingsByModule = new HashMap<>();
   private Map<String, Map<String, FileData>> fileDataByModuleAndPath = new HashMap<>();
   private Date lastAnalysisDate;
@@ -45,7 +43,7 @@ public class ProjectRepositories {
   public Map<String, String> settings(String moduleKey) {
     return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap();
   }
-  
+
   public Map<String, Map<String, String>> settings() {
     return settingsByModule;
   }
@@ -60,24 +58,6 @@ public class ProjectRepositories {
     return this;
   }
 
-  public Collection<QProfile> qProfiles() {
-    return qprofilesByLanguage.values();
-  }
-
-  public ProjectRepositories addQProfile(QProfile qProfile) {
-    qprofilesByLanguage.put(qProfile.language(), qProfile);
-    return this;
-  }
-
-  public Collection<ActiveRule> activeRules() {
-    return activeRules;
-  }
-
-  public ProjectRepositories addActiveRule(ActiveRule activeRule) {
-    activeRules.add(activeRule);
-    return this;
-  }
-
   public Map<String, Map<String, FileData>> fileDataByModuleAndPath() {
     return fileDataByModuleAndPath;
   }
@@ -126,4 +106,19 @@ public class ProjectRepositories {
     return GsonHelper.create().fromJson(json, ProjectRepositories.class);
   }
 
+  public Collection<QProfile> qProfiles() {
+    return new ArrayList<>();
+  }
+
+  public Collection<ActiveRule> activeRules() {
+    return new ArrayList<>();
+  }
+
+  public void addQProfile(QProfile qProfile) {
+    // do nothing
+  }
+
+  public void addActiveRule(ActiveRule activeRule) {
+    // do nothing
+  }
 }
diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoriesTest.java
deleted file mode 100644 (file)
index 91a1b17..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * 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.protocol.input;
-
-import org.junit.Test;
-import org.sonar.test.JsonAssert;
-
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.HashMap;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class ProjectRepositoriesTest {
-
-  public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
-
-  @Test
-  public void testToJson() throws Exception {
-    ProjectRepositories ref = new ProjectRepositories();
-    assertThat(ref.settings("foo")).isEmpty();
-
-    ref.addQProfile(new QProfile("squid-java", "Java", "java", DATE_FORMAT.parse("2013-01-01T12:00:00+0100")));
-    HashMap<String, String> settings = new HashMap<>();
-    settings.put("prop1", "value1");
-    ref.addSettings("foo", settings);
-    settings = new HashMap<>();
-    settings.put("prop2", "value2");
-    ref.addSettings("foo", settings);
-    ref.settings("foo").put("prop", "value");
-    ActiveRule activeRule = new ActiveRule("repo", "rule", "templateRule", "Rule", "MAJOR", "rule", "java");
-    activeRule.addParam("param1", "value1");
-    ref.addActiveRule(activeRule);
-    ref.setLastAnalysisDate(DATE_FORMAT.parse("2014-05-18T15:50:45+0100"));
-    ref.setTimestamp(10);
-    ref.addFileData("foo", "src/main/java/Foo.java", new FileData("xyz", true));
-    ref.addFileData("foo", "src/main/java/Foo2.java", new FileData("xyz", false));
-
-    JsonAssert.assertJson(ref.toJson())
-      .isSimilarTo(getClass().getResource("ProjectRepositoriesTest/testToJson.json"));
-  }
-
-  @Test
-  public void testFromJson() throws ParseException {
-    ProjectRepositories ref = ProjectRepositories
-      .fromJson("{timestamp:1,"
-        + "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"2013-01-01T12:00:00+0100\"}},"
-        + "activeRules:[{repositoryKey:repo,ruleKey:rule,templateRuleKey:templateRule,name:Rule,severity:MAJOR,internalKey:rule1,language:java,params:{param1:value1}}],"
-        + "settingsByModule:{foo:{prop:value}},"
-        + "fileDataByModuleAndPath:{foo:{\"src/main/java/Foo.java\":{hash:xyz,needBlame:true,scmLastCommitDatetimesByLine:\"1\u003d12345,2\u003d3456\",scmRevisionsByLine:\"1\u003d345,2\u003d345\",scmAuthorsByLine:\"1\u003dhenryju,2\u003dgaudin\"}}},"
-        + "lastAnalysisDate:\"2014-10-31T00:00:00+0100\"}");
-
-    assertThat(ref.timestamp()).isEqualTo(1);
-
-    ActiveRule activeRule = ref.activeRules().iterator().next();
-    assertThat(activeRule.ruleKey()).isEqualTo("rule");
-    assertThat(activeRule.repositoryKey()).isEqualTo("repo");
-    assertThat(activeRule.templateRuleKey()).isEqualTo("templateRule");
-    assertThat(activeRule.name()).isEqualTo("Rule");
-    assertThat(activeRule.severity()).isEqualTo("MAJOR");
-    assertThat(activeRule.internalKey()).isEqualTo("rule1");
-    assertThat(activeRule.language()).isEqualTo("java");
-    assertThat(activeRule.params()).containsEntry("param1", "value1");
-    assertThat(activeRule.param("param1")).isEqualTo("value1");
-    QProfile qProfile = ref.qProfiles().iterator().next();
-    assertThat(qProfile.key()).isEqualTo("squid-java");
-    assertThat(qProfile.name()).isEqualTo("Java");
-    assertThat(qProfile.rulesUpdatedAt().getTime()).isEqualTo(DATE_FORMAT.parse("2013-01-01T12:00:00+0100").getTime());
-    assertThat(ref.settings("foo")).containsEntry("prop", "value");
-
-    assertThat(ref.fileData("foo2", "src/main/java/Foo3.java")).isNull();
-
-    assertThat(ref.fileData("foo", "src/main/java/Foo.java").hash()).isEqualTo("xyz");
-    assertThat(ref.fileData("foo", "src/main/java/Foo.java").needBlame()).isTrue();
-
-    assertThat(ref.lastAnalysisDate().getTime()).isEqualTo(DATE_FORMAT.parse("2014-10-31T00:00:00+0100").getTime());
-  }
-}
index d728bdc441479d8d649a47577e04e14834b7f42f..ba7489143a6400ccd080d8a6af8eb729a1a55445 100644 (file)
@@ -1,25 +1,5 @@
 {
   "timestamp": 10,
-  "qprofilesByLanguage": {
-    "java": {
-      "key": "squid-java",
-      "name": "Java",
-      "language": "java",
-      "rulesUpdatedAt": "2013-01-01T12:00:00+0100"
-    }
-  },
-  "activeRules": [
-    {
-      "repositoryKey": "repo",
-      "ruleKey": "rule",
-      "templateRuleKey": "templateRule",
-      "name": "Rule",
-      "severity": "MAJOR",
-      "internalKey": "rule",
-      "language": "java",
-      "params": {"param1": "value1"}
-    }
-  ],
   "settingsByModule": {
     "foo": {
       "prop1": "value1",
     "foo": {
       "src/main/java/Foo.java": {
         "hash": "xyz",
-        "needBlame": true,
+        "needBlame": true
       },
       "src/main/java/Foo2.java": {
         "hash": "xyz",
-        "needBlame": false,
+        "needBlame": false
       }
     }
   },
index a3b38ee4ec54a48d61dd37eb0febe75998c5707f..f47200656131515ce21c670f5acff0cafaeb2af5 100644 (file)
  */
 package org.sonar.batch.repository;
 
-import org.sonar.batch.cache.WSLoaderResult;
-
-import org.sonar.batch.analysis.DefaultAnalysisMode;
-import org.sonar.batch.cache.WSLoader;
-
 import javax.annotation.Nullable;
-
 import org.apache.commons.lang.mutable.MutableBoolean;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.sonar.api.utils.MessageException;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.cache.WSLoader;
+import org.sonar.batch.cache.WSLoaderResult;
 import org.sonar.batch.protocol.input.ProjectRepositories;
 import org.sonar.batch.rule.ModuleQProfiles;
 import org.sonar.batch.util.BatchUtils;
@@ -58,7 +54,6 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
     url += "&preview=" + analysisMode.isIssues();
 
     ProjectRepositories projectRepositories = load(url, fromCache);
-    validateProjectRepositories(projectRepositories);
     return projectRepositories;
   }
 
@@ -69,10 +64,4 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
     }
     return ProjectRepositories.fromJson(result.get());
   }
-
-  private static void validateProjectRepositories(ProjectRepositories projectRepositories) {
-    if (projectRepositories.qProfiles().isEmpty()) {
-      throw MessageException.of("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
-    }
-  }
 }
index 8216eea1323415062e55c6c6ee5add81b2a7cf65..0e20b4eed9f7fcf6c85e346804e772b5574e57c5 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.batch.mediumtest.cache;
 
 import com.google.common.collect.ImmutableMap;
+import java.util.Date;
 import org.junit.After;
 import org.junit.Rule;
 import org.junit.Test;
@@ -31,8 +32,6 @@ import org.sonar.batch.protocol.input.FileData;
 import org.sonar.xoo.XooPlugin;
 import org.sonar.xoo.rule.XooRulesDefinition;
 
-import java.util.Date;
-
 public class CacheSyncTest {
   @Rule
   public ExpectedException exception = ExpectedException.none();
@@ -49,7 +48,7 @@ public class CacheSyncTest {
 
   @Test
   public void testSyncFirstTime() {
-    FileData file1 = new FileData("hash", true);
+    FileData file1 = new FileData("hash", "123456789");
 
     tester = BatchMediumTester.builder()
       .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
@@ -64,10 +63,10 @@ public class CacheSyncTest {
     tester.start();
     tester.syncProject("test-project");
   }
-  
+
   @Test
   public void testNonAssociated() {
-    FileData file1 = new FileData("hash", true);
+    FileData file1 = new FileData("hash", "123456789");
 
     tester = BatchMediumTester.builder()
       .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
@@ -85,7 +84,7 @@ public class CacheSyncTest {
 
   @Test
   public void testNoQProfile() {
-    FileData file1 = new FileData("hash", true);
+    FileData file1 = new FileData("hash", "123456789");
 
     tester = BatchMediumTester.builder()
       .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
index 2dfe12c6b34602b2e694d183bdde486d16f6597b..28a13a38d5598c9987f1bf2fa26d4c61e6d052ce 100644 (file)
@@ -55,7 +55,7 @@ public class ScmMediumTest {
   public BatchMediumTester tester = BatchMediumTester.builder()
     .registerPlugin("xoo", new XooPlugin())
     .addDefaultQProfile("xoo", "Sonar Way")
-    .addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), false))
+    .addFileData("com.foo.project", "src/sample2.xoo", new FileData(DigestUtils.md5Hex(SAMPLE_XOO_CONTENT), null))
     .build();
 
   @Before
index 9d0388fd6b6e7476cce0a99f59bd3f11374c2298..0a4b7b7b3403144f94834a11ddb0ecfe12ba9f05 100644 (file)
@@ -54,8 +54,8 @@ public class DefaultProjectSettingsLoaderTest {
     projectRepositories = new ProjectRepositories();
     projectRepositories.setLastAnalysisDate(new Date(1000));
 
-    f1 = new FileData("hash1", true);
-    f2 = new FileData("hash2", true);
+    f1 = new FileData("hash1", "123456789");
+    f2 = new FileData("hash2", "123456789");
     projectRepositories.addFileData("module1", "file1", f1);
     projectRepositories.addFileData("module1", "file2", f2);
 
index 7aa79e5554e74858ec8ef28fea702618132946ff..98b17dd6a56b5ee19cafbe49d32cf71e22891f69 100644 (file)
  */
 package org.sonar.batch.scan.filesystem;
 
-import com.google.common.collect.ImmutableTable;
-
 import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.ImmutableTable;
 import com.google.common.collect.Table;
-
-import org.sonar.batch.repository.ProjectSettingsRepo;
 import org.junit.Test;
 import org.sonar.api.batch.fs.InputFile;
 import org.sonar.batch.protocol.input.FileData;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+
 import static org.assertj.core.api.Assertions.assertThat;
 
 public class StatusDetectionTest {
@@ -45,8 +44,8 @@ public class StatusDetectionTest {
   private static Table<String, String, FileData> createTable() {
     Table<String, String, FileData> t = HashBasedTable.create();
 
-    t.put("foo", "src/Foo.java", new FileData("ABCDE", true));
-    t.put("foo", "src/Bar.java", new FileData("FGHIJ", true));
+    t.put("foo", "src/Foo.java", new FileData("ABCDE", "12345789"));
+    t.put("foo", "src/Bar.java", new FileData("FGHIJ", "123456789"));
 
     return t;
   }
index 85e3c45ceb6176d46ad4938ded34961487f2e413..08f4394c1c534b064d2d094144445f12f4f8eba3 100644 (file)
@@ -26,6 +26,7 @@ public class FilePathWithHashDto {
   private String moduleUuid;
   private String path;
   private String srcHash;
+  private String revision;
 
   public String getSrcHash() {
     return srcHash;
@@ -51,6 +52,14 @@ public class FilePathWithHashDto {
     this.path = path;
   }
 
+  public String getRevision() {
+    return revision;
+  }
+
+  public void setRevision(String revision) {
+    this.revision = revision;
+  }
+
   public String getUuid() {
     return uuid;
   }
@@ -58,4 +67,5 @@ public class FilePathWithHashDto {
   public void setUuid(String uuid) {
     this.uuid = uuid;
   }
+
 }
index bcfcbeac7b413fb439a7156bd3425cb5e216b5c7..da674300494a26a7596f77576739c88c55edad6d 100644 (file)
   </sql>
 
   <select id="selectEnabledFilesFromProject" parameterType="map" resultType="FilePathWithHash">
-    SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash
+    SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash, fs.revision
     FROM projects p
     INNER JOIN file_sources fs ON fs.file_uuid=p.uuid and fs.data_type='SOURCE'
     <where>
   </select>
 
   <select id="selectDescendantFiles" parameterType="map" resultType="FilePathWithHash">
-    SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash
+    SELECT p.uuid, p.path, p.module_uuid as moduleUuid, fs.src_hash as srcHash, fs.revision
     FROM projects p
     INNER JOIN file_sources fs ON fs.file_uuid=p.uuid and fs.data_type='SOURCE'
     <include refid="modulesTreeQuery"/>
index 1343b4d0b0dbf01be35645ba15ec6a39ad0ee0fa..f7125fd1d34ffebd042071482a87b849b02dc5a5 100644 (file)
@@ -384,6 +384,7 @@ public class ComponentDaoTest {
     assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI");
     assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK");
     assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java");
+    assertThat(files).extracting("revision").containsOnly("123456789");
 
     // From module
     files = underTest.selectEnabledDescendantFiles(dbSession, "EFGH");
@@ -391,6 +392,7 @@ public class ComponentDaoTest {
     assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI");
     assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK");
     assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java");
+    assertThat(files).extracting("revision").containsOnly("123456789");
 
     // From sub module
     files = underTest.selectEnabledDescendantFiles(dbSession, "FGHI");
@@ -398,6 +400,7 @@ public class ComponentDaoTest {
     assertThat(files).extracting("moduleUuid").containsOnly("FGHI");
     assertThat(files).extracting("srcHash").containsOnly("srcHIJK");
     assertThat(files).extracting("path").containsOnly("src/org/struts/RequestContext.java");
+    assertThat(files).extracting("revision").containsOnly("123456789");
 
     // From directory
     assertThat(underTest.selectEnabledDescendantFiles(dbSession, "GHIJ")).isEmpty();
index fe7f43ee5a3c696862b2b59d11dc5f2c0a9d21b6..703f88968ac46096b50afca8b2857db4b6c456e6 100644 (file)
@@ -23,7 +23,7 @@
                 binary_data=",,,,,,,,,,,,,,,unchanged&#13;&#10;,,,,,,,,,,,,,,,content&#13;&#10;"
                 line_hashes="lineEFGHI"
                 data_hash="dataEFGHI"
-                src_hash="srcEFGHI"
+                src_hash="srcEFGHI" revision="123456789"
                 created_at="1412952242000" updated_at="1412952242000" data_type="SOURCE"/>
 
   <!-- sub module -->
@@ -50,7 +50,7 @@
                 binary_data=",,,,,,,,,,,,,,,unchanged&#13;&#10;,,,,,,,,,,,,,,,content&#13;&#10;"
                 line_hashes="lineHIJK"
                 data_hash="dataHIJK"
-                src_hash="srcHIJK"
+                src_hash="srcHIJK" revision="123456789"
                 created_at="1412952242000" updated_at="1412952242000" data_type="SOURCE"/>
 
 </dataset>
diff --git a/sonar-ws/src/main/gen-java/org/sonarqube/ws/WsBatch.java b/sonar-ws/src/main/gen-java/org/sonarqube/ws/WsBatch.java
new file mode 100644 (file)
index 0000000..991ac25
--- /dev/null
@@ -0,0 +1,2417 @@
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+// source: ws-batch.proto
+
+package org.sonarqube.ws;
+
+public final class WsBatch {
+  private WsBatch() {}
+  public static void registerAllExtensions(
+      com.google.protobuf.ExtensionRegistry registry) {
+  }
+  public interface WsProjectResponseOrBuilder extends
+      // @@protoc_insertion_point(interface_extends:sonarqube.ws.batch.WsProjectResponse)
+      com.google.protobuf.MessageOrBuilder {
+
+    /**
+     * <code>optional int64 timestamp = 1;</code>
+     */
+    boolean hasTimestamp();
+    /**
+     * <code>optional int64 timestamp = 1;</code>
+     */
+    long getTimestamp();
+
+    /**
+     * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.Settings&gt; settingsByModule = 2;</code>
+     */
+    java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+    getSettingsByModule();
+
+    /**
+     * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileDataByPath&gt; fileDataByModuleAndPatch = 3;</code>
+     */
+    java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+    getFileDataByModuleAndPatch();
+
+    /**
+     * <code>optional int64 lastAnalysisDate = 4;</code>
+     */
+    boolean hasLastAnalysisDate();
+    /**
+     * <code>optional int64 lastAnalysisDate = 4;</code>
+     */
+    long getLastAnalysisDate();
+  }
+  /**
+   * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse}
+   *
+   * <pre>
+   * WS api/batch/project
+   * </pre>
+   */
+  public  static final class WsProjectResponse extends
+      com.google.protobuf.GeneratedMessage implements
+      // @@protoc_insertion_point(message_implements:sonarqube.ws.batch.WsProjectResponse)
+      WsProjectResponseOrBuilder {
+    // Use WsProjectResponse.newBuilder() to construct.
+    private WsProjectResponse(com.google.protobuf.GeneratedMessage.Builder builder) {
+      super(builder);
+    }
+    private WsProjectResponse() {
+      timestamp_ = 0L;
+      lastAnalysisDate_ = 0L;
+    }
+
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+    getUnknownFields() {
+      return this.unknownFields;
+    }
+    private WsProjectResponse(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry) {
+      this();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              timestamp_ = input.readInt64();
+              break;
+            }
+            case 18: {
+              if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+                settingsByModule_ = com.google.protobuf.MapField.newMapField(
+                    SettingsByModuleDefaultEntryHolder.defaultEntry);
+                mutable_bitField0_ |= 0x00000002;
+              }
+              com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+              settingsByModule = input.readMessage(
+                  SettingsByModuleDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+              settingsByModule_.getMutableMap().put(settingsByModule.getKey(), settingsByModule.getValue());
+              break;
+            }
+            case 26: {
+              if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
+                fileDataByModuleAndPatch_ = com.google.protobuf.MapField.newMapField(
+                    FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry);
+                mutable_bitField0_ |= 0x00000004;
+              }
+              com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+              fileDataByModuleAndPatch = input.readMessage(
+                  FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+              fileDataByModuleAndPatch_.getMutableMap().put(fileDataByModuleAndPatch.getKey(), fileDataByModuleAndPatch.getValue());
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000002;
+              lastAnalysisDate_ = input.readInt64();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw new RuntimeException(e.setUnfinishedMessage(this));
+      } catch (java.io.IOException e) {
+        throw new RuntimeException(
+            new com.google.protobuf.InvalidProtocolBufferException(
+                e.getMessage()).setUnfinishedMessage(this));
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor;
+    }
+
+    @SuppressWarnings({"rawtypes"})
+    protected com.google.protobuf.MapField internalGetMapField(
+        int number) {
+      switch (number) {
+        case 2:
+          return internalGetSettingsByModule();
+        case 3:
+          return internalGetFileDataByModuleAndPatch();
+        default:
+          throw new RuntimeException(
+              "Invalid map field number: " + number);
+      }
+    }
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.sonarqube.ws.WsBatch.WsProjectResponse.class, org.sonarqube.ws.WsBatch.WsProjectResponse.Builder.class);
+    }
+
+    public interface SettingsOrBuilder extends
+        // @@protoc_insertion_point(interface_extends:sonarqube.ws.batch.WsProjectResponse.Settings)
+        com.google.protobuf.MessageOrBuilder {
+
+      /**
+       * <code>map&lt;string, string&gt; settings = 1;</code>
+       */
+      java.util.Map<java.lang.String, java.lang.String>
+      getSettings();
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.Settings}
+     */
+    public  static final class Settings extends
+        com.google.protobuf.GeneratedMessage implements
+        // @@protoc_insertion_point(message_implements:sonarqube.ws.batch.WsProjectResponse.Settings)
+        SettingsOrBuilder {
+      // Use Settings.newBuilder() to construct.
+      private Settings(com.google.protobuf.GeneratedMessage.Builder builder) {
+        super(builder);
+      }
+      private Settings() {
+      }
+
+      @java.lang.Override
+      public final com.google.protobuf.UnknownFieldSet
+      getUnknownFields() {
+        return this.unknownFields;
+      }
+      private Settings(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry) {
+        this();
+        int mutable_bitField0_ = 0;
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+            com.google.protobuf.UnknownFieldSet.newBuilder();
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              default: {
+                if (!parseUnknownField(input, unknownFields,
+                                       extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+              case 10: {
+                if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                  settings_ = com.google.protobuf.MapField.newMapField(
+                      SettingsDefaultEntryHolder.defaultEntry);
+                  mutable_bitField0_ |= 0x00000001;
+                }
+                com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
+                settings = input.readMessage(
+                    SettingsDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+                settings_.getMutableMap().put(settings.getKey(), settings.getValue());
+                break;
+              }
+            }
+          }
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw new RuntimeException(e.setUnfinishedMessage(this));
+        } catch (java.io.IOException e) {
+          throw new RuntimeException(
+              new com.google.protobuf.InvalidProtocolBufferException(
+                  e.getMessage()).setUnfinishedMessage(this));
+        } finally {
+          this.unknownFields = unknownFields.build();
+          makeExtensionsImmutable();
+        }
+      }
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor;
+      }
+
+      @SuppressWarnings({"rawtypes"})
+      protected com.google.protobuf.MapField internalGetMapField(
+          int number) {
+        switch (number) {
+          case 1:
+            return internalGetSettings();
+          default:
+            throw new RuntimeException(
+                "Invalid map field number: " + number);
+        }
+      }
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.class, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.Builder.class);
+      }
+
+      public static final int SETTINGS_FIELD_NUMBER = 1;
+      private static final class SettingsDefaultEntryHolder {
+        static final com.google.protobuf.MapEntry<
+            java.lang.String, java.lang.String> defaultEntry =
+                com.google.protobuf.MapEntry
+                .<java.lang.String, java.lang.String>newDefaultInstance(
+                    org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_descriptor, 
+                    com.google.protobuf.WireFormat.FieldType.STRING,
+                    "",
+                    com.google.protobuf.WireFormat.FieldType.STRING,
+                    "");
+      }
+      private com.google.protobuf.MapField<
+          java.lang.String, java.lang.String> settings_;
+      private com.google.protobuf.MapField<java.lang.String, java.lang.String>
+      internalGetSettings() {
+        if (settings_ == null) {
+          return com.google.protobuf.MapField.emptyMapField(
+              SettingsDefaultEntryHolder.defaultEntry);
+       }
+        return settings_;
+      }
+      /**
+       * <code>map&lt;string, string&gt; settings = 1;</code>
+       */
+
+      public java.util.Map<java.lang.String, java.lang.String> getSettings() {
+        return internalGetSettings().getMap();
+      }
+
+      private byte memoizedIsInitialized = -1;
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized == 1) return true;
+        if (isInitialized == 0) return false;
+
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        for (java.util.Map.Entry<java.lang.String, java.lang.String> entry
+             : internalGetSettings().getMap().entrySet()) {
+          com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
+          settings = SettingsDefaultEntryHolder.defaultEntry.newBuilderForType()
+              .setKey(entry.getKey())
+              .setValue(entry.getValue())
+              .build();
+          output.writeMessage(1, settings);
+        }
+        unknownFields.writeTo(output);
+      }
+
+      private int memoizedSerializedSize = -1;
+      public int getSerializedSize() {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        for (java.util.Map.Entry<java.lang.String, java.lang.String> entry
+             : internalGetSettings().getMap().entrySet()) {
+          com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
+          settings = SettingsDefaultEntryHolder.defaultEntry.newBuilderForType()
+              .setKey(entry.getKey())
+              .setValue(entry.getValue())
+              .build();
+          size += com.google.protobuf.CodedOutputStream
+              .computeMessageSize(1, settings);
+        }
+        size += unknownFields.getSerializedSize();
+        memoizedSerializedSize = size;
+        return size;
+      }
+
+      private static final long serialVersionUID = 0L;
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder() {
+        return DEFAULT_INSTANCE.toBuilder();
+      }
+      public static Builder newBuilder(org.sonarqube.ws.WsBatch.WsProjectResponse.Settings prototype) {
+        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+      }
+      public Builder toBuilder() {
+        return this == DEFAULT_INSTANCE
+            ? new Builder() : new Builder().mergeFrom(this);
+      }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.Settings}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+          // @@protoc_insertion_point(builder_implements:sonarqube.ws.batch.WsProjectResponse.Settings)
+          org.sonarqube.ws.WsBatch.WsProjectResponse.SettingsOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor;
+        }
+
+        @SuppressWarnings({"rawtypes"})
+        protected com.google.protobuf.MapField internalGetMapField(
+            int number) {
+          switch (number) {
+            case 1:
+              return internalGetSettings();
+            default:
+              throw new RuntimeException(
+                  "Invalid map field number: " + number);
+          }
+        }
+        @SuppressWarnings({"rawtypes"})
+        protected com.google.protobuf.MapField internalGetMutableMapField(
+            int number) {
+          switch (number) {
+            case 1:
+              return internalGetMutableSettings();
+            default:
+              throw new RuntimeException(
+                  "Invalid map field number: " + number);
+          }
+        }
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.class, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.Builder.class);
+        }
+
+        // Construct using org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.newBuilder()
+        private Builder() {
+          maybeForceBuilderInitialization();
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+          super(parent);
+          maybeForceBuilderInitialization();
+        }
+        private void maybeForceBuilderInitialization() {
+          if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          }
+        }
+        public Builder clear() {
+          super.clear();
+          internalGetMutableSettings().clear();
+          return this;
+        }
+
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.Settings getDefaultInstanceForType() {
+          return org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.getDefaultInstance();
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.Settings build() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.Settings result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.Settings buildPartial() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.Settings result = new org.sonarqube.ws.WsBatch.WsProjectResponse.Settings(this);
+          int from_bitField0_ = bitField0_;
+          result.settings_ = internalGetSettings();
+          result.settings_.makeImmutable();
+          onBuilt();
+          return result;
+        }
+
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof org.sonarqube.ws.WsBatch.WsProjectResponse.Settings) {
+            return mergeFrom((org.sonarqube.ws.WsBatch.WsProjectResponse.Settings)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(org.sonarqube.ws.WsBatch.WsProjectResponse.Settings other) {
+          if (other == org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.getDefaultInstance()) return this;
+          internalGetMutableSettings().mergeFrom(
+              other.internalGetSettings());
+          this.mergeUnknownFields(other.unknownFields);
+          onChanged();
+          return this;
+        }
+
+        public final boolean isInitialized() {
+          return true;
+        }
+
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.Settings parsedMessage = null;
+          try {
+            parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            parsedMessage = (org.sonarqube.ws.WsBatch.WsProjectResponse.Settings) e.getUnfinishedMessage();
+            throw e;
+          } finally {
+            if (parsedMessage != null) {
+              mergeFrom(parsedMessage);
+            }
+          }
+          return this;
+        }
+        private int bitField0_;
+
+        private com.google.protobuf.MapField<
+            java.lang.String, java.lang.String> settings_;
+        private com.google.protobuf.MapField<java.lang.String, java.lang.String>
+        internalGetSettings() {
+          if (settings_ == null) {
+            return com.google.protobuf.MapField.emptyMapField(
+                SettingsDefaultEntryHolder.defaultEntry);
+         }
+          return settings_;
+        }
+        private com.google.protobuf.MapField<java.lang.String, java.lang.String>
+        internalGetMutableSettings() {
+          onChanged();;
+          if (settings_ == null) {
+            settings_ = com.google.protobuf.MapField.newMapField(
+                SettingsDefaultEntryHolder.defaultEntry);
+          }
+          if (!settings_.isMutable()) {
+            settings_ = settings_.copy();
+          }
+          return settings_;
+        }
+        /**
+         * <code>map&lt;string, string&gt; settings = 1;</code>
+         */
+        public java.util.Map<java.lang.String, java.lang.String> getSettings() {
+          return internalGetSettings().getMap();
+        }
+        /**
+         * <code>map&lt;string, string&gt; settings = 1;</code>
+         */
+        public java.util.Map<java.lang.String, java.lang.String>
+        getMutableSettings() {
+          return internalGetMutableSettings().getMutableMap();
+        }
+
+        // @@protoc_insertion_point(builder_scope:sonarqube.ws.batch.WsProjectResponse.Settings)
+      }
+
+      // @@protoc_insertion_point(class_scope:sonarqube.ws.batch.WsProjectResponse.Settings)
+      private static final org.sonarqube.ws.WsBatch.WsProjectResponse.Settings DEFAULT_INSTANCE;
+      static {
+        DEFAULT_INSTANCE = new org.sonarqube.ws.WsBatch.WsProjectResponse.Settings();
+      }
+
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.Settings getDefaultInstance() {
+        return DEFAULT_INSTANCE;
+      }
+
+      public static final com.google.protobuf.Parser<Settings> PARSER =
+          new com.google.protobuf.AbstractParser<Settings>() {
+        public Settings parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          try {
+            return new Settings(input, extensionRegistry);
+          } catch (RuntimeException e) {
+            if (e.getCause() instanceof
+                com.google.protobuf.InvalidProtocolBufferException) {
+              throw (com.google.protobuf.InvalidProtocolBufferException)
+                  e.getCause();
+            }
+            throw e;
+          }
+        }
+      };
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<Settings> getParserForType() {
+        return PARSER;
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse.Settings getDefaultInstanceForType() {
+        return DEFAULT_INSTANCE;
+      }
+
+    }
+
+    public interface FileDataByPathOrBuilder extends
+        // @@protoc_insertion_point(interface_extends:sonarqube.ws.batch.WsProjectResponse.FileDataByPath)
+        com.google.protobuf.MessageOrBuilder {
+
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileData&gt; FileDataByPath = 1;</code>
+       */
+      java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+      getFileDataByPath();
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.FileDataByPath}
+     */
+    public  static final class FileDataByPath extends
+        com.google.protobuf.GeneratedMessage implements
+        // @@protoc_insertion_point(message_implements:sonarqube.ws.batch.WsProjectResponse.FileDataByPath)
+        FileDataByPathOrBuilder {
+      // Use FileDataByPath.newBuilder() to construct.
+      private FileDataByPath(com.google.protobuf.GeneratedMessage.Builder builder) {
+        super(builder);
+      }
+      private FileDataByPath() {
+      }
+
+      @java.lang.Override
+      public final com.google.protobuf.UnknownFieldSet
+      getUnknownFields() {
+        return this.unknownFields;
+      }
+      private FileDataByPath(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry) {
+        this();
+        int mutable_bitField0_ = 0;
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+            com.google.protobuf.UnknownFieldSet.newBuilder();
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              default: {
+                if (!parseUnknownField(input, unknownFields,
+                                       extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+              case 10: {
+                if (!((mutable_bitField0_ & 0x00000001) == 0x00000001)) {
+                  fileDataByPath_ = com.google.protobuf.MapField.newMapField(
+                      FileDataByPathDefaultEntryHolder.defaultEntry);
+                  mutable_bitField0_ |= 0x00000001;
+                }
+                com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+                fileDataByPath = input.readMessage(
+                    FileDataByPathDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
+                fileDataByPath_.getMutableMap().put(fileDataByPath.getKey(), fileDataByPath.getValue());
+                break;
+              }
+            }
+          }
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw new RuntimeException(e.setUnfinishedMessage(this));
+        } catch (java.io.IOException e) {
+          throw new RuntimeException(
+              new com.google.protobuf.InvalidProtocolBufferException(
+                  e.getMessage()).setUnfinishedMessage(this));
+        } finally {
+          this.unknownFields = unknownFields.build();
+          makeExtensionsImmutable();
+        }
+      }
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor;
+      }
+
+      @SuppressWarnings({"rawtypes"})
+      protected com.google.protobuf.MapField internalGetMapField(
+          int number) {
+        switch (number) {
+          case 1:
+            return internalGetFileDataByPath();
+          default:
+            throw new RuntimeException(
+                "Invalid map field number: " + number);
+        }
+      }
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.class, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.Builder.class);
+      }
+
+      public static final int FILEDATABYPATH_FIELD_NUMBER = 1;
+      private static final class FileDataByPathDefaultEntryHolder {
+        static final com.google.protobuf.MapEntry<
+            java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> defaultEntry =
+                com.google.protobuf.MapEntry
+                .<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>newDefaultInstance(
+                    org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_descriptor, 
+                    com.google.protobuf.WireFormat.FieldType.STRING,
+                    "",
+                    com.google.protobuf.WireFormat.FieldType.MESSAGE,
+                    org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.getDefaultInstance());
+      }
+      private com.google.protobuf.MapField<
+          java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> fileDataByPath_;
+      private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+      internalGetFileDataByPath() {
+        if (fileDataByPath_ == null) {
+          return com.google.protobuf.MapField.emptyMapField(
+              FileDataByPathDefaultEntryHolder.defaultEntry);
+       }
+        return fileDataByPath_;
+      }
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileData&gt; FileDataByPath = 1;</code>
+       */
+
+      public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> getFileDataByPath() {
+        return internalGetFileDataByPath().getMap();
+      }
+
+      private byte memoizedIsInitialized = -1;
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized == 1) return true;
+        if (isInitialized == 0) return false;
+
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> entry
+             : internalGetFileDataByPath().getMap().entrySet()) {
+          com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+          fileDataByPath = FileDataByPathDefaultEntryHolder.defaultEntry.newBuilderForType()
+              .setKey(entry.getKey())
+              .setValue(entry.getValue())
+              .build();
+          output.writeMessage(1, fileDataByPath);
+        }
+        unknownFields.writeTo(output);
+      }
+
+      private int memoizedSerializedSize = -1;
+      public int getSerializedSize() {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> entry
+             : internalGetFileDataByPath().getMap().entrySet()) {
+          com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+          fileDataByPath = FileDataByPathDefaultEntryHolder.defaultEntry.newBuilderForType()
+              .setKey(entry.getKey())
+              .setValue(entry.getValue())
+              .build();
+          size += com.google.protobuf.CodedOutputStream
+              .computeMessageSize(1, fileDataByPath);
+        }
+        size += unknownFields.getSerializedSize();
+        memoizedSerializedSize = size;
+        return size;
+      }
+
+      private static final long serialVersionUID = 0L;
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder() {
+        return DEFAULT_INSTANCE.toBuilder();
+      }
+      public static Builder newBuilder(org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath prototype) {
+        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+      }
+      public Builder toBuilder() {
+        return this == DEFAULT_INSTANCE
+            ? new Builder() : new Builder().mergeFrom(this);
+      }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.FileDataByPath}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+          // @@protoc_insertion_point(builder_implements:sonarqube.ws.batch.WsProjectResponse.FileDataByPath)
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPathOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor;
+        }
+
+        @SuppressWarnings({"rawtypes"})
+        protected com.google.protobuf.MapField internalGetMapField(
+            int number) {
+          switch (number) {
+            case 1:
+              return internalGetFileDataByPath();
+            default:
+              throw new RuntimeException(
+                  "Invalid map field number: " + number);
+          }
+        }
+        @SuppressWarnings({"rawtypes"})
+        protected com.google.protobuf.MapField internalGetMutableMapField(
+            int number) {
+          switch (number) {
+            case 1:
+              return internalGetMutableFileDataByPath();
+            default:
+              throw new RuntimeException(
+                  "Invalid map field number: " + number);
+          }
+        }
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.class, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.Builder.class);
+        }
+
+        // Construct using org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.newBuilder()
+        private Builder() {
+          maybeForceBuilderInitialization();
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+          super(parent);
+          maybeForceBuilderInitialization();
+        }
+        private void maybeForceBuilderInitialization() {
+          if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          }
+        }
+        public Builder clear() {
+          super.clear();
+          internalGetMutableFileDataByPath().clear();
+          return this;
+        }
+
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath getDefaultInstanceForType() {
+          return org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.getDefaultInstance();
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath build() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath buildPartial() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath result = new org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath(this);
+          int from_bitField0_ = bitField0_;
+          result.fileDataByPath_ = internalGetFileDataByPath();
+          result.fileDataByPath_.makeImmutable();
+          onBuilt();
+          return result;
+        }
+
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath) {
+            return mergeFrom((org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath other) {
+          if (other == org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.getDefaultInstance()) return this;
+          internalGetMutableFileDataByPath().mergeFrom(
+              other.internalGetFileDataByPath());
+          this.mergeUnknownFields(other.unknownFields);
+          onChanged();
+          return this;
+        }
+
+        public final boolean isInitialized() {
+          return true;
+        }
+
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath parsedMessage = null;
+          try {
+            parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            parsedMessage = (org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath) e.getUnfinishedMessage();
+            throw e;
+          } finally {
+            if (parsedMessage != null) {
+              mergeFrom(parsedMessage);
+            }
+          }
+          return this;
+        }
+        private int bitField0_;
+
+        private com.google.protobuf.MapField<
+            java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> fileDataByPath_;
+        private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+        internalGetFileDataByPath() {
+          if (fileDataByPath_ == null) {
+            return com.google.protobuf.MapField.emptyMapField(
+                FileDataByPathDefaultEntryHolder.defaultEntry);
+         }
+          return fileDataByPath_;
+        }
+        private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+        internalGetMutableFileDataByPath() {
+          onChanged();;
+          if (fileDataByPath_ == null) {
+            fileDataByPath_ = com.google.protobuf.MapField.newMapField(
+                FileDataByPathDefaultEntryHolder.defaultEntry);
+          }
+          if (!fileDataByPath_.isMutable()) {
+            fileDataByPath_ = fileDataByPath_.copy();
+          }
+          return fileDataByPath_;
+        }
+        /**
+         * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileData&gt; FileDataByPath = 1;</code>
+         */
+        public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData> getFileDataByPath() {
+          return internalGetFileDataByPath().getMap();
+        }
+        /**
+         * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileData&gt; FileDataByPath = 1;</code>
+         */
+        public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData>
+        getMutableFileDataByPath() {
+          return internalGetMutableFileDataByPath().getMutableMap();
+        }
+
+        // @@protoc_insertion_point(builder_scope:sonarqube.ws.batch.WsProjectResponse.FileDataByPath)
+      }
+
+      // @@protoc_insertion_point(class_scope:sonarqube.ws.batch.WsProjectResponse.FileDataByPath)
+      private static final org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath DEFAULT_INSTANCE;
+      static {
+        DEFAULT_INSTANCE = new org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath();
+      }
+
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath getDefaultInstance() {
+        return DEFAULT_INSTANCE;
+      }
+
+      public static final com.google.protobuf.Parser<FileDataByPath> PARSER =
+          new com.google.protobuf.AbstractParser<FileDataByPath>() {
+        public FileDataByPath parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          try {
+            return new FileDataByPath(input, extensionRegistry);
+          } catch (RuntimeException e) {
+            if (e.getCause() instanceof
+                com.google.protobuf.InvalidProtocolBufferException) {
+              throw (com.google.protobuf.InvalidProtocolBufferException)
+                  e.getCause();
+            }
+            throw e;
+          }
+        }
+      };
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<FileDataByPath> getParserForType() {
+        return PARSER;
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath getDefaultInstanceForType() {
+        return DEFAULT_INSTANCE;
+      }
+
+    }
+
+    public interface FileDataOrBuilder extends
+        // @@protoc_insertion_point(interface_extends:sonarqube.ws.batch.WsProjectResponse.FileData)
+        com.google.protobuf.MessageOrBuilder {
+
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      boolean hasHash();
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      java.lang.String getHash();
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      com.google.protobuf.ByteString
+          getHashBytes();
+
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      boolean hasRevision();
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      java.lang.String getRevision();
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      com.google.protobuf.ByteString
+          getRevisionBytes();
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.FileData}
+     */
+    public  static final class FileData extends
+        com.google.protobuf.GeneratedMessage implements
+        // @@protoc_insertion_point(message_implements:sonarqube.ws.batch.WsProjectResponse.FileData)
+        FileDataOrBuilder {
+      // Use FileData.newBuilder() to construct.
+      private FileData(com.google.protobuf.GeneratedMessage.Builder builder) {
+        super(builder);
+      }
+      private FileData() {
+        hash_ = "";
+        revision_ = "";
+      }
+
+      @java.lang.Override
+      public final com.google.protobuf.UnknownFieldSet
+      getUnknownFields() {
+        return this.unknownFields;
+      }
+      private FileData(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry) {
+        this();
+        int mutable_bitField0_ = 0;
+        com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+            com.google.protobuf.UnknownFieldSet.newBuilder();
+        try {
+          boolean done = false;
+          while (!done) {
+            int tag = input.readTag();
+            switch (tag) {
+              case 0:
+                done = true;
+                break;
+              default: {
+                if (!parseUnknownField(input, unknownFields,
+                                       extensionRegistry, tag)) {
+                  done = true;
+                }
+                break;
+              }
+              case 10: {
+                com.google.protobuf.ByteString bs = input.readBytes();
+                bitField0_ |= 0x00000001;
+                hash_ = bs;
+                break;
+              }
+              case 18: {
+                com.google.protobuf.ByteString bs = input.readBytes();
+                bitField0_ |= 0x00000002;
+                revision_ = bs;
+                break;
+              }
+            }
+          }
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          throw new RuntimeException(e.setUnfinishedMessage(this));
+        } catch (java.io.IOException e) {
+          throw new RuntimeException(
+              new com.google.protobuf.InvalidProtocolBufferException(
+                  e.getMessage()).setUnfinishedMessage(this));
+        } finally {
+          this.unknownFields = unknownFields.build();
+          makeExtensionsImmutable();
+        }
+      }
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.class, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.Builder.class);
+      }
+
+      private int bitField0_;
+      public static final int HASH_FIELD_NUMBER = 1;
+      private volatile java.lang.Object hash_;
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      public boolean hasHash() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      public java.lang.String getHash() {
+        java.lang.Object ref = hash_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            hash_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>optional string hash = 1;</code>
+       */
+      public com.google.protobuf.ByteString
+          getHashBytes() {
+        java.lang.Object ref = hash_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          hash_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      public static final int REVISION_FIELD_NUMBER = 2;
+      private volatile java.lang.Object revision_;
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      public boolean hasRevision() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      public java.lang.String getRevision() {
+        java.lang.Object ref = revision_;
+        if (ref instanceof java.lang.String) {
+          return (java.lang.String) ref;
+        } else {
+          com.google.protobuf.ByteString bs = 
+              (com.google.protobuf.ByteString) ref;
+          java.lang.String s = bs.toStringUtf8();
+          if (bs.isValidUtf8()) {
+            revision_ = s;
+          }
+          return s;
+        }
+      }
+      /**
+       * <code>optional string revision = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getRevisionBytes() {
+        java.lang.Object ref = revision_;
+        if (ref instanceof java.lang.String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          revision_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+
+      private byte memoizedIsInitialized = -1;
+      public final boolean isInitialized() {
+        byte isInitialized = memoizedIsInitialized;
+        if (isInitialized == 1) return true;
+        if (isInitialized == 0) return false;
+
+        memoizedIsInitialized = 1;
+        return true;
+      }
+
+      public void writeTo(com.google.protobuf.CodedOutputStream output)
+                          throws java.io.IOException {
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          output.writeBytes(1, getHashBytes());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          output.writeBytes(2, getRevisionBytes());
+        }
+        unknownFields.writeTo(output);
+      }
+
+      private int memoizedSerializedSize = -1;
+      public int getSerializedSize() {
+        int size = memoizedSerializedSize;
+        if (size != -1) return size;
+
+        size = 0;
+        if (((bitField0_ & 0x00000001) == 0x00000001)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(1, getHashBytes());
+        }
+        if (((bitField0_ & 0x00000002) == 0x00000002)) {
+          size += com.google.protobuf.CodedOutputStream
+            .computeBytesSize(2, getRevisionBytes());
+        }
+        size += unknownFields.getSerializedSize();
+        memoizedSerializedSize = size;
+        return size;
+      }
+
+      private static final long serialVersionUID = 0L;
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          com.google.protobuf.ByteString data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          com.google.protobuf.ByteString data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(byte[] data)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          byte[] data,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return PARSER.parseFrom(data, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseDelimitedFrom(java.io.InputStream input)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseDelimitedFrom(
+          java.io.InputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseDelimitedFrom(input, extensionRegistry);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          com.google.protobuf.CodedInputStream input)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input);
+      }
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parseFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        return PARSER.parseFrom(input, extensionRegistry);
+      }
+
+      public Builder newBuilderForType() { return newBuilder(); }
+      public static Builder newBuilder() {
+        return DEFAULT_INSTANCE.toBuilder();
+      }
+      public static Builder newBuilder(org.sonarqube.ws.WsBatch.WsProjectResponse.FileData prototype) {
+        return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+      }
+      public Builder toBuilder() {
+        return this == DEFAULT_INSTANCE
+            ? new Builder() : new Builder().mergeFrom(this);
+      }
+
+      @java.lang.Override
+      protected Builder newBuilderForType(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        Builder builder = new Builder(parent);
+        return builder;
+      }
+      /**
+       * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse.FileData}
+       */
+      public static final class Builder extends
+          com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+          // @@protoc_insertion_point(builder_implements:sonarqube.ws.batch.WsProjectResponse.FileData)
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataOrBuilder {
+        public static final com.google.protobuf.Descriptors.Descriptor
+            getDescriptor() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor;
+        }
+
+        protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+            internalGetFieldAccessorTable() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_fieldAccessorTable
+              .ensureFieldAccessorsInitialized(
+                  org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.class, org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.Builder.class);
+        }
+
+        // Construct using org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.newBuilder()
+        private Builder() {
+          maybeForceBuilderInitialization();
+        }
+
+        private Builder(
+            com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+          super(parent);
+          maybeForceBuilderInitialization();
+        }
+        private void maybeForceBuilderInitialization() {
+          if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          }
+        }
+        public Builder clear() {
+          super.clear();
+          hash_ = "";
+          bitField0_ = (bitField0_ & ~0x00000001);
+          revision_ = "";
+          bitField0_ = (bitField0_ & ~0x00000002);
+          return this;
+        }
+
+        public com.google.protobuf.Descriptors.Descriptor
+            getDescriptorForType() {
+          return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileData getDefaultInstanceForType() {
+          return org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.getDefaultInstance();
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileData build() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileData result = buildPartial();
+          if (!result.isInitialized()) {
+            throw newUninitializedMessageException(result);
+          }
+          return result;
+        }
+
+        public org.sonarqube.ws.WsBatch.WsProjectResponse.FileData buildPartial() {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileData result = new org.sonarqube.ws.WsBatch.WsProjectResponse.FileData(this);
+          int from_bitField0_ = bitField0_;
+          int to_bitField0_ = 0;
+          if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+            to_bitField0_ |= 0x00000001;
+          }
+          result.hash_ = hash_;
+          if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+            to_bitField0_ |= 0x00000002;
+          }
+          result.revision_ = revision_;
+          result.bitField0_ = to_bitField0_;
+          onBuilt();
+          return result;
+        }
+
+        public Builder mergeFrom(com.google.protobuf.Message other) {
+          if (other instanceof org.sonarqube.ws.WsBatch.WsProjectResponse.FileData) {
+            return mergeFrom((org.sonarqube.ws.WsBatch.WsProjectResponse.FileData)other);
+          } else {
+            super.mergeFrom(other);
+            return this;
+          }
+        }
+
+        public Builder mergeFrom(org.sonarqube.ws.WsBatch.WsProjectResponse.FileData other) {
+          if (other == org.sonarqube.ws.WsBatch.WsProjectResponse.FileData.getDefaultInstance()) return this;
+          if (other.hasHash()) {
+            bitField0_ |= 0x00000001;
+            hash_ = other.hash_;
+            onChanged();
+          }
+          if (other.hasRevision()) {
+            bitField0_ |= 0x00000002;
+            revision_ = other.revision_;
+            onChanged();
+          }
+          this.mergeUnknownFields(other.unknownFields);
+          onChanged();
+          return this;
+        }
+
+        public final boolean isInitialized() {
+          return true;
+        }
+
+        public Builder mergeFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws java.io.IOException {
+          org.sonarqube.ws.WsBatch.WsProjectResponse.FileData parsedMessage = null;
+          try {
+            parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+          } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+            parsedMessage = (org.sonarqube.ws.WsBatch.WsProjectResponse.FileData) e.getUnfinishedMessage();
+            throw e;
+          } finally {
+            if (parsedMessage != null) {
+              mergeFrom(parsedMessage);
+            }
+          }
+          return this;
+        }
+        private int bitField0_;
+
+        private java.lang.Object hash_ = "";
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public boolean hasHash() {
+          return ((bitField0_ & 0x00000001) == 0x00000001);
+        }
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public java.lang.String getHash() {
+          java.lang.Object ref = hash_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            if (bs.isValidUtf8()) {
+              hash_ = s;
+            }
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public com.google.protobuf.ByteString
+            getHashBytes() {
+          java.lang.Object ref = hash_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            hash_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public Builder setHash(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+          hash_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public Builder clearHash() {
+          bitField0_ = (bitField0_ & ~0x00000001);
+          hash_ = getDefaultInstance().getHash();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string hash = 1;</code>
+         */
+        public Builder setHashBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000001;
+          hash_ = value;
+          onChanged();
+          return this;
+        }
+
+        private java.lang.Object revision_ = "";
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public boolean hasRevision() {
+          return ((bitField0_ & 0x00000002) == 0x00000002);
+        }
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public java.lang.String getRevision() {
+          java.lang.Object ref = revision_;
+          if (!(ref instanceof java.lang.String)) {
+            com.google.protobuf.ByteString bs =
+                (com.google.protobuf.ByteString) ref;
+            java.lang.String s = bs.toStringUtf8();
+            if (bs.isValidUtf8()) {
+              revision_ = s;
+            }
+            return s;
+          } else {
+            return (java.lang.String) ref;
+          }
+        }
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public com.google.protobuf.ByteString
+            getRevisionBytes() {
+          java.lang.Object ref = revision_;
+          if (ref instanceof String) {
+            com.google.protobuf.ByteString b = 
+                com.google.protobuf.ByteString.copyFromUtf8(
+                    (java.lang.String) ref);
+            revision_ = b;
+            return b;
+          } else {
+            return (com.google.protobuf.ByteString) ref;
+          }
+        }
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public Builder setRevision(
+            java.lang.String value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          revision_ = value;
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public Builder clearRevision() {
+          bitField0_ = (bitField0_ & ~0x00000002);
+          revision_ = getDefaultInstance().getRevision();
+          onChanged();
+          return this;
+        }
+        /**
+         * <code>optional string revision = 2;</code>
+         */
+        public Builder setRevisionBytes(
+            com.google.protobuf.ByteString value) {
+          if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+          revision_ = value;
+          onChanged();
+          return this;
+        }
+
+        // @@protoc_insertion_point(builder_scope:sonarqube.ws.batch.WsProjectResponse.FileData)
+      }
+
+      // @@protoc_insertion_point(class_scope:sonarqube.ws.batch.WsProjectResponse.FileData)
+      private static final org.sonarqube.ws.WsBatch.WsProjectResponse.FileData DEFAULT_INSTANCE;
+      static {
+        DEFAULT_INSTANCE = new org.sonarqube.ws.WsBatch.WsProjectResponse.FileData();
+      }
+
+      public static org.sonarqube.ws.WsBatch.WsProjectResponse.FileData getDefaultInstance() {
+        return DEFAULT_INSTANCE;
+      }
+
+      public static final com.google.protobuf.Parser<FileData> PARSER =
+          new com.google.protobuf.AbstractParser<FileData>() {
+        public FileData parsePartialFrom(
+            com.google.protobuf.CodedInputStream input,
+            com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+            throws com.google.protobuf.InvalidProtocolBufferException {
+          try {
+            return new FileData(input, extensionRegistry);
+          } catch (RuntimeException e) {
+            if (e.getCause() instanceof
+                com.google.protobuf.InvalidProtocolBufferException) {
+              throw (com.google.protobuf.InvalidProtocolBufferException)
+                  e.getCause();
+            }
+            throw e;
+          }
+        }
+      };
+
+      @java.lang.Override
+      public com.google.protobuf.Parser<FileData> getParserForType() {
+        return PARSER;
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse.FileData getDefaultInstanceForType() {
+        return DEFAULT_INSTANCE;
+      }
+
+    }
+
+    private int bitField0_;
+    public static final int TIMESTAMP_FIELD_NUMBER = 1;
+    private long timestamp_;
+    /**
+     * <code>optional int64 timestamp = 1;</code>
+     */
+    public boolean hasTimestamp() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional int64 timestamp = 1;</code>
+     */
+    public long getTimestamp() {
+      return timestamp_;
+    }
+
+    public static final int SETTINGSBYMODULE_FIELD_NUMBER = 2;
+    private static final class SettingsByModuleDefaultEntryHolder {
+      static final com.google.protobuf.MapEntry<
+          java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> defaultEntry =
+              com.google.protobuf.MapEntry
+              .<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>newDefaultInstance(
+                  org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_descriptor, 
+                  com.google.protobuf.WireFormat.FieldType.STRING,
+                  "",
+                  com.google.protobuf.WireFormat.FieldType.MESSAGE,
+                  org.sonarqube.ws.WsBatch.WsProjectResponse.Settings.getDefaultInstance());
+    }
+    private com.google.protobuf.MapField<
+        java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> settingsByModule_;
+    private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+    internalGetSettingsByModule() {
+      if (settingsByModule_ == null) {
+        return com.google.protobuf.MapField.emptyMapField(
+            SettingsByModuleDefaultEntryHolder.defaultEntry);
+     }
+      return settingsByModule_;
+    }
+    /**
+     * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.Settings&gt; settingsByModule = 2;</code>
+     */
+
+    public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> getSettingsByModule() {
+      return internalGetSettingsByModule().getMap();
+    }
+
+    public static final int FILEDATABYMODULEANDPATCH_FIELD_NUMBER = 3;
+    private static final class FileDataByModuleAndPatchDefaultEntryHolder {
+      static final com.google.protobuf.MapEntry<
+          java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> defaultEntry =
+              com.google.protobuf.MapEntry
+              .<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>newDefaultInstance(
+                  org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_descriptor, 
+                  com.google.protobuf.WireFormat.FieldType.STRING,
+                  "",
+                  com.google.protobuf.WireFormat.FieldType.MESSAGE,
+                  org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath.getDefaultInstance());
+    }
+    private com.google.protobuf.MapField<
+        java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> fileDataByModuleAndPatch_;
+    private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+    internalGetFileDataByModuleAndPatch() {
+      if (fileDataByModuleAndPatch_ == null) {
+        return com.google.protobuf.MapField.emptyMapField(
+            FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry);
+     }
+      return fileDataByModuleAndPatch_;
+    }
+    /**
+     * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileDataByPath&gt; fileDataByModuleAndPatch = 3;</code>
+     */
+
+    public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> getFileDataByModuleAndPatch() {
+      return internalGetFileDataByModuleAndPatch().getMap();
+    }
+
+    public static final int LASTANALYSISDATE_FIELD_NUMBER = 4;
+    private long lastAnalysisDate_;
+    /**
+     * <code>optional int64 lastAnalysisDate = 4;</code>
+     */
+    public boolean hasLastAnalysisDate() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional int64 lastAnalysisDate = 4;</code>
+     */
+    public long getLastAnalysisDate() {
+      return lastAnalysisDate_;
+    }
+
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized == 1) return true;
+      if (isInitialized == 0) return false;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeInt64(1, timestamp_);
+      }
+      for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> entry
+           : internalGetSettingsByModule().getMap().entrySet()) {
+        com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+        settingsByModule = SettingsByModuleDefaultEntryHolder.defaultEntry.newBuilderForType()
+            .setKey(entry.getKey())
+            .setValue(entry.getValue())
+            .build();
+        output.writeMessage(2, settingsByModule);
+      }
+      for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> entry
+           : internalGetFileDataByModuleAndPatch().getMap().entrySet()) {
+        com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+        fileDataByModuleAndPatch = FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry.newBuilderForType()
+            .setKey(entry.getKey())
+            .setValue(entry.getValue())
+            .build();
+        output.writeMessage(3, fileDataByModuleAndPatch);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeInt64(4, lastAnalysisDate_);
+      }
+      unknownFields.writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(1, timestamp_);
+      }
+      for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> entry
+           : internalGetSettingsByModule().getMap().entrySet()) {
+        com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+        settingsByModule = SettingsByModuleDefaultEntryHolder.defaultEntry.newBuilderForType()
+            .setKey(entry.getKey())
+            .setValue(entry.getValue())
+            .build();
+        size += com.google.protobuf.CodedOutputStream
+            .computeMessageSize(2, settingsByModule);
+      }
+      for (java.util.Map.Entry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> entry
+           : internalGetFileDataByModuleAndPatch().getMap().entrySet()) {
+        com.google.protobuf.MapEntry<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+        fileDataByModuleAndPatch = FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry.newBuilderForType()
+            .setKey(entry.getKey())
+            .setValue(entry.getValue())
+            .build();
+        size += com.google.protobuf.CodedOutputStream
+            .computeMessageSize(3, fileDataByModuleAndPatch);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(4, lastAnalysisDate_);
+      }
+      size += unknownFields.getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder() {
+      return DEFAULT_INSTANCE.toBuilder();
+    }
+    public static Builder newBuilder(org.sonarqube.ws.WsBatch.WsProjectResponse prototype) {
+      return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() {
+      return this == DEFAULT_INSTANCE
+          ? new Builder() : new Builder().mergeFrom(this);
+    }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code sonarqube.ws.batch.WsProjectResponse}
+     *
+     * <pre>
+     * WS api/batch/project
+     * </pre>
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder> implements
+        // @@protoc_insertion_point(builder_implements:sonarqube.ws.batch.WsProjectResponse)
+        org.sonarqube.ws.WsBatch.WsProjectResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor;
+      }
+
+      @SuppressWarnings({"rawtypes"})
+      protected com.google.protobuf.MapField internalGetMapField(
+          int number) {
+        switch (number) {
+          case 2:
+            return internalGetSettingsByModule();
+          case 3:
+            return internalGetFileDataByModuleAndPatch();
+          default:
+            throw new RuntimeException(
+                "Invalid map field number: " + number);
+        }
+      }
+      @SuppressWarnings({"rawtypes"})
+      protected com.google.protobuf.MapField internalGetMutableMapField(
+          int number) {
+        switch (number) {
+          case 2:
+            return internalGetMutableSettingsByModule();
+          case 3:
+            return internalGetMutableFileDataByModuleAndPatch();
+          default:
+            throw new RuntimeException(
+                "Invalid map field number: " + number);
+        }
+      }
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.sonarqube.ws.WsBatch.WsProjectResponse.class, org.sonarqube.ws.WsBatch.WsProjectResponse.Builder.class);
+      }
+
+      // Construct using org.sonarqube.ws.WsBatch.WsProjectResponse.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      public Builder clear() {
+        super.clear();
+        timestamp_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        internalGetMutableSettingsByModule().clear();
+        internalGetMutableFileDataByModuleAndPatch().clear();
+        lastAnalysisDate_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        return this;
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.sonarqube.ws.WsBatch.internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor;
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse getDefaultInstanceForType() {
+        return org.sonarqube.ws.WsBatch.WsProjectResponse.getDefaultInstance();
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse build() {
+        org.sonarqube.ws.WsBatch.WsProjectResponse result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.sonarqube.ws.WsBatch.WsProjectResponse buildPartial() {
+        org.sonarqube.ws.WsBatch.WsProjectResponse result = new org.sonarqube.ws.WsBatch.WsProjectResponse(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.timestamp_ = timestamp_;
+        result.settingsByModule_ = internalGetSettingsByModule();
+        result.settingsByModule_.makeImmutable();
+        result.fileDataByModuleAndPatch_ = internalGetFileDataByModuleAndPatch();
+        result.fileDataByModuleAndPatch_.makeImmutable();
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.lastAnalysisDate_ = lastAnalysisDate_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.sonarqube.ws.WsBatch.WsProjectResponse) {
+          return mergeFrom((org.sonarqube.ws.WsBatch.WsProjectResponse)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.sonarqube.ws.WsBatch.WsProjectResponse other) {
+        if (other == org.sonarqube.ws.WsBatch.WsProjectResponse.getDefaultInstance()) return this;
+        if (other.hasTimestamp()) {
+          setTimestamp(other.getTimestamp());
+        }
+        internalGetMutableSettingsByModule().mergeFrom(
+            other.internalGetSettingsByModule());
+        internalGetMutableFileDataByModuleAndPatch().mergeFrom(
+            other.internalGetFileDataByModuleAndPatch());
+        if (other.hasLastAnalysisDate()) {
+          setLastAnalysisDate(other.getLastAnalysisDate());
+        }
+        this.mergeUnknownFields(other.unknownFields);
+        onChanged();
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.sonarqube.ws.WsBatch.WsProjectResponse parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.sonarqube.ws.WsBatch.WsProjectResponse) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      private long timestamp_ ;
+      /**
+       * <code>optional int64 timestamp = 1;</code>
+       */
+      public boolean hasTimestamp() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional int64 timestamp = 1;</code>
+       */
+      public long getTimestamp() {
+        return timestamp_;
+      }
+      /**
+       * <code>optional int64 timestamp = 1;</code>
+       */
+      public Builder setTimestamp(long value) {
+        bitField0_ |= 0x00000001;
+        timestamp_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 timestamp = 1;</code>
+       */
+      public Builder clearTimestamp() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        timestamp_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      private com.google.protobuf.MapField<
+          java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> settingsByModule_;
+      private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+      internalGetSettingsByModule() {
+        if (settingsByModule_ == null) {
+          return com.google.protobuf.MapField.emptyMapField(
+              SettingsByModuleDefaultEntryHolder.defaultEntry);
+       }
+        return settingsByModule_;
+      }
+      private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+      internalGetMutableSettingsByModule() {
+        onChanged();;
+        if (settingsByModule_ == null) {
+          settingsByModule_ = com.google.protobuf.MapField.newMapField(
+              SettingsByModuleDefaultEntryHolder.defaultEntry);
+        }
+        if (!settingsByModule_.isMutable()) {
+          settingsByModule_ = settingsByModule_.copy();
+        }
+        return settingsByModule_;
+      }
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.Settings&gt; settingsByModule = 2;</code>
+       */
+      public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings> getSettingsByModule() {
+        return internalGetSettingsByModule().getMap();
+      }
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.Settings&gt; settingsByModule = 2;</code>
+       */
+      public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.Settings>
+      getMutableSettingsByModule() {
+        return internalGetMutableSettingsByModule().getMutableMap();
+      }
+
+      private com.google.protobuf.MapField<
+          java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> fileDataByModuleAndPatch_;
+      private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+      internalGetFileDataByModuleAndPatch() {
+        if (fileDataByModuleAndPatch_ == null) {
+          return com.google.protobuf.MapField.emptyMapField(
+              FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry);
+       }
+        return fileDataByModuleAndPatch_;
+      }
+      private com.google.protobuf.MapField<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+      internalGetMutableFileDataByModuleAndPatch() {
+        onChanged();;
+        if (fileDataByModuleAndPatch_ == null) {
+          fileDataByModuleAndPatch_ = com.google.protobuf.MapField.newMapField(
+              FileDataByModuleAndPatchDefaultEntryHolder.defaultEntry);
+        }
+        if (!fileDataByModuleAndPatch_.isMutable()) {
+          fileDataByModuleAndPatch_ = fileDataByModuleAndPatch_.copy();
+        }
+        return fileDataByModuleAndPatch_;
+      }
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileDataByPath&gt; fileDataByModuleAndPatch = 3;</code>
+       */
+      public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath> getFileDataByModuleAndPatch() {
+        return internalGetFileDataByModuleAndPatch().getMap();
+      }
+      /**
+       * <code>map&lt;string, .sonarqube.ws.batch.WsProjectResponse.FileDataByPath&gt; fileDataByModuleAndPatch = 3;</code>
+       */
+      public java.util.Map<java.lang.String, org.sonarqube.ws.WsBatch.WsProjectResponse.FileDataByPath>
+      getMutableFileDataByModuleAndPatch() {
+        return internalGetMutableFileDataByModuleAndPatch().getMutableMap();
+      }
+
+      private long lastAnalysisDate_ ;
+      /**
+       * <code>optional int64 lastAnalysisDate = 4;</code>
+       */
+      public boolean hasLastAnalysisDate() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional int64 lastAnalysisDate = 4;</code>
+       */
+      public long getLastAnalysisDate() {
+        return lastAnalysisDate_;
+      }
+      /**
+       * <code>optional int64 lastAnalysisDate = 4;</code>
+       */
+      public Builder setLastAnalysisDate(long value) {
+        bitField0_ |= 0x00000008;
+        lastAnalysisDate_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 lastAnalysisDate = 4;</code>
+       */
+      public Builder clearLastAnalysisDate() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        lastAnalysisDate_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:sonarqube.ws.batch.WsProjectResponse)
+    }
+
+    // @@protoc_insertion_point(class_scope:sonarqube.ws.batch.WsProjectResponse)
+    private static final org.sonarqube.ws.WsBatch.WsProjectResponse DEFAULT_INSTANCE;
+    static {
+      DEFAULT_INSTANCE = new org.sonarqube.ws.WsBatch.WsProjectResponse();
+    }
+
+    public static org.sonarqube.ws.WsBatch.WsProjectResponse getDefaultInstance() {
+      return DEFAULT_INSTANCE;
+    }
+
+    public static final com.google.protobuf.Parser<WsProjectResponse> PARSER =
+        new com.google.protobuf.AbstractParser<WsProjectResponse>() {
+      public WsProjectResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        try {
+          return new WsProjectResponse(input, extensionRegistry);
+        } catch (RuntimeException e) {
+          if (e.getCause() instanceof
+              com.google.protobuf.InvalidProtocolBufferException) {
+            throw (com.google.protobuf.InvalidProtocolBufferException)
+                e.getCause();
+          }
+          throw e;
+        }
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<WsProjectResponse> getParserForType() {
+      return PARSER;
+    }
+
+    public org.sonarqube.ws.WsBatch.WsProjectResponse getDefaultInstanceForType() {
+      return DEFAULT_INSTANCE;
+    }
+
+  }
+
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_fieldAccessorTable;
+
+  public static com.google.protobuf.Descriptors.FileDescriptor
+      getDescriptor() {
+    return descriptor;
+  }
+  private static com.google.protobuf.Descriptors.FileDescriptor
+      descriptor;
+  static {
+    java.lang.String[] descriptorData = {
+      "\n\016ws-batch.proto\022\022sonarqube.ws.batch\"\364\006\n" +
+      "\021WsProjectResponse\022\021\n\ttimestamp\030\001 \001(\003\022U\n" +
+      "\020settingsByModule\030\002 \003(\0132;.sonarqube.ws.b" +
+      "atch.WsProjectResponse.SettingsByModuleE" +
+      "ntry\022e\n\030fileDataByModuleAndPatch\030\003 \003(\0132C" +
+      ".sonarqube.ws.batch.WsProjectResponse.Fi" +
+      "leDataByModuleAndPatchEntry\022\030\n\020lastAnaly" +
+      "sisDate\030\004 \001(\003\032g\n\025SettingsByModuleEntry\022\013" +
+      "\n\003key\030\001 \001(\t\022=\n\005value\030\002 \001(\0132..sonarqube.w" +
+      "s.batch.WsProjectResponse.Settings:\0028\001\032u",
+      "\n\035FileDataByModuleAndPatchEntry\022\013\n\003key\030\001" +
+      " \001(\t\022C\n\005value\030\002 \001(\01324.sonarqube.ws.batch" +
+      ".WsProjectResponse.FileDataByPath:\0028\001\032\213\001" +
+      "\n\010Settings\022N\n\010settings\030\001 \003(\0132<.sonarqube" +
+      ".ws.batch.WsProjectResponse.Settings.Set" +
+      "tingsEntry\032/\n\rSettingsEntry\022\013\n\003key\030\001 \001(\t" +
+      "\022\r\n\005value\030\002 \001(\t:\0028\001\032\331\001\n\016FileDataByPath\022`" +
+      "\n\016FileDataByPath\030\001 \003(\0132H.sonarqube.ws.ba" +
+      "tch.WsProjectResponse.FileDataByPath.Fil" +
+      "eDataByPathEntry\032e\n\023FileDataByPathEntry\022",
+      "\013\n\003key\030\001 \001(\t\022=\n\005value\030\002 \001(\0132..sonarqube." +
+      "ws.batch.WsProjectResponse.FileData:\0028\001\032" +
+      "*\n\010FileData\022\014\n\004hash\030\001 \001(\t\022\020\n\010revision\030\002 " +
+      "\001(\tB\035\n\020org.sonarqube.wsB\007WsBatchH\001"
+    };
+    com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
+        new com.google.protobuf.Descriptors.FileDescriptor.    InternalDescriptorAssigner() {
+          public com.google.protobuf.ExtensionRegistry assignDescriptors(
+              com.google.protobuf.Descriptors.FileDescriptor root) {
+            descriptor = root;
+            return null;
+          }
+        };
+    com.google.protobuf.Descriptors.FileDescriptor
+      .internalBuildGeneratedFileFrom(descriptorData,
+        new com.google.protobuf.Descriptors.FileDescriptor[] {
+        }, assigner);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor =
+      getDescriptor().getMessageTypes().get(0);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor,
+        new java.lang.String[] { "Timestamp", "SettingsByModule", "FileDataByModuleAndPatch", "LastAnalysisDate", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor.getNestedTypes().get(0);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_SettingsByModuleEntry_descriptor,
+        new java.lang.String[] { "Key", "Value", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor.getNestedTypes().get(1);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByModuleAndPatchEntry_descriptor,
+        new java.lang.String[] { "Key", "Value", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor.getNestedTypes().get(2);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor,
+        new java.lang.String[] { "Settings", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_descriptor.getNestedTypes().get(0);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_Settings_SettingsEntry_descriptor,
+        new java.lang.String[] { "Key", "Value", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor.getNestedTypes().get(3);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor,
+        new java.lang.String[] { "FileDataByPath", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_descriptor.getNestedTypes().get(0);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_FileDataByPath_FileDataByPathEntry_descriptor,
+        new java.lang.String[] { "Key", "Value", });
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor =
+      internal_static_sonarqube_ws_batch_WsProjectResponse_descriptor.getNestedTypes().get(4);
+    internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_fieldAccessorTable = new
+      com.google.protobuf.GeneratedMessage.FieldAccessorTable(
+        internal_static_sonarqube_ws_batch_WsProjectResponse_FileData_descriptor,
+        new java.lang.String[] { "Hash", "Revision", });
+  }
+
+  // @@protoc_insertion_point(outer_class_scope)
+}
diff --git a/sonar-ws/src/main/protobuf/ws-batch.proto b/sonar-ws/src/main/protobuf/ws-batch.proto
new file mode 100644 (file)
index 0000000..cf46d50
--- /dev/null
@@ -0,0 +1,47 @@
+// SonarQube, open source software quality management tool.
+// Copyright (C) 2008-2015 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.
+
+syntax = "proto2";
+
+package sonarqube.ws.batch;
+
+option java_package = "org.sonarqube.ws";
+option java_outer_classname = "WsBatch";
+
+option optimize_for = SPEED;
+
+// WS api/batch/project
+message WsProjectResponse {
+  optional int64 timestamp = 1;
+  map<string, Settings> settingsByModule = 2;
+  map<string, FileDataByPath> fileDataByModuleAndPatch = 3;
+  optional int64 lastAnalysisDate = 4;
+
+  message Settings {
+    map<string,string> settings = 1;
+  }
+
+  message FileDataByPath {
+    map<string, FileData> FileDataByPath = 1;
+  }
+
+  message FileData {
+    optional string hash = 1;
+    optional string revision = 2;
+  }
+}