Merge changes I2f989c94,I5f4074a3,I21db4f14

* changes:
  Filter out types used in DynamicItem when copying bindings to plugins
  Allow plugins to replace gerrit-provided hot-replaceable DynamicItem, too
  Restore gerrit-provided DynamicItem when plugin unloads
This commit is contained in:
Shawn Pearce 2014-03-26 23:59:42 +00:00 committed by Gerrit Code Review
commit 9db362f564
2 changed files with 24 additions and 18 deletions

View File

@ -149,24 +149,21 @@ public class DynamicItem<T> {
*/
public RegistrationHandle set(Provider<T> impl, String pluginName) {
final NamedProvider<T> item = new NamedProvider<T>(impl, pluginName);
while (!ref.compareAndSet(null, item)) {
NamedProvider<T> old = ref.get();
if (old != null) {
if ("gerrit".equals(old.pluginName)) {
if (ref.compareAndSet(old, item)) {
break;
}
old = ref.get();
}
NamedProvider<T> old = null;
while (!ref.compareAndSet(old, item)) {
old = ref.get();
if (old != null && !"gerrit".equals(old.pluginName)) {
throw new ProvisionException(String.format(
"%s already provided by %s, ignoring plugin %s",
key.getTypeLiteral(), old.pluginName, pluginName));
}
}
final NamedProvider<T> defaultItem = old;
return new RegistrationHandle() {
@Override
public void remove() {
ref.compareAndSet(item, null);
ref.compareAndSet(item, defaultItem);
}
};
}
@ -184,24 +181,27 @@ public class DynamicItem<T> {
public ReloadableRegistrationHandle<T> set(Key<T> key, Provider<T> impl,
String pluginName) {
final NamedProvider<T> item = new NamedProvider<T>(impl, pluginName);
while (!ref.compareAndSet(null, item)) {
NamedProvider<T> old = ref.get();
if (old != null) {
NamedProvider<T> old = null;
while (!ref.compareAndSet(old, item)) {
old = ref.get();
if (old != null && !"gerrit".equals(old.pluginName)) {
throw new ProvisionException(String.format(
"%s already provided by %s, ignoring plugin %s",
this.key.getTypeLiteral(), old.pluginName, pluginName));
}
}
return new ReloadableHandle(key, item);
return new ReloadableHandle(key, item, old);
}
private class ReloadableHandle implements ReloadableRegistrationHandle<T> {
private final Key<T> key;
private final NamedProvider<T> item;
private final NamedProvider<T> defaultItem;
ReloadableHandle(Key<T> key, NamedProvider<T> item) {
ReloadableHandle(Key<T> key, NamedProvider<T> item, NamedProvider<T> defaultItem) {
this.key = key;
this.item = item;
this.defaultItem = defaultItem;
}
@Override
@ -211,14 +211,14 @@ public class DynamicItem<T> {
@Override
public void remove() {
ref.compareAndSet(item, null);
ref.compareAndSet(item, defaultItem);
}
@Override
public ReloadableHandle replace(Key<T> newKey, Provider<T> newItem) {
NamedProvider<T> n = new NamedProvider<T>(newItem, item.pluginName);
if (ref.compareAndSet(item, n)) {
return new ReloadableHandle(newKey, n);
return new ReloadableHandle(newKey, n, defaultItem);
}
return null;
}

View File

@ -469,9 +469,13 @@ public class PluginGuiceEnvironment {
private Module copy(Injector src) {
Set<TypeLiteral<?>> dynamicTypes = Sets.newHashSet();
Set<TypeLiteral<?>> dynamicItemTypes = Sets.newHashSet();
for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
TypeLiteral<?> type = e.getKey().getTypeLiteral();
if (type.getRawType() == DynamicSet.class
if (type.getRawType() == DynamicItem.class) {
ParameterizedType t = (ParameterizedType) type.getType();
dynamicItemTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
} else if (type.getRawType() == DynamicSet.class
|| type.getRawType() == DynamicMap.class) {
ParameterizedType t = (ParameterizedType) type.getType();
dynamicTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
@ -488,6 +492,8 @@ public class PluginGuiceEnvironment {
// using DynamicSet<F> or DynamicMap<F> internally. That should be
// exported to plugins.
continue;
} else if (dynamicItemTypes.contains(e.getKey().getTypeLiteral())) {
continue;
} else if (shouldCopy(e.getKey())) {
bindings.put(e.getKey(), e.getValue());
}