| // 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); | |
| } | |
| } | |
| } |