| // 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.pgm.init; |
| |
| import static java.util.Comparator.comparing; |
| |
| import com.google.gerrit.common.PluginData; |
| import com.google.gerrit.pgm.init.api.ConsoleUI; |
| import com.google.gerrit.pgm.init.api.InitFlags; |
| import com.google.gerrit.pgm.init.api.InitStep; |
| import com.google.gerrit.server.config.SitePaths; |
| import com.google.gerrit.server.plugins.JarPluginProvider; |
| import com.google.inject.Inject; |
| import com.google.inject.Injector; |
| import com.google.inject.Singleton; |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.List; |
| import java.util.jar.Attributes; |
| import java.util.jar.JarFile; |
| import java.util.jar.Manifest; |
| |
| @Singleton |
| public class InitPlugins implements InitStep { |
| public static final String PLUGIN_DIR = "WEB-INF/plugins/"; |
| public static final String JAR = ".jar"; |
| |
| public static List<PluginData> listPlugins( |
| SitePaths site, PluginsDistribution pluginsDistribution) throws IOException { |
| return listPlugins(site, false, pluginsDistribution); |
| } |
| |
| public static List<PluginData> listPluginsAndRemoveTempFiles( |
| SitePaths site, PluginsDistribution pluginsDistribution) throws IOException { |
| return listPlugins(site, true, pluginsDistribution); |
| } |
| |
| private static List<PluginData> listPlugins( |
| final SitePaths site, |
| final boolean deleteTempPluginFile, |
| PluginsDistribution pluginsDistribution) |
| throws IOException { |
| final List<PluginData> result = new ArrayList<>(); |
| pluginsDistribution.foreach( |
| (pluginName, in) -> { |
| Path tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site); |
| String pluginVersion = getVersion(tmpPlugin); |
| if (deleteTempPluginFile) { |
| Files.delete(tmpPlugin); |
| } |
| result.add(new PluginData(pluginName, pluginVersion, tmpPlugin)); |
| }); |
| result.sort(comparing(p -> p.name)); |
| return result; |
| } |
| |
| private final ConsoleUI ui; |
| private final SitePaths site; |
| private final InitFlags initFlags; |
| private final InitPluginStepsLoader pluginLoader; |
| private final PluginsDistribution pluginsDistribution; |
| |
| private Injector postRunInjector; |
| |
| @Inject |
| InitPlugins( |
| final ConsoleUI ui, |
| final SitePaths site, |
| InitFlags initFlags, |
| InitPluginStepsLoader pluginLoader, |
| PluginsDistribution pluginsDistribution) { |
| this.ui = ui; |
| this.site = site; |
| this.initFlags = initFlags; |
| this.pluginLoader = pluginLoader; |
| this.pluginsDistribution = pluginsDistribution; |
| } |
| |
| @Override |
| public void run() throws Exception { |
| ui.header("Plugins"); |
| |
| installPlugins(); |
| initPlugins(); |
| } |
| |
| @Override |
| public void postRun() throws Exception { |
| postInitPlugins(); |
| } |
| |
| @Inject(optional = true) |
| void setPostRunInjector(Injector injector) { |
| postRunInjector = injector; |
| } |
| |
| private void installPlugins() throws IOException { |
| ui.message("Installing plugins.\n"); |
| List<PluginData> plugins = listPlugins(site, pluginsDistribution); |
| for (PluginData plugin : plugins) { |
| String pluginName = plugin.name; |
| try { |
| final Path tmpPlugin = plugin.pluginPath; |
| Path p = site.plugins_dir.resolve(plugin.name + ".jar"); |
| boolean upgrade = Files.exists(p); |
| |
| if (!(initFlags.installPlugins.contains(pluginName) |
| || initFlags.installAllPlugins |
| || ui.yesno(upgrade, "Install plugin %s version %s", pluginName, plugin.version))) { |
| Files.deleteIfExists(tmpPlugin); |
| continue; |
| } |
| |
| if (upgrade) { |
| final String installedPluginVersion = getVersion(p); |
| if (!ui.yesno( |
| upgrade, |
| "%s %s is already installed, overwrite it", |
| plugin.name, |
| installedPluginVersion)) { |
| Files.deleteIfExists(tmpPlugin); |
| continue; |
| } |
| try { |
| Files.delete(p); |
| } catch (IOException e) { |
| throw new IOException( |
| "Failed to delete plugin " + pluginName + ": " + p.toAbsolutePath(), e); |
| } |
| } |
| try { |
| Files.move(tmpPlugin, p); |
| if (upgrade) { |
| // or update that is not an upgrade |
| ui.message("Updated %s to %s\n", plugin.name, plugin.version); |
| } else { |
| ui.message("Installed %s %s\n", plugin.name, plugin.version); |
| } |
| } catch (IOException e) { |
| throw new IOException( |
| "Failed to install plugin " |
| + pluginName |
| + ": " |
| + tmpPlugin.toAbsolutePath() |
| + " -> " |
| + p.toAbsolutePath(), |
| e); |
| } |
| } finally { |
| Files.deleteIfExists(plugin.pluginPath); |
| } |
| } |
| if (plugins.isEmpty()) { |
| ui.message("No plugins found to install.\n"); |
| } |
| } |
| |
| private void initPlugins() throws Exception { |
| ui.message("Initializing plugins.\n"); |
| Collection<InitStep> initSteps = pluginLoader.getInitSteps(); |
| if (initSteps.isEmpty()) { |
| ui.message("No plugins found with init steps.\n"); |
| } else { |
| for (InitStep initStep : initSteps) { |
| initStep.run(); |
| } |
| } |
| } |
| |
| private void postInitPlugins() throws Exception { |
| for (InitStep initStep : pluginLoader.getInitSteps()) { |
| postRunInjector.injectMembers(initStep); |
| initStep.postRun(); |
| } |
| } |
| |
| private static String getVersion(Path plugin) throws IOException { |
| try (JarFile jarFile = new JarFile(plugin.toFile())) { |
| Manifest manifest = jarFile.getManifest(); |
| Attributes main = manifest.getMainAttributes(); |
| return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION); |
| } |
| } |
| } |