• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

grpc / grpc-java / #20152

20 Jan 2026 04:00PM UTC coverage: 88.666% (-0.007%) from 88.673%
#20152

push

github

ejona86
api: Remove unused ServiceProviders.load()

load() unused since c8a94d105 in 2020.

35345 of 39863 relevant lines covered (88.67%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.89
/../api/src/main/java/io/grpc/ServiceProviders.java
1
/*
2
 * Copyright 2017 The gRPC 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 io.grpc;
18

19
import com.google.common.annotations.VisibleForTesting;
20
import java.util.ArrayList;
21
import java.util.Collections;
22
import java.util.Comparator;
23
import java.util.List;
24
import java.util.ServiceConfigurationError;
25
import java.util.ServiceLoader;
26

27
final class ServiceProviders {
28
  private ServiceProviders() {
29
    // do not instantiate
30
  }
31

32
  /**
33
   * If this is not Android, returns all available implementations discovered via
34
   * {@link ServiceLoader}.
35
   * If this is Android, returns all available implementations in {@code hardcoded}.
36
   * The list is sorted in descending priority order.
37
   */
38
  public static <T> List<T> loadAll(
39
      Class<T> klass,
40
      Iterable<Class<?>> hardcoded,
41
      ClassLoader cl,
42
      final PriorityAccessor<T> priorityAccessor) {
43
    Iterable<T> candidates;
44
    if (isAndroid(cl)) {
1✔
45
      candidates = getCandidatesViaHardCoded(klass, hardcoded);
×
46
    } else {
47
      candidates = getCandidatesViaServiceLoader(klass, cl);
1✔
48
    }
49
    List<T> list = new ArrayList<>();
1✔
50
    for (T current: candidates) {
1✔
51
      if (!priorityAccessor.isAvailable(current)) {
1✔
52
        continue;
1✔
53
      }
54
      list.add(current);
1✔
55
    }
1✔
56

57
    // Sort descending based on priority.  If priorities are equal, compare the class names to
58
    // get a reliable result.
59
    Collections.sort(list, Collections.reverseOrder(new Comparator<T>() {
1✔
60
      @Override
61
      public int compare(T f1, T f2) {
62
        int pd = priorityAccessor.getPriority(f1) - priorityAccessor.getPriority(f2);
1✔
63
        if (pd != 0) {
1✔
64
          return pd;
1✔
65
        }
66
        return f1.getClass().getName().compareTo(f2.getClass().getName());
1✔
67
      }
68
    }));
69
    return Collections.unmodifiableList(list);
1✔
70
  }
71

72
  /**
73
   * Returns true if the {@link ClassLoader} is for android.
74
   */
75
  static boolean isAndroid(ClassLoader cl) {
76
    try {
77
      // Specify a class loader instead of null because we may be running under Robolectric
78
      Class.forName("android.app.Application", /*initialize=*/ false, cl);
×
79
      return true;
×
80
    } catch (Exception e) {
1✔
81
      // If Application isn't loaded, it might as well not be Android.
82
      return false;
1✔
83
    }
84
  }
85

86
  /**
87
   * Loads service providers for the {@code klass} service using {@link ServiceLoader}.
88
   */
89
  @VisibleForTesting
90
  public static <T> Iterable<T> getCandidatesViaServiceLoader(Class<T> klass, ClassLoader cl) {
91
    Iterable<T> i = ServiceLoader.load(klass, cl);
1✔
92
    // Attempt to load using the context class loader and ServiceLoader.
93
    // This allows frameworks like http://aries.apache.org/modules/spi-fly.html to plug in.
94
    if (!i.iterator().hasNext()) {
1✔
95
      i = ServiceLoader.load(klass);
1✔
96
    }
97
    return i;
1✔
98
  }
99

100
  /**
101
   * Load providers from a hard-coded list. This avoids using getResource(), which has performance
102
   * problems on Android (see https://github.com/grpc/grpc-java/issues/2037).
103
   */
104
  @VisibleForTesting
105
  static <T> Iterable<T> getCandidatesViaHardCoded(Class<T> klass, Iterable<Class<?>> hardcoded) {
106
    List<T> list = new ArrayList<>();
1✔
107
    for (Class<?> candidate : hardcoded) {
1✔
108
      T t = createForHardCoded(klass, candidate);
1✔
109
      if (t == null) {
1✔
110
        continue;
1✔
111
      }
112
      list.add(t);
1✔
113
    }
1✔
114
    return list;
1✔
115
  }
116

117
  private static <T> T createForHardCoded(Class<T> klass, Class<?> rawClass) {
118
    try {
119
      return rawClass.asSubclass(klass).getConstructor().newInstance();
1✔
120
    } catch (ClassCastException ex) {
1✔
121
      // Tools like Proguard that perform obfuscation rewrite strings only when the class they
122
      // reference is known, as otherwise they wouldn't know its new name. This means some
123
      // hard-coded Class.forNames() won't be rewritten. This can cause ClassCastException at
124
      // runtime if the class ends up appearing on the classpath but that class is part of a
125
      // separate copy of grpc. With tools like Maven Shade Plugin the class wouldn't be found at
126
      // all and so would be skipped. We want to skip in this case as well.
127
      return null;
1✔
128
    } catch (Throwable t) {
1✔
129
      throw new ServiceConfigurationError(
1✔
130
          String.format("Provider %s could not be instantiated %s", rawClass.getName(), t), t);
1✔
131
    }
132
  }
133

134
  /**
135
   * An interface that allows us to get priority information about a provider.
136
   */
137
  public interface PriorityAccessor<T> {
138
    /**
139
     * Checks this provider is available for use, taking the current environment into consideration.
140
     * If {@code false}, no other methods are safe to be called.
141
     */
142
    boolean isAvailable(T provider);
143

144
    /**
145
     * A priority, from 0 to 10 that this provider should be used, taking the current environment
146
     * into consideration. 5 should be considered the default, and then tweaked based on environment
147
     * detection. A priority of 0 does not imply that the provider wouldn't work; just that it
148
     * should be last in line.
149
     */
150
    int getPriority(T provider);
151
  }
152
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc