2 * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.mdsal.binding.dom.codec.loader;
10 import static com.google.common.base.Verify.verify;
12 import com.google.common.collect.ImmutableMap;
13 import com.google.common.collect.ImmutableMap.Builder;
14 import java.security.AccessController;
15 import java.security.PrivilegedAction;
16 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
17 import org.slf4j.Logger;
18 import org.slf4j.LoggerFactory;
20 // A root codec classloader, binding only whatever is available StaticClassPool
21 final class RootCodecClassLoader extends CodecClassLoader {
22 private static final Logger LOG = LoggerFactory.getLogger(RootCodecClassLoader.class);
25 verify(registerAsParallelCapable());
28 @SuppressWarnings("rawtypes")
29 private static final AtomicReferenceFieldUpdater<RootCodecClassLoader, ImmutableMap> LOADERS_UPDATER =
30 AtomicReferenceFieldUpdater.newUpdater(RootCodecClassLoader.class, ImmutableMap.class, "loaders");
32 private volatile ImmutableMap<ClassLoader, CodecClassLoader> loaders = ImmutableMap.of();
34 RootCodecClassLoader() {
39 CodecClassLoader findClassLoader(final Class<?> bindingClass) {
40 final ClassLoader target = bindingClass.getClassLoader();
42 // No class loader associated ... well, let's use root then
47 ImmutableMap<ClassLoader, CodecClassLoader> local = loaders;
48 final CodecClassLoader known = local.get(target);
53 // Alright, we need to determine if the class is accessible through our hierarchy (in which case we use
54 // ourselves) or we need to create a new Leaf.
55 final CodecClassLoader found;
56 if (!isOurClass(bindingClass)) {
57 StaticClassPool.verifyStaticLinkage(target);
58 found = AccessController.doPrivileged(
59 (PrivilegedAction<CodecClassLoader>)() -> new LeafCodecClassLoader(this, target));
64 // Now make sure we cache this result
66 final Builder<ClassLoader, CodecClassLoader> builder = ImmutableMap.builderWithExpectedSize(
68 builder.putAll(local);
69 builder.put(target, found);
71 if (LOADERS_UPDATER.compareAndSet(this, local, builder.build())) {
76 final CodecClassLoader recheck = local.get(target);
77 if (recheck != null) {
83 private boolean isOurClass(final Class<?> bindingClass) {
84 final Class<?> ourClass;
86 ourClass = loadClass(bindingClass.getName(), false);
87 } catch (ClassNotFoundException e) {
88 LOG.debug("Failed to load {}", bindingClass, e);
91 return bindingClass.equals(ourClass);