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 com.google.common.base.MoreObjects; 18 : import com.google.common.collect.ImmutableList; 19 : import com.google.gerrit.common.Nullable; 20 : import com.google.gerrit.extensions.annotations.PluginName; 21 : import com.google.gerrit.pgm.init.api.ConsoleUI; 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.gerrit.server.plugins.PluginUtil; 26 : import com.google.inject.AbstractModule; 27 : import com.google.inject.Inject; 28 : import com.google.inject.Injector; 29 : import com.google.inject.Singleton; 30 : import java.io.IOException; 31 : import java.net.URL; 32 : import java.net.URLClassLoader; 33 : import java.nio.file.Path; 34 : import java.util.ArrayList; 35 : import java.util.Collection; 36 : import java.util.List; 37 : import java.util.jar.Attributes; 38 : import java.util.jar.JarFile; 39 : 40 : @Singleton 41 : public class InitPluginStepsLoader { 42 : private final Path pluginsDir; 43 : private final Injector initInjector; 44 : final ConsoleUI ui; 45 : 46 : @Inject 47 15 : public InitPluginStepsLoader(final ConsoleUI ui, SitePaths sitePaths, Injector initInjector) { 48 15 : this.pluginsDir = sitePaths.plugins_dir; 49 15 : this.initInjector = initInjector; 50 15 : this.ui = ui; 51 15 : } 52 : 53 : public Collection<InitStep> getInitSteps() { 54 1 : List<Path> jars = scanJarsInPluginsDirectory(); 55 1 : ArrayList<InitStep> pluginsInitSteps = new ArrayList<>(); 56 : 57 1 : for (Path jar : jars) { 58 0 : InitStep init = loadInitStep(jar); 59 0 : if (init != null) { 60 0 : pluginsInitSteps.add(init); 61 : } 62 0 : } 63 1 : return pluginsInitSteps; 64 : } 65 : 66 : @Nullable 67 : private InitStep loadInitStep(Path jar) { 68 : try { 69 0 : URLClassLoader pluginLoader = 70 0 : URLClassLoader.newInstance( 71 0 : new URL[] {jar.toUri().toURL()}, InitPluginStepsLoader.class.getClassLoader()); 72 0 : try (JarFile jarFile = new JarFile(jar.toFile())) { 73 0 : Attributes jarFileAttributes = jarFile.getManifest().getMainAttributes(); 74 0 : String initClassName = jarFileAttributes.getValue("Gerrit-InitStep"); 75 0 : if (initClassName == null) { 76 0 : return null; 77 : } 78 : @SuppressWarnings("unchecked") 79 0 : Class<? extends InitStep> initStepClass = 80 0 : (Class<? extends InitStep>) pluginLoader.loadClass(initClassName); 81 0 : return getPluginInjector(jar).getInstance(initStepClass); 82 0 : } catch (ClassCastException e) { 83 0 : ui.message( 84 : "WARN: InitStep from plugin %s does not implement %s (Exception: %s)\n", 85 0 : jar.getFileName(), InitStep.class.getName(), e.getMessage()); 86 0 : return null; 87 0 : } catch (NoClassDefFoundError e) { 88 0 : ui.message( 89 : "WARN: Failed to run InitStep from plugin %s (Missing class: %s)\n", 90 0 : jar.getFileName(), e.getMessage()); 91 0 : return null; 92 : } 93 0 : } catch (Exception e) { 94 0 : ui.message( 95 : "WARN: Cannot load and get plugin init step for %s (Exception: %s)\n", 96 0 : jar, e.getMessage()); 97 0 : return null; 98 : } 99 : } 100 : 101 : private Injector getPluginInjector(Path jarPath) throws IOException { 102 0 : final String pluginName = 103 0 : MoreObjects.firstNonNull( 104 0 : JarPluginProvider.getJarPluginName(jarPath), PluginUtil.nameOf(jarPath)); 105 0 : return initInjector.createChildInjector( 106 0 : new AbstractModule() { 107 : @Override 108 : protected void configure() { 109 0 : bind(String.class).annotatedWith(PluginName.class).toInstance(pluginName); 110 0 : } 111 : }); 112 : } 113 : 114 : private List<Path> scanJarsInPluginsDirectory() { 115 : try { 116 1 : return PluginUtil.listPlugins(pluginsDir, ".jar"); 117 0 : } catch (IOException e) { 118 0 : ui.message("WARN: Cannot list %s: %s", pluginsDir.toAbsolutePath(), e.getMessage()); 119 0 : return ImmutableList.of(); 120 : } 121 : } 122 : }