2 * SonarQube, open source software quality management tool.
3 * Copyright (C) 2008-2014 SonarSource
4 * mailto:contact AT sonarsource DOT com
6 * SonarQube 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 * SonarQube 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.
21 package org.sonar.server.db.migrations.v50;
23 import com.google.common.base.Splitter;
24 import com.google.common.base.Strings;
25 import org.apache.ibatis.session.ResultContext;
26 import org.apache.ibatis.session.ResultHandler;
27 import org.sonar.api.resources.Scopes;
28 import org.sonar.api.utils.internal.Uuids;
29 import org.sonar.core.persistence.DbSession;
30 import org.sonar.core.persistence.migration.v50.Component;
31 import org.sonar.core.persistence.migration.v50.Migration50Mapper;
32 import org.sonar.server.db.DbClient;
33 import org.sonar.server.db.migrations.DatabaseMigration;
34 import org.sonar.server.util.ProgressLogger;
36 import java.util.List;
38 import java.util.concurrent.atomic.AtomicLong;
40 import static com.google.common.collect.Lists.newArrayList;
41 import static com.google.common.collect.Maps.newHashMap;
44 * Used in the Active Record Migration 705
48 public class PopulateProjectsUuidColumnsMigration implements DatabaseMigration {
50 private final DbClient db;
51 private final AtomicLong counter = new AtomicLong(0L);
52 private final ProgressLogger progress = ProgressLogger.create(getClass(), counter);
54 public PopulateProjectsUuidColumnsMigration(DbClient db) {
59 public void execute() {
62 final DbSession readSession = db.openSession(false);
63 final DbSession writeSession = db.openSession(true);
65 readSession.select("org.sonar.core.persistence.migration.v50.Migration50Mapper.selectRootProjects", new ResultHandler() {
67 public void handleResult(ResultContext context) {
68 Component project = (Component) context.getResultObject();
69 Map<Long, String> uuidByComponentId = newHashMap();
70 migrateEnabledComponents(readSession, writeSession, project, uuidByComponentId);
71 migrateDisabledComponents(readSession, writeSession, project, uuidByComponentId);
74 writeSession.commit();
77 migrateComponentsWithoutUuid(readSession, writeSession);
78 writeSession.commit();
80 // log the total number of process rows
89 private void migrateEnabledComponents(DbSession readSession, DbSession writeSession, Component project, Map<Long, String> uuidByComponentId) {
90 Map<Long, Component> componentsBySnapshotId = newHashMap();
92 List<Component> components = readSession.getMapper(Migration50Mapper.class).selectComponentChildrenForProjects(project.getId());
93 components.add(project);
94 List<Component> componentsToMigrate = newArrayList();
95 for (Component component : components) {
96 componentsBySnapshotId.put(component.getSnapshotId(), component);
98 // Not migrate components already having an UUID
99 if (component.getUuid() == null) {
100 component.setUuid(getOrCreateUuid(component, uuidByComponentId));
101 component.setProjectUuid(getOrCreateUuid(project, uuidByComponentId));
102 componentsToMigrate.add(component);
106 for (Component component : componentsToMigrate) {
107 updateComponent(component, project, componentsBySnapshotId, uuidByComponentId);
108 writeSession.getMapper(Migration50Mapper.class).updateComponentUuids(component);
109 counter.getAndIncrement();
113 private void migrateDisabledComponents(DbSession readSession, DbSession writeSession, Component project, Map<Long, String> uuidByComponentId) {
114 String projectUuid = getOrCreateUuid(project, uuidByComponentId);
115 for (Component component : readSession.getMapper(Migration50Mapper.class).selectDisabledDirectComponentChildrenForProjects(project.getId())) {
116 component.setUuid(getOrCreateUuid(component, uuidByComponentId));
117 component.setProjectUuid(projectUuid);
119 writeSession.getMapper(Migration50Mapper.class).updateComponentUuids(component);
120 counter.getAndIncrement();
122 for (Component component : readSession.getMapper(Migration50Mapper.class).selectDisabledNoneDirectComponentChildrenForProjects(project.getId())) {
123 component.setUuid(getOrCreateUuid(component, uuidByComponentId));
124 component.setProjectUuid(projectUuid);
126 writeSession.getMapper(Migration50Mapper.class).updateComponentUuids(component);
127 counter.getAndIncrement();
131 private void updateComponent(Component component, Component project, Map<Long, Component> componentsBySnapshotId, Map<Long, String> uuidByComponentId) {
132 String snapshotPath = component.getSnapshotPath();
133 StringBuilder moduleUuidPath = new StringBuilder();
134 Component lastModule = null;
135 if (!Strings.isNullOrEmpty(snapshotPath)) {
136 for (String s : Splitter.on(".").omitEmptyStrings().split(snapshotPath)) {
137 Long snapshotId = Long.valueOf(s);
138 Component currentComponent = componentsBySnapshotId.get(snapshotId);
139 if (currentComponent.getScope().equals(Scopes.PROJECT)) {
140 lastModule = currentComponent;
141 moduleUuidPath.append(currentComponent.getUuid()).append(".");
145 if (moduleUuidPath.length() > 0) {
147 moduleUuidPath.deleteCharAt(moduleUuidPath.length() - 1);
148 component.setModuleUuidPath(moduleUuidPath.toString());
151 // Module UUID contains direct module of a component
152 if (lastModule != null) {
153 component.setModuleUuid(getOrCreateUuid(lastModule, uuidByComponentId));
157 private void migrateComponentsWithoutUuid(DbSession readSession, DbSession writeSession) {
158 for (Component component : readSession.getMapper(Migration50Mapper.class).selectComponentsWithoutUuid()) {
159 String uuid = Uuids.create();
160 component.setUuid(uuid);
161 component.setProjectUuid(uuid);
163 writeSession.getMapper(Migration50Mapper.class).updateComponentUuids(component);
164 counter.getAndIncrement();
168 private static String getOrCreateUuid(Component component, Map<Long, String> uuidByComponentId) {
169 String existingUuid = component.getUuid();
170 String uuid = existingUuid == null ? uuidByComponentId.get(component.getId()) : existingUuid;
172 String newUuid = Uuids.create();
173 uuidByComponentId.put(component.getId(), newUuid);