Remove unneeded doc dependency
[mdsal.git] / binding / mdsal-binding-dom-codec / src / main / java / org / opendaylight / mdsal / binding / dom / codec / loader / LeafCodecClassLoader.java
1 /*
2  * Copyright (c) 2019 PANTHEON.tech, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.mdsal.binding.dom.codec.loader;
9
10 import static com.google.common.base.Verify.verify;
11 import static java.util.Objects.requireNonNull;
12
13 import com.google.common.collect.ImmutableSet;
14 import java.util.ArrayList;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
21
22 // A leaf class loader, binding together a root class loader and some other class loader
23 final class LeafCodecClassLoader extends CodecClassLoader {
24     static {
25         verify(registerAsParallelCapable());
26     }
27
28     private static final Logger LOG = LoggerFactory.getLogger(LeafCodecClassLoader.class);
29
30     private final @NonNull RootCodecClassLoader root;
31     private final @NonNull ClassLoader target;
32
33     @SuppressWarnings("rawtypes")
34     private static final AtomicReferenceFieldUpdater<LeafCodecClassLoader, ImmutableSet> DEPENDENCIES_UPDATER =
35             AtomicReferenceFieldUpdater.newUpdater(LeafCodecClassLoader.class, ImmutableSet.class, "dependencies");
36     private volatile ImmutableSet<LeafCodecClassLoader> dependencies = ImmutableSet.of();
37
38     LeafCodecClassLoader(final RootCodecClassLoader root, final ClassLoader target) {
39         super(root);
40         this.root = requireNonNull(root);
41         this.target = requireNonNull(target);
42     }
43
44     @Override
45     protected Class<?> findClass(final String name) throws ClassNotFoundException {
46         try {
47             return target.loadClass(name);
48         } catch (ClassNotFoundException e) {
49             LOG.trace("Class {} not found in target, looking through dependencies", name);
50             for (LeafCodecClassLoader loader : dependencies) {
51                 // Careful: a loading operation may be underway, make sure that process has completed
52                 synchronized (loader.getClassLoadingLock(name)) {
53                     final Class<?> loaded = loader.findLoadedClass(name);
54                     if (loaded != null) {
55                         LOG.trace("Class {} found in dependency {}", name, loader);
56                         return loaded;
57                     }
58                 }
59             }
60
61             throw e;
62         }
63     }
64
65     @Override
66     CodecClassLoader findClassLoader(final Class<?> bindingClass) {
67         final ClassLoader bindingTarget = bindingClass.getClassLoader();
68         return target.equals(bindingTarget) ? this : root.findClassLoader(bindingClass);
69     }
70
71     @Override
72     void appendLoaders(final Set<LeafCodecClassLoader> newLoaders) {
73         while (true) {
74             final ImmutableSet<LeafCodecClassLoader> local = dependencies;
75             final List<LeafCodecClassLoader> builder = new ArrayList<>(local.size() + newLoaders.size());
76             builder.addAll(local);
77             builder.addAll(newLoaders);
78             final ImmutableSet<LeafCodecClassLoader> updated = ImmutableSet.copyOf(builder);
79             if (local.equals(updated) || DEPENDENCIES_UPDATER.compareAndSet(this, local, updated)) {
80                 // No need for an update or the update was successful
81                 return;
82             }
83         }
84     }
85 }