]> source.dussan.org Git - sonarqube.git/blob
0b1b23cb79c1ddcd217d581347d89eb740320b38
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2016 SonarSource SA
4  * mailto:contact AT sonarsource DOT com
5  *
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.
10  *
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.
15  *
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.
19  */
20 package org.sonar.server.computation.task.projectanalysis.step;
21
22 import java.util.List;
23 import javax.annotation.CheckForNull;
24 import javax.annotation.Nullable;
25 import org.sonar.api.utils.System2;
26 import org.sonar.db.DbClient;
27 import org.sonar.db.DbSession;
28 import org.sonar.db.component.SnapshotDto;
29 import org.sonar.server.computation.task.projectanalysis.analysis.AnalysisMetadataHolder;
30 import org.sonar.server.computation.task.projectanalysis.component.Component;
31 import org.sonar.server.computation.task.projectanalysis.component.CrawlerDepthLimit;
32 import org.sonar.server.computation.task.projectanalysis.component.PathAwareCrawler;
33 import org.sonar.server.computation.task.projectanalysis.component.PathAwareVisitorAdapter;
34 import org.sonar.server.computation.task.projectanalysis.component.TreeRootHolder;
35 import org.sonar.server.computation.task.projectanalysis.period.Period;
36 import org.sonar.server.computation.task.projectanalysis.period.PeriodsHolder;
37 import org.sonar.server.computation.task.step.ComputationStep;
38
39 /**
40  * Persist analysis
41  */
42 public class PersistAnalysisStep implements ComputationStep {
43
44   private final System2 system2;
45   private final DbClient dbClient;
46   private final TreeRootHolder treeRootHolder;
47   private final AnalysisMetadataHolder analysisMetadataHolder;
48   private final PeriodsHolder periodsHolder;
49
50   public PersistAnalysisStep(System2 system2, DbClient dbClient, TreeRootHolder treeRootHolder,
51     AnalysisMetadataHolder analysisMetadataHolder, PeriodsHolder periodsHolder) {
52     this.system2 = system2;
53     this.dbClient = dbClient;
54     this.treeRootHolder = treeRootHolder;
55     this.analysisMetadataHolder = analysisMetadataHolder;
56     this.periodsHolder = periodsHolder;
57   }
58
59   @Override
60   public void execute() {
61     DbSession session = dbClient.openSession(false);
62     try {
63       new PathAwareCrawler<>(
64         new PersistSnapshotsPathAwareVisitor(session, analysisMetadataHolder.getAnalysisDate()))
65           .visit(treeRootHolder.getRoot());
66       session.commit();
67     } finally {
68       dbClient.closeSession(session);
69     }
70   }
71
72   private class PersistSnapshotsPathAwareVisitor extends PathAwareVisitorAdapter<SnapshotDtoHolder> {
73
74     private final DbSession dbSession;
75     private final long analysisDate;
76
77     public PersistSnapshotsPathAwareVisitor(DbSession dbSession, long analysisDate) {
78       super(CrawlerDepthLimit.ROOTS, Order.PRE_ORDER, SnapshotDtoHolderFactory.INSTANCE);
79       this.dbSession = dbSession;
80       this.analysisDate = analysisDate;
81     }
82
83     @Override
84     public void visitProject(Component project, Path<SnapshotDtoHolder> path) {
85       SnapshotDto snapshot = createAnalysis(analysisMetadataHolder.getUuid(), project, true);
86       updateSnapshotPeriods(snapshot);
87       persist(snapshot, dbSession);
88     }
89
90     @Override
91     public void visitView(Component view, Path<SnapshotDtoHolder> path) {
92       SnapshotDto snapshot = createAnalysis(analysisMetadataHolder.getUuid(), view, false);
93       updateSnapshotPeriods(snapshot);
94       persist(snapshot, dbSession);
95     }
96
97     private void updateSnapshotPeriods(SnapshotDto snapshotDto) {
98       List<Period> periods = periodsHolder.getPeriods();
99       if (periods.isEmpty()) {
100         return;
101       }
102       Period period = periods.get(0);
103       snapshotDto.setPeriodMode(period.getMode());
104       snapshotDto.setPeriodParam(period.getModeParameter());
105       snapshotDto.setPeriodDate(period.getSnapshotDate());
106     }
107
108     private SnapshotDto createAnalysis(String snapshotUuid, Component component, boolean setVersion) {
109       String componentUuid = component.getUuid();
110       return new SnapshotDto()
111         .setUuid(snapshotUuid)
112         .setVersion(setVersion ? component.getReportAttributes().getVersion() : null)
113         .setComponentUuid(componentUuid)
114         .setLast(false)
115         .setStatus(SnapshotDto.STATUS_UNPROCESSED)
116         .setCreatedAt(analysisDate)
117         .setBuildDate(system2.now());
118     }
119
120     private void persist(SnapshotDto snapshotDto, DbSession dbSession) {
121       dbClient.snapshotDao().insert(dbSession, snapshotDto);
122     }
123   }
124
125   private static final class SnapshotDtoHolder {
126     @CheckForNull
127     private SnapshotDto snapshotDto;
128
129     @CheckForNull
130     public SnapshotDto getSnapshotDto() {
131       return snapshotDto;
132     }
133
134     public void setSnapshotDto(@Nullable SnapshotDto snapshotDto) {
135       this.snapshotDto = snapshotDto;
136     }
137   }
138
139   /**
140    * Factory of SnapshotDtoHolder.
141    *
142    * No need to create an instance for components of type FILE and PROJECT_VIEW, since they are the leaves of their
143    * respective trees, no one will consume the value of the holder, so we save on creating useless objects.
144    */
145   private static class SnapshotDtoHolderFactory extends PathAwareVisitorAdapter.SimpleStackElementFactory<SnapshotDtoHolder> {
146     public static final SnapshotDtoHolderFactory INSTANCE = new SnapshotDtoHolderFactory();
147
148     @Override
149     public SnapshotDtoHolder createForAny(Component component) {
150       return new SnapshotDtoHolder();
151     }
152
153     @Override
154     public SnapshotDtoHolder createForFile(Component file) {
155       return null;
156     }
157
158     @Override
159     public SnapshotDtoHolder createForProjectView(Component projectView) {
160       return null;
161     }
162   }
163
164   @Override
165   public String getDescription() {
166     return "Persist analysis";
167   }
168 }