PageRenderTime 46ms CodeModel.GetById 26ms app.highlight 17ms RepoModel.GetById 0ms app.codeStats 1ms

/java/com/google/gerrit/server/plugins/ServerPlugin.java

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