| // Copyright (C) 2009 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.lifecycle; |
| |
| import static com.google.common.base.Preconditions.checkState; |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.flogger.FluentLogger; |
| import com.google.gerrit.extensions.events.LifecycleListener; |
| import com.google.gerrit.extensions.registration.RegistrationHandle; |
| import com.google.inject.Binding; |
| import com.google.inject.Injector; |
| import com.google.inject.Provider; |
| import com.google.inject.TypeLiteral; |
| import com.google.inject.util.Providers; |
| import java.util.List; |
| |
| /** Tracks and executes registered {@link LifecycleListener}s. */ |
| public class LifecycleManager { |
| private static final FluentLogger logger = FluentLogger.forEnclosingClass(); |
| |
| private final List<Provider<LifecycleListener>> listeners = newList(); |
| private final List<RegistrationHandle> handles = newList(); |
| |
| /** Index of the last listener to start successfully; -1 when not started. */ |
| private int startedIndex = -1; |
| |
| /** |
| * Add a handle that must be cleared during stop. |
| * |
| * @param handle the handle to add. |
| */ |
| public void add(RegistrationHandle handle) { |
| handles.add(handle); |
| } |
| |
| /** |
| * Add a single listener. |
| * |
| * @param listener the listener to add. |
| */ |
| public void add(LifecycleListener listener) { |
| listeners.add(Providers.of(listener)); |
| } |
| |
| /** |
| * Add a single listener. |
| * |
| * @param listener the listener to add. |
| */ |
| public void add(Provider<LifecycleListener> listener) { |
| listeners.add(listener); |
| } |
| |
| /** |
| * Add all {@link LifecycleListener}s registered in the Injector. |
| * |
| * @param injector the injector to add. |
| */ |
| public void add(Injector injector) { |
| checkState(startedIndex < 0, "Already started"); |
| for (Binding<LifecycleListener> binding : get(injector)) { |
| add(binding.getProvider()); |
| } |
| } |
| |
| /** |
| * Add all {@link LifecycleListener}s registered in the Injectors. |
| * |
| * @param injectors the injectors to add. |
| */ |
| public void add(Injector... injectors) { |
| for (Injector i : injectors) { |
| add(i); |
| } |
| } |
| |
| /** Start all listeners, in the order they were registered. */ |
| public void start() { |
| for (int i = startedIndex + 1; i < listeners.size(); i++) { |
| LifecycleListener listener = listeners.get(i).get(); |
| startedIndex = i; |
| listener.start(); |
| } |
| } |
| |
| /** Stop all listeners, in the reverse order they were registered. */ |
| public void stop() { |
| for (int i = handles.size() - 1; 0 <= i; i--) { |
| handles.get(i).remove(); |
| } |
| handles.clear(); |
| |
| for (int i = startedIndex; 0 <= i; i--) { |
| LifecycleListener obj = listeners.get(i).get(); |
| try { |
| obj.stop(); |
| } catch (RuntimeException err) { |
| logger.atWarning().withCause(err).log("Failed to stop %s", obj.getClass()); |
| } |
| startedIndex = i - 1; |
| } |
| } |
| |
| private static List<Binding<LifecycleListener>> get(Injector i) { |
| return i.findBindingsByType(new TypeLiteral<LifecycleListener>() {}); |
| } |
| |
| private static <T> List<T> newList() { |
| return Lists.newArrayListWithCapacity(4); |
| } |
| } |