Package com.google.gerrit.server.schema

Source Code of com.google.gerrit.server.schema.Schema_69

// Copyright (C) 2012 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.Strings.isNullOrEmpty;

import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
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.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.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.naming.NamingException;
import javax.naming.ldap.LdapName;

public class Schema_69 extends SchemaVersion {
  private final GitRepositoryManager mgr;
  private final PersonIdent serverUser;

  @Inject
  Schema_69(Provider<Schema_68> prior,
      GitRepositoryManager mgr,
      @GerritPersonIdent PersonIdent serverUser) {
    super(prior);
    this.mgr = mgr;
    this.serverUser = serverUser;
  }

  @Override
  protected void migrateData(ReviewDb db, UpdateUI ui)
      throws OrmException, SQLException {

    // Find all groups that have an LDAP type.
    Map<AccountGroup.UUID, GroupReference> ldapUUIDMap = Maps.newHashMap();
    Set<AccountGroup.UUID> toResolve = Sets.newHashSet();
    List<AccountGroup.Id> toDelete = Lists.newArrayList();
    List<AccountGroup.NameKey> namesToDelete = Lists.newArrayList();
    Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
    try {
      ResultSet rs = stmt.executeQuery(
          "SELECT group_id, group_uuid, external_name, name FROM account_groups"
          + " WHERE group_type ='LDAP'");
      try {
        while (rs.next()) {
          AccountGroup.Id groupId = new AccountGroup.Id(rs.getInt(1));
          AccountGroup.UUID groupUUID = new AccountGroup.UUID(rs.getString(2));
          AccountGroup.NameKey name = new AccountGroup.NameKey(rs.getString(4));
          String dn = rs.getString(3);

          if (isNullOrEmpty(dn)) {
            // The LDAP group does not have a DN. Determine if the UUID is used.
            toResolve.add(groupUUID);
          } else {
            toDelete.add(groupId);
            namesToDelete.add(name);
            GroupReference ref = groupReference(dn);
            ldapUUIDMap.put(groupUUID, ref);
          }
        }
      } catch (NamingException e) {
        throw new RuntimeException(e);
      } finally {
        rs.close();
      }
    } finally {
      stmt.close();
    }
    if (toDelete.isEmpty() && toResolve.isEmpty()) {
      return; // No ldap groups. Nothing to do.
    }

    ui.message("Update LDAP groups to be GroupReferences.");

    // Update the groupOwnerUUID for LDAP groups to point to the new UUID.
    List<AccountGroup> toUpdate = Lists.newArrayList();
    Set<AccountGroup.UUID> resolveToUpdate = Sets.newHashSet();
    Map<AccountGroup.UUID, AccountGroup> resolveGroups = Maps.newHashMap();
    for (AccountGroup g : db.accountGroups().all()) {
      if (ldapUUIDMap.containsKey(g.getGroupUUID())) {
        continue; // Ignore the LDAP groups with a valid DN.
      } else if (toResolve.contains(g.getGroupUUID())) {
        resolveGroups.put(g.getGroupUUID(), g); // Keep the ones to resolve.
        continue;
      }

      GroupReference ref = ldapUUIDMap.get(g.getOwnerGroupUUID());
      if (ref != null) {
        // Update the owner group UUID to the new ldap UUID scheme.
        g.setOwnerGroupUUID(ref.getUUID());
        toUpdate.add(g);
      } else if (toResolve.contains(g.getOwnerGroupUUID())) {
        // The unresolved group is used as an owner.
        // Add to the list of LDAP groups to be made INTERNAL.
        resolveToUpdate.add(g.getOwnerGroupUUID());
      }
    }

    toResolve.removeAll(resolveToUpdate);

    // Update project.config group references to use the new LDAP GroupReference
    for (Project.NameKey name : mgr.list()) {
      Repository git;
      try {
        git = mgr.openRepository(name);
      } catch (RepositoryNotFoundException e) {
        throw new OrmException(e);
      } catch (IOException e) {
        throw new OrmException(e);
      }

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

        ProjectConfig config = ProjectConfig.read(md);

        // Update the existing refences to the new reference.
        boolean updated = false;
        for (Map.Entry<AccountGroup.UUID, GroupReference> entry: ldapUUIDMap.entrySet()) {
          GroupReference ref = config.getGroup(entry.getKey());
          if (ref != null) {
            updated = true;
            ref.setName(entry.getValue().getName());
            ref.setUUID(entry.getValue().getUUID());
            config.resolve(ref);
          }
        }

        // Determine if a toResolve group is used and should be made INTERNAL.
        Iterator<AccountGroup.UUID> iter = toResolve.iterator();
        while (iter.hasNext()) {
          AccountGroup.UUID uuid = iter.next();
          if (config.getGroup(uuid) != null) {
            resolveToUpdate.add(uuid);
            iter.remove();
          }
        }

        if (!updated) {
          continue;
        }

        md.setMessage("Switch LDAP group UUIDs to DNs\n");
        config.commit(md);
      } catch (IOException e) {
        throw new OrmException(e);
      } catch (ConfigInvalidException e) {
        throw new OrmException(e);
      } finally {
        git.close();
      }
    }

    for (AccountGroup.UUID uuid : resolveToUpdate) {
      AccountGroup group = resolveGroups.get(uuid);
      group.setType(AccountGroup.Type.INTERNAL);
      toUpdate.add(group);

      ui.message(String.format(
          "*** Group has no DN and is inuse. Updated to be INTERNAL: %s",
          group.getName()));
    }

    for (AccountGroup.UUID uuid : toResolve) {
      AccountGroup group = resolveGroups.get(uuid);
      toDelete.add(group.getId());
      namesToDelete.add(group.getNameKey());
    }

    // Update group owners
    db.accountGroups().update(toUpdate);
    // Delete existing LDAP groups
    db.accountGroupNames().deleteKeys(namesToDelete);
    db.accountGroups().deleteKeys(toDelete);
  }

  private static GroupReference groupReference(String dn)
      throws NamingException {
    LdapName name = new LdapName(dn);
    Preconditions.checkState(!name.isEmpty(), "Invalid LDAP dn: %s", dn);
    String cn = name.get(name.size() - 1);
    int index = cn.indexOf('=');
    if (index >= 0) {
      cn = cn.substring(index + 1);
    }
    return new GroupReference(new AccountGroup.UUID("ldap:" + dn), "ldap/" + cn);
  }
}
TOP

Related Classes of com.google.gerrit.server.schema.Schema_69

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.