| // 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); | |
| } | |
| } |