import org.opendaylight.mdsal.binding.dom.codec.api.MissingClassInLoadingStrategyException;
import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaException;
import org.opendaylight.mdsal.binding.dom.codec.api.MissingSchemaForClassException;
+import org.opendaylight.mdsal.binding.model.api.DefaultType;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
-import org.opendaylight.mdsal.binding.runtime.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.binding.BindingObject;
import org.opendaylight.yangtools.yang.binding.DataObject;
throw new MissingSchemaForClassException(childClass);
}
- final ClassLoadingStrategy strategy = runtimeContext.getStrategy();
try {
- strategy.loadClass(childClass.getName());
+ runtimeContext.loadClass(DefaultType.of(childClass));
} catch (final ClassNotFoundException e) {
throw new MissingClassInLoadingStrategyException(
- "User supplied class " + childClass.getName() + " is not available in " + strategy, e);
+ "User supplied class " + childClass.getName() + " is not available in " + runtimeContext, e);
}
throw IncorrectNestingException.create(message, args);
import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
import org.opendaylight.mdsal.binding.model.api.JavaTypeName;
import org.opendaylight.mdsal.binding.model.api.Type;
-import org.opendaylight.mdsal.binding.runtime.api.ClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.spec.reflect.BindingReflections;
import org.opendaylight.yangtools.concepts.Immutable;
import org.opendaylight.yangtools.util.ClassLoaderUtils;
}
private DataContainerCodecPrototype<?> getAugmentationPrototype(final Type value) {
- final ClassLoadingStrategy loader = factory().getRuntimeContext().getStrategy();
- @SuppressWarnings("rawtypes")
- final Class augClass;
+ final BindingRuntimeContext ctx = factory().getRuntimeContext();
+
+ final Class<? extends Augmentation<?>> augClass;
try {
- augClass = loader.loadClass(value);
+ augClass = ctx.loadClass(value);
} catch (final ClassNotFoundException e) {
+ // FIXME: MDSAL-578: this is disallowed
LOG.debug("Failed to load augmentation prototype for {}. Will be retried when needed.", value, e);
return null;
}
- @SuppressWarnings("unchecked")
- final Entry<AugmentationIdentifier, AugmentationSchemaNode> augSchema = factory().getRuntimeContext()
- .getResolvedAugmentationSchema(getSchema(), augClass);
+ final Entry<AugmentationIdentifier, AugmentationSchemaNode> augSchema =
+ ctx.getResolvedAugmentationSchema(getSchema(), augClass);
return DataContainerCodecPrototype.from(augClass, augSchema.getKey(), augSchema.getValue(), factory());
}
+++ /dev/null
-/*
- * Copyright (c) 2015 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.dom.codec.impl;
-
-import static java.util.Objects.requireNonNull;
-import static org.junit.Assert.assertNotNull;
-
-import java.util.HashSet;
-import java.util.Map.Entry;
-import java.util.Set;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
-import org.opendaylight.mdsal.binding.dom.codec.api.MissingClassInLoadingStrategyException;
-import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
-import org.opendaylight.mdsal.binding.runtime.api.ClassLoadingStrategy;
-import org.opendaylight.mdsal.binding.runtime.api.DefaultBindingRuntimeContext;
-import org.opendaylight.mdsal.binding.runtime.spi.BindingRuntimeHelpers;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeComplexUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeLeafOnlyAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.augment.rev140709.TreeLeafOnlyAugmentBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.mdsal.test.binding.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
-
-/**
- * This sets of tests are designed in way, that schema context contains models for all augmentations, but backing class
- * loading strategy is not aware of some of the classes, and becames aware of them after codec was used.
- *
- * <p>
- * The idea of this suite is to test that codecs will work even if situation like this happens.
- */
-public class AugmentationClassDiscoveredAfterCodecTest {
- private BindingNormalizedNodeSerializer serializer;
- private FilteringClassLoadingStrategy filter;
-
- @Before
- public void setup() {
- // Baseline state: strategy is cognizant of the classes
- final BindingRuntimeContext delegate = BindingRuntimeHelpers.createRuntimeContext();
-
- // Class loading filter, manipulated by tests
- filter = new FilteringClassLoadingStrategy(delegate.getStrategy());
- serializer = new BindingCodecContext(DefaultBindingRuntimeContext.create(delegate.getTypes(), filter));
- }
-
- private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
- private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier.builder(Top.class)
- .child(TopLevelList.class, TOP_FOO_KEY).build();
- private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST
- .augmentation(TreeLeafOnlyAugment.class);
-
- @Test(expected = MissingClassInLoadingStrategyException.class)
- public void testCorrectExceptionThrown() {
- materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
- serializer.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
- }
-
- @Test
- public void testUsingBindingInstanceIdentifier() {
- materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
- filter.includeClass(TreeLeafOnlyAugment.class);
- final YangInstanceIdentifier domYY = serializer.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY);
- assertNotNull(domYY);
- }
-
- @Test
- public void testUsingBindingData() {
- materializeWithExclusions(TreeLeafOnlyAugment.class, TreeComplexUsesAugment.class);
- filter.includeClass(TreeLeafOnlyAugment.class);
- final TopLevelList data = new TopLevelListBuilder()
- .withKey(TOP_FOO_KEY)
- .addAugmentation(new TreeLeafOnlyAugmentBuilder().setSimpleValue("foo").build())
- .build();
- final Entry<YangInstanceIdentifier, NormalizedNode<?, ?>> domData =
- serializer.toNormalizedNode(BA_TOP_LEVEL_LIST, data);
- assertNotNull(domData);
- }
-
- private void materializeWithExclusions(final Class<?>... clzToExclude) {
- for (final Class<?> clz : clzToExclude) {
- filter.excludeClass(clz);
- }
- serializer.toYangInstanceIdentifier(BA_TOP_LEVEL_LIST);
- }
-
- private static final class FilteringClassLoadingStrategy implements ClassLoadingStrategy {
- private final Set<String> exclusions = new HashSet<>();
- private final ClassLoadingStrategy delegate;
-
- FilteringClassLoadingStrategy(final ClassLoadingStrategy delegate) {
- this.delegate = requireNonNull(delegate);
- }
-
- void excludeClass(final Class<?> clz) {
- exclusions.add(clz.getName());
- }
-
- void includeClass(final Class<?> clz) {
- exclusions.remove(clz.getName());
- }
-
- @Override
- public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
- if (exclusions.contains(fullyQualifiedName)) {
- throw new ClassNotFoundException(String.format("Class %s is not available for test reasons.",
- fullyQualifiedName));
- }
- return delegate.loadClass(fullyQualifiedName);
- }
- }
-}
final Optional<Type> identityType = getTypes().findIdentity(key);
checkArgument(identityType.isPresent(), "Supplied QName %s is not a valid identity", key);
try {
- return getStrategy().loadClass(identityType.get());
+ return loadClass(identityType.get());
} catch (final ClassNotFoundException e) {
throw new IllegalArgumentException("Required class " + identityType + "was not found.", e);
}
final Set<Class<?>> ret = new HashSet<>(cazes.size());
for (final Type caze : cazes) {
try {
- ret.add(getStrategy().loadClass(caze));
+ ret.add(loadClass(caze));
} catch (final ClassNotFoundException e) {
LOG.warn("Failed to load class for case {}, ignoring it", caze, e);
}
childSchema, origSchema);
try {
- return getStrategy().loadClass(clazzType.get());
+ return loadClass(clazzType.get());
} catch (final ClassNotFoundException e) {
throw new IllegalStateException(e);
}
*/
@Beta
public interface BindingRuntimeContext extends EffectiveModelContextProvider, Immutable {
- /**
- * Returns a class loading strategy associated with this binding runtime context
- * which is used to load classes.
- *
- * @return Class loading strategy.
- */
- @NonNull ClassLoadingStrategy getStrategy();
-
@NonNull BindingRuntimeTypes getTypes();
+ @NonNull <T> Class<T> loadClass(Type type) throws ClassNotFoundException;
+
@Override
default EffectiveModelContext getEffectiveModelContext() {
return getTypes().getEffectiveModelContext();
+++ /dev/null
-/*
- * Copyright (c) 2013 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.api;
-
-import org.opendaylight.mdsal.binding.model.api.Type;
-
-public interface ClassLoadingStrategy {
-
- default Class<?> loadClass(final Type type) throws ClassNotFoundException {
- return loadClass(type.getFullyQualifiedName());
- }
-
- Class<?> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
-}
import com.google.common.annotations.Beta;
import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
/**
@Beta
public final class DefaultBindingRuntimeContext extends AbstractBindingRuntimeContext {
private final @NonNull BindingRuntimeTypes runtimeTypes;
- private final @NonNull ClassLoadingStrategy strategy;
+ private final @NonNull ModuleInfoSnapshot moduleInfos;
- private DefaultBindingRuntimeContext(final BindingRuntimeTypes runtimeTypes, final ClassLoadingStrategy strategy) {
+ public DefaultBindingRuntimeContext(final BindingRuntimeTypes runtimeTypes, final ModuleInfoSnapshot moduleInfos) {
this.runtimeTypes = requireNonNull(runtimeTypes);
- this.strategy = requireNonNull(strategy);
+ this.moduleInfos = requireNonNull(moduleInfos);
}
- /**
- * Creates Binding Runtime Context from supplied class loading strategy and schema context.
- *
- * @param strategy Class loading strategy to retrieve generated Binding classes
- * @param runtimeTypes Binding classes to YANG schema mapping
- * @return A new instance
- */
- public static @NonNull DefaultBindingRuntimeContext create(final BindingRuntimeTypes runtimeTypes,
- final ClassLoadingStrategy strategy) {
- return new DefaultBindingRuntimeContext(runtimeTypes, strategy);
- }
-
- /**
- * Returns a class loading strategy associated with this binding runtime context
- * which is used to load classes.
- *
- * @return Class loading strategy.
- */
@Override
- public @NonNull ClassLoadingStrategy getStrategy() {
- return strategy;
+ public BindingRuntimeTypes getTypes() {
+ return runtimeTypes;
}
@Override
- public @NonNull BindingRuntimeTypes getTypes() {
- return runtimeTypes;
+ public <T> Class<T> loadClass(Type type) throws ClassNotFoundException {
+ return moduleInfos.loadClass(type.getFullyQualifiedName());
}
}
import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
@Beta
-public interface ModuleInfoSnapshot extends Immutable, ClassLoadingStrategy, EffectiveModelContextProvider,
+public interface ModuleInfoSnapshot extends Immutable, EffectiveModelContextProvider,
SchemaSourceProvider<YangTextSchemaSource> {
+ <T> Class<T> loadClass(String fullyQualifiedName) throws ClassNotFoundException;
}
instances.put(snapshot, factory.newInstance(OSGiBindingRuntimeContextImpl.props(
snapshot.getGeneration(), snapshot.getServiceRanking(),
- DefaultBindingRuntimeContext.create(types, context))));
+ new DefaultBindingRuntimeContext(types, context))));
}
@Override
public static @NonNull BindingRuntimeContext createRuntimeContext() {
final ModuleInfoSnapshot infos = prepareContext(ServiceLoaderState.ParserFactory.INSTANCE,
BindingReflections.loadModuleInfos());
- return DefaultBindingRuntimeContext.create(ServiceLoaderState.Generator.INSTANCE.generateTypeMapping(
+ return new DefaultBindingRuntimeContext(ServiceLoaderState.Generator.INSTANCE.generateTypeMapping(
infos.getEffectiveModelContext()), infos);
}
final ModuleInfoSnapshot infos = prepareContext(parserFactory, classes.stream()
.map(BindingRuntimeHelpers::extractYangModuleInfo)
.collect(Collectors.toList()));
- return DefaultBindingRuntimeContext.create(
- generator.generateTypeMapping(infos.getEffectiveModelContext()), infos);
+ return new DefaultBindingRuntimeContext(generator.generateTypeMapping(infos.getEffectiveModelContext()), infos);
}
@SuppressWarnings("checkstyle:IllegalCatch")
}
@Override
- public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+ public <T> Class<T> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
final String packageName = BindingReflections.getModelRootPackageName(fullyQualifiedName);
final ClassLoader loader = classLoaders.get(packageName);
if (loader == null) {
throw new ClassNotFoundException("Package " + packageName + " not found");
}
- return loader.loadClass(fullyQualifiedName);
+ @SuppressWarnings("unchecked")
+ final Class<T> loaded = (Class<T>) loader.loadClass(fullyQualifiedName);
+ return loaded;
}
}
import org.opendaylight.mdsal.binding.model.api.Type;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeContext;
import org.opendaylight.mdsal.binding.runtime.api.BindingRuntimeTypes;
-import org.opendaylight.mdsal.binding.runtime.api.ClassLoadingStrategy;
import org.opendaylight.yangtools.yang.binding.Action;
import org.opendaylight.yangtools.yang.binding.Augmentation;
import org.opendaylight.yangtools.yang.common.QName;
@Override
protected abstract BindingRuntimeContext delegate();
- @Override
- public ClassLoadingStrategy getStrategy() {
- return delegate().getStrategy();
- }
-
@Override
public BindingRuntimeTypes getTypes() {
return delegate().getTypes();
public Class<?> getIdentityClass(final QName input) {
return delegate().getIdentityClass(input);
}
+
+ @Override
+ public <T> Class<T> loadClass(final Type type) throws ClassNotFoundException {
+ return delegate().loadClass(type);
+ }
}
protected abstract ModuleInfoSnapshot delegate();
@Override
- public Class<?> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
+ public <T> Class<T> loadClass(final String fullyQualifiedName) throws ClassNotFoundException {
return delegate().loadClass(fullyQualifiedName);
}