diff options
author | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-08-17 16:49:34 +0200 |
---|---|---|
committer | Sébastien Lesaint <sebastien.lesaint@sonarsource.com> | 2016-08-22 10:25:43 +0200 |
commit | e9ac521dd1204c523dc0e497f141529e6abd4e3f (patch) | |
tree | 6d0272be6f1b2433affd3196e132d14d8fbe4fe2 /sonar-db/src/main | |
parent | 6dac2f2642d8ac888e1c07066f2081b61ea37ae3 (diff) | |
download | sonarqube-e9ac521dd1204c523dc0e497f141529e6abd4e3f.tar.gz sonarqube-e9ac521dd1204c523dc0e497f141529e6abd4e3f.zip |
SONAR-7844 add ScannerContextDao
Diffstat (limited to 'sonar-db/src/main')
7 files changed, 217 insertions, 8 deletions
diff --git a/sonar-db/src/main/java/org/sonar/db/DaoModule.java b/sonar-db/src/main/java/org/sonar/db/DaoModule.java index ba299a873ca..d18f35a86dd 100644 --- a/sonar-db/src/main/java/org/sonar/db/DaoModule.java +++ b/sonar-db/src/main/java/org/sonar/db/DaoModule.java @@ -27,10 +27,10 @@ import org.sonar.db.ce.CeActivityDao; import org.sonar.db.ce.CeQueueDao; import org.sonar.db.ce.CeTaskInputDao; import org.sonar.db.component.ComponentDao; +import org.sonar.db.component.ComponentKeyUpdaterDao; import org.sonar.db.component.ComponentLinkDao; import org.sonar.db.component.ResourceDao; import org.sonar.db.component.ResourceIndexDao; -import org.sonar.db.component.ComponentKeyUpdaterDao; import org.sonar.db.component.SnapshotDao; import org.sonar.db.dashboard.ActiveDashboardDao; import org.sonar.db.dashboard.DashboardDao; @@ -50,8 +50,8 @@ import org.sonar.db.measure.custom.CustomMeasureDao; import org.sonar.db.metric.MetricDao; import org.sonar.db.notification.NotificationQueueDao; import org.sonar.db.permission.PermissionDao; -import org.sonar.db.permission.template.PermissionTemplateDao; import org.sonar.db.permission.template.PermissionTemplateCharacteristicDao; +import org.sonar.db.permission.template.PermissionTemplateDao; import org.sonar.db.property.PropertiesDao; import org.sonar.db.purge.PurgeDao; import org.sonar.db.qualitygate.ProjectQgateAssociationDao; @@ -60,6 +60,7 @@ import org.sonar.db.qualitygate.QualityGateDao; import org.sonar.db.qualityprofile.ActiveRuleDao; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.rule.RuleDao; +import org.sonar.db.scannercontext.ScannerContextDao; import org.sonar.db.source.FileSourceDao; import org.sonar.db.user.AuthorDao; import org.sonar.db.user.AuthorizationDao; @@ -102,11 +103,12 @@ public class DaoModule extends Module { PermissionTemplateDao.class, PermissionTemplateCharacteristicDao.class, PropertiesDao.class, + ProjectQgateAssociationDao.class, + PurgeDao.class, QualityGateDao.class, QualityGateConditionDao.class, - ProjectQgateAssociationDao.class, QualityProfileDao.class, - PurgeDao.class, + ScannerContextDao.class, RuleDao.class, ActiveRuleDao.class, ResourceIndexDao.class, diff --git a/sonar-db/src/main/java/org/sonar/db/DbClient.java b/sonar-db/src/main/java/org/sonar/db/DbClient.java index 527b3dd7630..929813bfd66 100644 --- a/sonar-db/src/main/java/org/sonar/db/DbClient.java +++ b/sonar-db/src/main/java/org/sonar/db/DbClient.java @@ -60,6 +60,7 @@ import org.sonar.db.qualitygate.QualityGateDao; import org.sonar.db.qualityprofile.ActiveRuleDao; import org.sonar.db.qualityprofile.QualityProfileDao; import org.sonar.db.rule.RuleDao; +import org.sonar.db.scannercontext.ScannerContextDao; import org.sonar.db.source.FileSourceDao; import org.sonar.db.user.AuthorDao; import org.sonar.db.user.AuthorizationDao; @@ -121,6 +122,7 @@ public class DbClient { private final GroupDao groupDao; private final RuleDao ruleDao; private final ActiveRuleDao activeRuleDao; + private final ScannerContextDao scannerContextDao; public DbClient(Database database, MyBatis myBatis, Dao... daos) { this.database = database; @@ -177,6 +179,7 @@ public class DbClient { groupDao = getDao(map, GroupDao.class); ruleDao = getDao(map, RuleDao.class); activeRuleDao = getDao(map, ActiveRuleDao.class); + scannerContextDao = getDao(map, ScannerContextDao.class); doOnLoad(map); } @@ -385,6 +388,10 @@ public class DbClient { return activeRuleDao; } + public ScannerContextDao scannerContextDao() { + return scannerContextDao; + } + protected <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) { return (K) map.get(clazz); } diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java index a4666c5c1e9..9ea48e9e2cb 100644 --- a/sonar-db/src/main/java/org/sonar/db/MyBatis.java +++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java @@ -36,6 +36,7 @@ import org.sonar.db.ce.CeQueueMapper; import org.sonar.db.ce.CeTaskInputMapper; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentDtoWithSnapshotId; +import org.sonar.db.component.ComponentKeyUpdaterMapper; import org.sonar.db.component.ComponentLinkDto; import org.sonar.db.component.ComponentLinkMapper; import org.sonar.db.component.ComponentMapper; @@ -43,7 +44,6 @@ import org.sonar.db.component.FilePathWithHashDto; import org.sonar.db.component.ResourceDto; import org.sonar.db.component.ResourceIndexDto; import org.sonar.db.component.ResourceIndexMapper; -import org.sonar.db.component.ComponentKeyUpdaterMapper; import org.sonar.db.component.ResourceMapper; import org.sonar.db.component.SnapshotDto; import org.sonar.db.component.SnapshotMapper; @@ -84,13 +84,13 @@ import org.sonar.db.metric.MetricMapper; import org.sonar.db.notification.NotificationQueueDto; import org.sonar.db.notification.NotificationQueueMapper; import org.sonar.db.permission.GroupWithPermissionDto; +import org.sonar.db.permission.UserWithPermissionDto; +import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; +import org.sonar.db.permission.template.PermissionTemplateCharacteristicMapper; import org.sonar.db.permission.template.PermissionTemplateDto; import org.sonar.db.permission.template.PermissionTemplateGroupDto; import org.sonar.db.permission.template.PermissionTemplateMapper; import org.sonar.db.permission.template.PermissionTemplateUserDto; -import org.sonar.db.permission.UserWithPermissionDto; -import org.sonar.db.permission.template.PermissionTemplateCharacteristicDto; -import org.sonar.db.permission.template.PermissionTemplateCharacteristicMapper; import org.sonar.db.property.PropertiesMapper; import org.sonar.db.property.PropertyDto; import org.sonar.db.purge.IdUuidPair; diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java new file mode 100644 index 00000000000..ab55e461818 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/scannercontext/LogsIteratorInputStream.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.db.scannercontext; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import org.sonar.core.util.CloseableIterator; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * An {@link InputStream} that will read from a {@link CloseableIterator} of {@link String}, inserting {@code \n} between + * each element of the Iterator. + */ +final class LogsIteratorInputStream extends InputStream { + private static final int UNSET = -1; + private static final int END_OF_STREAM = -1; + + private final Charset charset; + private final byte[] lineFeed; + private CloseableIterator<String> logsIterator; + private byte[] buf; + private int nextChar = UNSET; + + LogsIteratorInputStream(CloseableIterator<String> logsIterator, Charset charset) { + checkArgument(logsIterator.hasNext(), "LogsIterator can't be empty or already read"); + this.charset = charset; + this.lineFeed = "\n".getBytes(charset); + this.logsIterator = logsIterator; + } + + @Override + public int read() throws IOException { + if (nextChar == UNSET || nextChar >= buf.length) { + fill(); + if (nextChar == UNSET) { + return END_OF_STREAM; + } + } + return buf[nextChar++]; + } + + private void fill() { + if (logsIterator.hasNext()) { + byte[] line = logsIterator.next().getBytes(charset); + boolean hasNextLine = logsIterator.hasNext(); + int bufLength = hasNextLine ? (line.length + lineFeed.length) : line.length; + // empty last line + if (bufLength == 0) { + this.buf = null; + this.nextChar = UNSET; + } else { + this.buf = new byte[bufLength]; + System.arraycopy(line, 0, buf, 0, line.length); + if (hasNextLine) { + System.arraycopy(lineFeed, 0, buf, line.length, lineFeed.length); + } + this.nextChar = 0; + } + } else { + this.buf = null; + this.nextChar = UNSET; + } + } + + @Override + public void close() throws IOException { + this.logsIterator.close(); + this.buf = null; + + super.close(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java new file mode 100644 index 00000000000..c294922548c --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/scannercontext/ScannerContextDao.java @@ -0,0 +1,84 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.db.scannercontext; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.Charset; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Optional; +import org.apache.commons.io.IOUtils; +import org.sonar.api.utils.System2; +import org.sonar.core.util.CloseableIterator; +import org.sonar.db.Dao; +import org.sonar.db.DbSession; + +import static com.google.common.base.Preconditions.checkArgument; + +public class ScannerContextDao implements Dao { + + private static final Charset UTF_8 = Charset.forName("UTF-8"); + + private final System2 system; + + public ScannerContextDao(System2 system) { + this.system = system; + } + + /** + * @throws IllegalArgumentException if {@code scannerContextLines} is empty or fully read. + */ + public void insert(DbSession dbSession, String analysisUuid, CloseableIterator<String> scannerContextLines) { + checkArgument(scannerContextLines.hasNext(), "Scanner context can not be empty"); + long now = system.now(); + try (PreparedStatement stmt = dbSession.getConnection().prepareStatement( + "INSERT INTO scanner_context (analysis_uuid, created_at, updated_at, data) VALUES (?, ?, ?, ?)"); + InputStream inputStream = new LogsIteratorInputStream(scannerContextLines, UTF_8)) { + stmt.setString(1, analysisUuid); + stmt.setLong(2, now); + stmt.setLong(3, now); + stmt.setBinaryStream(4, inputStream); + stmt.executeUpdate(); + } catch (SQLException | IOException e) { + throw new IllegalStateException("Fail to insert scanner context for analysis " + analysisUuid, e); + } + } + + /** + * The scanner context is very likely to contain lines, which are forcefully separated by {@code \n} characters, + * whichever the platform SQ is running on ({@see LogsIteratorInputStream}). + */ + public Optional<String> selectScannerContext(DbSession dbSession, String analysisUuid) { + try (PreparedStatement stmt = dbSession.getConnection().prepareStatement("select data from scanner_context where analysis_uuid=?")) { + stmt.setString(1, analysisUuid); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return Optional.of(IOUtils.toString(rs.getBinaryStream(1), UTF_8)); + } + return Optional.empty(); + } + } catch (SQLException | IOException e) { + throw new IllegalStateException("Fail to retrieve scanner context of analysis " + analysisUuid, e); + } + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java b/sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java new file mode 100644 index 00000000000..de8b7394f01 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/scannercontext/package-info.java @@ -0,0 +1,24 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.db.scannercontext; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl index 7559720c657..3aeed281ed8 100644 --- a/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl +++ b/sonar-db/src/main/resources/org/sonar/db/version/schema-h2.ddl @@ -544,6 +544,7 @@ CREATE TABLE "CE_ACTIVITY" ( ); CREATE TABLE "CE_TASK_INPUT" ( + "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1), "TASK_UUID" VARCHAR(40) NOT NULL, "DATA" BLOB(167772150), "CREATED_AT" BIGINT NOT NULL, |