From: Jenkins CI Date: Mon, 27 Apr 2015 15:53:24 +0000 (+0200) Subject: Automatic merge from branch-5.1 X-Git-Tag: 5.2-RC1~2110 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3ab0154887668e1e25cd14fca33f5fbdf00acdb7;p=sonarqube.git Automatic merge from branch-5.1 * origin/branch-5.1: SONAR-6493 java.lang.NullPointerException in the PopulateProjectsUuidColumns migration --- 3ab0154887668e1e25cd14fca33f5fbdf00acdb7 diff --cc server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationStep.java index 6cd5337d7db,00000000000..8f111e489ea mode 100644,000000..100644 --- a/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationStep.java +++ b/server/sonar-server/src/main/java/org/sonar/server/db/migrations/v50/PopulateProjectsUuidColumnsMigrationStep.java @@@ -1,197 -1,0 +1,199 @@@ +/* + * 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.db.migrations.v50; + +import com.google.common.base.Splitter; +import com.google.common.base.Strings; +import org.apache.ibatis.session.ResultContext; +import org.apache.ibatis.session.ResultHandler; +import org.sonar.api.resources.Scopes; +import org.sonar.api.utils.internal.Uuids; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.migration.v50.Component; +import org.sonar.core.persistence.migration.v50.Migration50Mapper; +import org.sonar.server.db.DbClient; +import org.sonar.server.db.migrations.MigrationStep; +import org.sonar.server.util.ProgressLogger; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicLong; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; + +/** + * Used in the Active Record Migration 705 + * + * @since 5.0 + */ +public class PopulateProjectsUuidColumnsMigrationStep implements MigrationStep { + + private static final Logger LOG = Loggers.get(PopulateProjectsUuidColumnsMigrationStep.class); + ++ private static final Logger LOG = Loggers.get(PopulateProjectsUuidColumnsMigration.class); ++ + private final DbClient db; + private final AtomicLong counter = new AtomicLong(0L); + + public PopulateProjectsUuidColumnsMigrationStep(DbClient db) { + this.db = db; + } + + @Override + public void execute() { + ProgressLogger progress = ProgressLogger.create(getClass(), counter); + progress.start(); + + final DbSession readSession = db.openSession(false); + final DbSession writeSession = db.openSession(true); + try { + readSession.select("org.sonar.core.persistence.migration.v50.Migration50Mapper.selectRootProjects", new ResultHandler() { + @Override + public void handleResult(ResultContext context) { + Component project = (Component) context.getResultObject(); + List components = readSession.getMapper(Migration50Mapper.class).selectComponentChildrenForProjects(project.getId()); + MigrationContext migrationContext = new MigrationContext(readSession, writeSession, project, components); + migrateEnabledComponents(migrationContext); + migrateDisabledComponents(migrationContext); + } + }); + writeSession.commit(true); + readSession.commit(true); + + migrateComponentsWithoutUuid(readSession, writeSession); + writeSession.commit(true); + + // log the total number of process rows + progress.log(); + } finally { + readSession.close(); + writeSession.close(); + progress.stop(); + } + } + + private void migrateEnabledComponents(MigrationContext migrationContext) { + saveComponent(migrationContext.writeSession, migrationContext.project); + for (Component component : migrationContext.componentsToMigrate) { + migrationContext.updateComponent(component); + if (Strings.isNullOrEmpty(component.getModuleUuidPath())) { + LOG.warn(String.format("Ignoring component id '%s' because the module uuid path could not be created", component.getId())); + } else { + migrationContext.updateComponent(component); + saveComponent(migrationContext.writeSession, component); + } + } + } + + private void migrateDisabledComponents(MigrationContext migrationContext) { + for (Component component : migrationContext.readSession.getMapper(Migration50Mapper.class).selectDisabledDirectComponentChildrenForProjects(migrationContext.project.getId())) { + migrationContext.updateComponent(component); + saveComponent(migrationContext.writeSession, component); + } + for (Component component : migrationContext.readSession.getMapper(Migration50Mapper.class).selectDisabledNoneDirectComponentChildrenForProjects( + migrationContext.project.getId())) { + migrationContext.updateComponent(component); + saveComponent(migrationContext.writeSession, component); + } + } + + private void migrateComponentsWithoutUuid(DbSession readSession, DbSession writeSession) { + for (Component component : readSession.getMapper(Migration50Mapper.class).selectComponentsWithoutUuid()) { + String uuid = Uuids.create(); + component.setUuid(uuid); + component.setProjectUuid(uuid); + saveComponent(writeSession, component); + } + } + + private void saveComponent(DbSession writeSession, Component component) { + writeSession.getMapper(Migration50Mapper.class).updateComponentUuids(component); + counter.getAndIncrement(); + } + + private static class MigrationContext { + private final DbSession readSession; + private final DbSession writeSession; + private final Component project; + private final Map componentsBySnapshotId = newHashMap(); + private final Map uuidByComponentId = newHashMap(); + private final List componentsToMigrate = newArrayList(); + + private MigrationContext(DbSession readSession, DbSession writeSession, Component project, List components) { + this.readSession = readSession; + this.writeSession = writeSession; + this.project = project; + + project.setUuid(getOrCreateUuid(project)); + project.setProjectUuid(project.getUuid()); + + componentsBySnapshotId.put(project.getSnapshotId(), project); + for (Component component : components) { + componentsBySnapshotId.put(component.getSnapshotId(), component); + if (component.getUuid() == null) { + componentsToMigrate.add(component); + } + } + } + + public void updateComponent(Component component) { + component.setUuid(getOrCreateUuid(component)); + component.setProjectUuid(getOrCreateUuid(project)); + + String snapshotPath = component.getSnapshotPath(); + StringBuilder moduleUuidPath = new StringBuilder(); + String lastModuleUuid = null; + if (!Strings.isNullOrEmpty(snapshotPath)) { + for (String s : Splitter.on(".").omitEmptyStrings().split(snapshotPath)) { + Long snapshotId = Long.valueOf(s); + Component currentComponent = componentsBySnapshotId.get(snapshotId); + if (currentComponent != null && currentComponent.getScope().equals(Scopes.PROJECT)) { + lastModuleUuid = getOrCreateUuid(currentComponent); + moduleUuidPath.append(lastModuleUuid).append("."); + } + } + } + + if (moduleUuidPath.length() > 0 && lastModuleUuid != null) { + // Remove last '.' + moduleUuidPath.deleteCharAt(moduleUuidPath.length() - 1); + + component.setModuleUuidPath(moduleUuidPath.toString()); + component.setModuleUuid(lastModuleUuid); + } + } + + private String getOrCreateUuid(Component component) { + String existingUuid = component.getUuid(); + String uuid = existingUuid == null ? uuidByComponentId.get(component.getId()) : existingUuid; + if (uuid == null) { + String newUuid = Uuids.create(); + uuidByComponentId.put(component.getId(), newUuid); + return newUuid; + } + return uuid; + } + } + +}