3 * Copyright (C) 2009-2023 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.ce.task.projectexport.analysis;
22 import com.sonarsource.governance.projectdump.protobuf.ProjectDump;
23 import java.sql.PreparedStatement;
24 import java.sql.ResultSet;
25 import java.sql.SQLException;
26 import org.slf4j.LoggerFactory;
27 import org.sonar.ce.task.projectexport.component.ComponentRepository;
28 import org.sonar.ce.task.projectexport.steps.DumpElement;
29 import org.sonar.ce.task.projectexport.steps.DumpWriter;
30 import org.sonar.ce.task.projectexport.steps.ProjectHolder;
31 import org.sonar.ce.task.projectexport.steps.StreamWriter;
32 import org.sonar.ce.task.step.ComputationStep;
33 import org.sonar.db.DatabaseUtils;
34 import org.sonar.db.DbClient;
35 import org.sonar.db.DbSession;
37 import static java.lang.String.format;
38 import static org.apache.commons.lang.StringUtils.defaultString;
39 import static org.sonar.db.DatabaseUtils.getString;
40 import static org.sonar.db.component.SnapshotDto.STATUS_PROCESSED;
42 public class ExportAnalysesStep implements ComputationStep {
44 // contrary to naming convention used in other tables, the column snapshots.created_at is
45 // the functional date (for instance when using property sonar.projectDate=2010-01-01). The
46 // column "build_date" is the technical date of scanner execution. It must not be exported.
47 private static final String QUERY = "select" +
48 " p.uuid, s.version, s.created_at," +
49 " s.period1_mode, s.period1_param, s.period1_date," +
50 " s.uuid, s.build_string" +
52 " inner join components p on s.root_component_uuid=p.uuid" +
53 " inner join project_branches pb on pb.uuid=p.uuid" +
54 " where pb.project_uuid=? and pb.branch_type = 'BRANCH' and pb.exclude_from_purge=? and s.status=? and p.enabled=?" +
55 " order by s.build_date asc";
57 private final DbClient dbClient;
58 private final ProjectHolder projectHolder;
59 private final ComponentRepository componentRepository;
60 private final DumpWriter dumpWriter;
62 public ExportAnalysesStep(DbClient dbClient, ProjectHolder projectHolder, ComponentRepository componentRepository, DumpWriter dumpWriter) {
63 this.dbClient = dbClient;
64 this.projectHolder = projectHolder;
65 this.componentRepository = componentRepository;
66 this.dumpWriter = dumpWriter;
70 public void execute(Context context) {
73 StreamWriter<ProjectDump.Analysis> output = dumpWriter.newStreamWriter(DumpElement.ANALYSES);
74 DbSession dbSession = dbClient.openSession(false);
75 PreparedStatement stmt = buildSelectStatement(dbSession);
76 ResultSet rs = stmt.executeQuery()) {
78 ProjectDump.Analysis.Builder builder = ProjectDump.Analysis.newBuilder();
80 // Results are ordered by ascending id so that any parent is located
81 // before its children.
82 ProjectDump.Analysis analysis = convertToAnalysis(rs, builder);
83 output.write(analysis);
86 LoggerFactory.getLogger(getClass()).debug("{} analyses exported", count);
88 } catch (Exception e) {
89 throw new IllegalStateException(format("Analysis Export failed after processing %d analyses successfully", count), e);
93 private PreparedStatement buildSelectStatement(DbSession dbSession) throws SQLException {
94 PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(dbSession, QUERY);
96 stmt.setString(1, projectHolder.projectDto().getUuid());
97 stmt.setBoolean(2, true);
98 stmt.setString(3, STATUS_PROCESSED);
99 stmt.setBoolean(4, true);
101 } catch (Exception t) {
102 DatabaseUtils.closeQuietly(stmt);
107 private ProjectDump.Analysis convertToAnalysis(ResultSet rs, ProjectDump.Analysis.Builder builder) throws SQLException {
109 long componentRef = componentRepository.getRef(rs.getString(1));
111 .setComponentRef(componentRef)
112 .setProjectVersion(defaultString(getString(rs, 2)))
113 .setDate(rs.getLong(3))
114 .setPeriod1Mode(defaultString(getString(rs, 4)))
115 .setPeriod1Param(defaultString(getString(rs, 5)))
116 .setPeriod1Date(rs.getLong(6))
117 .setUuid(rs.getString(7))
118 .setBuildString(defaultString(getString(rs, 8)))
123 public String getDescription() {
124 return "Export analyses";