com.google.gerrit.server.schema.Schema_77.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gerrit.server.schema.Schema_77.java

Source

// Copyright (C) 2013 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.gerrit.server.schema;

import static com.google.common.base.Preconditions.checkArgument;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gerrit.common.data.LabelType;
import com.google.gerrit.common.data.LabelTypes;
import com.google.gerrit.common.data.LabelValue;
import com.google.gerrit.reviewdb.client.PatchSetApproval.LabelId;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.MetaDataUpdate;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.schema.sql.DialectH2;
import com.google.gwtorm.schema.sql.DialectMySQL;
import com.google.gwtorm.schema.sql.DialectPostgreSQL;
import com.google.gwtorm.schema.sql.SqlDialect;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;

import java.io.IOException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;

public class Schema_77 extends SchemaVersion {
    private final GitRepositoryManager mgr;
    private final AllProjectsName allProjects;
    private final PersonIdent serverUser;

    @Inject
    Schema_77(Provider<Schema_76> prior, AllProjectsName allProjects, GitRepositoryManager mgr,
            @GerritPersonIdent PersonIdent serverUser) {
        super(prior);
        this.allProjects = allProjects;
        this.mgr = mgr;
        this.serverUser = serverUser;
    }

    @Override
    protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
        try {
            LegacyLabelTypes labelTypes = getLegacyTypes(db);
            SqlDialect dialect = ((JdbcSchema) db).getDialect();
            if (dialect instanceof DialectH2) {
                alterTable(db, "ALTER TABLE %s ALTER COLUMN %s varchar(255)");
            } else if (dialect instanceof DialectPostgreSQL) {
                alterTable(db, "ALTER TABLE %s ALTER %s TYPE varchar(255)");
            } else if (dialect instanceof DialectMySQL) {
                alterTable(db, "ALTER TABLE %s MODIFY %s varchar(255) BINARY");
            } else {
                alterTable(db, "ALTER TABLE %s MODIFY %s varchar(255)");
            }
            migratePatchSetApprovals(db, labelTypes);
            migrateLabelsToAllProjects(db, labelTypes);
        } catch (RepositoryNotFoundException e) {
            throw new OrmException(e);
        } catch (SQLException e) {
            throw new OrmException(e);
        } catch (IOException e) {
            throw new OrmException(e);
        } catch (ConfigInvalidException e) {
            throw new OrmException(e);
        }
        ui.message("Migrated label types from database to All-Projects project.config");
    }

    private void alterTable(ReviewDb db, String sqlFormat) throws SQLException {
        Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
        try {
            stmt.executeUpdate(String.format(sqlFormat, "patch_set_approvals", "category_id"));
        } finally {
            stmt.close();
        }
    }

    private void migrateLabelsToAllProjects(ReviewDb db, LegacyLabelTypes labelTypes)
            throws SQLException, RepositoryNotFoundException, IOException, ConfigInvalidException {
        Repository git = mgr.openRepository(allProjects);

        try {
            MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjects, git);
            md.getCommitBuilder().setAuthor(serverUser);
            md.getCommitBuilder().setCommitter(serverUser);

            ProjectConfig config = ProjectConfig.read(md);
            Map<String, LabelType> configTypes = config.getLabelSections();
            List<LabelType> newTypes = Lists.newArrayList();
            for (LegacyLabelType type : labelTypes.getLegacyLabelTypes()) {
                if (!configTypes.containsKey(type.getName())) {
                    newTypes.add(type);
                }
            }
            newTypes.addAll(configTypes.values());
            configTypes.clear();
            for (LabelType type : newTypes) {
                configTypes.put(type.getName(), type);
            }
            md.setMessage("Upgrade to Gerrit Code Review schema 77\n");
            config.commit(md);
        } finally {
            git.close();
        }
    }

    private void migratePatchSetApprovals(ReviewDb db, LegacyLabelTypes labelTypes) throws SQLException {
        PreparedStatement stmt = ((JdbcSchema) db).getConnection()
                .prepareStatement("UPDATE patch_set_approvals SET category_id = ? WHERE category_id = ?");
        try {
            for (LegacyLabelType type : labelTypes.getLegacyLabelTypes()) {
                stmt.setString(1, type.getName());
                stmt.setString(2, type.getId());
                stmt.addBatch();
            }
            stmt.executeBatch();
        } finally {
            stmt.close();
        }
    }

    static class LegacyLabelType extends LabelType {
        private String id;

        private LegacyLabelType(String name, List<LabelValue> values) {
            super(name, values);
        }

        String getId() {
            return id;
        }

        private void setId(String id) {
            checkArgument(id.length() <= 4, "Invalid legacy label ID: \"%s\"", id);
            this.id = id;
        }
    }

    static class LegacyLabelTypes extends LabelTypes {
        private final List<LegacyLabelType> legacyTypes;

        private final Map<String, LegacyLabelType> byId;

        private LegacyLabelTypes(List<LegacyLabelType> types) {
            super(types);
            legacyTypes = types;
            byId = Maps.newHashMap();
            for (LegacyLabelType type : types) {
                byId.put(type.getId(), type);
            }
        }

        List<LegacyLabelType> getLegacyLabelTypes() {
            return legacyTypes;
        }

        @Override
        public LegacyLabelType byLabel(LabelId labelId) {
            LegacyLabelType t = byId.get(labelId.get());
            return t != null ? t : (LegacyLabelType) super.byLabel(labelId);
        }

        LegacyLabelType byId(LabelId id) {
            return byId.get(id.get());
        }
    }

    static LegacyLabelTypes getLegacyTypes(ReviewDb db) throws SQLException {
        List<LegacyLabelType> types = Lists.newArrayListWithCapacity(2);
        Statement catStmt = null;
        PreparedStatement valStmt = null;
        ResultSet catRs = null;
        try {
            catStmt = ((JdbcSchema) db).getConnection().createStatement();
            catRs = catStmt.executeQuery("SELECT category_id, name, abbreviated_name, function_name, "
                    + " copy_min_score" + " FROM approval_categories" + " ORDER BY position, name");
            valStmt = ((JdbcSchema) db).getConnection().prepareStatement(
                    "SELECT value, name" + " FROM approval_category_values" + " WHERE category_id = ?");
            while (catRs.next()) {
                String id = catRs.getString("category_id");
                valStmt.setString(1, id);
                List<LabelValue> values = Lists.newArrayListWithCapacity(5);
                ResultSet valRs = valStmt.executeQuery();
                try {
                    while (valRs.next()) {
                        values.add(new LabelValue(valRs.getShort("value"), valRs.getString("name")));
                    }
                } finally {
                    valRs.close();
                }
                LegacyLabelType type = new LegacyLabelType(getLabelName(catRs.getString("name")), values);
                type.setId(id);
                type.setAbbreviation(catRs.getString("abbreviated_name"));
                type.setFunctionName(catRs.getString("function_name"));
                type.setCopyMinScore("Y".equals(catRs.getString("copy_min_score")));
                types.add(type);
            }
        } finally {
            if (valStmt != null) {
                valStmt.close();
            }
            if (catRs != null) {
                catRs.close();
            }
            if (catStmt != null) {
                catStmt.close();
            }
        }
        return new LegacyLabelTypes(types);
    }

    private static String getLabelName(String name) {
        StringBuilder r = new StringBuilder();
        for (int i = 0; i < name.length(); i++) {
            char c = name.charAt(i);
            if (('0' <= c && c <= '9') //
                    || ('a' <= c && c <= 'z') //
                    || ('A' <= c && c <= 'Z') //
                    || (c == '-')) {
                r.append(c);
            } else if (c == ' ') {
                r.append('-');
            }
        }
        return r.toString();
    }
}