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