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

talsma-ict / context-propagation / #1454

28 Oct 2024 08:19PM CUT coverage: 84.389% (-10.3%) from 94.737%
#1454

Pull #510

sjoerdtalsma
Move ContextAwareCompletableFuture to core.concurrent package

Signed-off-by: Sjoerd Talsma <sjoerdtalsma@users.noreply.github.com>
Pull Request #510: Add deprecations

464 of 627 new or added lines in 32 files covered. (74.0%)

12 existing lines in 3 files now uncovered.

1119 of 1326 relevant lines covered (84.39%)

0.84 hits per line

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

66.67
/context-propagation/src/main/java/nl/talsmasoftware/context/core/PriorityServiceLoader.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.Iterator;
21
import java.util.List;
22
import java.util.Locale;
23
import java.util.Map;
24
import java.util.WeakHashMap;
25
import java.util.logging.Level;
26
import java.util.logging.Logger;
27

28
import static java.util.Collections.emptyList;
29
import static java.util.Collections.singletonList;
30
import static java.util.Collections.sort;
31
import static java.util.Collections.unmodifiableList;
32

33
/**
34
 * Loader class to delegate to JDK 6 {@code ServiceLoader} or fallback to the old
35
 * {@link javax.imageio.spi.ServiceRegistry ServiceRegistry}.
36
 *
37
 * @param <SVC> The type of service to load.
38
 * @author Sjoerd Talsma
39
 * @deprecated We will switch to plain ServiceLoader in next major version to reduce complexity.
40
 */
41
@Deprecated
42
final class PriorityServiceLoader<SVC> implements Iterable<SVC> {
43
    private static final Logger LOGGER = Logger.getLogger(PriorityServiceLoader.class.getName());
1✔
44
    private static final String SYSTEMPROPERTY_CACHING = "talsmasoftware.context.caching";
45
    private static final String ENVIRONMENT_CACHING_VALUE = System.getenv(
1✔
46
            SYSTEMPROPERTY_CACHING.replace('.', '_').toUpperCase(Locale.ENGLISH));
1✔
47

48
    // Set from ContextManagers.useClassLoader(); sometimes a single, fixed classloader may be necessary (e.g. #97)
49
    static volatile ClassLoader classLoaderOverride = null;
1✔
50
    private final Class<SVC> serviceType;
51
    private final Map<ClassLoader, List<SVC>> cache = new WeakHashMap<ClassLoader, List<SVC>>();
1✔
52

53
    PriorityServiceLoader(Class<SVC> serviceType) {
1✔
54
        if (serviceType == null) throw new NullPointerException("Service type is <null>.");
1✔
55
        this.serviceType = serviceType;
1✔
56
    }
1✔
57

58
    @SuppressWarnings("unchecked")
59
    public Iterator<SVC> iterator() {
60
        final ClassLoader classLoader =
1✔
61
                classLoaderOverride == null ? Thread.currentThread().getContextClassLoader() : classLoaderOverride;
1✔
62
        List<SVC> services = cache.get(classLoader);
1✔
63
        if (services == null) {
1✔
64
            services = findServices(classLoader);
1✔
65
            if (!isCachingDisabled()) cache.put(classLoader, services);
1✔
66
        }
67
        return services.iterator();
1✔
68
    }
69

70
    void replaceInCache(SVC current, SVC replacement) {
NEW
71
        final ClassLoader classLoader =
×
NEW
72
                classLoaderOverride == null ? Thread.currentThread().getContextClassLoader() : classLoaderOverride;
×
NEW
73
        List<SVC> services = cache.get(classLoader);
×
NEW
74
        if (services != null) {
×
NEW
75
            int idx = services.indexOf(current);
×
NEW
76
            if (idx >= 0) {
×
NEW
77
                ArrayList<SVC> copy = new ArrayList<SVC>(services);
×
NEW
78
                copy.set(idx, replacement);
×
NEW
79
                cache.put(classLoader, sortAndMakeUnmodifiable(copy));
×
80
            }
81
        }
NEW
82
    }
×
83

84
    /**
85
     * Remove the cache so the next call to {@linkplain #iterator()} will attempt to load the objects again.
86
     */
87
    void clearCache() {
88
        cache.clear();
1✔
89
    }
1✔
90

91
    private static boolean isCachingDisabled() {
92
        final String cachingProperty = System.getProperty(SYSTEMPROPERTY_CACHING, ENVIRONMENT_CACHING_VALUE);
1✔
93
        return "0".equals(cachingProperty) || "false".equalsIgnoreCase(cachingProperty);
1✔
94
    }
95

96
    private List<SVC> findServices(ClassLoader classLoader) {
97
        ArrayList<SVC> found = new ArrayList<SVC>();
1✔
98
        for (Iterator<SVC> iterator = loadServices(serviceType, classLoader); iterator.hasNext(); ) {
1✔
99
            SVC service = iterator.next();
1✔
100
            if (service != null) found.add(service);
1✔
101
        }
1✔
102
        return sortAndMakeUnmodifiable(found);
1✔
103
    }
104

105
    private static <T> List<T> sortAndMakeUnmodifiable(ArrayList<T> services) {
106
        if (services.isEmpty()) return emptyList();
1✔
107
        else if (services.size() == 1) return singletonList(services.get(0));
1✔
108
        else if (PriorityComparator.PRIORITY_AVAILABLE) sort(services, PriorityComparator.INSTANCE);
1✔
109
        services.trimToSize();
1✔
110
        return unmodifiableList(services);
1✔
111
    }
112

113
    @SuppressWarnings("Since15")
114
    private static <SVC> Iterator<SVC> loadServices(Class<SVC> serviceType, ClassLoader classLoader) {
115
        try {
116
            return java.util.ServiceLoader.load(serviceType, classLoader).iterator();
1✔
NEW
117
        } catch (LinkageError le) {
×
NEW
118
            LOGGER.log(Level.FINEST, "No ServiceLoader available, probably running on Java 1.5.", le);
×
NEW
119
            return javax.imageio.spi.ServiceRegistry.lookupProviders(serviceType);
×
NEW
120
        } catch (RuntimeException loadingException) {
×
NEW
121
            LOGGER.log(Level.WARNING, "Unexpected error loading services of " + serviceType, loadingException);
×
NEW
122
            return Collections.<SVC>emptySet().iterator();
×
123
        }
124
    }
125

126
}
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

© 2025 Coveralls, Inc