Register DynamicSet, DynamicMap from parent injectors
If the HTTP or SSH injector registers implementations of a type that is tracked by a DynamicSet or DynamicMap from the system injector, ensure those are registered when these injectors are started by the LifecycleManager. Change-Id: I6d4134f6689c872b162b04f8cf5935d50bd0fd9d
This commit is contained in:
@@ -0,0 +1,171 @@
|
|||||||
|
// Copyright (C) 2012 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.extensions.registration;
|
||||||
|
|
||||||
|
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||||
|
import com.google.inject.Binding;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Injector;
|
||||||
|
import com.google.inject.Key;
|
||||||
|
import com.google.inject.TypeLiteral;
|
||||||
|
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/** <b>DO NOT USE</b> */
|
||||||
|
public class PrivateInternals_DynamicTypes {
|
||||||
|
public static Map<TypeLiteral<?>, DynamicSet<?>> dynamicSetsOf(Injector src) {
|
||||||
|
Map<TypeLiteral<?>, DynamicSet<?>> m = newHashMap();
|
||||||
|
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
||||||
|
TypeLiteral<?> type = e.getKey().getTypeLiteral();
|
||||||
|
if (type.getRawType() == DynamicSet.class) {
|
||||||
|
ParameterizedType p = (ParameterizedType) type.getType();
|
||||||
|
m.put(TypeLiteral.get(p.getActualTypeArguments()[0]),
|
||||||
|
(DynamicSet<?>) e.getValue().getProvider().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<TypeLiteral<?>, DynamicMap<?>> dynamicMapsOf(Injector src) {
|
||||||
|
Map<TypeLiteral<?>, DynamicMap<?>> m = newHashMap();
|
||||||
|
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
||||||
|
TypeLiteral<?> type = e.getKey().getTypeLiteral();
|
||||||
|
if (type.getRawType() == DynamicMap.class) {
|
||||||
|
ParameterizedType p = (ParameterizedType) type.getType();
|
||||||
|
m.put(TypeLiteral.get(p.getActualTypeArguments()[0]),
|
||||||
|
(DynamicMap<?>) e.getValue().getProvider().get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m.isEmpty()) {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
return Collections.unmodifiableMap(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RegistrationHandle> attachSets(
|
||||||
|
Injector src,
|
||||||
|
Map<TypeLiteral<?>, DynamicSet<?>> sets) {
|
||||||
|
if (src == null || sets == null || sets.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RegistrationHandle> handles = new ArrayList<RegistrationHandle>(4);
|
||||||
|
try {
|
||||||
|
for (Map.Entry<TypeLiteral<?>, DynamicSet<?>> e : sets.entrySet()) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
DynamicSet<Object> set = (DynamicSet<Object>) e.getValue();
|
||||||
|
|
||||||
|
for (Binding<Object> b : bindings(src, type)) {
|
||||||
|
handles.add(set.add(b.getKey(), b.getProvider()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
remove(handles);
|
||||||
|
throw e;
|
||||||
|
} catch (Error e) {
|
||||||
|
remove(handles);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<RegistrationHandle> attachMaps(
|
||||||
|
Injector src,
|
||||||
|
String groupName,
|
||||||
|
Map<TypeLiteral<?>, DynamicMap<?>> maps) {
|
||||||
|
if (src == null || maps == null || maps.isEmpty()) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<RegistrationHandle> handles = new ArrayList<RegistrationHandle>(4);
|
||||||
|
try {
|
||||||
|
for (Map.Entry<TypeLiteral<?>, DynamicMap<?>> e : maps.entrySet()) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
PrivateInternals_DynamicMapImpl<Object> set =
|
||||||
|
(PrivateInternals_DynamicMapImpl<Object>) e.getValue();
|
||||||
|
|
||||||
|
for (Binding<Object> b : bindings(src, type)) {
|
||||||
|
handles.add(set.put(groupName, b.getKey(), b.getProvider()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
remove(handles);
|
||||||
|
throw e;
|
||||||
|
} catch (Error e) {
|
||||||
|
remove(handles);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
return handles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LifecycleListener registerInParentInjectors() {
|
||||||
|
return new LifecycleListener() {
|
||||||
|
private List<RegistrationHandle> handles;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
private Injector self;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void start() {
|
||||||
|
handles = new ArrayList<RegistrationHandle>(4);
|
||||||
|
Injector parent = self.getParent();
|
||||||
|
while (parent != null) {
|
||||||
|
handles.addAll(attachSets(self, dynamicSetsOf(parent)));
|
||||||
|
handles.addAll(attachMaps(self, "gerrit", dynamicMapsOf(parent)));
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
if (handles.isEmpty()) {
|
||||||
|
handles = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop() {
|
||||||
|
remove(handles);
|
||||||
|
handles = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void remove(List<RegistrationHandle> handles) {
|
||||||
|
if (handles != null) {
|
||||||
|
for (RegistrationHandle handle : handles) {
|
||||||
|
handle.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <K,V> Map<K, V> newHashMap() {
|
||||||
|
return new HashMap<K,V>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static <T> List<Binding<T>> bindings(Injector src, TypeLiteral<T> type) {
|
||||||
|
return src.findBindingsByType(type);
|
||||||
|
}
|
||||||
|
}
|
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.httpd;
|
package com.google.gerrit.httpd;
|
||||||
|
|
||||||
import static com.google.inject.Scopes.SINGLETON;
|
import static com.google.inject.Scopes.SINGLETON;
|
||||||
|
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.registerInParentInjectors;
|
||||||
|
|
||||||
import com.google.gerrit.common.data.GerritConfig;
|
import com.google.gerrit.common.data.GerritConfig;
|
||||||
import com.google.gerrit.httpd.auth.become.BecomeAnyAccountLoginServlet;
|
import com.google.gerrit.httpd.auth.become.BecomeAnyAccountLoginServlet;
|
||||||
@@ -23,6 +24,7 @@ import com.google.gerrit.httpd.auth.container.HttpsClientSslCertModule;
|
|||||||
import com.google.gerrit.httpd.auth.ldap.LdapAuthModule;
|
import com.google.gerrit.httpd.auth.ldap.LdapAuthModule;
|
||||||
import com.google.gerrit.httpd.gitweb.GitWebModule;
|
import com.google.gerrit.httpd.gitweb.GitWebModule;
|
||||||
import com.google.gerrit.httpd.rpc.UiRpcModule;
|
import com.google.gerrit.httpd.rpc.UiRpcModule;
|
||||||
|
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||||
import com.google.gerrit.server.CurrentUser;
|
import com.google.gerrit.server.CurrentUser;
|
||||||
import com.google.gerrit.server.IdentifiedUser;
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
import com.google.gerrit.server.RemotePeer;
|
import com.google.gerrit.server.RemotePeer;
|
||||||
@@ -147,5 +149,12 @@ public class WebModule extends FactoryModule {
|
|||||||
|
|
||||||
bind(CurrentUser.class).toProvider(HttpCurrentUserProvider.class);
|
bind(CurrentUser.class).toProvider(HttpCurrentUserProvider.class);
|
||||||
bind(IdentifiedUser.class).toProvider(HttpIdentifiedUserProvider.class);
|
bind(IdentifiedUser.class).toProvider(HttpIdentifiedUserProvider.class);
|
||||||
|
|
||||||
|
install(new LifecycleModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
listener().toInstance(registerInParentInjectors());
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
package com.google.gerrit.server.plugins;
|
package com.google.gerrit.server.plugins;
|
||||||
|
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicMapsOf;
|
||||||
|
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicSetsOf;
|
||||||
|
|
||||||
import com.google.common.collect.LinkedListMultimap;
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
import com.google.common.collect.ListMultimap;
|
import com.google.common.collect.ListMultimap;
|
||||||
@@ -23,6 +25,7 @@ import com.google.gerrit.extensions.events.LifecycleListener;
|
|||||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||||
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
|
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
|
||||||
|
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes;
|
||||||
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
import com.google.gerrit.extensions.registration.RegistrationHandle;
|
||||||
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
|
||||||
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
import com.google.gerrit.extensions.systemstatus.ServerInformation;
|
||||||
@@ -188,40 +191,18 @@ public class PluginGuiceEnvironment {
|
|||||||
private void attachSet(Map<TypeLiteral<?>, DynamicSet<?>> sets,
|
private void attachSet(Map<TypeLiteral<?>, DynamicSet<?>> sets,
|
||||||
@Nullable Injector src,
|
@Nullable Injector src,
|
||||||
Plugin plugin) {
|
Plugin plugin) {
|
||||||
if (src != null && sets != null && !sets.isEmpty()) {
|
for (RegistrationHandle h : PrivateInternals_DynamicTypes
|
||||||
for (Map.Entry<TypeLiteral<?>, DynamicSet<?>> e : sets.entrySet()) {
|
.attachSets(src, sets)) {
|
||||||
@SuppressWarnings("unchecked")
|
plugin.add(h);
|
||||||
TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
DynamicSet<Object> set = (DynamicSet<Object>) e.getValue();
|
|
||||||
|
|
||||||
for (Binding<Object> b : bindings(src, type)) {
|
|
||||||
plugin.add(set.add(b.getKey(), b.getProvider()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void attachMap(Map<TypeLiteral<?>, DynamicMap<?>> maps,
|
private void attachMap(Map<TypeLiteral<?>, DynamicMap<?>> maps,
|
||||||
@Nullable Injector src,
|
@Nullable Injector src,
|
||||||
Plugin plugin) {
|
Plugin plugin) {
|
||||||
if (src != null && maps != null && !maps.isEmpty()) {
|
for (RegistrationHandle h : PrivateInternals_DynamicTypes
|
||||||
for (Map.Entry<TypeLiteral<?>, DynamicMap<?>> e : maps.entrySet()) {
|
.attachMaps(src, plugin.getName(), maps)) {
|
||||||
@SuppressWarnings("unchecked")
|
plugin.add(h);
|
||||||
TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
PrivateInternals_DynamicMapImpl<Object> set =
|
|
||||||
(PrivateInternals_DynamicMapImpl<Object>) e.getValue();
|
|
||||||
|
|
||||||
for (Binding<Object> b : bindings(src, type)) {
|
|
||||||
plugin.add(set.put(
|
|
||||||
plugin.getName(),
|
|
||||||
b.getKey(),
|
|
||||||
b.getProvider()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -385,32 +366,6 @@ public class PluginGuiceEnvironment {
|
|||||||
return src.findBindingsByType(type);
|
return src.findBindingsByType(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<TypeLiteral<?>, DynamicSet<?>> dynamicSetsOf(Injector src) {
|
|
||||||
Map<TypeLiteral<?>, DynamicSet<?>> m = Maps.newHashMap();
|
|
||||||
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
|
||||||
TypeLiteral<?> type = e.getKey().getTypeLiteral();
|
|
||||||
if (type.getRawType() == DynamicSet.class) {
|
|
||||||
ParameterizedType p = (ParameterizedType) type.getType();
|
|
||||||
m.put(TypeLiteral.get(p.getActualTypeArguments()[0]),
|
|
||||||
(DynamicSet<?>) e.getValue().getProvider().get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Map<TypeLiteral<?>, DynamicMap<?>> dynamicMapsOf(Injector src) {
|
|
||||||
Map<TypeLiteral<?>, DynamicMap<?>> m = Maps.newHashMap();
|
|
||||||
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
|
||||||
TypeLiteral<?> type = e.getKey().getTypeLiteral();
|
|
||||||
if (type.getRawType() == DynamicMap.class) {
|
|
||||||
ParameterizedType p = (ParameterizedType) type.getType();
|
|
||||||
m.put(TypeLiteral.get(p.getActualTypeArguments()[0]),
|
|
||||||
(DynamicMap<?>) e.getValue().getProvider().get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Module copy(Injector src) {
|
private static Module copy(Injector src) {
|
||||||
Set<TypeLiteral<?>> dynamicTypes = Sets.newHashSet();
|
Set<TypeLiteral<?>> dynamicTypes = Sets.newHashSet();
|
||||||
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.sshd;
|
package com.google.gerrit.sshd;
|
||||||
|
|
||||||
import static com.google.inject.Scopes.SINGLETON;
|
import static com.google.inject.Scopes.SINGLETON;
|
||||||
|
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.registerInParentInjectors;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.gerrit.lifecycle.LifecycleModule;
|
import com.google.gerrit.lifecycle.LifecycleModule;
|
||||||
@@ -121,6 +122,7 @@ public class SshModule extends FactoryModule {
|
|||||||
.annotatedWith(UniqueAnnotations.create())
|
.annotatedWith(UniqueAnnotations.create())
|
||||||
.to(SshPluginStarterCallback.class);
|
.to(SshPluginStarterCallback.class);
|
||||||
|
|
||||||
|
listener().toInstance(registerInParentInjectors());
|
||||||
listener().to(SshLog.class);
|
listener().to(SshLog.class);
|
||||||
listener().to(SshDaemon.class);
|
listener().to(SshDaemon.class);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user