All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gerrit.server.plugins.AbstractPreloadedPluginScanner Maven / Gradle / Ivy

The newest version!
// Copyright (C) 2014 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.server.plugins;

import static com.google.common.base.Preconditions.checkState;
import static java.nio.charset.StandardCharsets.UTF_8;

import com.google.common.collect.ImmutableMap;
import com.google.gerrit.extensions.annotations.Export;
import com.google.gerrit.server.plugins.Plugin.ApiType;
import com.google.inject.Module;
import com.google.inject.servlet.ServletModule;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.Manifest;

/**
 * Base plugin scanner for a set of pre-loaded classes.
 *
 * 

Utility base class for simplifying the development of Server plugin scanner based on a set of * externally pre-loaded classes. * *

Extending this class you can implement very easily a PluginContentScanner from a set of * pre-loaded Java Classes and an API Type. The convention used by this class is: - there is at most * one Guice module per Gerrit module type (SysModule, HttpModule, SshModule) - plugin is set to be * restartable in Gerrit Plugin MANIFEST - only Export and Listen annotated classes can be * self-discovered */ public abstract class AbstractPreloadedPluginScanner implements PluginContentScanner { protected final String pluginName; protected final String pluginVersion; protected final Set> preloadedClasses; protected final ApiType apiType; private Class sshModuleClass; private Class httpModuleClass; private Class sysModuleClass; public AbstractPreloadedPluginScanner( String pluginName, String pluginVersion, Set> preloadedClasses, Plugin.ApiType apiType) { this.pluginName = pluginName; this.pluginVersion = pluginVersion; this.preloadedClasses = preloadedClasses; this.apiType = apiType; } @Override public Manifest getManifest() throws IOException { scanGuiceModules(preloadedClasses); StringBuilder manifestString = new StringBuilder( "PluginName: " + pluginName + "\n" + "Implementation-Version: " + pluginVersion + "\n" + "Gerrit-ReloadMode: restart\n" + "Gerrit-ApiType: " + apiType + "\n"); appendIfNotNull(manifestString, "Gerrit-SshModule: ", sshModuleClass); appendIfNotNull(manifestString, "Gerrit-HttpModule: ", httpModuleClass); appendIfNotNull(manifestString, "Gerrit-Module: ", sysModuleClass); return new Manifest(new ByteArrayInputStream(manifestString.toString().getBytes(UTF_8))); } @Override public Map, Iterable> scan( String pluginName, Iterable> annotations) throws InvalidPluginException { ImmutableMap.Builder, Iterable> result = ImmutableMap.builder(); for (Class annotation : annotations) { Set classMetaDataSet = new HashSet<>(); result.put(annotation, classMetaDataSet); for (Class clazz : preloadedClasses) { if (!Modifier.isAbstract(clazz.getModifiers()) && clazz.getAnnotation(annotation) != null) { classMetaDataSet.add( new ExtensionMetaData(clazz.getName(), getExportAnnotationValue(clazz, annotation))); } } } return result.build(); } private void appendIfNotNull(StringBuilder string, String header, Class guiceModuleClass) { if (guiceModuleClass != null) { string.append(header); string.append(guiceModuleClass.getName()); string.append("\n"); } } private void scanGuiceModules(Set> classes) throws IOException { try { Class sysModuleBaseClass = Module.class; Class httpModuleBaseClass = ServletModule.class; Class sshModuleBaseClass = Class.forName("com.google.gerrit.sshd.CommandModule"); sshModuleClass = null; httpModuleClass = null; sysModuleClass = null; for (Class clazz : classes) { if (clazz.isLocalClass()) { continue; } if (sshModuleBaseClass.isAssignableFrom(clazz)) { sshModuleClass = getUniqueGuiceModule(sshModuleBaseClass, sshModuleClass, clazz); } else if (httpModuleBaseClass.isAssignableFrom(clazz)) { httpModuleClass = getUniqueGuiceModule(httpModuleBaseClass, httpModuleClass, clazz); } else if (sysModuleBaseClass.isAssignableFrom(clazz)) { sysModuleClass = getUniqueGuiceModule(sysModuleBaseClass, sysModuleClass, clazz); } } } catch (ClassNotFoundException e) { throw new IOException("Cannot find base Gerrit classes for Guice Plugin Modules", e); } } private Class getUniqueGuiceModule( Class guiceModuleBaseClass, Class existingGuiceModuleName, Class newGuiceModuleClass) { checkState( existingGuiceModuleName == null, "Multiple %s implementations: %s, %s", guiceModuleBaseClass, existingGuiceModuleName, newGuiceModuleClass); return newGuiceModuleClass; } private String getExportAnnotationValue( Class scriptClass, Class annotation) { return annotation == Export.class ? scriptClass.getAnnotation(Export.class).value() : ""; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy