]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6253 Cleanup SourcePersister on batch side
authorJulien HENRY <julien.henry@sonarsource.com>
Fri, 17 Apr 2015 10:02:07 +0000 (12:02 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Fri, 17 Apr 2015 10:18:28 +0000 (12:18 +0200)
and move FileSourceDao to sonar-server

30 files changed:
server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java
server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java
server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/source/db/package-info.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java
server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileSourcesStepTest.java
server/sonar-server/src/test/java/org/sonar/server/source/db/FileSourceDaoTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java
server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/insert-result.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/shared.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update-result.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml [new file with mode: 0644]
server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml [new file with mode: 0644]
sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java [deleted file]
sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java [deleted file]
sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java
sonar-core/src/main/java/org/sonar/core/source/SnapshotDataTypes.java [deleted file]
sonar-core/src/main/java/org/sonar/core/source/db/FileSourceDao.java [deleted file]
sonar-core/src/main/java/org/sonar/core/source/package-info.java [deleted file]
sonar-core/src/test/java/org/sonar/core/source/db/FileSourceDaoTest.java [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/insert-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/shared.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml [deleted file]
sonar-core/src/test/resources/org/sonar/core/source/db/SnapshotDataDaoTest/shared.xml [deleted file]

index 9bc46b01d205d98d253d0d7605be8c450a611e29..3b2b858d2515db3e14416c5b31eca4a04fb4de95 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.benchmark;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import org.apache.commons.dbutils.DbUtils;
 import org.apache.commons.io.IOUtils;
 import org.junit.Rule;
@@ -27,7 +29,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.sonar.api.utils.internal.Uuids;
 import org.sonar.core.persistence.DbTester;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.core.source.db.FileSourceDto;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.source.db.FileSourceDb;
index fe5106cc7d60f585fddb3bb380d0299342e7c0d4..028d5d9316e996b00cc332496e9192b17579c465 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.db;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import org.sonar.api.ServerComponent;
 import org.sonar.core.issue.db.ActionPlanDao;
 import org.sonar.core.issue.db.IssueChangeDao;
@@ -30,7 +32,6 @@ import org.sonar.core.persistence.MyBatis;
 import org.sonar.core.properties.PropertiesDao;
 import org.sonar.core.qualityprofile.db.QualityProfileDao;
 import org.sonar.core.resource.ResourceDao;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.core.technicaldebt.db.CharacteristicDao;
 import org.sonar.core.template.LoadedTemplateDao;
 import org.sonar.core.user.AuthorDao;
index 796372498fda9262a9673f5329344dd40fb5e02b..fefb9f9d378ab22b2a4fa31df9f3adc8ae3d7aad 100644 (file)
@@ -32,7 +32,6 @@ import org.sonar.api.rules.AnnotationRuleParser;
 import org.sonar.api.rules.XMLRuleParser;
 import org.sonar.api.server.rule.RulesDefinitionXmlLoader;
 import org.sonar.api.utils.Durations;
-import org.sonar.core.util.DefaultHttpDownloader;
 import org.sonar.api.utils.System2;
 import org.sonar.api.utils.UriReader;
 import org.sonar.api.utils.internal.TempFolderCleaner;
@@ -64,6 +63,7 @@ import org.sonar.core.test.TestablePerspectiveLoader;
 import org.sonar.core.timemachine.Periods;
 import org.sonar.core.user.DefaultUserFinder;
 import org.sonar.core.user.HibernateUserFinder;
+import org.sonar.core.util.DefaultHttpDownloader;
 import org.sonar.jpa.dao.MeasuresDao;
 import org.sonar.jpa.session.DatabaseSessionFactory;
 import org.sonar.jpa.session.DatabaseSessionProvider;
@@ -172,6 +172,7 @@ import org.sonar.server.search.IndexSynchronizer;
 import org.sonar.server.search.SearchClient;
 import org.sonar.server.source.HtmlSourceDecorator;
 import org.sonar.server.source.SourceService;
+import org.sonar.server.source.db.FileSourceDao;
 import org.sonar.server.source.index.SourceLineIndex;
 import org.sonar.server.source.index.SourceLineIndexDefinition;
 import org.sonar.server.source.index.SourceLineIndexer;
@@ -287,7 +288,8 @@ class ServerComponents {
 
       EventDao.class,
       ActivityDao.class,
-      AnalysisReportDao.class
+      AnalysisReportDao.class,
+      FileSourceDao.class
       ));
     components.addAll(CorePropertyDefinitions.all());
     components.addAll(DatabaseMigrations.CLASSES);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java b/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java
new file mode 100644 (file)
index 0000000..d19556f
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+ * 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.server.source.db;
+
+import org.sonar.core.source.db.FileSourceDto;
+import org.sonar.core.source.db.FileSourceMapper;
+
+import com.google.common.base.Function;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.io.IOUtils;
+import org.sonar.api.ServerComponent;
+import org.sonar.core.persistence.DaoComponent;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.persistence.MyBatis;
+
+import javax.annotation.CheckForNull;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+public class FileSourceDao implements ServerComponent, DaoComponent {
+
+  private final MyBatis mybatis;
+
+  public FileSourceDao(MyBatis myBatis) {
+    this.mybatis = myBatis;
+  }
+
+  @CheckForNull
+  public FileSourceDto select(String fileUuid) {
+    DbSession session = mybatis.openSession(false);
+    try {
+      FileSourceMapper mapper = session.getMapper(FileSourceMapper.class);
+      return mapper.select(fileUuid);
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public <T> void readDataStream(String fileUuid, Function<InputStream, T> function) {
+    DbSession dbSession = mybatis.openSession(false);
+    Connection connection = dbSession.getConnection();
+    PreparedStatement pstmt = null;
+    ResultSet rs = null;
+    InputStream input = null;
+    try {
+      pstmt = connection.prepareStatement("SELECT binary_data FROM file_sources WHERE file_uuid=?");
+      pstmt.setString(1, fileUuid);
+      rs = pstmt.executeQuery();
+      if (rs.next()) {
+        input = rs.getBinaryStream(1);
+        function.apply(input);
+      }
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to read FILE_SOURCES.BINARY_DATA of file " + fileUuid, e);
+    } finally {
+      IOUtils.closeQuietly(input);
+      DbUtils.closeQuietly(connection, pstmt, rs);
+      MyBatis.closeQuietly(dbSession);
+    }
+  }
+
+  public <T> void readLineHashesStream(DbSession dbSession, String fileUuid, Function<Reader, T> function) {
+    Connection connection = dbSession.getConnection();
+    PreparedStatement pstmt = null;
+    ResultSet rs = null;
+    Reader reader = null;
+    try {
+      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=?");
+      pstmt.setString(1, fileUuid);
+      rs = pstmt.executeQuery();
+      if (rs.next()) {
+        reader = rs.getCharacterStream(1);
+        function.apply(reader);
+      }
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e);
+    } finally {
+      IOUtils.closeQuietly(reader);
+      DbUtils.closeQuietly(connection, pstmt, rs);
+    }
+  }
+
+  public void insert(FileSourceDto dto) {
+    DbSession session = mybatis.openSession(false);
+    try {
+      insert(session, dto);
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public void insert(DbSession session, FileSourceDto dto) {
+    session.getMapper(FileSourceMapper.class).insert(dto);
+  }
+
+  public void update(FileSourceDto dto) {
+    DbSession session = mybatis.openSession(false);
+    try {
+      update(session, dto);
+      session.commit();
+    } finally {
+      MyBatis.closeQuietly(session);
+    }
+  }
+
+  public void update(DbSession session, FileSourceDto dto) {
+    session.getMapper(FileSourceMapper.class).update(dto);
+  }
+
+  public void updateDateWhenUpdatedDateIsZero(DbSession session, String projectUuid, long updateDate) {
+    session.getMapper(FileSourceMapper.class).updateDateWhenUpdatedDateIsZero(projectUuid, updateDate);
+  }
+
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/source/db/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/source/db/package-info.java
new file mode 100644 (file)
index 0000000..83a499f
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+
+@ParametersAreNonnullByDefault
+package org.sonar.server.source.db;
+
+import javax.annotation.ParametersAreNonnullByDefault;
index 829ad1a1dbd485e7d19f3b54ceefa28c750608b9..e51a2b1afcee0013c3d57e82638df9b186e766bd 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.sonar.server.batch;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import com.google.common.collect.ImmutableMap;
 import org.junit.After;
 import org.junit.Before;
@@ -41,7 +43,6 @@ import org.sonar.core.properties.PropertyDto;
 import org.sonar.core.qualityprofile.db.QualityProfileDto;
 import org.sonar.core.rule.RuleDto;
 import org.sonar.core.rule.RuleParamDto;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.core.source.db.FileSourceDto;
 import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.db.DbClient;
index 5f99a49d85c6500ef8872eff686f6a713aa7a914..1c7313091c04269e1a7984a47f0787afb9c67693 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.computation.step;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import org.elasticsearch.search.SearchHit;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -27,7 +29,6 @@ import org.sonar.api.config.Settings;
 import org.sonar.api.resources.Qualifiers;
 import org.sonar.batch.protocol.output.BatchReportReader;
 import org.sonar.core.persistence.DbTester;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.computation.ComputationContext;
 import org.sonar.server.db.DbClient;
index dc503775f8a5e2110878c1a37285f70c81a953d6..e96203439286835602b4ecdd6208fb30d3a11cb4 100644 (file)
@@ -20,6 +20,8 @@
 
 package org.sonar.server.computation.step;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import com.google.common.collect.Lists;
 import org.apache.commons.io.FileUtils;
 import org.junit.After;
@@ -37,7 +39,6 @@ import org.sonar.batch.protocol.output.BatchReportWriter;
 import org.sonar.batch.protocol.output.FileStructure;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.DbTester;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.core.source.db.FileSourceDto;
 import org.sonar.server.component.ComponentTesting;
 import org.sonar.server.computation.ComputationContext;
diff --git a/server/sonar-server/src/test/java/org/sonar/server/source/db/FileSourceDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/db/FileSourceDaoTest.java
new file mode 100644 (file)
index 0000000..56fbcaa
--- /dev/null
@@ -0,0 +1,171 @@
+/*
+ * 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.server.source.db;
+
+import com.google.common.base.Function;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.persistence.DbSession;
+import org.sonar.core.source.db.FileSourceDto;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FileSourceDaoTest extends AbstractDaoTestCase {
+
+  DbSession session;
+
+  FileSourceDao dao;
+
+  @Before
+  public void setUpTestData() {
+    session = getMyBatis().openSession(false);
+    dao = new FileSourceDao(getMyBatis());
+  }
+
+  @After
+  public void tearDown() throws Exception {
+    session.close();
+  }
+
+  @Test
+  public void select() throws Exception {
+    setupData("shared");
+
+    FileSourceDto fileSourceDto = dao.select("FILE1_UUID");
+
+    assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
+    assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
+    assertThat(fileSourceDto.getProjectUuid()).isEqualTo("PRJ_UUID");
+    assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
+    assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
+    assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
+  }
+
+  @Test
+  public void select_data() throws Exception {
+    setupData("shared");
+
+    InputStreamToStringFunction fn = new InputStreamToStringFunction();
+    dao.readDataStream("FILE1_UUID", fn);
+
+    assertThat(fn.result).isNotEmpty();
+  }
+
+  @Test
+  public void select_line_hashes() throws Exception {
+    setupData("shared");
+
+    ReaderToStringFunction fn = new ReaderToStringFunction();
+    dao.readLineHashesStream(session, "FILE1_UUID", fn);
+
+    assertThat(fn.result).isEqualTo("ABC\\nDEF\\nGHI");
+  }
+
+  @Test
+  public void no_line_hashes_on_unknown_file() throws Exception {
+    setupData("shared");
+
+    ReaderToStringFunction fn = new ReaderToStringFunction();
+    dao.readLineHashesStream(session, "unknown", fn);
+
+    assertThat(fn.result).isNull();
+  }
+
+  @Test
+  public void insert() throws Exception {
+    setupData("shared");
+
+    dao.insert(new FileSourceDto()
+      .setProjectUuid("PRJ_UUID")
+      .setFileUuid("FILE2_UUID")
+      .setBinaryData("FILE2_BINARY_DATA".getBytes())
+      .setDataHash("FILE2_DATA_HASH")
+      .setLineHashes("LINE1_HASH\\nLINE2_HASH")
+      .setSrcHash("FILE2_HASH")
+      .setCreatedAt(1500000000000L)
+      .setUpdatedAt(1500000000001L));
+
+    checkTable("insert", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
+  }
+
+  @Test
+  public void update() throws Exception {
+    setupData("shared");
+
+    dao.update(new FileSourceDto().setId(101L)
+      .setProjectUuid("PRJ_UUID")
+      .setFileUuid("FILE1_UUID")
+      .setBinaryData("updated data".getBytes())
+      .setDataHash("NEW_DATA_HASH")
+      .setSrcHash("NEW_FILE_HASH")
+      .setLineHashes("NEW_LINE_HASHES")
+      .setUpdatedAt(1500000000002L));
+
+    checkTable("update", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
+  }
+
+  @Test
+  public void update_date_when_updated_date_is_zero() throws Exception {
+    setupData("update_date_when_updated_date_is_zero");
+
+    dao.updateDateWhenUpdatedDateIsZero(session, "ABCD", 1500000000002L);
+    session.commit();
+
+    checkTable("update_date_when_updated_date_is_zero", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
+  }
+
+  private static class ReaderToStringFunction implements Function<Reader, String> {
+
+    String result = null;
+
+    @Override
+    public String apply(Reader input) {
+      try {
+        result = IOUtils.toString(input);
+        return IOUtils.toString(input);
+      } catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+
+  private static class InputStreamToStringFunction implements Function<InputStream, String> {
+
+    String result = null;
+
+    @Override
+    public String apply(InputStream input) {
+      try {
+        result = IOUtils.toString(input);
+        return IOUtils.toString(input);
+      } catch (IOException e) {
+        throw new RuntimeException(e);
+      }
+    }
+  }
+}
index 416c1e59daec5a0fb9a9f790676762005466db72..b8bdf6771ec2ee08ff5543eef23716043fe1fe5b 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.server.source.ws;
 
+import org.sonar.server.source.db.FileSourceDao;
+
 import org.junit.After;
 import org.junit.Before;
 import org.junit.ClassRule;
@@ -29,7 +31,6 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.sonar.api.web.UserRole;
 import org.sonar.core.persistence.DbSession;
 import org.sonar.core.persistence.DbTester;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.server.component.db.ComponentDao;
 import org.sonar.server.db.DbClient;
 import org.sonar.server.exceptions.ForbiddenException;
@@ -37,7 +38,6 @@ import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.user.MockUserSession;
 import org.sonar.server.ws.WsTester;
 import org.sonar.test.DbTests;
-
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
 
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/insert-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/insert-result.xml
new file mode 100644 (file)
index 0000000..67fb0ae
--- /dev/null
@@ -0,0 +1,19 @@
+<dataset>
+
+  <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+                binary_data="abcde" data_hash="hash"
+                test_data="[null]"
+                line_hashes="ABC\nDEF\nGHI"
+                src_hash="FILE_HASH"
+                created_at="1500000000000" updated_at="1500000000000" />
+
+
+  <file_sources id="102" project_uuid="PRJ_UUID" file_uuid="FILE2_UUID"
+                binary_data="[ignore]"
+                test_data="[null]"
+                data_hash="FILE2_DATA_HASH"
+                line_hashes="LINE1_HASH\nLINE2_HASH"
+                src_hash="FILE2_HASH"
+                created_at="1500000000000" updated_at="1500000000001" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/shared.xml
new file mode 100644 (file)
index 0000000..c04c92d
--- /dev/null
@@ -0,0 +1,10 @@
+<dataset>
+
+    <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+                  binary_data="abcde" data_hash="hash"
+                  test_data="[null]"
+                  line_hashes="ABC\nDEF\nGHI"
+                  src_hash="FILE_HASH"
+                  created_at="1500000000000" updated_at="1500000000000" />
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update-result.xml
new file mode 100644 (file)
index 0000000..2d71f37
--- /dev/null
@@ -0,0 +1,12 @@
+<dataset>
+
+  <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+                binary_data="[ignore]"
+                test_data="[null]"
+                data_hash="NEW_DATA_HASH"
+                line_hashes="NEW_LINE_HASHES"
+                src_hash="NEW_FILE_HASH"
+                created_at="1500000000000" updated_at="1500000000002" />
+
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
new file mode 100644 (file)
index 0000000..0450883
--- /dev/null
@@ -0,0 +1,21 @@
+<dataset>
+
+  <!-- Updated -->
+  <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="1500000000002"/>
+
+  <!-- Not updated because updated_at is not null -->
+  <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="1500000000000"/>
+
+  <!-- Not updated because on another project -->
+  <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="0"/>
+
+</dataset>
diff --git a/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
new file mode 100644 (file)
index 0000000..5444e33
--- /dev/null
@@ -0,0 +1,19 @@
+<dataset>
+
+  <!-- Only this source should be updated -->
+  <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="0"/>
+
+  <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="1500000000000"/>
+
+  <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+                test_data="[null]"
+                created_at="1500000000000" updated_at="0"/>
+
+</dataset>
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java
deleted file mode 100644 (file)
index 53950be..0000000
+++ /dev/null
@@ -1,371 +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.index;
-
-import com.google.common.base.CharMatcher;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.duplication.Duplication;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.protocol.output.*;
-import org.sonar.batch.protocol.output.BatchReport.Range;
-import org.sonar.batch.protocol.output.BatchReport.Scm;
-import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
-import org.sonar.batch.protocol.output.BatchReport.Symbols;
-import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting;
-import org.sonar.batch.report.BatchReportUtils;
-import org.sonar.batch.report.ReportPublisher;
-import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.core.source.db.FileSourceDto;
-import org.sonar.server.source.db.FileSourceDb;
-import org.sonar.server.source.db.FileSourceDb.Data.Builder;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.*;
-
-/**
- * Consolidate different caches for the export of file sources to server.
- * @see org.sonar.server.source.db.FileSourceDb
- */
-public class SourceDataFactory implements BatchComponent {
-
-  private static final String BOM = "\uFEFF";
-
-  private final MeasureCache measureCache;
-  private final DuplicationCache duplicationCache;
-  private final ReportPublisher reportPublisher;
-
-  private final ResourceCache resourceCache;
-
-  public SourceDataFactory(MeasureCache measureCache, DuplicationCache duplicationCache, ReportPublisher reportPublisher, ResourceCache resourceCache) {
-    this.measureCache = measureCache;
-    this.duplicationCache = duplicationCache;
-    this.reportPublisher = reportPublisher;
-    this.resourceCache = resourceCache;
-  }
-
-  public byte[] consolidateData(DefaultInputFile inputFile) throws IOException {
-    FileSourceDb.Data.Builder dataBuilder = createForSource(inputFile);
-    if (!inputFile.isEmpty()) {
-      applyLineMeasures(inputFile, dataBuilder);
-    }
-    applyScm(inputFile, dataBuilder);
-    applyDuplications(inputFile.key(), dataBuilder);
-    applyHighlighting(inputFile, dataBuilder);
-    applySymbolReferences(inputFile, dataBuilder);
-    return FileSourceDto.encodeData(dataBuilder.build());
-  }
-
-  FileSourceDb.Data.Builder createForSource(DefaultInputFile inputFile) throws IOException {
-    FileSourceDb.Data.Builder result = FileSourceDb.Data.newBuilder();
-    List<String> lines = FileUtils.readLines(inputFile.file(), inputFile.charset());
-    // Missing empty last line
-    if (lines.size() == inputFile.lines() - 1) {
-      lines.add("");
-    }
-    for (int lineIdx = 1; lineIdx <= lines.size(); lineIdx++) {
-      String s = CharMatcher.anyOf(BOM).removeFrom(lines.get(lineIdx - 1));
-      FileSourceDb.Line.Builder linesBuilder = result.addLinesBuilder();
-      linesBuilder.setLine(lineIdx).setSource(s);
-    }
-    return result;
-  }
-
-  void applyScm(DefaultInputFile inputFile, Builder dataBuilder) {
-    BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
-    Scm componentScm = reader.readComponentScm(resourceCache.get(inputFile).batchId());
-    if (componentScm != null) {
-      for (int i = 0; i < componentScm.getChangesetIndexByLineCount(); i++) {
-        int index = componentScm.getChangesetIndexByLine(i);
-        Changeset changeset = componentScm.getChangeset(index);
-        if (i < dataBuilder.getLinesCount()) {
-          FileSourceDb.Line.Builder lineBuilder = dataBuilder.getLinesBuilder(i);
-          if (changeset.hasAuthor()) {
-            lineBuilder.setScmAuthor(changeset.getAuthor());
-          }
-          if (changeset.hasRevision()) {
-            lineBuilder.setScmRevision(changeset.getRevision());
-          }
-          if (changeset.hasDate()) {
-            lineBuilder.setScmDate(changeset.getDate());
-          }
-        }
-      }
-    }
-  }
-
-  void applyLineMeasures(DefaultInputFile file, FileSourceDb.Data.Builder dataBuilder) {
-    applyLineMeasure(file.key(), CoreMetrics.COVERAGE_LINE_HITS_DATA_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setUtLineHits(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setUtConditions(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.COVERED_CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setUtCoveredConditions(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.IT_COVERAGE_LINE_HITS_DATA_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setItLineHits(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.IT_CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setItConditions(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setItCoveredConditions(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setOverallLineHits(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.OVERALL_CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setOverallConditions(Integer.parseInt(value));
-      }
-    });
-    applyLineMeasure(file.key(), CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE_KEY, dataBuilder, new MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setOverallCoveredConditions(Integer.parseInt(value));
-      }
-    });
-  }
-
-  void applyLineMeasure(String inputFileKey, String metricKey, FileSourceDb.Data.Builder to, MeasureOperation op) {
-    Iterable<Measure> measures = measureCache.byMetric(inputFileKey, metricKey);
-    if (measures.iterator().hasNext()) {
-      Measure measure = measures.iterator().next();
-      Map<Integer, String> lineMeasures = KeyValueFormat.parseIntString((String) measure.value());
-      for (Map.Entry<Integer, String> lineMeasure : lineMeasures.entrySet()) {
-        int lineIdx = lineMeasure.getKey();
-        if (lineIdx <= to.getLinesCount()) {
-          String value = lineMeasure.getValue();
-          if (StringUtils.isNotEmpty(value)) {
-            FileSourceDb.Line.Builder lineBuilder = to.getLinesBuilder(lineIdx - 1);
-            op.apply(value, lineBuilder);
-          }
-        }
-      }
-    }
-  }
-
-  static interface MeasureOperation {
-    void apply(String value, FileSourceDb.Line.Builder lineBuilder);
-  }
-
-  void applyHighlighting(DefaultInputFile inputFile, FileSourceDb.Data.Builder to) {
-    BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
-    File highlightingFile = reader.readComponentSyntaxHighlighting(resourceCache.get(inputFile).batchId());
-    if (highlightingFile == null) {
-      return;
-    }
-    StringBuilder[] highlightingPerLine = new StringBuilder[inputFile.lines()];
-    RuleItemWriter ruleItemWriter = new RuleItemWriter();
-    int currentLineIdx = 1;
-
-    InputStream inputStream = null;
-    try {
-      inputStream = FileUtils.openInputStream(highlightingFile);
-      BatchReport.SyntaxHighlighting rule = BatchReport.SyntaxHighlighting.PARSER.parseDelimitedFrom(inputStream);
-      while (rule != null) {
-        while (currentLineIdx < inputFile.lines() && rule.getRange().getStartLine() > currentLineIdx) {
-          // This rule starts on another line so advance
-          currentLineIdx++;
-        }
-        // Now we know current rule starts on current line
-        writeDataPerLine(inputFile.originalLineOffsets(), rule, rule.getRange(), highlightingPerLine, ruleItemWriter);
-
-        // Get next element
-        rule = BatchReport.SyntaxHighlighting.PARSER.parseDelimitedFrom(inputStream);
-      }
-
-    } catch (Exception e) {
-      throw new IllegalStateException("Can't read syntax highlighting for " + inputFile.absolutePath(), e);
-    } finally {
-      IOUtils.closeQuietly(inputStream);
-    }
-    for (int i = 0; i < highlightingPerLine.length; i++) {
-      StringBuilder sb = highlightingPerLine[i];
-      if (sb != null) {
-        to.getLinesBuilder(i).setHighlighting(sb.toString());
-      }
-    }
-  }
-
-  void applySymbolReferences(DefaultInputFile inputFile, FileSourceDb.Data.Builder to) {
-    BatchReportReader reader = new BatchReportReader(reportPublisher.getReportDir());
-    List<Symbols.Symbol> symbols = new ArrayList<Symbols.Symbol>(reader.readComponentSymbols(resourceCache.get(inputFile).batchId()));
-    if (symbols.isEmpty()) {
-      return;
-    }
-    StringBuilder[] refsPerLine = new StringBuilder[inputFile.lines()];
-    int symbolId = 1;
-    // Sort symbols to avoid false variation that would lead to an unnecessary update
-    Collections.sort(symbols, new Comparator<Symbols.Symbol>() {
-      @Override
-      public int compare(Symbols.Symbol o1, Symbols.Symbol o2) {
-        if (o1.getDeclaration().getStartLine() == o2.getDeclaration().getStartLine()) {
-          return Integer.compare(o1.getDeclaration().getStartOffset(), o2.getDeclaration().getStartOffset());
-        } else {
-          return Integer.compare(o1.getDeclaration().getStartLine(), o2.getDeclaration().getStartLine());
-        }
-      }
-    });
-    for (Symbols.Symbol symbol : symbols) {
-      addSymbol(symbolId, symbol.getDeclaration(), inputFile.originalLineOffsets(), refsPerLine);
-      for (Range reference : symbol.getReferenceList()) {
-        addSymbol(symbolId, reference, inputFile.originalLineOffsets(), refsPerLine);
-      }
-      symbolId++;
-    }
-    for (int i = 0; i < refsPerLine.length; i++) {
-      StringBuilder sb = refsPerLine[i];
-      if (sb != null) {
-        to.getLinesBuilder(i).setSymbols(sb.toString());
-      }
-    }
-  }
-
-  private void addSymbol(int symbolId, Range range, int[] originalLineOffsets, StringBuilder[] result) {
-    writeDataPerLine(originalLineOffsets, symbolId, range, result, new SymbolItemWriter());
-  }
-
-  private <G> void writeDataPerLine(int[] originalLineOffsets, G item, Range range, StringBuilder[] dataPerLine, RangeItemWriter<G> writer) {
-    int currentLineIdx = range.getStartLine();
-    long ruleStartOffsetCurrentLine = range.getStartOffset();
-    while (currentLineIdx < dataPerLine.length && range.getEndLine() > currentLineIdx) {
-      // item continue on next line so write current line and continue on next line with same item
-      writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine, lineLength(originalLineOffsets, currentLineIdx), writer);
-      currentLineIdx++;
-      ruleStartOffsetCurrentLine = 0;
-    }
-    // item ends on current line
-    writeItem(item, dataPerLine, currentLineIdx, ruleStartOffsetCurrentLine, range.getEndOffset(), writer);
-  }
-
-  private int lineLength(int[] originalLineOffsets, int currentLineIdx) {
-    return originalLineOffsets[currentLineIdx]
-      - originalLineOffsets[currentLineIdx - 1];
-  }
-
-  private <G> void writeItem(G item, StringBuilder[] dataPerLine, int currentLineIdx, long startLineOffset, long endLineOffset, RangeItemWriter<G> writer) {
-    if (startLineOffset == endLineOffset || currentLineIdx > dataPerLine.length) {
-      // empty items or bad line index
-      return;
-    }
-    if (dataPerLine[currentLineIdx - 1] == null) {
-      dataPerLine[currentLineIdx - 1] = new StringBuilder();
-    }
-    StringBuilder currentLineSb = dataPerLine[currentLineIdx - 1];
-    writer.writeItem(currentLineSb, startLineOffset, endLineOffset, item);
-  }
-
-  private static interface RangeItemWriter<G> {
-    /**
-     * Write item on a single line
-     */
-    void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, G item);
-  }
-
-  private static class RuleItemWriter implements RangeItemWriter<SyntaxHighlighting> {
-    @Override
-    public void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, SyntaxHighlighting item) {
-      if (currentLineSb.length() > 0) {
-        currentLineSb.append(';');
-      }
-      currentLineSb.append(startLineOffset)
-        .append(',')
-        .append(endLineOffset)
-        .append(',')
-        .append(BatchReportUtils.toCssClass(item.getType()));
-    }
-
-  }
-
-  private static class SymbolItemWriter implements RangeItemWriter<Integer> {
-    @Override
-    public void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, Integer symbolId) {
-      if (currentLineSb.length() > 0) {
-        currentLineSb.append(";");
-      }
-      currentLineSb.append(startLineOffset)
-        .append(",")
-        .append(endLineOffset)
-        .append(",")
-        .append(symbolId);
-    }
-  }
-
-  void applyDuplications(String inputFileKey, FileSourceDb.Data.Builder to) {
-    Iterable<DefaultDuplication> groups = duplicationCache.byComponent(inputFileKey);
-    int blockId = 1;
-    for (Iterator<DefaultDuplication> it = groups.iterator(); it.hasNext();) {
-      Duplication group = it.next();
-      addBlock(blockId, group.originBlock(), to);
-      blockId++;
-      for (Iterator<Duplication.Block> dupsIt = group.duplicates().iterator(); dupsIt.hasNext();) {
-        Duplication.Block dups = dupsIt.next();
-        if (inputFileKey.equals(dups.resourceKey())) {
-          addBlock(blockId, dups, to);
-          blockId++;
-        }
-      }
-    }
-  }
-
-  private void addBlock(int blockId, Duplication.Block block, FileSourceDb.Data.Builder to) {
-    int currentLine = block.startLine();
-    for (int i = 0; i < block.length(); i++) {
-      if (currentLine <= to.getLinesCount()) {
-        to.getLinesBuilder(currentLine - 1).addDuplication(blockId);
-        currentLine++;
-      }
-    }
-  }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java b/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java
deleted file mode 100644 (file)
index 55df774..0000000
+++ /dev/null
@@ -1,148 +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.index;
-
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.fs.internal.FileMetadata;
-import org.sonar.api.batch.fs.internal.FileMetadata.LineHashConsumer;
-import org.sonar.api.utils.System2;
-import org.sonar.batch.ProjectTree;
-import org.sonar.batch.scan.filesystem.InputPathCache;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-import org.sonar.core.source.db.FileSourceDto;
-import org.sonar.core.source.db.FileSourceMapper;
-
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-
-import java.io.IOException;
-import java.util.Map;
-
-public class SourcePersister implements ScanPersister {
-
-  private final MyBatis mybatis;
-  private final System2 system2;
-  private final ProjectTree projectTree;
-  private final ResourceCache resourceCache;
-  private final InputPathCache inputPathCache;
-  private final SourceDataFactory dataFactory;
-
-  public SourcePersister(InputPathCache inputPathCache, MyBatis mybatis, System2 system2,
-    ProjectTree projectTree, ResourceCache resourceCache, SourceDataFactory dataFactory) {
-    this.inputPathCache = inputPathCache;
-    this.mybatis = mybatis;
-    this.system2 = system2;
-    this.projectTree = projectTree;
-    this.resourceCache = resourceCache;
-    this.dataFactory = dataFactory;
-  }
-
-  @Override
-  public void persist() {
-    // Don't use batch insert for file_sources since keeping all data in memory can produce OOM for big files
-//    try (DbSession session = mybatis.openSession(false)) {
-//
-//      final Map<String, FileSourceDto> previousDtosByUuid = new HashMap<>();
-//      session.select("org.sonar.core.source.db.FileSourceMapper.selectHashesForProject", projectTree.getRootProject().getUuid(), new ResultHandler() {
-//        @Override
-//        public void handleResult(ResultContext context) {
-//          FileSourceDto dto = (FileSourceDto) context.getResultObject();
-//          previousDtosByUuid.put(dto.getFileUuid(), dto);
-//        }
-//      });
-//
-//      FileSourceMapper mapper = session.getMapper(FileSourceMapper.class);
-//      for (InputFile inputFile : inputPathCache.allFiles()) {
-//        persist(session, mapper, (DefaultInputFile) inputFile, previousDtosByUuid);
-//      }
-//    } catch (Exception e) {
-//      throw new IllegalStateException("Unable to save file sources", e);
-//    }
-
-  }
-
-  private void persist(DbSession session, FileSourceMapper mapper, DefaultInputFile inputFile, Map<String, FileSourceDto> previousDtosByUuid) {
-    String fileUuid = resourceCache.get(inputFile).resource().getUuid();
-
-    byte[] data = computeData(inputFile);
-    String dataHash = DigestUtils.md5Hex(data);
-    FileSourceDto previousDto = previousDtosByUuid.get(fileUuid);
-    if (previousDto == null) {
-      FileSourceDto dto = new FileSourceDto()
-        .setProjectUuid(projectTree.getRootProject().getUuid())
-        .setFileUuid(fileUuid)
-        .setBinaryData(data)
-        .setDataHash(dataHash)
-        .setSrcHash(inputFile.hash())
-        .setLineHashes(lineHashesAsMd5Hex(inputFile))
-        .setCreatedAt(system2.now())
-        .setUpdatedAt(0L);
-      mapper.insert(dto);
-      session.commit();
-    } else {
-      // Update only if data_hash has changed or if src_hash is missing (progressive migration)
-      boolean binaryDataUpdated = !dataHash.equals(previousDto.getDataHash());
-      boolean srcHashUpdated = !inputFile.hash().equals(previousDto.getSrcHash());
-      if (binaryDataUpdated || srcHashUpdated) {
-        previousDto
-          .setBinaryData(data)
-          .setDataHash(dataHash)
-          .setSrcHash(inputFile.hash())
-          .setLineHashes(lineHashesAsMd5Hex(inputFile));
-        // Optimization only change updated at when updating binary data to avoid unecessary indexation by E/S
-        if (binaryDataUpdated) {
-          previousDto.setUpdatedAt(0L);
-        }
-        mapper.update(previousDto);
-        session.commit();
-      }
-    }
-  }
-
-  @CheckForNull
-  private String lineHashesAsMd5Hex(DefaultInputFile f) {
-    // A md5 string is 32 char long + '\n' = 33
-    final StringBuilder result = new StringBuilder(f.lines() * (32 + 1));
-
-    FileMetadata.computeLineHashesForIssueTracking(f, new LineHashConsumer() {
-
-      @Override
-      public void consume(int lineIdx, @Nullable byte[] hash) {
-        if (lineIdx > 1) {
-          result.append("\n");
-        }
-        result.append(hash != null ? Hex.encodeHexString(hash) : "");
-      }
-    });
-
-    return result.toString();
-  }
-
-  private byte[] computeData(DefaultInputFile inputFile) {
-    try {
-      return dataFactory.consolidateData(inputFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to read file " + inputFile, e);
-    }
-  }
-}
index 12b0bc0f21d68eb3f9e20d4e3067ae7dbcc3aaf1..e510aae33a6a5b77dbee2bd776acd75fa1ce4141 100644 (file)
@@ -129,7 +129,6 @@ public class ProjectScanContainer extends ComponentContainer {
       DefaultFileLinesContextFactory.class,
       Caches.class,
       ResourceCache.class,
-      SourceDataFactory.class,
 
       // file system
       InputPathCache.class,
@@ -196,7 +195,6 @@ public class ProjectScanContainer extends ComponentContainer {
   private void addDataBaseComponents() {
     add(
       ResourcePersister.class,
-      SourcePersister.class,
       ResourceKeyMigration.class,
 
       // Users
diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java
deleted file mode 100644 (file)
index b1c45ac..0000000
+++ /dev/null
@@ -1,426 +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.index;
-
-import com.google.common.base.Charsets;
-import com.google.common.collect.Lists;
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-import org.sonar.api.batch.fs.internal.DefaultFileSystem;
-import org.sonar.api.batch.fs.internal.DefaultInputFile;
-import org.sonar.api.batch.sensor.duplication.Duplication;
-import org.sonar.api.batch.sensor.duplication.internal.DefaultDuplication;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.measures.Metric;
-import org.sonar.batch.duplication.DuplicationCache;
-import org.sonar.batch.protocol.Constants.HighlightingType;
-import org.sonar.batch.protocol.output.BatchReport;
-import org.sonar.batch.protocol.output.BatchReport.Range;
-import org.sonar.batch.protocol.output.BatchReport.Scm;
-import org.sonar.batch.protocol.output.BatchReport.Scm.Changeset;
-import org.sonar.batch.protocol.output.BatchReport.SyntaxHighlighting;
-import org.sonar.batch.protocol.output.BatchReportWriter;
-import org.sonar.batch.report.ReportPublisher;
-import org.sonar.batch.scan.measure.MeasureCache;
-import org.sonar.server.source.db.FileSourceDb;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Collections;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class SourceDataFactoryTest {
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  private MeasureCache measureCache = mock(MeasureCache.class);
-  private DuplicationCache duplicationCache = mock(DuplicationCache.class);
-  private DefaultInputFile inputFile;
-  private SourceDataFactory sut;
-  private FileSourceDb.Data.Builder output;
-  private File reportDir;
-  private BatchReportWriter batchReportWriter;
-
-  @Before
-  public void setUp() throws Exception {
-    ReportPublisher reportPublisher = mock(ReportPublisher.class);
-    reportDir = temp.newFolder();
-    batchReportWriter = new BatchReportWriter(reportDir);
-    when(reportPublisher.getReportDir()).thenReturn(reportDir);
-    ResourceCache resourceCache = new ResourceCache();
-    resourceCache.add(org.sonar.api.resources.File.create("src/Foo.java").setEffectiveKey("module_key:src/Foo.java"), null);
-    when(measureCache.byMetric(anyString(), anyString())).thenReturn(Collections.<Measure>emptyList());
-    sut = new SourceDataFactory(measureCache, duplicationCache, reportPublisher, resourceCache);
-    // generate a file with 3 lines
-    File baseDir = temp.newFolder();
-    DefaultFileSystem fs = new DefaultFileSystem(baseDir.toPath());
-    inputFile = new DefaultInputFile("module_key", "src/Foo.java")
-      .setLines(3)
-      .setCharset(Charsets.UTF_8);
-    fs.add(inputFile);
-    FileUtils.write(inputFile.file(), "one\ntwo\nthree\n");
-    output = sut.createForSource(inputFile);
-    when(duplicationCache.byComponent(anyString())).thenReturn(Collections.<DefaultDuplication>emptyList());
-  }
-
-  @Test
-  public void createForSource() throws Exception {
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLinesCount()).isEqualTo(3);
-    for (int index = 1; index <= 3; index++) {
-      assertThat(data.getLines(index - 1).getLine()).isEqualTo(index);
-    }
-  }
-
-  @Test
-  public void consolidateData() throws Exception {
-    byte[] bytes = sut.consolidateData(inputFile);
-    assertThat(bytes).isNotEmpty();
-  }
-
-  @Test
-  public void applyLineMeasure() throws Exception {
-    Metric metric = CoreMetrics.COVERAGE_LINE_HITS_DATA;
-    when(measureCache.byMetric("component_key", metric.key())).thenReturn(
-      // line 1 has 10 hits, ...
-      Arrays.asList(new Measure().setData("1=10;3=4").setMetric(metric)));
-
-    sut.applyLineMeasure("component_key", metric.key(), output, new SourceDataFactory.MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setUtLineHits(Integer.parseInt(value));
-      }
-    });
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getUtLineHits()).isEqualTo(10);
-    assertThat(data.getLines(1).hasUtLineHits()).isFalse();
-    assertThat(data.getLines(2).getUtLineHits()).isEqualTo(4);
-  }
-
-  @Test
-  public void applyLineMeasure_ignore_bad_line_numbers() throws Exception {
-    Metric metric = CoreMetrics.COVERAGE_LINE_HITS_DATA;
-    when(measureCache.byMetric("component_key", metric.key())).thenReturn(
-      // line 30 does not exist
-      Arrays.asList(new Measure().setData("30=42").setMetric(metric)));
-
-    sut.applyLineMeasure("component_key", metric.key(), output, new SourceDataFactory.MeasureOperation() {
-      @Override
-      public void apply(String value, FileSourceDb.Line.Builder lineBuilder) {
-        lineBuilder.setUtLineHits(Integer.parseInt(value));
-      }
-    });
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLinesCount()).isEqualTo(3);
-  }
-
-  @Test
-  public void applyScm() throws Exception {
-    BatchReportWriter writer = new BatchReportWriter(reportDir);
-    writer.writeComponentScm(Scm.newBuilder().setComponentRef(1)
-      .addChangeset(Changeset.newBuilder()
-        .setRevision("ABC")
-        .setAuthor("him")
-        .setDate(123456L)
-        .build())
-      .addChangeset(Changeset.newBuilder()
-        .build())
-      .addChangesetIndexByLine(0)
-      .addChangesetIndexByLine(1)
-      .addChangesetIndexByLine(0)
-      // This should never happens but here there is 4 data but inputfile has only 3 lines
-      .addChangesetIndexByLine(1)
-      .build());
-
-    sut.applyScm(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getScmRevision()).isEqualTo("ABC");
-    assertThat(data.getLines(0).getScmAuthor()).isEqualTo("him");
-
-    assertThat(data.getLines(1).hasScmRevision()).isFalse();
-    assertThat(data.getLines(1).hasScmAuthor()).isFalse();
-
-    assertThat(data.getLines(2).getScmRevision()).isEqualTo("ABC");
-    assertThat(data.getLines(2).getScmAuthor()).isEqualTo("him");
-
-  }
-
-  @Test
-  public void applyLineMeasures() throws Exception {
-    setupLineMeasure(CoreMetrics.COVERAGE_LINE_HITS_DATA, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.COVERED_CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.IT_COVERAGE_LINE_HITS_DATA, "1=11;2=4");
-    setupLineMeasure(CoreMetrics.IT_COVERED_CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.IT_CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.OVERALL_COVERAGE_LINE_HITS_DATA, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.OVERALL_CONDITIONS_BY_LINE, "1=10;3=4");
-    setupLineMeasure(CoreMetrics.OVERALL_COVERED_CONDITIONS_BY_LINE, "1=10;3=4");
-
-    sut.applyLineMeasures(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getUtLineHits()).isEqualTo(10);
-    assertThat(data.getLines(0).getItLineHits()).isEqualTo(11);
-
-    assertThat(data.getLines(1).hasUtLineHits()).isFalse();
-    assertThat(data.getLines(1).getItLineHits()).isEqualTo(4);
-
-    assertThat(data.getLines(2).getUtLineHits()).isEqualTo(4);
-  }
-
-  private void setupLineMeasure(Metric metric, String dataPerLine) {
-    when(measureCache.byMetric(inputFile.key(), metric.key())).thenReturn(
-      Arrays.asList(new Measure().setData(dataPerLine).setMetric(metric)));
-  }
-
-  @Test
-  public void applyDuplications() throws Exception {
-    DefaultDuplication group1 = new DefaultDuplication().setOriginBlock(new Duplication.Block(inputFile.key(), 1, 1));
-    group1.duplicates().add(new Duplication.Block(inputFile.key(), 3, 1));
-    group1.duplicates().add(new Duplication.Block("anotherFile1", 12, 1));
-    group1.duplicates().add(new Duplication.Block("anotherFile2", 13, 1));
-    DefaultDuplication group2 = new DefaultDuplication().setOriginBlock(new Duplication.Block(inputFile.key(), 1, 2));
-    group2.duplicates().add(new Duplication.Block("anotherFile1", 12, 2));
-    group2.duplicates().add(new Duplication.Block("anotherFile2", 13, 2));
-    when(duplicationCache.byComponent(inputFile.key())).thenReturn(Lists.newArrayList(group1, group2));
-
-    sut.applyDuplications(inputFile.key(), output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getDuplicationList()).containsExactly(1, 3);
-    assertThat(data.getLines(1).getDuplicationList()).containsExactly(3);
-    assertThat(data.getLines(2).getDuplicationList()).containsExactly(2);
-  }
-
-  @Test
-  public void applyDuplications_ignore_bad_lines() throws Exception {
-    // duplication on 10 lines
-    DefaultDuplication group1 = new DefaultDuplication().setOriginBlock(new Duplication.Block(inputFile.key(), 1, 10));
-    group1.duplicates().add(new Duplication.Block("anotherFile1", 12, 1));
-    group1.duplicates().add(new Duplication.Block("anotherFile2", 13, 1));
-    when(duplicationCache.byComponent(inputFile.key())).thenReturn(Lists.newArrayList(group1));
-
-    sut.applyDuplications(inputFile.key(), output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getDuplicationList()).containsExactly(1);
-    assertThat(data.getLines(1).getDuplicationList()).containsExactly(1);
-    assertThat(data.getLines(2).getDuplicationList()).containsExactly(1);
-  }
-
-  @Test
-  public void applyHighlighting_missing() throws Exception {
-    sut.applyHighlighting(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).hasHighlighting()).isFalse();
-    assertThat(data.getLines(1).hasHighlighting()).isFalse();
-    assertThat(data.getLines(2).hasHighlighting()).isFalse();
-  }
-
-  @Test
-  public void applyHighlighting() throws Exception {
-    batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
-      newRule(1, 0, 1, 4, HighlightingType.ANNOTATION),
-      newRule(2, 0, 2, 1, HighlightingType.COMMENT),
-      newRule(3, 1, 3, 9, HighlightingType.CONSTANT)));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-    sut.applyHighlighting(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,4,a");
-    assertThat(data.getLines(1).getHighlighting()).isEqualTo("0,1,cd");
-    assertThat(data.getLines(2).getHighlighting()).isEqualTo("1,9,c");
-  }
-
-  @Test
-  public void applyHighlighting_multiple_lines() throws Exception {
-    batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
-      newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
-      newRule(2, 0, 3, 2, HighlightingType.COMMENT),
-      newRule(3, 3, 3, 9, HighlightingType.CONSTANT)));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applyHighlighting(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
-    assertThat(data.getLines(1).getHighlighting()).isEqualTo("0,3,cd");
-    assertThat(data.getLines(2).getHighlighting()).isEqualTo("0,2,cd;3,9,c");
-  }
-
-  @Test
-  public void applyHighlighting_nested_rules() throws Exception {
-    batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
-      newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
-      newRule(2, 0, 2, 2, HighlightingType.COMMENT),
-      newRule(3, 0, 3, 9, HighlightingType.CONSTANT),
-      newRule(3, 1, 3, 8, HighlightingType.KEYWORD)));
-
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applyHighlighting(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
-    assertThat(data.getLines(1).getHighlighting()).isEqualTo("0,2,cd");
-    assertThat(data.getLines(2).getHighlighting()).isEqualTo("0,9,c;1,8,k");
-  }
-
-  @Test
-  public void applyHighlighting_nested_rules_and_multiple_lines() throws Exception {
-    batchReportWriter.writeComponentSyntaxHighlighting(1, Arrays.asList(
-      newRule(1, 0, 1, 3, HighlightingType.ANNOTATION),
-      newRule(2, 0, 3, 9, HighlightingType.CONSTANT),
-      newRule(2, 0, 2, 2, HighlightingType.COMMENT),
-      newRule(3, 1, 3, 8, HighlightingType.KEYWORD)));
-
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applyHighlighting(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getHighlighting()).isEqualTo("0,3,a");
-    assertThat(data.getLines(1).getHighlighting()).isEqualTo("0,3,c;0,2,cd");
-    assertThat(data.getLines(2).getHighlighting()).isEqualTo("0,9,c;1,8,k");
-  }
-
-  private SyntaxHighlighting newRule(int startLine, int startOffset, int endLine, int endOffset, HighlightingType type) {
-    return BatchReport.SyntaxHighlighting.newBuilder()
-      .setRange(Range.newBuilder().setStartLine(startLine).setStartOffset(startOffset).setEndLine(endLine).setEndOffset(endOffset).build())
-      .setType(type)
-      .build();
-  }
-
-  private BatchReport.Symbols.Symbol newSymbol(int startLine, int startOffset, int endLine, int endOffset,
-    int startLine1, int startOffset1, int endLine1, int endOffset1,
-    int startLine2, int startOffset2, int endLine2, int endOffset2) {
-    return BatchReport.Symbols.Symbol.newBuilder()
-      .setDeclaration(Range.newBuilder().setStartLine(startLine).setStartOffset(startOffset).setEndLine(endLine).setEndOffset(endOffset).build())
-      .addReference(Range.newBuilder().setStartLine(startLine1).setStartOffset(startOffset1).setEndLine(endLine1).setEndOffset(endOffset1).build())
-      .addReference(Range.newBuilder().setStartLine(startLine2).setStartOffset(startOffset2).setEndLine(endLine2).setEndOffset(endOffset2).build())
-      .build();
-  }
-
-  @Test
-  public void applySymbolReferences_missing() throws Exception {
-    sut.applySymbolReferences(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).hasSymbols()).isFalse();
-    assertThat(data.getLines(1).hasSymbols()).isFalse();
-    assertThat(data.getLines(2).hasSymbols()).isFalse();
-  }
-
-  @Test
-  public void applySymbolReferences() throws Exception {
-    batchReportWriter.writeComponentSymbols(1, Arrays.asList(
-      newSymbol(1, 1, 1, 2,
-        2, 0, 2, 1,
-        3, 4, 3, 5),
-      newSymbol(2, 0, 2, 2,
-        1, 0, 1, 2,
-        3, 0, 3, 2)
-      ));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applySymbolReferences(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getSymbols()).isEqualTo("1,2,1;0,2,2");
-    assertThat(data.getLines(1).getSymbols()).isEqualTo("0,1,1;0,2,2");
-    assertThat(data.getLines(2).getSymbols()).isEqualTo("4,5,1;0,2,2");
-  }
-
-  @Test
-  public void applySymbolReferences2() throws Exception {
-    batchReportWriter.writeComponentSymbols(1, Arrays.asList(
-      newSymbol(2, 0, 2, 2,
-        1, 1, 1, 2,
-        3, 0, 3, 2),
-      newSymbol(3, 1, 3, 2,
-        1, 0, 1, 1,
-        3, 4, 3, 5)
-      ));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applySymbolReferences(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getSymbols()).isEqualTo("1,2,1;0,1,2");
-    assertThat(data.getLines(1).getSymbols()).isEqualTo("0,2,1");
-    assertThat(data.getLines(2).getSymbols()).isEqualTo("0,2,1;1,2,2;4,5,2");
-  }
-
-  @Test
-  public void applySymbolReferences3() throws Exception {
-    batchReportWriter.writeComponentSymbols(1, Arrays.asList(
-      newSymbol(2, 0, 2, 2,
-        1, 0, 1, 1,
-        3, 0, 3, 2),
-      newSymbol(3, 1, 3, 2,
-        1, 1, 1, 2,
-        3, 4, 3, 5)
-      ));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applySymbolReferences(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getSymbols()).isEqualTo("0,1,1;1,2,2");
-    assertThat(data.getLines(1).getSymbols()).isEqualTo("0,2,1");
-    assertThat(data.getLines(2).getSymbols()).isEqualTo("0,2,1;1,2,2;4,5,2");
-  }
-
-  @Test
-  public void applySymbolReferences_declaration_order_is_not_important() throws Exception {
-    batchReportWriter.writeComponentSymbols(1, Arrays.asList(
-      newSymbol(2, 0, 2, 2,
-        1, 0, 1, 2,
-        3, 0, 3, 2),
-      newSymbol(1, 1, 1, 2,
-        2, 0, 2, 1,
-        3, 4, 3, 5)
-
-      ));
-    inputFile.setOriginalLineOffsets(new int[] {0, 4, 7});
-
-    sut.applySymbolReferences(inputFile, output);
-
-    FileSourceDb.Data data = output.build();
-    assertThat(data.getLines(0).getSymbols()).isEqualTo("1,2,1;0,2,2");
-    assertThat(data.getLines(1).getSymbols()).isEqualTo("0,1,1;0,2,2");
-    assertThat(data.getLines(2).getSymbols()).isEqualTo("4,5,1;0,2,2");
-  }
-}
index 92f369464286b4cfdb14c6c63ea6ab170d6d0ade..052120c913b93fa0b73536dbc176dc6cd8b2c2f7 100644 (file)
@@ -38,7 +38,6 @@ import org.sonar.core.resource.ResourceDao;
 import org.sonar.core.resource.ResourceIndexerDao;
 import org.sonar.core.resource.ResourceKeyUpdaterDao;
 import org.sonar.core.rule.RuleDao;
-import org.sonar.core.source.db.FileSourceDao;
 import org.sonar.core.technicaldebt.db.CharacteristicDao;
 import org.sonar.core.template.LoadedTemplateDao;
 import org.sonar.core.user.*;
@@ -68,7 +67,6 @@ public final class DaoUtils {
       AuthorizationDao.class,
       DashboardDao.class,
       DuplicationDao.class,
-      FileSourceDao.class,
       GraphDao.class,
       GroupMembershipDao.class,
       IssueDao.class,
@@ -90,7 +88,7 @@ public final class DaoUtils {
       RuleDao.class,
       SemaphoreDao.class,
       UserDao.class
-    );
+      );
   }
 
   /**
@@ -116,7 +114,7 @@ public final class DaoUtils {
     StringBuilder sb = new StringBuilder();
     for (int i = 0; i < count; i++) {
       sb.append(sql);
-      if (i < count-1) {
+      if (i < count - 1) {
         sb.append(" ").append(separator).append(" ");
       }
     }
diff --git a/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataTypes.java b/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataTypes.java
deleted file mode 100644 (file)
index 96d11d5..0000000
+++ /dev/null
@@ -1,27 +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.core.source;
-
-public interface SnapshotDataTypes {
-
-  String SYNTAX_HIGHLIGHTING = "highlight_syntax";
-  String SYMBOL_HIGHLIGHTING = "symbol";
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/source/db/FileSourceDao.java b/sonar-core/src/main/java/org/sonar/core/source/db/FileSourceDao.java
deleted file mode 100644 (file)
index cbd9204..0000000
+++ /dev/null
@@ -1,136 +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.core.source.db;
-
-import com.google.common.base.Function;
-import org.apache.commons.dbutils.DbUtils;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.BatchComponent;
-import org.sonar.api.ServerComponent;
-import org.sonar.core.persistence.DaoComponent;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.persistence.MyBatis;
-
-import javax.annotation.CheckForNull;
-
-import java.io.InputStream;
-import java.io.Reader;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-
-public class FileSourceDao implements BatchComponent, ServerComponent, DaoComponent {
-
-  private final MyBatis mybatis;
-
-  public FileSourceDao(MyBatis myBatis) {
-    this.mybatis = myBatis;
-  }
-
-  @CheckForNull
-  public FileSourceDto select(String fileUuid) {
-    DbSession session = mybatis.openSession(false);
-    try {
-      FileSourceMapper mapper = session.getMapper(FileSourceMapper.class);
-      return mapper.select(fileUuid);
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  public <T> void readDataStream(String fileUuid, Function<InputStream, T> function) {
-    DbSession dbSession = mybatis.openSession(false);
-    Connection connection = dbSession.getConnection();
-    PreparedStatement pstmt = null;
-    ResultSet rs = null;
-    InputStream input = null;
-    try {
-      pstmt = connection.prepareStatement("SELECT binary_data FROM file_sources WHERE file_uuid=?");
-      pstmt.setString(1, fileUuid);
-      rs = pstmt.executeQuery();
-      if (rs.next()) {
-        input = rs.getBinaryStream(1);
-        function.apply(input);
-      }
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to read FILE_SOURCES.BINARY_DATA of file " + fileUuid, e);
-    } finally {
-      IOUtils.closeQuietly(input);
-      DbUtils.closeQuietly(connection, pstmt, rs);
-      MyBatis.closeQuietly(dbSession);
-    }
-  }
-
-  public <T> void readLineHashesStream(DbSession dbSession, String fileUuid, Function<Reader, T> function) {
-    Connection connection = dbSession.getConnection();
-    PreparedStatement pstmt = null;
-    ResultSet rs = null;
-    Reader reader = null;
-    try {
-      pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=?");
-      pstmt.setString(1, fileUuid);
-      rs = pstmt.executeQuery();
-      if (rs.next()) {
-        reader = rs.getCharacterStream(1);
-        function.apply(reader);
-      }
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e);
-    } finally {
-      IOUtils.closeQuietly(reader);
-      DbUtils.closeQuietly(connection, pstmt, rs);
-    }
-  }
-
-  public void insert(FileSourceDto dto) {
-    DbSession session = mybatis.openSession(false);
-    try {
-      insert(session, dto);
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  public void insert(DbSession session, FileSourceDto dto) {
-    session.getMapper(FileSourceMapper.class).insert(dto);
-  }
-
-  public void update(FileSourceDto dto) {
-    DbSession session = mybatis.openSession(false);
-    try {
-      update(session, dto);
-      session.commit();
-    } finally {
-      MyBatis.closeQuietly(session);
-    }
-  }
-
-  public void update(DbSession session, FileSourceDto dto) {
-    session.getMapper(FileSourceMapper.class).update(dto);
-  }
-
-  public void updateDateWhenUpdatedDateIsZero(DbSession session, String projectUuid, long updateDate) {
-    session.getMapper(FileSourceMapper.class).updateDateWhenUpdatedDateIsZero(projectUuid, updateDate);
-  }
-
-}
diff --git a/sonar-core/src/main/java/org/sonar/core/source/package-info.java b/sonar-core/src/main/java/org/sonar/core/source/package-info.java
deleted file mode 100644 (file)
index 6e1e0ae..0000000
+++ /dev/null
@@ -1,24 +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.
- */
-
-@ParametersAreNonnullByDefault
-package org.sonar.core.source;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-core/src/test/java/org/sonar/core/source/db/FileSourceDaoTest.java b/sonar-core/src/test/java/org/sonar/core/source/db/FileSourceDaoTest.java
deleted file mode 100644 (file)
index 8f2ed1f..0000000
+++ /dev/null
@@ -1,170 +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.core.source.db;
-
-import com.google.common.base.Function;
-import org.apache.commons.io.IOUtils;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.sonar.core.persistence.AbstractDaoTestCase;
-import org.sonar.core.persistence.DbSession;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.Reader;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class FileSourceDaoTest extends AbstractDaoTestCase {
-
-  DbSession session;
-
-  FileSourceDao dao;
-
-  @Before
-  public void setUpTestData() {
-    session = getMyBatis().openSession(false);
-    dao = new FileSourceDao(getMyBatis());
-  }
-
-  @After
-  public void tearDown() throws Exception {
-    session.close();
-  }
-
-  @Test
-  public void select() throws Exception {
-    setupData("shared");
-
-    FileSourceDto fileSourceDto = dao.select("FILE1_UUID");
-
-    assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
-    assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
-    assertThat(fileSourceDto.getProjectUuid()).isEqualTo("PRJ_UUID");
-    assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
-    assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
-    assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
-  }
-
-  @Test
-  public void select_data() throws Exception {
-    setupData("shared");
-
-    InputStreamToStringFunction fn = new InputStreamToStringFunction();
-    dao.readDataStream("FILE1_UUID", fn);
-
-    assertThat(fn.result).isNotEmpty();
-  }
-
-  @Test
-  public void select_line_hashes() throws Exception {
-    setupData("shared");
-
-    ReaderToStringFunction fn = new ReaderToStringFunction();
-    dao.readLineHashesStream(session, "FILE1_UUID", fn);
-
-    assertThat(fn.result).isEqualTo("ABC\\nDEF\\nGHI");
-  }
-
-  @Test
-  public void no_line_hashes_on_unknown_file() throws Exception {
-    setupData("shared");
-
-    ReaderToStringFunction fn = new ReaderToStringFunction();
-    dao.readLineHashesStream(session, "unknown", fn);
-
-    assertThat(fn.result).isNull();
-  }
-
-  @Test
-  public void insert() throws Exception {
-    setupData("shared");
-
-    dao.insert(new FileSourceDto()
-      .setProjectUuid("PRJ_UUID")
-      .setFileUuid("FILE2_UUID")
-      .setBinaryData("FILE2_BINARY_DATA".getBytes())
-      .setDataHash("FILE2_DATA_HASH")
-      .setLineHashes("LINE1_HASH\\nLINE2_HASH")
-      .setSrcHash("FILE2_HASH")
-      .setCreatedAt(1500000000000L)
-      .setUpdatedAt(1500000000001L));
-
-    checkTable("insert", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
-  }
-
-  @Test
-  public void update() throws Exception {
-    setupData("shared");
-
-    dao.update(new FileSourceDto().setId(101L)
-      .setProjectUuid("PRJ_UUID")
-      .setFileUuid("FILE1_UUID")
-      .setBinaryData("updated data".getBytes())
-      .setDataHash("NEW_DATA_HASH")
-      .setSrcHash("NEW_FILE_HASH")
-      .setLineHashes("NEW_LINE_HASHES")
-      .setUpdatedAt(1500000000002L));
-
-    checkTable("update", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
-  }
-
-  @Test
-  public void update_date_when_updated_date_is_zero() throws Exception {
-    setupData("update_date_when_updated_date_is_zero");
-
-    dao.updateDateWhenUpdatedDateIsZero(session, "ABCD", 1500000000002L);
-    session.commit();
-
-    checkTable("update_date_when_updated_date_is_zero", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at");
-  }
-
-  private static class ReaderToStringFunction implements Function<Reader, String> {
-
-    String result = null;
-
-    @Override
-    public String apply(Reader input) {
-      try {
-        result = IOUtils.toString(input);
-        return IOUtils.toString(input);
-      } catch (IOException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-
-  private static class InputStreamToStringFunction implements Function<InputStream, String> {
-
-    String result = null;
-
-    @Override
-    public String apply(InputStream input) {
-      try {
-        result = IOUtils.toString(input);
-        return IOUtils.toString(input);
-      } catch (IOException e) {
-        throw new RuntimeException(e);
-      }
-    }
-  }
-}
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/insert-result.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/insert-result.xml
deleted file mode 100644 (file)
index 67fb0ae..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
-  <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
-                binary_data="abcde" data_hash="hash"
-                test_data="[null]"
-                line_hashes="ABC\nDEF\nGHI"
-                src_hash="FILE_HASH"
-                created_at="1500000000000" updated_at="1500000000000" />
-
-
-  <file_sources id="102" project_uuid="PRJ_UUID" file_uuid="FILE2_UUID"
-                binary_data="[ignore]"
-                test_data="[null]"
-                data_hash="FILE2_DATA_HASH"
-                line_hashes="LINE1_HASH\nLINE2_HASH"
-                src_hash="FILE2_HASH"
-                created_at="1500000000000" updated_at="1500000000001" />
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/shared.xml
deleted file mode 100644 (file)
index c04c92d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
-    <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
-                  binary_data="abcde" data_hash="hash"
-                  test_data="[null]"
-                  line_hashes="ABC\nDEF\nGHI"
-                  src_hash="FILE_HASH"
-                  created_at="1500000000000" updated_at="1500000000000" />
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update-result.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update-result.xml
deleted file mode 100644 (file)
index 2d71f37..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-
-  <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
-                binary_data="[ignore]"
-                test_data="[null]"
-                data_hash="NEW_DATA_HASH"
-                line_hashes="NEW_LINE_HASHES"
-                src_hash="NEW_FILE_HASH"
-                created_at="1500000000000" updated_at="1500000000002" />
-
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
deleted file mode 100644 (file)
index 0450883..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<dataset>
-
-  <!-- Updated -->
-  <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="1500000000002"/>
-
-  <!-- Not updated because updated_at is not null -->
-  <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="1500000000000"/>
-
-  <!-- Not updated because on another project -->
-  <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="0"/>
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
deleted file mode 100644 (file)
index 5444e33..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
-  <!-- Only this source should be updated -->
-  <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="0"/>
-
-  <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="1500000000000"/>
-
-  <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
-                binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
-                test_data="[null]"
-                created_at="1500000000000" updated_at="0"/>
-
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/source/db/SnapshotDataDaoTest/shared.xml b/sonar-core/src/test/resources/org/sonar/core/source/db/SnapshotDataDaoTest/shared.xml
deleted file mode 100644 (file)
index 0b64abe..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<dataset>
-
-  <projects id="1" kee="org.apache.struts:struts:Dispatcher" enabled="[true]"/>
-
-  <snapshot_data id="101" resource_id="1" snapshot_id="10" snapshot_data="0,10,k;" data_type="highlight_syntax"/>
-  <snapshot_data id="102" resource_id="1" snapshot_id="10" snapshot_data="20,25,20,35,45;" data_type="symbol"/>
-
-</dataset>