Line data Source code
1 : // Copyright (C) 2012 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.pgm.init; 16 : 17 : import static java.util.Comparator.comparing; 18 : 19 : import com.google.gerrit.common.PluginData; 20 : import com.google.gerrit.pgm.init.api.ConsoleUI; 21 : import com.google.gerrit.pgm.init.api.InitFlags; 22 : import com.google.gerrit.pgm.init.api.InitStep; 23 : import com.google.gerrit.server.config.SitePaths; 24 : import com.google.gerrit.server.plugins.JarPluginProvider; 25 : import com.google.inject.Inject; 26 : import com.google.inject.Injector; 27 : import com.google.inject.Singleton; 28 : import java.io.IOException; 29 : import java.nio.file.Files; 30 : import java.nio.file.Path; 31 : import java.util.ArrayList; 32 : import java.util.Collection; 33 : import java.util.List; 34 : import java.util.jar.Attributes; 35 : import java.util.jar.JarFile; 36 : import java.util.jar.Manifest; 37 : 38 : @Singleton 39 : public class InitPlugins implements InitStep { 40 : public static final String PLUGIN_DIR = "WEB-INF/plugins/"; 41 : public static final String JAR = ".jar"; 42 : 43 : public static List<PluginData> listPlugins( 44 : SitePaths site, PluginsDistribution pluginsDistribution) throws IOException { 45 1 : return listPlugins(site, false, pluginsDistribution); 46 : } 47 : 48 : public static List<PluginData> listPluginsAndRemoveTempFiles( 49 : SitePaths site, PluginsDistribution pluginsDistribution) throws IOException { 50 1 : return listPlugins(site, true, pluginsDistribution); 51 : } 52 : 53 : private static List<PluginData> listPlugins( 54 : final SitePaths site, 55 : final boolean deleteTempPluginFile, 56 : PluginsDistribution pluginsDistribution) 57 : throws IOException { 58 1 : final List<PluginData> result = new ArrayList<>(); 59 1 : pluginsDistribution.foreach( 60 : (pluginName, in) -> { 61 0 : Path tmpPlugin = JarPluginProvider.storeInTemp(pluginName, in, site); 62 0 : String pluginVersion = getVersion(tmpPlugin); 63 0 : if (deleteTempPluginFile) { 64 0 : Files.delete(tmpPlugin); 65 : } 66 0 : result.add(new PluginData(pluginName, pluginVersion, tmpPlugin)); 67 0 : }); 68 1 : result.sort(comparing(p -> p.name)); 69 1 : return result; 70 : } 71 : 72 : private final ConsoleUI ui; 73 : private final SitePaths site; 74 : private final InitFlags initFlags; 75 : private final InitPluginStepsLoader pluginLoader; 76 : private final PluginsDistribution pluginsDistribution; 77 : 78 : private Injector postRunInjector; 79 : 80 : @Inject 81 : InitPlugins( 82 : final ConsoleUI ui, 83 : final SitePaths site, 84 : InitFlags initFlags, 85 : InitPluginStepsLoader pluginLoader, 86 15 : PluginsDistribution pluginsDistribution) { 87 15 : this.ui = ui; 88 15 : this.site = site; 89 15 : this.initFlags = initFlags; 90 15 : this.pluginLoader = pluginLoader; 91 15 : this.pluginsDistribution = pluginsDistribution; 92 15 : } 93 : 94 : @Override 95 : public void run() throws Exception { 96 1 : ui.header("Plugins"); 97 : 98 1 : installPlugins(); 99 1 : initPlugins(); 100 1 : } 101 : 102 : @Override 103 : public void postRun() throws Exception { 104 1 : postInitPlugins(); 105 1 : } 106 : 107 : @Inject(optional = true) 108 : void setPostRunInjector(Injector injector) { 109 15 : postRunInjector = injector; 110 15 : } 111 : 112 : private void installPlugins() throws IOException { 113 1 : ui.message("Installing plugins.\n"); 114 1 : List<PluginData> plugins = listPlugins(site, pluginsDistribution); 115 1 : for (PluginData plugin : plugins) { 116 0 : String pluginName = plugin.name; 117 : try { 118 0 : final Path tmpPlugin = plugin.pluginPath; 119 0 : Path p = site.plugins_dir.resolve(plugin.name + ".jar"); 120 0 : boolean upgrade = Files.exists(p); 121 : 122 0 : if (!(initFlags.installPlugins.contains(pluginName) 123 : || initFlags.installAllPlugins 124 0 : || ui.yesno(upgrade, "Install plugin %s version %s", pluginName, plugin.version))) { 125 0 : Files.deleteIfExists(tmpPlugin); 126 : continue; 127 : } 128 : 129 0 : if (upgrade) { 130 0 : final String installedPluginVersion = getVersion(p); 131 0 : if (!ui.yesno( 132 0 : upgrade, 133 : "%s %s is already installed, overwrite it", 134 : plugin.name, 135 : installedPluginVersion)) { 136 0 : Files.deleteIfExists(tmpPlugin); 137 : continue; 138 : } 139 : try { 140 0 : Files.delete(p); 141 0 : } catch (IOException e) { 142 0 : throw new IOException( 143 0 : "Failed to delete plugin " + pluginName + ": " + p.toAbsolutePath(), e); 144 0 : } 145 : } 146 : try { 147 0 : Files.move(tmpPlugin, p); 148 0 : if (upgrade) { 149 : // or update that is not an upgrade 150 0 : ui.message("Updated %s to %s\n", plugin.name, plugin.version); 151 : } else { 152 0 : ui.message("Installed %s %s\n", plugin.name, plugin.version); 153 : } 154 0 : } catch (IOException e) { 155 0 : throw new IOException( 156 : "Failed to install plugin " 157 : + pluginName 158 : + ": " 159 0 : + tmpPlugin.toAbsolutePath() 160 : + " -> " 161 0 : + p.toAbsolutePath(), 162 : e); 163 0 : } 164 : } finally { 165 0 : Files.deleteIfExists(plugin.pluginPath); 166 : } 167 0 : } 168 1 : if (plugins.isEmpty()) { 169 1 : ui.message("No plugins found to install.\n"); 170 : } 171 1 : } 172 : 173 : private void initPlugins() throws Exception { 174 1 : ui.message("Initializing plugins.\n"); 175 1 : Collection<InitStep> initSteps = pluginLoader.getInitSteps(); 176 1 : if (initSteps.isEmpty()) { 177 1 : ui.message("No plugins found with init steps.\n"); 178 : } else { 179 0 : for (InitStep initStep : initSteps) { 180 0 : initStep.run(); 181 0 : } 182 : } 183 1 : } 184 : 185 : private void postInitPlugins() throws Exception { 186 1 : for (InitStep initStep : pluginLoader.getInitSteps()) { 187 0 : postRunInjector.injectMembers(initStep); 188 0 : initStep.postRun(); 189 0 : } 190 1 : } 191 : 192 : private static String getVersion(Path plugin) throws IOException { 193 0 : try (JarFile jarFile = new JarFile(plugin.toFile())) { 194 0 : Manifest manifest = jarFile.getManifest(); 195 0 : Attributes main = manifest.getMainAttributes(); 196 0 : return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION); 197 : } 198 : } 199 : }