// 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<?>, DynamicItem<?>> dynamicItemsOf(Injector src) { Map<TypeLiteral<?>, DynamicItem<?>> m = new HashMap<>(); for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) { TypeLiteral<?> type = e.getKey().getTypeLiteral(); if (type.getRawType() == DynamicItem.class) { ParameterizedType p = (ParameterizedType) type.getType(); m.put(TypeLiteral.get(p.getActualTypeArguments()[0]), (DynamicItem<?>) e.getValue().getProvider().get()); } } if (m.isEmpty()) { return Collections.emptyMap(); } return Collections.unmodifiableMap(m); } public static Map<TypeLiteral<?>, DynamicSet<?>> dynamicSetsOf(Injector src) { Map<TypeLiteral<?>, DynamicSet<?>> m = new HashMap<>(); 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 = new HashMap<>(); 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> attachItems( Injector src, Map<TypeLiteral<?>, DynamicItem<?>> items, String pluginName) { if (src == null || items == null || items.isEmpty()) { return Collections.emptyList(); } List<RegistrationHandle> handles = new ArrayList<>(4); try { for (Map.Entry<TypeLiteral<?>, DynamicItem<?>> e : items.entrySet()) { @SuppressWarnings("unchecked") TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey(); @SuppressWarnings("unchecked") DynamicItem<Object> item = (DynamicItem<Object>) e.getValue(); for (Binding<Object> b : bindings(src, type)) { handles.add(item.set(b.getKey(), b.getProvider(), pluginName)); } } } catch (RuntimeException e) { remove(handles); throw e; } catch (Error e) { remove(handles); throw e; } return handles; } 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<>(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)) { if (b.getKey().getAnnotation() != null) { 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<>(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)) { if (b.getKey().getAnnotation() != null) { 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<>(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 <T> List<Binding<T>> bindings(Injector src, TypeLiteral<T> type) { return src.findBindingsByType(type); } }