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

talsma-ict / context-propagation / #1555

08 Nov 2024 01:56PM UTC coverage: 94.898% (+3.2%) from 91.679%
#1555

Pull #515

sjoerdtalsma
Replace several fully qualified names by simple names + import.

Signed-off-by: Sjoerd Talsma <sjoerdtalsma@users.noreply.github.com>
Pull Request #515: Cleanup deprecations to develop next major version (v2)

256 of 282 new or added lines in 27 files covered. (90.78%)

837 of 882 relevant lines covered (94.9%)

0.95 hits per line

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

95.65
/context-propagation-core/src/main/java/nl/talsmasoftware/context/core/ServiceCache.java
1
/*
2
 * Copyright 2016-2024 Talsma ICT
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
package nl.talsmasoftware.context.core;
17

18
import java.util.ArrayList;
19
import java.util.Collections;
20
import java.util.List;
21
import java.util.ServiceLoader;
22
import java.util.concurrent.ConcurrentHashMap;
23
import java.util.concurrent.ConcurrentMap;
24
import java.util.logging.Logger;
25

26
/**
27
 * Cache for resolved services.
28
 *
29
 * <p>
30
 * This is required because the ServiceLoader itself is not thread-safe due to its internal lazy iterator.
31
 */
NEW
32
class ServiceCache {
×
33
    private static final Logger LOGGER = Logger.getLogger(ServiceCache.class.getName());
1✔
34

35
    /**
36
     * Internal concurrent map as cache.
37
     */
38
    @SuppressWarnings("rawtypes")
39
    private static final ConcurrentMap<Class, List> CACHE = new ConcurrentHashMap<>();
1✔
40

41
    /**
42
     * Sometimes a single, fixed classloader may be necessary (e.g. #97)
43
     */
44
    private static volatile ClassLoader classLoaderOverride = null;
1✔
45

46
    static synchronized void useClassLoader(ClassLoader classLoader) {
47
        if (classLoaderOverride == classLoader) {
1✔
48
            LOGGER.finest(() -> "Maintaining classloader override as " + classLoader + " (unchanged)");
1✔
49
            return;
1✔
50
        }
51
        LOGGER.fine(() -> "Updating classloader override to " + classLoader + " (was: " + classLoaderOverride + ")");
1✔
52
        classLoaderOverride = classLoader;
1✔
53
        CACHE.clear();
1✔
54
    }
1✔
55

56
    @SuppressWarnings("unchecked")
57
    static <T> List<T> cached(Class<T> serviceClass) {
58
        return (List<T>) CACHE.computeIfAbsent(serviceClass, ServiceCache::load);
1✔
59
    }
60

61
    static void clear() {
62
        CACHE.clear();
1✔
63
    }
1✔
64

65
    /**
66
     * Loads the service implementations of the requested type.
67
     *
68
     * <p>
69
     * This method is synchronized because ServiceLoader is not thread-safe.
70
     * Fortunately this only gets called after a cache miss, so should not affect performance.
71
     *
72
     * <p>
73
     * The returned {@code List} will be {@linkplain Collections#unmodifiableList(List) unmodifiable}.
74
     *
75
     * @param serviceType The service type to load.
76
     * @param <T>         The service type to load.
77
     * @return Unmodifiable list of service implementations.
78
     */
79
    private synchronized static <T> List<T> load(Class<T> serviceType) {
80
        final ArrayList<T> services = new ArrayList<>();
1✔
81
        final ServiceLoader<T> loader = classLoaderOverride == null
1✔
82
                ? ServiceLoader.load(serviceType)
1✔
83
                : ServiceLoader.load(serviceType, classLoaderOverride);
1✔
84
        for (T service : loader) {
1✔
85
            services.add(service);
1✔
86
        }
1✔
87
        services.trimToSize();
1✔
88
        // TODO debug logging
89
        return Collections.unmodifiableList(services);
1✔
90
    }
91
}
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