blob: e3c02a5ee0e76809c96155636f91127c38b21504 [file] [log] [blame]
// 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.googlesource.gerrit.plugins.download.command.project;
import com.google.common.collect.Maps;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.extensions.config.DownloadCommand;
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.config.PluginConfig;
import com.google.gerrit.server.git.WorkQueue;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.ProjectState;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Singleton
public class DownloadCommandUpdater implements GitReferenceUpdatedListener, LifecycleListener {
private static final Logger log = LoggerFactory.getLogger(DownloadCommandUpdater.class);
private final String pluginName;
private final DynamicMap<DownloadCommand> downloadCommands;
private final MetaDataUpdate.Server metaDataUpdateFactory;
private final ProjectCache projectCache;
private final Map<String, ProjectDownloadCommand> projectDownloadCommands;
private final Map<String, RegistrationHandle> registrationHandles;
private final ScheduledExecutorService executor;
@Inject
DownloadCommandUpdater(
@PluginName String pluginName,
DynamicMap<DownloadCommand> downloadCommands,
MetaDataUpdate.Server metaDataUpdateFactory,
ProjectCache projectCache,
WorkQueue queue) {
this.pluginName = pluginName;
this.downloadCommands = downloadCommands;
this.metaDataUpdateFactory = metaDataUpdateFactory;
this.projectCache = projectCache;
this.projectDownloadCommands = Maps.newHashMap();
this.registrationHandles = Maps.newHashMap();
this.executor = queue.createQueue(1, "download-command-updater");
}
@Override
public void start() {
executor.submit(
new Runnable() {
@Override
public void run() {
for (Project.NameKey p : projectCache.all()) {
ProjectState projectState = projectCache.get(p);
if (projectState != null) {
PluginConfig cfg = projectState.getConfig().getPluginConfig(pluginName);
for (String name : cfg.getNames()) {
installCommand(projectState.getProject().getNameKey(), name, cfg.getString(name));
}
}
}
}
});
}
@Override
public void stop() {
for (RegistrationHandle rh : registrationHandles.values()) {
rh.remove();
}
registrationHandles.clear();
projectDownloadCommands.clear();
}
@Override
public void onGitReferenceUpdated(Event event) {
if (event.getRefName().equals(RefNames.REFS_CONFIG)) {
Project.NameKey p = new Project.NameKey(event.getProjectName());
try {
ProjectConfig oldCfg =
ProjectConfig.read(
metaDataUpdateFactory.create(p), ObjectId.fromString(event.getOldObjectId()));
PluginConfig oldPluginCfg = oldCfg.getPluginConfig(pluginName);
for (String name : oldPluginCfg.getNames()) {
removeCommand(p, name);
}
ProjectConfig newCfg =
ProjectConfig.read(
metaDataUpdateFactory.create(p), ObjectId.fromString(event.getNewObjectId()));
PluginConfig newPluginCfg = newCfg.getPluginConfig(pluginName);
for (String name : newPluginCfg.getNames()) {
installCommand(p, name, newPluginCfg.getString(name));
}
} catch (IOException | ConfigInvalidException e) {
log.error(
"Failed to update download commands for project "
+ p.get()
+ " on update of "
+ RefNames.REFS_CONFIG,
e);
}
}
}
private void installCommand(final Project.NameKey p, String name, final String command) {
ProjectDownloadCommand dc = projectDownloadCommands.get(name);
if (dc != null) {
dc.add(p, command);
} else {
dc = new ProjectDownloadCommand(projectCache, p, command);
projectDownloadCommands.put(name, dc);
registrationHandles.put(name, map().put(pluginName, name.replaceAll("-", " "), provider(dc)));
}
}
private Provider<DownloadCommand> provider(final DownloadCommand dc) {
return new Provider<DownloadCommand>() {
@Override
public DownloadCommand get() {
return dc;
}
};
}
private void removeCommand(Project.NameKey p, String name) {
ProjectDownloadCommand dc = projectDownloadCommands.get(name);
dc.remove(p);
if (!dc.hasCommands()) {
registrationHandles.remove(name).remove();
}
}
private PrivateInternals_DynamicMapImpl<DownloadCommand> map() {
return (PrivateInternals_DynamicMapImpl<DownloadCommand>) downloadCommands;
}
}