LCOV - code coverage report
Current view: top level - server/plugins - ServerPlugin.java (source / functions) Hit Total Coverage
Test: _coverage_report.dat Lines: 96 131 73.3 %
Date: 2022-11-19 15:00:39 Functions: 18 20 90.0 %

          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.server.plugins;
      16             : 
      17             : import com.google.common.base.Strings;
      18             : import com.google.common.collect.Lists;
      19             : import com.google.common.flogger.FluentLogger;
      20             : import com.google.gerrit.common.Nullable;
      21             : import com.google.gerrit.extensions.registration.RegistrationHandle;
      22             : import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
      23             : import com.google.gerrit.lifecycle.LifecycleManager;
      24             : import com.google.gerrit.server.PluginUser;
      25             : import com.google.gerrit.server.config.GerritRuntime;
      26             : import com.google.gerrit.server.util.RequestContext;
      27             : import com.google.inject.Guice;
      28             : import com.google.inject.Injector;
      29             : import com.google.inject.Module;
      30             : import java.io.IOException;
      31             : import java.nio.file.Path;
      32             : import java.util.ArrayList;
      33             : import java.util.List;
      34             : import java.util.jar.Attributes;
      35             : import java.util.jar.Manifest;
      36             : import org.eclipse.jgit.internal.storage.file.FileSnapshot;
      37             : 
      38             : public class ServerPlugin extends Plugin {
      39          13 :   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
      40             : 
      41             :   private final Manifest manifest;
      42             :   private final PluginContentScanner scanner;
      43             :   private final Path dataDir;
      44             :   private final String pluginCanonicalWebUrl;
      45             :   private final ClassLoader classLoader;
      46             :   private final String metricsPrefix;
      47             :   private final GerritRuntime gerritRuntime;
      48             :   protected Class<? extends Module> sysModule;
      49             :   protected Class<? extends Module> batchModule;
      50             :   protected Class<? extends Module> sshModule;
      51             :   protected Class<? extends Module> httpModule;
      52             : 
      53             :   private Injector sysInjector;
      54             :   private Injector sshInjector;
      55             :   private Injector httpInjector;
      56             :   private LifecycleManager serverManager;
      57             :   private List<ReloadableRegistrationHandle<?>> reloadableHandles;
      58             : 
      59             :   public ServerPlugin(
      60             :       String name,
      61             :       String pluginCanonicalWebUrl,
      62             :       PluginUser pluginUser,
      63             :       Path srcJar,
      64             :       FileSnapshot snapshot,
      65             :       PluginContentScanner scanner,
      66             :       Path dataDir,
      67             :       ClassLoader classLoader,
      68             :       String metricsPrefix,
      69             :       GerritRuntime gerritRuntime)
      70             :       throws InvalidPluginException {
      71          13 :     super(
      72             :         name,
      73             :         srcJar,
      74             :         pluginUser,
      75             :         snapshot,
      76          13 :         scanner == null ? ApiType.PLUGIN : Plugin.getApiType(getPluginManifest(scanner)));
      77          13 :     this.pluginCanonicalWebUrl = pluginCanonicalWebUrl;
      78          13 :     this.scanner = scanner;
      79          13 :     this.dataDir = dataDir;
      80          13 :     this.classLoader = classLoader;
      81          13 :     this.manifest = scanner == null ? null : getPluginManifest(scanner);
      82          13 :     this.metricsPrefix = metricsPrefix;
      83          13 :     this.gerritRuntime = gerritRuntime;
      84          13 :     if (manifest != null) {
      85           1 :       loadGuiceModules(manifest, classLoader);
      86             :     }
      87          13 :   }
      88             : 
      89             :   private void loadGuiceModules(Manifest manifest, ClassLoader classLoader)
      90             :       throws InvalidPluginException {
      91           1 :     Attributes main = manifest.getMainAttributes();
      92           1 :     String sysName = main.getValue("Gerrit-Module");
      93           1 :     String sshName = main.getValue("Gerrit-SshModule");
      94           1 :     String httpName = main.getValue("Gerrit-HttpModule");
      95           1 :     String batchName = main.getValue("Gerrit-BatchModule");
      96             : 
      97           1 :     if (!Strings.isNullOrEmpty(sshName) && getApiType() != Plugin.ApiType.PLUGIN) {
      98           0 :       throw new InvalidPluginException(
      99           0 :           String.format(
     100             :               "Using Gerrit-SshModule requires Gerrit-ApiType: %s", Plugin.ApiType.PLUGIN));
     101             :     }
     102             : 
     103             :     try {
     104           1 :       this.batchModule = load(batchName, classLoader);
     105           1 :       this.sysModule = load(sysName, classLoader);
     106           1 :       this.sshModule = load(sshName, classLoader);
     107           1 :       this.httpModule = load(httpName, classLoader);
     108           0 :     } catch (ClassNotFoundException e) {
     109           0 :       throw new InvalidPluginException("Unable to load plugin Guice Modules", e);
     110           1 :     }
     111           1 :   }
     112             : 
     113             :   @Nullable
     114             :   @SuppressWarnings("unchecked")
     115             :   protected static Class<? extends Module> load(@Nullable String name, ClassLoader pluginLoader)
     116             :       throws ClassNotFoundException {
     117          13 :     if (Strings.isNullOrEmpty(name)) {
     118          13 :       return null;
     119             :     }
     120             : 
     121          12 :     Class<?> clazz = Class.forName(name, false, pluginLoader);
     122          12 :     if (!Module.class.isAssignableFrom(clazz)) {
     123           0 :       throw new ClassCastException(
     124           0 :           String.format("Class %s does not implement %s", name, Module.class.getName()));
     125             :     }
     126          12 :     return (Class<? extends Module>) clazz;
     127             :   }
     128             : 
     129             :   Path getDataDir() {
     130          13 :     return dataDir;
     131             :   }
     132             : 
     133             :   String getPluginCanonicalWebUrl() {
     134          13 :     return pluginCanonicalWebUrl;
     135             :   }
     136             : 
     137             :   String getMetricsPrefix() {
     138          13 :     return metricsPrefix;
     139             :   }
     140             : 
     141             :   private static Manifest getPluginManifest(PluginContentScanner scanner)
     142             :       throws InvalidPluginException {
     143             :     try {
     144           1 :       return scanner.getManifest();
     145           0 :     } catch (IOException e) {
     146           0 :       throw new InvalidPluginException("Cannot get plugin manifest", e);
     147             :     }
     148             :   }
     149             : 
     150             :   @Override
     151             :   @Nullable
     152             :   public String getVersion() {
     153           1 :     Attributes main = manifest.getMainAttributes();
     154           1 :     return main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
     155             :   }
     156             : 
     157             :   @Override
     158             :   @Nullable
     159             :   public String getApiVersion() {
     160           1 :     Attributes main = manifest.getMainAttributes();
     161           1 :     return main.getValue("Gerrit-ApiVersion");
     162             :   }
     163             : 
     164             :   @Override
     165             :   protected boolean canReload() {
     166           0 :     Attributes main = manifest.getMainAttributes();
     167           0 :     String v = main.getValue("Gerrit-ReloadMode");
     168           0 :     if (Strings.isNullOrEmpty(v) || "reload".equalsIgnoreCase(v)) {
     169           0 :       return true;
     170           0 :     } else if ("restart".equalsIgnoreCase(v)) {
     171           0 :       return false;
     172             :     } else {
     173           0 :       logger.atWarning().log(
     174           0 :           "Plugin %s has invalid Gerrit-ReloadMode %s; assuming restart", getName(), v);
     175           0 :       return false;
     176             :     }
     177             :   }
     178             : 
     179             :   @Override
     180             :   protected void start(PluginGuiceEnvironment env) throws Exception {
     181          13 :     RequestContext oldContext = env.enter(this);
     182             :     try {
     183          13 :       startPlugin(env);
     184             :     } finally {
     185          13 :       env.exit(oldContext);
     186             :     }
     187          13 :   }
     188             : 
     189             :   private void startPlugin(PluginGuiceEnvironment env) throws Exception {
     190          13 :     Injector root = newRootInjector(env);
     191          13 :     serverManager = new LifecycleManager();
     192          13 :     serverManager.add(root);
     193             : 
     194          13 :     if (gerritRuntime == GerritRuntime.BATCH) {
     195           0 :       if (batchModule != null) {
     196           0 :         sysInjector = root.createChildInjector(root.getInstance(batchModule));
     197           0 :         serverManager.add(sysInjector);
     198             :       } else {
     199           0 :         sysInjector = root;
     200             :       }
     201             : 
     202           0 :       serverManager.start();
     203           0 :       return;
     204             :     }
     205             : 
     206          13 :     AutoRegisterModules auto = null;
     207          13 :     if (sysModule == null && sshModule == null && httpModule == null) {
     208           1 :       auto = new AutoRegisterModules(getName(), env, scanner, classLoader);
     209           1 :       auto.discover();
     210             :     }
     211             : 
     212          13 :     if (sysModule != null) {
     213          12 :       sysInjector = root.createChildInjector(root.getInstance(sysModule));
     214          12 :       serverManager.add(sysInjector);
     215           2 :     } else if (auto != null && auto.sysModule != null) {
     216           0 :       sysInjector = root.createChildInjector(auto.sysModule);
     217           0 :       serverManager.add(sysInjector);
     218             :     } else {
     219           2 :       sysInjector = root;
     220             :     }
     221             : 
     222          13 :     if (env.hasSshModule()) {
     223           2 :       List<Module> modules = new ArrayList<>();
     224           2 :       if (getApiType() == ApiType.PLUGIN) {
     225           2 :         modules.add(env.getSshModule());
     226             :       }
     227           2 :       if (sshModule != null) {
     228           0 :         modules.add(sysInjector.getInstance(sshModule));
     229           0 :         sshInjector = sysInjector.createChildInjector(modules);
     230           0 :         serverManager.add(sshInjector);
     231           2 :       } else if (auto != null && auto.sshModule != null) {
     232           0 :         modules.add(auto.sshModule);
     233           0 :         sshInjector = sysInjector.createChildInjector(modules);
     234           0 :         serverManager.add(sshInjector);
     235             :       }
     236             :     }
     237             : 
     238          13 :     if (env.hasHttpModule()) {
     239           9 :       List<Module> modules = new ArrayList<>();
     240           9 :       if (getApiType() == ApiType.PLUGIN) {
     241           9 :         modules.add(env.getHttpModule());
     242             :       }
     243           9 :       if (httpModule != null) {
     244           1 :         modules.add(sysInjector.getInstance(httpModule));
     245           1 :         httpInjector = sysInjector.createChildInjector(modules);
     246           1 :         serverManager.add(httpInjector);
     247           9 :       } else if (auto != null && auto.httpModule != null) {
     248           0 :         modules.add(auto.httpModule);
     249           0 :         httpInjector = sysInjector.createChildInjector(modules);
     250           0 :         serverManager.add(httpInjector);
     251             :       }
     252             :     }
     253             : 
     254          13 :     serverManager.start();
     255          13 :   }
     256             : 
     257             :   private Injector newRootInjector(PluginGuiceEnvironment env) {
     258          13 :     List<Module> modules = Lists.newArrayListWithCapacity(2);
     259          13 :     if (getApiType() == ApiType.PLUGIN) {
     260          12 :       modules.add(env.getSysModule());
     261             :     }
     262          13 :     modules.add(new ServerPluginInfoModule(this, env.getServerMetrics()));
     263          13 :     return Guice.createInjector(modules);
     264             :   }
     265             : 
     266             :   @Override
     267             :   protected void stop(PluginGuiceEnvironment env) {
     268          13 :     if (serverManager != null) {
     269          13 :       RequestContext oldContext = env.enter(this);
     270             :       try {
     271          13 :         serverManager.stop();
     272             :       } finally {
     273          13 :         env.exit(oldContext);
     274             :       }
     275          13 :       serverManager = null;
     276          13 :       sysInjector = null;
     277          13 :       sshInjector = null;
     278          13 :       httpInjector = null;
     279             :     }
     280          13 :   }
     281             : 
     282             :   @Override
     283             :   public Injector getSysInjector() {
     284          13 :     return sysInjector;
     285             :   }
     286             : 
     287             :   @Override
     288             :   @Nullable
     289             :   public Injector getSshInjector() {
     290          13 :     return sshInjector;
     291             :   }
     292             : 
     293             :   @Override
     294             :   @Nullable
     295             :   public Injector getHttpInjector() {
     296          13 :     return httpInjector;
     297             :   }
     298             : 
     299             :   @Override
     300             :   public void add(RegistrationHandle handle) {
     301          13 :     if (serverManager != null) {
     302          13 :       if (handle instanceof ReloadableRegistrationHandle) {
     303          13 :         if (reloadableHandles == null) {
     304          13 :           reloadableHandles = new ArrayList<>();
     305             :         }
     306          13 :         reloadableHandles.add((ReloadableRegistrationHandle<?>) handle);
     307             :       }
     308          13 :       serverManager.add(handle);
     309             :     }
     310          13 :   }
     311             : 
     312             :   @Override
     313             :   public PluginContentScanner getContentScanner() {
     314           0 :     return scanner;
     315             :   }
     316             : }

Generated by: LCOV version 1.16+git.20220603.dfeb750