xref: /aosp_15_r20/external/dagger2/java/dagger/producers/internal/AbstractProducesMethodProducer.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2018 The Dagger Authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package dagger.producers.internal;
18 
19 import static dagger.internal.Preconditions.checkNotNull;
20 import static dagger.internal.Providers.asDaggerProvider;
21 
22 import com.google.common.util.concurrent.AsyncFunction;
23 import com.google.common.util.concurrent.Futures;
24 import com.google.common.util.concurrent.ListenableFuture;
25 import dagger.internal.Provider;
26 import dagger.producers.monitoring.ProducerMonitor;
27 import dagger.producers.monitoring.ProducerToken;
28 import dagger.producers.monitoring.ProductionComponentMonitor;
29 import java.util.concurrent.Executor;
30 import org.checkerframework.checker.nullness.compatqual.NullableDecl;
31 
32 /**
33  * An {@link AbstractProducer} for all {@link dagger.producers.Produces} methods.
34  *
35  * @param <D> the type of asynchronous dependencies. These will be collected in {@link
36  *     #collectDependencies()} and then made available to the {@code @Produces method in} {@link
37  *     #callProducesMethod(Object)}. If there is only one asynchronous dependency, {@code D} can be
38  *     the key for that dependency. If there are multiple, they should be wrapped in a list and
39  *     unwrapped in {@link #callProducesMethod(Object)}.
40  * @param <T> the produced type
41  */
42 public abstract class AbstractProducesMethodProducer<D, T> extends AbstractProducer<T>
43     implements AsyncFunction<D, T>, Executor {
44   private final Provider<ProductionComponentMonitor> monitorProvider;
45   @NullableDecl private final ProducerToken token;
46   private final Provider<Executor> executorProvider;
47   private volatile ProducerMonitor monitor = null;
48 
AbstractProducesMethodProducer( Provider<ProductionComponentMonitor> monitorProvider, @NullableDecl ProducerToken token, Provider<Executor> executorProvider)49   protected AbstractProducesMethodProducer(
50       Provider<ProductionComponentMonitor> monitorProvider,
51       @NullableDecl ProducerToken token,
52       Provider<Executor> executorProvider) {
53     this.monitorProvider = checkNotNull(monitorProvider);
54     this.token = token;
55     this.executorProvider = checkNotNull(executorProvider);
56   }
57 
58   /**
59    * Legacy javax version of the method to support libraries compiled with an older version of
60    * Dagger. Do not use directly.
61    */
62   @Deprecated
AbstractProducesMethodProducer( javax.inject.Provider<ProductionComponentMonitor> monitorProvider, @NullableDecl ProducerToken token, javax.inject.Provider<Executor> executorProvider)63   protected AbstractProducesMethodProducer(
64       javax.inject.Provider<ProductionComponentMonitor> monitorProvider,
65       @NullableDecl ProducerToken token,
66       javax.inject.Provider<Executor> executorProvider) {
67     this(asDaggerProvider(monitorProvider), token, asDaggerProvider(executorProvider));
68   }
69 
70   @Override
compute()71   protected final ListenableFuture<T> compute() {
72     monitor = monitorProvider.get().producerMonitorFor(token);
73     monitor.requested();
74     ListenableFuture<T> result = Futures.transformAsync(collectDependencies(), this, this);
75     monitor.addCallbackTo(result);
76     return result;
77   }
78 
79   /**
80    * Collects the asynchronous dependencies to be passed to {@link
81    * Futures#transformAsync(ListenableFuture, AsyncFunction, Executor)}.
82    */
collectDependencies()83   protected abstract ListenableFuture<D> collectDependencies();
84 
85   /** @deprecated this may only be called from the internal {@link #compute()} */
86   @Deprecated
87   @Override
apply(D asyncDependencies)88   public final ListenableFuture<T> apply(D asyncDependencies) throws Exception {
89     // NOTE(beder): We don't worry about catching exceptions from the monitor methods themselves
90     // because we'll wrap all monitoring in non-throwing monitors before we pass them to the
91     // factories.
92     monitor.methodStarting();
93     try {
94       return callProducesMethod(asyncDependencies);
95     } finally {
96       monitor.methodFinished();
97     }
98   }
99 
100   /**
101    * Calls the {@link dagger.producers.Produces} method. This will always be called on the {@link
102    * Executor} provided to this producer.
103    */
callProducesMethod(D asyncDependencies)104   protected abstract ListenableFuture<T> callProducesMethod(D asyncDependencies) throws Exception;
105 
106   /** @deprecated this may only be called from the internal {@link #compute()} */
107   @Deprecated
108   @Override
execute(Runnable runnable)109   public final void execute(Runnable runnable) {
110     monitor.ready();
111     executorProvider.get().execute(runnable);
112   }
113 }
114