blob: fa9f710c9cef5dc6a0950a30c7bd7cfad2606651 [file] [log] [blame]
// 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 com.google.common.base.MoreObjects;
import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.pgm.init.api.ConsoleUI;
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.gerrit.server.plugins.PluginLoader;
import com.google.inject.AbstractModule;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Singleton;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
@Singleton
public class InitPluginStepsLoader {
private final File pluginsDir;
private final Injector initInjector;
final ConsoleUI ui;
@Inject
public InitPluginStepsLoader(final ConsoleUI ui, final SitePaths sitePaths,
final Injector initInjector) {
this.pluginsDir = sitePaths.plugins_dir;
this.initInjector = initInjector;
this.ui = ui;
}
public Collection<InitStep> getInitSteps() {
List<File> jars = scanJarsInPluginsDirectory();
ArrayList<InitStep> pluginsInitSteps = new ArrayList<>();
for (File jar : jars) {
InitStep init = loadInitStep(jar);
if (init != null) {
pluginsInitSteps.add(init);
}
}
return pluginsInitSteps;
}
@SuppressWarnings("resource")
private InitStep loadInitStep(File jar) {
try {
URLClassLoader pluginLoader =
new URLClassLoader(new URL[] {jar.toURI().toURL()},
InitPluginStepsLoader.class.getClassLoader());
try (JarFile jarFile = new JarFile(jar)) {
Attributes jarFileAttributes = jarFile.getManifest().getMainAttributes();
String initClassName = jarFileAttributes.getValue("Gerrit-InitStep");
if (initClassName == null) {
return null;
}
@SuppressWarnings("unchecked")
Class<? extends InitStep> initStepClass =
(Class<? extends InitStep>) pluginLoader.loadClass(initClassName);
return getPluginInjector(jar).getInstance(initStepClass);
} catch (ClassCastException e) {
ui.message(
"WARN: InitStep from plugin %s does not implement %s (Exception: %s)\n",
jar.getName(), InitStep.class.getName(), e.getMessage());
return null;
} catch (NoClassDefFoundError e) {
ui.message(
"WARN: Failed to run InitStep from plugin %s (Missing class: %s)\n",
jar.getName(), e.getMessage());
return null;
}
} catch (Exception e) {
ui.message(
"WARN: Cannot load and get plugin init step for %s (Exception: %s)\n",
jar, e.getMessage());
return null;
}
}
private Injector getPluginInjector(final File jarFile) throws IOException {
final String pluginName =
MoreObjects.firstNonNull(
JarPluginProvider.getJarPluginName(jarFile),
PluginLoader.nameOf(jarFile));
return initInjector.createChildInjector(new AbstractModule() {
@Override
protected void configure() {
bind(String.class).annotatedWith(PluginName.class).toInstance(
pluginName);
}
});
}
private List<File> scanJarsInPluginsDirectory() {
if (pluginsDir == null || !pluginsDir.exists()) {
return Collections.emptyList();
}
File[] matches = pluginsDir.listFiles(new FileFilter() {
@Override
public boolean accept(File pathname) {
String n = pathname.getName();
return (n.endsWith(".jar") && pathname.isFile());
}
});
if (matches == null) {
ui.message("WARN: Cannot list %s", pluginsDir.getAbsolutePath());
return Collections.emptyList();
}
Arrays.sort(matches, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
return o1.getName().compareTo(o2.getName());
}
});
return Arrays.asList(matches);
}
}