import static java.util.Objects.requireNonNull;
import com.google.common.base.MoreObjects;
-import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
-import com.google.common.util.concurrent.ListenableFuture;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.IOException;
import java.util.ArrayList;
* Note this class has some locking quirks and may end up being further refactored.
*/
abstract class AbstractModuleInfoTracker implements Mutable {
- abstract static class AbstractRegisteredModuleInfo {
+ private static final class RegisteredModuleInfo {
final YangTextSchemaSourceRegistration reg;
final YangModuleInfo info;
final ClassLoader loader;
- AbstractRegisteredModuleInfo(final YangModuleInfo info, final YangTextSchemaSourceRegistration reg,
+ private int refcount = 1;
+
+ RegisteredModuleInfo(final YangModuleInfo info, final YangTextSchemaSourceRegistration reg,
final ClassLoader loader) {
this.info = requireNonNull(info);
this.reg = requireNonNull(reg);
this.loader = requireNonNull(loader);
}
- @Override
- public final String toString() {
- return addToStringAttributes(MoreObjects.toStringHelper(this)).toString();
- }
-
- ToStringHelper addToStringAttributes(final ToStringHelper helper) {
- return helper.add("info", info).add("registration", reg).add("classLoader", loader);
- }
- }
-
- private static final class ExplicitRegisteredModuleInfo extends AbstractRegisteredModuleInfo {
- private int refcount = 1;
-
- ExplicitRegisteredModuleInfo(final YangModuleInfo info, final YangTextSchemaSourceRegistration reg,
- final ClassLoader loader) {
- super(info, reg, loader);
- }
-
void incRef() {
++refcount;
}
}
@Override
- ToStringHelper addToStringAttributes(final ToStringHelper helper) {
- return super.addToStringAttributes(helper).add("refCount", refcount);
- }
- }
-
- private static final class ImplicitRegisteredModuleInfo extends AbstractRegisteredModuleInfo {
- ImplicitRegisteredModuleInfo(final YangModuleInfo info, final YangTextSchemaSourceRegistration reg,
- final ClassLoader loader) {
- super(info, reg, loader);
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("info", info).add("registration", reg)
+ .add("classLoader", loader).add("refCount", refcount).toString();
}
}
private final YangTextSchemaContextResolver ctxResolver;
@GuardedBy("this")
- private final ListMultimap<String, AbstractRegisteredModuleInfo> packageToInfoReg =
- MultimapBuilder.hashKeys().arrayListValues().build();
- @GuardedBy("this")
- private final ListMultimap<SourceIdentifier, AbstractRegisteredModuleInfo> sourceToInfoReg =
+ private final ListMultimap<SourceIdentifier, RegisteredModuleInfo> sourceToInfoReg =
MultimapBuilder.hashKeys().arrayListValues().build();
@GuardedBy("this")
private @Nullable ModuleInfoSnapshot currentSnapshot;
@Holding("this")
private ObjectRegistration<YangModuleInfo> register(final @NonNull YangModuleInfo moduleInfo) {
- final Builder<ExplicitRegisteredModuleInfo> regBuilder = ImmutableList.builder();
+ final Builder<RegisteredModuleInfo> regBuilder = ImmutableList.builder();
for (YangModuleInfo info : flatDependencies(moduleInfo)) {
- regBuilder.add(registerExplicitModuleInfo(info));
+ regBuilder.add(registerModuleInfo(info));
}
- final ImmutableList<ExplicitRegisteredModuleInfo> regInfos = regBuilder.build();
+ final ImmutableList<RegisteredModuleInfo> regInfos = regBuilder.build();
return new AbstractObjectRegistration<>(moduleInfo) {
@Override
};
}
- @Holding("this")
- final void registerImplicitBindingClass(final Class<?> bindingClass) {
- registerImplicitModuleInfo(BindingRuntimeHelpers.extractYangModuleInfo(bindingClass));
- }
-
- @Holding("this")
- final @Nullable ClassLoader findClassLoader(final String fullyQualifiedName) {
- // This performs an explicit check for binding classes
- final String modulePackageName = BindingReflections.getModelRootPackageName(fullyQualifiedName);
-
- // Try to find a loaded class loader
- // FIXME: two-step process, try explicit registrations first
- for (AbstractRegisteredModuleInfo reg : packageToInfoReg.get(modulePackageName)) {
- return reg.loader;
- }
- return null;
- }
-
- /*
- * Perform implicit registration of a YangModuleInfo and any of its dependencies. If there is a registration for
- * a particular source, we do not create a duplicate registration.
- */
- @Holding("this")
- private void registerImplicitModuleInfo(final @NonNull YangModuleInfo moduleInfo) {
- for (YangModuleInfo info : flatDependencies(moduleInfo)) {
- final Class<?> infoClass = info.getClass();
- final SourceIdentifier sourceId = sourceIdentifierFrom(info);
- if (sourceToInfoReg.containsKey(sourceId)) {
- LOG.debug("Skipping implicit registration of {} as source {} is already registered", info, sourceId);
- continue;
- }
-
- final YangTextSchemaSourceRegistration reg;
- try {
- reg = ctxResolver.registerSource(toYangTextSource(sourceId, info));
- } catch (YangSyntaxErrorException | SchemaSourceException | IOException e) {
- LOG.warn("Failed to register info {} source {}, ignoring it", info, sourceId, e);
- continue;
- }
-
- final ImplicitRegisteredModuleInfo regInfo = new ImplicitRegisteredModuleInfo(info, reg,
- infoClass.getClassLoader());
- sourceToInfoReg.put(sourceId, regInfo);
- packageToInfoReg.put(BindingReflections.getModelRootPackageName(infoClass.getPackage()), regInfo);
- }
- }
-
/*
- * Perform explicit registration of a YangModuleInfo. This always results in a new explicit registration. In case
- * there is a pre-existing implicit registration, it is removed just after the explicit registration is made.
+ * Perform registration of a YangModuleInfo.
*/
@Holding("this")
- private ExplicitRegisteredModuleInfo registerExplicitModuleInfo(final @NonNull YangModuleInfo info) {
+ private RegisteredModuleInfo registerModuleInfo(final @NonNull YangModuleInfo info) {
// First search for an existing explicit registration
final SourceIdentifier sourceId = sourceIdentifierFrom(info);
- for (AbstractRegisteredModuleInfo reg : sourceToInfoReg.get(sourceId)) {
- if (reg instanceof ExplicitRegisteredModuleInfo && info.equals(reg.info)) {
- final ExplicitRegisteredModuleInfo explicit = (ExplicitRegisteredModuleInfo) reg;
- explicit.incRef();
- LOG.debug("Reusing explicit registration {}", explicit);
- return explicit;
+ for (RegisteredModuleInfo reg : sourceToInfoReg.get(sourceId)) {
+ if (info.equals(reg.info)) {
+ reg.incRef();
+ LOG.debug("Reusing registration {}", reg);
+ return reg;
}
}
throw new IllegalStateException("Failed to register info " + info, e);
}
- final Class<?> infoClass = info.getClass();
- final String packageName = BindingReflections.getModelRootPackageName(infoClass.getPackage());
- final ExplicitRegisteredModuleInfo regInfo = new ExplicitRegisteredModuleInfo(info, reg,
- infoClass.getClassLoader());
- LOG.debug("Created new explicit registration {}", regInfo);
+ final RegisteredModuleInfo regInfo = new RegisteredModuleInfo(info, reg, info.getClass().getClassLoader());
+ LOG.debug("Created new registration {}", regInfo);
sourceToInfoReg.put(sourceId, regInfo);
- removeImplicit(sourceToInfoReg.get(sourceId));
- packageToInfoReg.put(packageName, regInfo);
- removeImplicit(packageToInfoReg.get(packageName));
-
return regInfo;
}
- // Reconsider utility of this
- final Optional<? extends EffectiveModelContext> getResolverEffectiveModel() {
- return ctxResolver.getEffectiveModelContext();
- }
-
- @Deprecated
- final ListenableFuture<? extends YangTextSchemaSource> getResolverSource(final SourceIdentifier sourceIdentifier) {
- return ctxResolver.getSource(sourceIdentifier);
- }
-
@Holding("this")
final @NonNull ModuleInfoSnapshot updateSnapshot() {
final EffectiveModelContext effectiveModel = ctxResolver.getEffectiveModelContext().orElseThrow();
final Map<SourceIdentifier, YangModuleInfo> moduleInfos = new HashMap<>();
final Map<String, ClassLoader> classLoaders = new HashMap<>();
for (SourceIdentifier source : sources) {
- final List<AbstractRegisteredModuleInfo> regs = sourceToInfoReg.get(source);
+ final List<RegisteredModuleInfo> regs = sourceToInfoReg.get(source);
checkState(!regs.isEmpty(), "No registration for %s", source);
- AbstractRegisteredModuleInfo reg = regs.stream()
- .filter(ExplicitRegisteredModuleInfo.class::isInstance).findFirst()
- .orElse(null);
- if (reg == null) {
- reg = regs.get(0);
- }
-
+ final RegisteredModuleInfo reg = regs.get(0);
final YangModuleInfo info = reg.info;
moduleInfos.put(source, info);
final Class<?> infoClass = info.getClass();
@SuppressFBWarnings(value = "UPM_UNCALLED_PRIVATE_METHOD",
justification = "https://github.com/spotbugs/spotbugs/issues/811")
- private synchronized void unregister(final ImmutableList<ExplicitRegisteredModuleInfo> regInfos) {
- for (ExplicitRegisteredModuleInfo regInfo : regInfos) {
+ private synchronized void unregister(final ImmutableList<RegisteredModuleInfo> regInfos) {
+ for (RegisteredModuleInfo regInfo : regInfos) {
if (!regInfo.decRef()) {
LOG.debug("Registration {} has references, not removing it", regInfo);
continue;
LOG.warn("Failed to find {} registered under {}", regInfo, sourceId);
}
- final String packageName = BindingReflections.getModelRootPackageName(regInfo.info.getClass().getPackage());
- if (!packageToInfoReg.remove(packageName, regInfo)) {
- LOG.warn("Failed to find {} registered under {}", regInfo, packageName);
- }
-
regInfo.reg.close();
}
}
- @Holding("this")
- private static void removeImplicit(final List<AbstractRegisteredModuleInfo> regs) {
- /*
- * Search for implicit registration for a sourceId/packageName.
- *
- * Since we are called while an explicit registration is being created (and has already been inserted, we know
- * there is at least one entry in the maps. We also know registrations retain the order in which they were
- * created and that implicit registrations are not created if there already is a registration.
- *
- * This means that if an implicit registration exists, it will be the first entry in the list.
- */
- final AbstractRegisteredModuleInfo reg = regs.get(0);
- if (reg instanceof ImplicitRegisteredModuleInfo) {
- LOG.debug("Removing implicit registration {}", reg);
- regs.remove(0);
- reg.reg.close();
- }
- }
-
private static @NonNull YangTextSchemaSource toYangTextSource(final SourceIdentifier identifier,
final YangModuleInfo moduleInfo) {
return YangTextSchemaSource.delegateForByteSource(identifier, moduleInfo.getYangTextByteSource());
+++ /dev/null
-/*
- * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.mdsal.binding.runtime.spi;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.Beta;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.util.concurrent.ListenableFuture;
-import java.util.Optional;
-import java.util.Set;
-import org.checkerframework.checker.lock.qual.Holding;
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
-import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeGenerator;
-import org.opendaylight.mdsal.binding.runtime.api.ClassLoadingStrategy;
-import org.opendaylight.mdsal.binding.runtime.api.DefaultBindingRuntimeContext;
-import org.opendaylight.yangtools.util.ClassLoaderUtils;
-import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
-import org.opendaylight.yangtools.yang.model.api.EffectiveModelContextProvider;
-import org.opendaylight.yangtools.yang.model.parser.api.YangParserFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
-import org.opendaylight.yangtools.yang.parser.repo.YangTextSchemaContextResolver;
-
-@Beta
-@Deprecated(forRemoval = true)
-public class ModuleInfoBackedContext extends AbstractModuleInfoTracker implements ClassLoadingStrategy,
- EffectiveModelContextProvider, SchemaSourceProvider<YangTextSchemaSource> {
- private static final class WithFallback extends ModuleInfoBackedContext {
- private final @NonNull ClassLoadingStrategy fallback;
-
- WithFallback(final YangTextSchemaContextResolver resolver, final ClassLoadingStrategy fallback) {
- super(resolver);
- this.fallback = requireNonNull(fallback);
- }
-
- @Override
- Class<?> loadUnknownClass(final String fullyQualifiedName) throws ClassNotFoundException {
- // We have not found a matching registration, consult the backing strategy
- final Class<?> cls = fallback.loadClass(fullyQualifiedName);
- registerImplicitBindingClass(cls);
- return cls;
- }
- }
-
- private static final LoadingCache<ClassLoadingStrategy,
- LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext>> CONTEXT_CACHES = CacheBuilder.newBuilder()
- .weakKeys().build(new CacheLoader<ClassLoadingStrategy,
- LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext>>() {
- @Override
- public LoadingCache<ImmutableSet<YangModuleInfo>, ModuleInfoBackedContext> load(
- final ClassLoadingStrategy strategy) {
- return CacheBuilder.newBuilder().weakValues().build(
- new CacheLoader<Set<YangModuleInfo>, ModuleInfoBackedContext>() {
- @Override
- public ModuleInfoBackedContext load(final Set<YangModuleInfo> key) {
- final ModuleInfoBackedContext context = ModuleInfoBackedContext.create(strategy);
- context.registerModuleInfos(key);
- return context;
- }
- });
- }
- });
-
- ModuleInfoBackedContext(final YangTextSchemaContextResolver resolver) {
- super(resolver);
- }
-
- @Beta
- public static ModuleInfoBackedContext cacheContext(final ClassLoadingStrategy loadingStrategy,
- final ImmutableSet<YangModuleInfo> infos) {
- return CONTEXT_CACHES.getUnchecked(loadingStrategy).getUnchecked(infos);
- }
-
- public static ModuleInfoBackedContext create() {
- return create("unnamed");
- }
-
- public static ModuleInfoBackedContext create(final String id) {
- return new ModuleInfoBackedContext(YangTextSchemaContextResolver.create(id));
- }
-
- public static ModuleInfoBackedContext create(final ClassLoadingStrategy loadingStrategy) {
- return create("unnamed", loadingStrategy);
- }
-
- public static ModuleInfoBackedContext create(final String id, final ClassLoadingStrategy loadingStrategy) {
- return new WithFallback(YangTextSchemaContextResolver.create(id), loadingStrategy);
- }
-
- public static ModuleInfoBackedContext create(final String id, final YangParserFactory factory) {
- return new ModuleInfoBackedContext(YangTextSchemaContextResolver.create(id, factory));
- }
-
- public static ModuleInfoBackedContext create(final String id, final YangParserFactory factory,
- final ClassLoadingStrategy loadingStrategy) {
- return new WithFallback(YangTextSchemaContextResolver.create(id, factory), loadingStrategy);
- }
-
- @Override
- public final EffectiveModelContext getEffectiveModelContext() {
- final Optional<? extends EffectiveModelContext> contextOptional = tryToCreateModelContext();
- checkState(contextOptional.isPresent(), "Unable to recreate SchemaContext, error while parsing");
- return contextOptional.get();
- }
-
- @Override
- public final synchronized Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
- final ClassLoader loader = findClassLoader(fullyQualifiedName);
- return loader != null ? ClassLoaderUtils.loadClass(loader, fullyQualifiedName)
- : loadUnknownClass(fullyQualifiedName);
- }
-
- @Override
- public final ListenableFuture<? extends YangTextSchemaSource> getSource(final SourceIdentifier sourceIdentifier) {
- return getResolverSource(sourceIdentifier);
- }
-
- @Beta
- public final @NonNull BindingRuntimeContext createRuntimeContext(final BindingRuntimeGenerator generator) {
- return DefaultBindingRuntimeContext.create(
- generator.generateTypeMapping(tryToCreateModelContext().orElseThrow()), this);
- }
-
- // TODO finish schema parsing and expose as SchemaService
- // Unite with current SchemaService
-
- public final Optional<? extends EffectiveModelContext> tryToCreateModelContext() {
- return getResolverEffectiveModel();
- }
-
- @Holding("this")
- Class<?> loadUnknownClass(final String fullyQualifiedName) throws ClassNotFoundException {
- throw new ClassNotFoundException(fullyQualifiedName);
- }
-}