blob: d948aef8c4e0b1f7fbdd0d1a5a58eb14296da569 [file] [log] [blame]
// Copyright (C) 2009 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.account;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.AccountGroupName;
import com.google.gerrit.reviewdb.ReviewDb;
import com.google.gerrit.server.cache.Cache;
import com.google.gerrit.server.cache.CacheModule;
import com.google.gerrit.server.cache.EntryCreator;
import com.google.gerrit.server.config.AuthConfig;
import com.google.gwtorm.client.SchemaFactory;
import com.google.inject.Inject;
import com.google.inject.Module;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Named;
import java.util.Collection;
/** Tracks group objects in memory for efficient access. */
@Singleton
public class GroupCacheImpl implements GroupCache {
private static final String BYID_NAME = "groups";
private static final String BYNAME_NAME = "groups_byname";
private static final String BYEXT_NAME = "groups_byext";
public static Module module() {
return new CacheModule() {
@Override
protected void configure() {
final TypeLiteral<Cache<AccountGroup.Id, AccountGroup>> byId =
new TypeLiteral<Cache<AccountGroup.Id, AccountGroup>>() {};
core(byId, BYID_NAME).populateWith(ByIdLoader.class);
final TypeLiteral<Cache<AccountGroup.NameKey, AccountGroup>> byName =
new TypeLiteral<Cache<AccountGroup.NameKey, AccountGroup>>() {};
core(byName, BYNAME_NAME).populateWith(ByNameLoader.class);
final TypeLiteral<Cache<AccountGroup.ExternalNameKey, Collection<AccountGroup>>> byExternalName =
new TypeLiteral<Cache<AccountGroup.ExternalNameKey, Collection<AccountGroup>>>() {};
core(byExternalName, BYEXT_NAME) //
.populateWith(ByExternalNameLoader.class);
bind(GroupCacheImpl.class);
bind(GroupCache.class).to(GroupCacheImpl.class);
}
};
}
private final Cache<AccountGroup.Id, AccountGroup> byId;
private final Cache<AccountGroup.NameKey, AccountGroup> byName;
private final Cache<AccountGroup.ExternalNameKey, Collection<AccountGroup>> byExternalName;
@Inject
GroupCacheImpl(
@Named(BYID_NAME) Cache<AccountGroup.Id, AccountGroup> byId,
@Named(BYNAME_NAME) Cache<AccountGroup.NameKey, AccountGroup> byName,
@Named(BYEXT_NAME) Cache<AccountGroup.ExternalNameKey, Collection<AccountGroup>> byExternalName) {
this.byId = byId;
this.byName = byName;
this.byExternalName = byExternalName;
}
public AccountGroup get(final AccountGroup.Id groupId) {
return byId.get(groupId);
}
public void evict(final AccountGroup group) {
byId.remove(group.getId());
byName.remove(group.getNameKey());
byExternalName.remove(group.getExternalNameKey());
}
public void evictAfterRename(final AccountGroup.NameKey oldName) {
byName.remove(oldName);
}
public AccountGroup get(final AccountGroup.NameKey name) {
return byName.get(name);
}
public Collection<AccountGroup> get(
final AccountGroup.ExternalNameKey externalName) {
return byExternalName.get(externalName);
}
static class ByIdLoader extends EntryCreator<AccountGroup.Id, AccountGroup> {
private final SchemaFactory<ReviewDb> schema;
private final AccountGroup.Id administrators;
@Inject
ByIdLoader(final SchemaFactory<ReviewDb> sf, final AuthConfig authConfig) {
schema = sf;
administrators = authConfig.getAdministratorsGroup();
}
@Override
public AccountGroup createEntry(final AccountGroup.Id key) throws Exception {
final ReviewDb db = schema.open();
try {
final AccountGroup group = db.accountGroups().get(key);
if (group != null) {
return group;
} else {
return missing(key);
}
} finally {
db.close();
}
}
@Override
public AccountGroup missing(final AccountGroup.Id key) {
final AccountGroup.NameKey name =
new AccountGroup.NameKey("Deleted Group" + key.toString());
final AccountGroup g = new AccountGroup(name, key);
g.setType(AccountGroup.Type.SYSTEM);
g.setOwnerGroupId(administrators);
return g;
}
}
static class ByNameLoader extends
EntryCreator<AccountGroup.NameKey, AccountGroup> {
private final SchemaFactory<ReviewDb> schema;
@Inject
ByNameLoader(final SchemaFactory<ReviewDb> sf) {
schema = sf;
}
@Override
public AccountGroup createEntry(final AccountGroup.NameKey key)
throws Exception {
final AccountGroupName r;
final ReviewDb db = schema.open();
try {
r = db.accountGroupNames().get(key);
if (r != null) {
return db.accountGroups().get(r.getId());
} else {
return null;
}
} finally {
db.close();
}
}
}
static class ByExternalNameLoader extends
EntryCreator<AccountGroup.ExternalNameKey, Collection<AccountGroup>> {
private final SchemaFactory<ReviewDb> schema;
@Inject
ByExternalNameLoader(final SchemaFactory<ReviewDb> sf) {
schema = sf;
}
@Override
public Collection<AccountGroup> createEntry(
final AccountGroup.ExternalNameKey key) throws Exception {
final ReviewDb db = schema.open();
try {
return db.accountGroups().byExternalName(key).toList();
} finally {
db.close();
}
}
}
}