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;
11 import static java.util.Objects.requireNonNull;
13 import com.google.common.collect.ImmutableSet;
14 import java.util.ArrayList;
15 import java.util.List;
17 import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory;
22 // A leaf class loader, binding together a root class loader and some other class loader
23 final class LeafCodecClassLoader extends CodecClassLoader {
25 verify(registerAsParallelCapable());
28 private static final Logger LOG = LoggerFactory.getLogger(LeafCodecClassLoader.class);
30 private final @NonNull RootCodecClassLoader root;
31 private final @NonNull ClassLoader target;
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();
38 LeafCodecClassLoader(final RootCodecClassLoader root, final ClassLoader target) {
40 this.root = requireNonNull(root);
41 this.target = requireNonNull(target);
45 protected Class<?> findClass(final String name) throws ClassNotFoundException {
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 final Class<?> loaded = loader.findLoadedClass(name);
53 LOG.trace("Class {} found in dependency {}", name, loader);
63 CodecClassLoader findClassLoader(final Class<?> bindingClass) {
64 final ClassLoader bindingTarget = bindingClass.getClassLoader();
65 return target.equals(bindingTarget) ? this : root.findClassLoader(bindingClass);
69 void appendLoaders(final Set<LeafCodecClassLoader> newLoaders) {
71 final ImmutableSet<LeafCodecClassLoader> local = dependencies;
72 final List<LeafCodecClassLoader> builder = new ArrayList<>(local.size() + newLoaders.size());
73 builder.addAll(local);
74 builder.addAll(newLoaders);
75 final ImmutableSet<LeafCodecClassLoader> updated = ImmutableSet.copyOf(builder);
76 if (local.equals(updated) || DEPENDENCIES_UPDATER.compareAndSet(this, local, updated)) {
77 // No need for an update or the update was successful