PageRenderTime 1179ms CodeModel.GetById 35ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://gitlab.com/chenfengxu/gerrit
Java | 648 lines | 525 code | 80 blank | 43 comment | 125 complexity | c676a774f45fdff394da89905a1c22b9 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 static com.google.common.base.Preconditions.checkNotNull;
  16. import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicItemsOf;
  17. import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicMapsOf;
  18. import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicSetsOf;
  19. import com.google.common.collect.LinkedListMultimap;
  20. import com.google.common.collect.ListMultimap;
  21. import com.google.common.collect.Lists;
  22. import com.google.gerrit.common.Nullable;
  23. import com.google.gerrit.extensions.annotations.RootRelative;
  24. import com.google.gerrit.extensions.events.LifecycleListener;
  25. import com.google.gerrit.extensions.registration.DynamicItem;
  26. import com.google.gerrit.extensions.registration.DynamicMap;
  27. import com.google.gerrit.extensions.registration.DynamicSet;
  28. import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
  29. import com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes;
  30. import com.google.gerrit.extensions.registration.RegistrationHandle;
  31. import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
  32. import com.google.gerrit.extensions.systemstatus.ServerInformation;
  33. import com.google.gerrit.extensions.webui.WebUiPlugin;
  34. import com.google.gerrit.index.IndexCollection;
  35. import com.google.gerrit.metrics.MetricMaker;
  36. import com.google.gerrit.server.util.PluginRequestContext;
  37. import com.google.gerrit.server.util.RequestContext;
  38. import com.google.gerrit.server.util.ThreadLocalRequestContext;
  39. import com.google.inject.AbstractModule;
  40. import com.google.inject.Binding;
  41. import com.google.inject.Guice;
  42. import com.google.inject.Inject;
  43. import com.google.inject.Injector;
  44. import com.google.inject.Key;
  45. import com.google.inject.Module;
  46. import com.google.inject.Provider;
  47. import com.google.inject.Singleton;
  48. import com.google.inject.TypeLiteral;
  49. import com.google.inject.internal.UniqueAnnotations;
  50. import java.lang.annotation.Annotation;
  51. import java.lang.reflect.ParameterizedType;
  52. import java.util.Collections;
  53. import java.util.HashMap;
  54. import java.util.HashSet;
  55. import java.util.Iterator;
  56. import java.util.LinkedHashMap;
  57. import java.util.List;
  58. import java.util.Map;
  59. import java.util.Set;
  60. import java.util.concurrent.CopyOnWriteArrayList;
  61. import javax.servlet.http.HttpServletRequest;
  62. import javax.servlet.http.HttpServletResponse;
  63. /**
  64. * Tracks Guice bindings that should be exposed to loaded plugins.
  65. *
  66. * <p>This is an internal implementation detail of how the main server is able to export its
  67. * explicit Guice bindings to tightly coupled plugins, giving them access to singletons and request
  68. * scoped resources just like any core code.
  69. */
  70. @Singleton
  71. public class PluginGuiceEnvironment {
  72. private final Injector sysInjector;
  73. private final ServerInformation srvInfo;
  74. private final ThreadLocalRequestContext local;
  75. private final CopyConfigModule copyConfigModule;
  76. private final Set<Key<?>> copyConfigKeys;
  77. private final List<StartPluginListener> onStart;
  78. private final List<StopPluginListener> onStop;
  79. private final List<ReloadPluginListener> onReload;
  80. private final MetricMaker serverMetrics;
  81. private Module sysModule;
  82. private Module sshModule;
  83. private Module httpModule;
  84. private Provider<ModuleGenerator> sshGen;
  85. private Provider<ModuleGenerator> httpGen;
  86. private Map<TypeLiteral<?>, DynamicItem<?>> sysItems;
  87. private Map<TypeLiteral<?>, DynamicItem<?>> sshItems;
  88. private Map<TypeLiteral<?>, DynamicItem<?>> httpItems;
  89. private Map<TypeLiteral<?>, DynamicSet<?>> sysSets;
  90. private Map<TypeLiteral<?>, DynamicSet<?>> sshSets;
  91. private Map<TypeLiteral<?>, DynamicSet<?>> httpSets;
  92. private Map<TypeLiteral<?>, DynamicMap<?>> sysMaps;
  93. private Map<TypeLiteral<?>, DynamicMap<?>> sshMaps;
  94. private Map<TypeLiteral<?>, DynamicMap<?>> httpMaps;
  95. @Inject
  96. PluginGuiceEnvironment(
  97. Injector sysInjector,
  98. ThreadLocalRequestContext local,
  99. ServerInformation srvInfo,
  100. CopyConfigModule ccm,
  101. MetricMaker serverMetrics) {
  102. this.sysInjector = sysInjector;
  103. this.srvInfo = srvInfo;
  104. this.local = local;
  105. this.copyConfigModule = ccm;
  106. this.copyConfigKeys = Guice.createInjector(ccm).getAllBindings().keySet();
  107. this.serverMetrics = serverMetrics;
  108. onStart = new CopyOnWriteArrayList<>();
  109. onStart.addAll(listeners(sysInjector, StartPluginListener.class));
  110. onStop = new CopyOnWriteArrayList<>();
  111. onStop.addAll(listeners(sysInjector, StopPluginListener.class));
  112. onReload = new CopyOnWriteArrayList<>();
  113. onReload.addAll(listeners(sysInjector, ReloadPluginListener.class));
  114. sysItems = dynamicItemsOf(sysInjector);
  115. sysSets = dynamicSetsOf(sysInjector);
  116. sysMaps = dynamicMapsOf(sysInjector);
  117. }
  118. ServerInformation getServerInformation() {
  119. return srvInfo;
  120. }
  121. MetricMaker getServerMetrics() {
  122. return serverMetrics;
  123. }
  124. boolean hasDynamicItem(TypeLiteral<?> type) {
  125. return sysItems.containsKey(type)
  126. || (sshItems != null && sshItems.containsKey(type))
  127. || (httpItems != null && httpItems.containsKey(type));
  128. }
  129. boolean hasDynamicSet(TypeLiteral<?> type) {
  130. return sysSets.containsKey(type)
  131. || (sshSets != null && sshSets.containsKey(type))
  132. || (httpSets != null && httpSets.containsKey(type));
  133. }
  134. boolean hasDynamicMap(TypeLiteral<?> type) {
  135. return sysMaps.containsKey(type)
  136. || (sshMaps != null && sshMaps.containsKey(type))
  137. || (httpMaps != null && httpMaps.containsKey(type));
  138. }
  139. public Module getSysModule() {
  140. return sysModule;
  141. }
  142. public void setDbCfgInjector(Injector dbInjector, Injector cfgInjector) {
  143. final Module db = copy(dbInjector);
  144. final Module cm = copy(cfgInjector);
  145. final Module sm = copy(sysInjector);
  146. sysModule =
  147. new AbstractModule() {
  148. @Override
  149. protected void configure() {
  150. install(copyConfigModule);
  151. install(db);
  152. install(cm);
  153. install(sm);
  154. }
  155. };
  156. }
  157. public void setSshInjector(Injector injector) {
  158. sshModule = copy(injector);
  159. sshGen = injector.getProvider(ModuleGenerator.class);
  160. sshItems = dynamicItemsOf(injector);
  161. sshSets = dynamicSetsOf(injector);
  162. sshMaps = dynamicMapsOf(injector);
  163. onStart.addAll(listeners(injector, StartPluginListener.class));
  164. onStop.addAll(listeners(injector, StopPluginListener.class));
  165. onReload.addAll(listeners(injector, ReloadPluginListener.class));
  166. }
  167. boolean hasSshModule() {
  168. return sshModule != null;
  169. }
  170. Module getSshModule() {
  171. return sshModule;
  172. }
  173. ModuleGenerator newSshModuleGenerator() {
  174. return sshGen.get();
  175. }
  176. public void setHttpInjector(Injector injector) {
  177. httpModule = copy(injector);
  178. httpGen = injector.getProvider(ModuleGenerator.class);
  179. httpItems = dynamicItemsOf(injector);
  180. httpSets = httpDynamicSetsOf(injector);
  181. httpMaps = dynamicMapsOf(injector);
  182. onStart.addAll(listeners(injector, StartPluginListener.class));
  183. onStop.addAll(listeners(injector, StopPluginListener.class));
  184. onReload.addAll(listeners(injector, ReloadPluginListener.class));
  185. }
  186. private Map<TypeLiteral<?>, DynamicSet<?>> httpDynamicSetsOf(Injector i) {
  187. // Copy binding of DynamicSet<WebUiPlugin> from sysInjector to HTTP.
  188. // This supports older plugins that bound a plugin in the HttpModule.
  189. TypeLiteral<WebUiPlugin> key = TypeLiteral.get(WebUiPlugin.class);
  190. DynamicSet<?> web = sysSets.get(key);
  191. checkNotNull(web, "DynamicSet<WebUiPlugin> exists in sysInjector");
  192. Map<TypeLiteral<?>, DynamicSet<?>> m = new HashMap<>(dynamicSetsOf(i));
  193. m.put(key, web);
  194. return Collections.unmodifiableMap(m);
  195. }
  196. boolean hasHttpModule() {
  197. return httpModule != null;
  198. }
  199. Module getHttpModule() {
  200. return httpModule;
  201. }
  202. ModuleGenerator newHttpModuleGenerator() {
  203. return httpGen.get();
  204. }
  205. public RequestContext enter(Plugin plugin) {
  206. return local.setContext(new PluginRequestContext(plugin.getPluginUser()));
  207. }
  208. public void exit(RequestContext old) {
  209. local.setContext(old);
  210. }
  211. public void onStartPlugin(Plugin plugin) {
  212. RequestContext oldContext = enter(plugin);
  213. try {
  214. attachItem(sysItems, plugin.getSysInjector(), plugin);
  215. attachItem(sshItems, plugin.getSshInjector(), plugin);
  216. attachItem(httpItems, plugin.getHttpInjector(), plugin);
  217. attachSet(sysSets, plugin.getSysInjector(), plugin);
  218. attachSet(sshSets, plugin.getSshInjector(), plugin);
  219. attachSet(httpSets, plugin.getHttpInjector(), plugin);
  220. attachMap(sysMaps, plugin.getSysInjector(), plugin);
  221. attachMap(sshMaps, plugin.getSshInjector(), plugin);
  222. attachMap(httpMaps, plugin.getHttpInjector(), plugin);
  223. } finally {
  224. exit(oldContext);
  225. }
  226. for (StartPluginListener l : onStart) {
  227. l.onStartPlugin(plugin);
  228. }
  229. }
  230. public void onStopPlugin(Plugin plugin) {
  231. for (StopPluginListener l : onStop) {
  232. l.onStopPlugin(plugin);
  233. }
  234. }
  235. private void attachItem(
  236. Map<TypeLiteral<?>, DynamicItem<?>> items, @Nullable Injector src, Plugin plugin) {
  237. for (RegistrationHandle h :
  238. PrivateInternals_DynamicTypes.attachItems(src, items, plugin.getName())) {
  239. plugin.add(h);
  240. }
  241. }
  242. private void attachSet(
  243. Map<TypeLiteral<?>, DynamicSet<?>> sets, @Nullable Injector src, Plugin plugin) {
  244. for (RegistrationHandle h : PrivateInternals_DynamicTypes.attachSets(src, sets)) {
  245. plugin.add(h);
  246. }
  247. }
  248. private void attachMap(
  249. Map<TypeLiteral<?>, DynamicMap<?>> maps, @Nullable Injector src, Plugin plugin) {
  250. for (RegistrationHandle h :
  251. PrivateInternals_DynamicTypes.attachMaps(src, plugin.getName(), maps)) {
  252. plugin.add(h);
  253. }
  254. }
  255. void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) {
  256. // Index all old registrations by the raw type. These may be replaced
  257. // during the reattach calls below. Any that are not replaced will be
  258. // removed when the old plugin does its stop routine.
  259. ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> old = LinkedListMultimap.create();
  260. for (ReloadableRegistrationHandle<?> h : oldPlugin.getReloadableHandles()) {
  261. old.put(h.getKey().getTypeLiteral(), h);
  262. }
  263. RequestContext oldContext = enter(newPlugin);
  264. try {
  265. reattachMap(old, sysMaps, newPlugin.getSysInjector(), newPlugin);
  266. reattachMap(old, sshMaps, newPlugin.getSshInjector(), newPlugin);
  267. reattachMap(old, httpMaps, newPlugin.getHttpInjector(), newPlugin);
  268. reattachSet(old, sysSets, newPlugin.getSysInjector(), newPlugin);
  269. reattachSet(old, sshSets, newPlugin.getSshInjector(), newPlugin);
  270. reattachSet(old, httpSets, newPlugin.getHttpInjector(), newPlugin);
  271. reattachItem(old, sysItems, newPlugin.getSysInjector(), newPlugin);
  272. reattachItem(old, sshItems, newPlugin.getSshInjector(), newPlugin);
  273. reattachItem(old, httpItems, newPlugin.getHttpInjector(), newPlugin);
  274. } finally {
  275. exit(oldContext);
  276. }
  277. for (ReloadPluginListener l : onReload) {
  278. l.onReloadPlugin(oldPlugin, newPlugin);
  279. }
  280. }
  281. private void reattachMap(
  282. ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
  283. Map<TypeLiteral<?>, DynamicMap<?>> maps,
  284. @Nullable Injector src,
  285. Plugin newPlugin) {
  286. if (src == null || maps == null || maps.isEmpty()) {
  287. return;
  288. }
  289. for (Map.Entry<TypeLiteral<?>, DynamicMap<?>> e : maps.entrySet()) {
  290. @SuppressWarnings("unchecked")
  291. TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
  292. @SuppressWarnings("unchecked")
  293. PrivateInternals_DynamicMapImpl<Object> map =
  294. (PrivateInternals_DynamicMapImpl<Object>) e.getValue();
  295. Map<Annotation, ReloadableRegistrationHandle<?>> am = new HashMap<>();
  296. for (ReloadableRegistrationHandle<?> h : oldHandles.get(type)) {
  297. Annotation a = h.getKey().getAnnotation();
  298. if (a != null && !UNIQUE_ANNOTATION.isInstance(a)) {
  299. am.put(a, h);
  300. }
  301. }
  302. for (Binding<?> binding : bindings(src, e.getKey())) {
  303. @SuppressWarnings("unchecked")
  304. Binding<Object> b = (Binding<Object>) binding;
  305. Key<Object> key = b.getKey();
  306. if (key.getAnnotation() == null) {
  307. continue;
  308. }
  309. @SuppressWarnings("unchecked")
  310. ReloadableRegistrationHandle<Object> h =
  311. (ReloadableRegistrationHandle<Object>) am.remove(key.getAnnotation());
  312. if (h != null) {
  313. replace(newPlugin, h, b);
  314. oldHandles.remove(type, h);
  315. } else {
  316. newPlugin.add(map.put(newPlugin.getName(), b.getKey(), b.getProvider()));
  317. }
  318. }
  319. }
  320. }
  321. /** Type used to declare unique annotations. Guice hides this, so extract it. */
  322. private static final Class<?> UNIQUE_ANNOTATION = UniqueAnnotations.create().annotationType();
  323. private void reattachSet(
  324. ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
  325. Map<TypeLiteral<?>, DynamicSet<?>> sets,
  326. @Nullable Injector src,
  327. Plugin newPlugin) {
  328. if (src == null || sets == null || sets.isEmpty()) {
  329. return;
  330. }
  331. for (Map.Entry<TypeLiteral<?>, DynamicSet<?>> e : sets.entrySet()) {
  332. @SuppressWarnings("unchecked")
  333. TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
  334. @SuppressWarnings("unchecked")
  335. DynamicSet<Object> set = (DynamicSet<Object>) e.getValue();
  336. // Index all old handles that match this DynamicSet<T> keyed by
  337. // annotations. Ignore the unique annotations, thereby favoring
  338. // the @Named annotations or some other non-unique naming.
  339. Map<Annotation, ReloadableRegistrationHandle<?>> am = new HashMap<>();
  340. List<ReloadableRegistrationHandle<?>> old = oldHandles.get(type);
  341. Iterator<ReloadableRegistrationHandle<?>> oi = old.iterator();
  342. while (oi.hasNext()) {
  343. ReloadableRegistrationHandle<?> h = oi.next();
  344. Annotation a = h.getKey().getAnnotation();
  345. if (a != null && !UNIQUE_ANNOTATION.isInstance(a)) {
  346. am.put(a, h);
  347. oi.remove();
  348. }
  349. }
  350. // Replace old handles with new bindings, favoring cases where there
  351. // is an exact match on an @Named annotation. If there is no match
  352. // pick any handle and replace it. We generally expect only one
  353. // handle of each DynamicSet type when using unique annotations, but
  354. // possibly multiple ones if @Named was used. Plugin authors that want
  355. // atomic replacement across reloads should use @Named annotations with
  356. // stable names that do not change across plugin versions to ensure the
  357. // handles are swapped correctly.
  358. oi = old.iterator();
  359. for (Binding<?> binding : bindings(src, type)) {
  360. @SuppressWarnings("unchecked")
  361. Binding<Object> b = (Binding<Object>) binding;
  362. Key<Object> key = b.getKey();
  363. if (key.getAnnotation() == null) {
  364. continue;
  365. }
  366. @SuppressWarnings("unchecked")
  367. ReloadableRegistrationHandle<Object> h1 =
  368. (ReloadableRegistrationHandle<Object>) am.remove(key.getAnnotation());
  369. if (h1 != null) {
  370. replace(newPlugin, h1, b);
  371. } else if (oi.hasNext()) {
  372. @SuppressWarnings("unchecked")
  373. ReloadableRegistrationHandle<Object> h2 =
  374. (ReloadableRegistrationHandle<Object>) oi.next();
  375. oi.remove();
  376. replace(newPlugin, h2, b);
  377. } else {
  378. newPlugin.add(set.add(b.getKey(), b.getProvider()));
  379. }
  380. }
  381. }
  382. }
  383. private void reattachItem(
  384. ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
  385. Map<TypeLiteral<?>, DynamicItem<?>> items,
  386. @Nullable Injector src,
  387. Plugin newPlugin) {
  388. if (src == null || items == null || items.isEmpty()) {
  389. return;
  390. }
  391. for (Map.Entry<TypeLiteral<?>, DynamicItem<?>> e : items.entrySet()) {
  392. @SuppressWarnings("unchecked")
  393. TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
  394. @SuppressWarnings("unchecked")
  395. DynamicItem<Object> item = (DynamicItem<Object>) e.getValue();
  396. Iterator<ReloadableRegistrationHandle<?>> oi = oldHandles.get(type).iterator();
  397. for (Binding<?> binding : bindings(src, type)) {
  398. @SuppressWarnings("unchecked")
  399. Binding<Object> b = (Binding<Object>) binding;
  400. if (oi.hasNext()) {
  401. @SuppressWarnings("unchecked")
  402. ReloadableRegistrationHandle<Object> h = (ReloadableRegistrationHandle<Object>) oi.next();
  403. oi.remove();
  404. replace(newPlugin, h, b);
  405. } else {
  406. newPlugin.add(item.set(b.getKey(), b.getProvider(), newPlugin.getName()));
  407. }
  408. }
  409. }
  410. }
  411. private static <T> void replace(
  412. Plugin newPlugin, ReloadableRegistrationHandle<T> h, Binding<T> b) {
  413. RegistrationHandle n = h.replace(b.getKey(), b.getProvider());
  414. if (n != null) {
  415. newPlugin.add(n);
  416. }
  417. }
  418. static <T> List<T> listeners(Injector src, Class<T> type) {
  419. List<Binding<T>> bindings = bindings(src, TypeLiteral.get(type));
  420. int cnt = bindings != null ? bindings.size() : 0;
  421. List<T> found = Lists.newArrayListWithCapacity(cnt);
  422. if (bindings != null) {
  423. for (Binding<T> b : bindings) {
  424. found.add(b.getProvider().get());
  425. }
  426. }
  427. return found;
  428. }
  429. private static <T> List<Binding<T>> bindings(Injector src, TypeLiteral<T> type) {
  430. return src.findBindingsByType(type);
  431. }
  432. private Module copy(Injector src) {
  433. Set<TypeLiteral<?>> dynamicTypes = new HashSet<>();
  434. Set<TypeLiteral<?>> dynamicItemTypes = new HashSet<>();
  435. for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
  436. TypeLiteral<?> type = e.getKey().getTypeLiteral();
  437. if (type.getRawType() == DynamicItem.class) {
  438. ParameterizedType t = (ParameterizedType) type.getType();
  439. dynamicItemTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
  440. } else if (type.getRawType() == DynamicSet.class || type.getRawType() == DynamicMap.class) {
  441. ParameterizedType t = (ParameterizedType) type.getType();
  442. dynamicTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
  443. }
  444. }
  445. final Map<Key<?>, Binding<?>> bindings = new LinkedHashMap<>();
  446. for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
  447. if (dynamicTypes.contains(e.getKey().getTypeLiteral())
  448. && e.getKey().getAnnotation() != null) {
  449. // A type used in DynamicSet or DynamicMap that has an annotation
  450. // must be picked up by the set/map itself. A type used in either
  451. // but without an annotation may be magic glue implementing F and
  452. // using DynamicSet<F> or DynamicMap<F> internally. That should be
  453. // exported to plugins.
  454. continue;
  455. } else if (dynamicItemTypes.contains(e.getKey().getTypeLiteral())) {
  456. continue;
  457. } else if (shouldCopy(e.getKey())) {
  458. bindings.put(e.getKey(), e.getValue());
  459. }
  460. }
  461. bindings.remove(Key.get(Injector.class));
  462. bindings.remove(Key.get(java.util.logging.Logger.class));
  463. @Nullable
  464. final Binding<HttpServletRequest> requestBinding =
  465. src.getExistingBinding(Key.get(HttpServletRequest.class));
  466. @Nullable
  467. final Binding<HttpServletResponse> responseBinding =
  468. src.getExistingBinding(Key.get(HttpServletResponse.class));
  469. return new AbstractModule() {
  470. @SuppressWarnings("unchecked")
  471. @Override
  472. protected void configure() {
  473. for (Map.Entry<Key<?>, Binding<?>> e : bindings.entrySet()) {
  474. Key<Object> k = (Key<Object>) e.getKey();
  475. Binding<Object> b = (Binding<Object>) e.getValue();
  476. bind(k).toProvider(b.getProvider());
  477. }
  478. if (requestBinding != null) {
  479. bind(HttpServletRequest.class)
  480. .annotatedWith(RootRelative.class)
  481. .toProvider(requestBinding.getProvider());
  482. }
  483. if (responseBinding != null) {
  484. bind(HttpServletResponse.class)
  485. .annotatedWith(RootRelative.class)
  486. .toProvider(responseBinding.getProvider());
  487. }
  488. }
  489. };
  490. }
  491. private boolean shouldCopy(Key<?> key) {
  492. if (copyConfigKeys.contains(key)) {
  493. return false;
  494. }
  495. Class<?> type = key.getTypeLiteral().getRawType();
  496. if (LifecycleListener.class.isAssignableFrom(type)
  497. // This is needed for secondary index to work from plugin listeners
  498. && !IndexCollection.class.isAssignableFrom(type)) {
  499. return false;
  500. }
  501. if (StartPluginListener.class.isAssignableFrom(type)) {
  502. return false;
  503. }
  504. if (StopPluginListener.class.isAssignableFrom(type)) {
  505. return false;
  506. }
  507. if (MetricMaker.class.isAssignableFrom(type)) {
  508. return false;
  509. }
  510. if (type.getName().startsWith("com.google.inject.")) {
  511. return false;
  512. }
  513. if (is("org.apache.sshd.server.Command", type)) {
  514. return false;
  515. }
  516. if (is("javax.servlet.Filter", type)) {
  517. return false;
  518. }
  519. if (is("javax.servlet.ServletContext", type)) {
  520. return false;
  521. }
  522. if (is("javax.servlet.ServletRequest", type)) {
  523. return false;
  524. }
  525. if (is("javax.servlet.ServletResponse", type)) {
  526. return false;
  527. }
  528. if (is("javax.servlet.http.HttpServlet", type)) {
  529. return false;
  530. }
  531. if (is("javax.servlet.http.HttpServletRequest", type)) {
  532. return false;
  533. }
  534. if (is("javax.servlet.http.HttpServletResponse", type)) {
  535. return false;
  536. }
  537. if (is("javax.servlet.http.HttpSession", type)) {
  538. return false;
  539. }
  540. if (Map.class.isAssignableFrom(type)
  541. && key.getAnnotationType() != null
  542. && "com.google.inject.servlet.RequestParameters"
  543. .equals(key.getAnnotationType().getName())) {
  544. return false;
  545. }
  546. if (type.getName().startsWith("com.google.gerrit.httpd.GitOverHttpServlet$")) {
  547. return false;
  548. }
  549. return true;
  550. }
  551. static boolean is(String name, Class<?> type) {
  552. while (type != null) {
  553. if (name.equals(type.getName())) {
  554. return true;
  555. }
  556. Class<?>[] interfaces = type.getInterfaces();
  557. if (interfaces != null) {
  558. for (Class<?> i : interfaces) {
  559. if (is(name, i)) {
  560. return true;
  561. }
  562. }
  563. }
  564. type = type.getSuperclass();
  565. }
  566. return false;
  567. }
  568. }