Line data Source code
1 : // Copyright (C) 2014 The Android Open Source Project 2 : // 3 : // Licensed under the Apache License, Version 2.0 (the "License"); 4 : // you may not use this file except in compliance with the License. 5 : // You may obtain a copy of the License at 6 : // 7 : // http://www.apache.org/licenses/LICENSE-2.0 8 : // 9 : // Unless required by applicable law or agreed to in writing, software 10 : // distributed under the License is distributed on an "AS IS" BASIS, 11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 : // See the License for the specific language governing permissions and 13 : // limitations under the License. 14 : 15 : package com.google.gerrit.server.project; 16 : 17 : import com.google.common.flogger.FluentLogger; 18 : import com.google.gerrit.common.Nullable; 19 : import com.google.gerrit.entities.AccountGroup; 20 : import com.google.gerrit.entities.GroupReference; 21 : import com.google.gerrit.entities.Project; 22 : import com.google.gerrit.server.git.ValidationError; 23 : import com.google.gerrit.server.git.meta.TabFile; 24 : import java.io.IOException; 25 : import java.util.ArrayList; 26 : import java.util.Collection; 27 : import java.util.HashMap; 28 : import java.util.List; 29 : import java.util.Map; 30 : import java.util.Set; 31 : 32 : /** 33 : * File format for group name aliases. 34 : * 35 : * <p>Project configuration must use aliases for groups used in the permission section. The 36 : * aliases/group mapping is stored in a file "groups", (de)serialized with this class. 37 : */ 38 : public class GroupList extends TabFile { 39 152 : private static final FluentLogger logger = FluentLogger.forEnclosingClass(); 40 : 41 : public static final String FILE_NAME = "groups"; 42 : 43 : private final Map<AccountGroup.UUID, GroupReference> byUUID; 44 : 45 152 : private GroupList(Map<AccountGroup.UUID, GroupReference> byUUID) { 46 152 : this.byUUID = byUUID; 47 152 : } 48 : 49 : public static GroupList parse(Project.NameKey project, String text, ValidationError.Sink errors) 50 : throws IOException { 51 152 : List<Row> rows = parse(text, FILE_NAME, TRIM, TRIM, errors); 52 152 : Map<AccountGroup.UUID, GroupReference> groupsByUUID = new HashMap<>(rows.size()); 53 152 : for (Row row : rows) { 54 151 : if (row.left == null) { 55 0 : logger.atWarning().log("null field in group list for %s:\n%s", project, text); 56 0 : continue; 57 : } 58 151 : AccountGroup.UUID uuid = AccountGroup.uuid(row.left); 59 151 : String name = row.right; 60 151 : GroupReference ref = GroupReference.create(uuid, name); 61 : 62 151 : groupsByUUID.put(uuid, ref); 63 151 : } 64 : 65 152 : return new GroupList(groupsByUUID); 66 : } 67 : 68 : @Nullable 69 : public GroupReference byUUID(AccountGroup.UUID uuid) { 70 2 : return byUUID.get(uuid); 71 : } 72 : 73 : public Map<AccountGroup.UUID, GroupReference> byUUID() { 74 151 : return byUUID; 75 : } 76 : 77 : @Nullable 78 : public GroupReference byName(String name) { 79 151 : return byUUID.entrySet().stream() 80 151 : .map(Map.Entry::getValue) 81 151 : .filter(groupReference -> groupReference.getName().equals(name)) 82 151 : .findAny() 83 151 : .orElse(null); 84 : } 85 : 86 : /** 87 : * Returns the {@link GroupReference} instance that {@link GroupList} holds on to that has the 88 : * same {@link com.google.gerrit.entities.AccountGroup.UUID} as the argument. Will store the 89 : * argument internally, if no group with this {@link com.google.gerrit.entities.AccountGroup.UUID} 90 : * was stored previously. 91 : */ 92 : public GroupReference resolve(GroupReference group) { 93 151 : if (group != null) { 94 151 : if (group.getUUID() == null || group.getUUID().get() == null) { 95 : // A GroupReference from ProjectConfig that refers to a group not found 96 : // in this file will have a null UUID. Since there may be multiple 97 : // different missing references, it's not appropriate to cache the 98 : // results, nor return null the set from #uuids. 99 1 : return group; 100 : } 101 151 : GroupReference ref = byUUID.get(group.getUUID()); 102 151 : if (ref != null) { 103 151 : return ref; 104 : } 105 151 : byUUID.put(group.getUUID(), group); 106 : } 107 151 : return group; 108 : } 109 : 110 : public void renameGroup(AccountGroup.UUID uuid, String name) { 111 2 : byUUID.replace(uuid, GroupReference.create(uuid, name)); 112 2 : } 113 : 114 : public Collection<GroupReference> references() { 115 10 : return byUUID.values(); 116 : } 117 : 118 : public Set<AccountGroup.UUID> uuids() { 119 1 : return byUUID.keySet(); 120 : } 121 : 122 : public void put(AccountGroup.UUID uuid, GroupReference reference) { 123 1 : if (uuid == null || uuid.get() == null) { 124 0 : return; // See note in #resolve above. 125 : } 126 1 : byUUID.put(uuid, reference); 127 1 : } 128 : 129 : @Nullable 130 : public String asText() { 131 151 : if (byUUID.isEmpty()) { 132 144 : return null; 133 : } 134 : 135 151 : List<Row> rows = new ArrayList<>(byUUID.size()); 136 151 : for (GroupReference g : sort(byUUID.values())) { 137 151 : if (g.getUUID() != null && g.getName() != null) { 138 151 : rows.add(new Row(g.getUUID().get(), g.getName())); 139 : } 140 151 : } 141 : 142 151 : return asText("UUID", "Group Name", rows); 143 : } 144 : 145 : public void retainUUIDs(Collection<AccountGroup.UUID> toBeRetained) { 146 151 : byUUID.keySet().retainAll(toBeRetained); 147 151 : } 148 : }