From: Julien HENRY Date: Fri, 17 Apr 2015 10:02:07 +0000 (+0200) Subject: SONAR-6253 Cleanup SourcePersister on batch side X-Git-Tag: 5.2-RC1~2234 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=fc072f94584c18f8312a2622475d7ce3e1eaa2d4;p=sonarqube.git SONAR-6253 Cleanup SourcePersister on batch side and move FileSourceDao to sonar-server --- diff --git a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java index 9bc46b01d20..3b2b858d251 100644 --- a/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java +++ b/server/sonar-server-benchmarks/src/test/java/org/sonar/server/benchmark/SourceDbBenchmarkTest.java @@ -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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java index fe5106cc7d6..028d5d9316e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/DbClient.java @@ -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; diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 796372498fd..fefb9f9d378 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -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 index 00000000000..d19556f3ec1 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/source/db/FileSourceDao.java @@ -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 void readDataStream(String fileUuid, Function 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 void readLineHashesStream(DbSession dbSession, String fileUuid, Function 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 index 00000000000..83a499f6401 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/source/db/package-info.java @@ -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; diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java index 829ad1a1dbd..e51a2b1afce 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java @@ -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; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java index 5f99a49d85c..1c7313091c0 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/IndexSourceLinesStepTest.java @@ -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; diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileSourcesStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileSourcesStepTest.java index dc503775f8a..e9620343928 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileSourcesStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/PersistFileSourcesStepTest.java @@ -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 index 00000000000..56fbcaa91b5 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/source/db/FileSourceDaoTest.java @@ -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 { + + 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 { + + 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/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java index 416c1e59dae..b8bdf6771ec 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/source/ws/HashActionTest.java @@ -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 index 00000000000..67fb0ae86e7 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/insert-result.xml @@ -0,0 +1,19 @@ + + + + + + + + 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 index 00000000000..c04c92d5c9b --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/shared.xml @@ -0,0 +1,10 @@ + + + + + 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 index 00000000000..2d71f379cf2 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update-result.xml @@ -0,0 +1,12 @@ + + + + + + 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 index 00000000000..0450883e306 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + 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 index 00000000000..5444e33435f --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml @@ -0,0 +1,19 @@ + + + + + + + + + + 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 index 53950bec479..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/index/SourceDataFactory.java +++ /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 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 measures = measureCache.byMetric(inputFileKey, metricKey); - if (measures.iterator().hasNext()) { - Measure measure = measures.iterator().next(); - Map lineMeasures = KeyValueFormat.parseIntString((String) measure.value()); - for (Map.Entry 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 = new ArrayList(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() { - @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 void writeDataPerLine(int[] originalLineOffsets, G item, Range range, StringBuilder[] dataPerLine, RangeItemWriter 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 void writeItem(G item, StringBuilder[] dataPerLine, int currentLineIdx, long startLineOffset, long endLineOffset, RangeItemWriter 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 { - /** - * Write item on a single line - */ - void writeItem(StringBuilder currentLineSb, long startLineOffset, long endLineOffset, G item); - } - - private static class RuleItemWriter implements RangeItemWriter { - @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 { - @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 groups = duplicationCache.byComponent(inputFileKey); - int blockId = 1; - for (Iterator it = groups.iterator(); it.hasNext();) { - Duplication group = it.next(); - addBlock(blockId, group.originBlock(), to); - blockId++; - for (Iterator 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 index 55df774b4ce..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/index/SourcePersister.java +++ /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 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 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); - } - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 12b0bc0f21d..e510aae33a6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -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 index b1c45ac1bd8..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/index/SourceDataFactoryTest.java +++ /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.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.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"); - } -} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java index 92f36946428..052120c913b 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DaoUtils.java @@ -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 index 96d11d51652..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/source/SnapshotDataTypes.java +++ /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 index cbd920455e9..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/source/db/FileSourceDao.java +++ /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 void readDataStream(String fileUuid, Function 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 void readLineHashesStream(DbSession dbSession, String fileUuid, Function 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 index 6e1e0aeb926..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/source/package-info.java +++ /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 index 8f2ed1fb45a..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/source/db/FileSourceDaoTest.java +++ /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 { - - 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 { - - 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 index 67fb0ae86e7..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/insert-result.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - 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 index c04c92d5c9b..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/shared.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - 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 index 2d71f379cf2..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update-result.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - 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 index 0450883e306..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - 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 index 5444e33435f..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - 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 index 0b64abea2ae..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/source/db/SnapshotDataDaoTest/shared.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - -