Eliminate ClassLoadingStrategy
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 30 Sep 2020 10:43:56 +0000 (12:43 +0200)
committerAnil Belur <abelur@linuxfoundation.org>
Wed, 19 Jun 2024 00:41:33 +0000 (10:41 +1000)
ClassLoadingStrategy as a separate concept is very confusing. The
reality is that ModuleInfoSnapshot needs to be able to load classes
based on their FQCN and BindingRuntimeContext needs to do the same
based on they binding.model.api.Type.

Split ClassLoadingStrategy's two methods appropriately and remove
it. Also adjust all users to not rely on it.

JIRA: MDSAL-578
Change-Id: Id4606efcd67d8ea7c42e78c48c48aa915cb11a52
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
13 files changed:
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataContainerCodecContext.java
binding/mdsal-binding-dom-codec/src/main/java/org/opendaylight/mdsal/binding/dom/codec/impl/DataObjectCodecContext.java
binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationClassDiscoveredAfterCodecTest.java [deleted file]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/AbstractBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/BindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ClassLoadingStrategy.java [deleted file]
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/DefaultBindingRuntimeContext.java
binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ModuleInfoSnapshot.java
binding/mdsal-binding-runtime-osgi/src/main/java/org/opendaylight/mdsal/binding/runtime/osgi/impl/OSGiBindingRuntime.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/BindingRuntimeHelpers.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/DefaultModuleInfoSnapshot.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingBindingRuntimeContext.java
binding/mdsal-binding-runtime-spi/src/main/java/org/opendaylight/mdsal/binding/runtime/spi/ForwardingModuleInfoSnapshot.java

index 5814671b0f43e932031fa8f151e8b4a313bbdcc0..e8bca5d0d1e5cde58b6f64affad6f8521c92f2eb 100644 (file)
@@ -27,8 +27,8 @@ import org.opendaylight.mdsal.binding.dom.codec.api.IncorrectNestingException;
 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;
@@ -211,12 +211,11 @@ abstract class DataContainerCodecContext<D extends DataObject, T extends WithSta
             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);
index cfe4f91f4f159bebff217c61a8d85cd000f916b9..79ec825abf40a4d7b759620beba35af4dde878d6 100644 (file)
@@ -31,7 +31,7 @@ import org.eclipse.jdt.annotation.Nullable;
 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;
@@ -489,19 +489,19 @@ public abstract class DataObjectCodecContext<D extends DataObject, T extends Dat
     }
 
     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());
     }
 
diff --git a/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationClassDiscoveredAfterCodecTest.java b/binding/mdsal-binding-dom-codec/src/test/java/org/opendaylight/mdsal/binding/dom/codec/impl/AugmentationClassDiscoveredAfterCodecTest.java
deleted file mode 100644 (file)
index fe94136..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * 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);
-        }
-    }
-}
index 33a0a1ba6ccfa58559d0100b4380c9ab8bba7448..920d11546b67dce331ec1c05c9c8d4828f9450a6 100644 (file)
@@ -72,7 +72,7 @@ public abstract class AbstractBindingRuntimeContext implements BindingRuntimeCon
                 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);
                 }
@@ -268,7 +268,7 @@ public abstract class AbstractBindingRuntimeContext implements BindingRuntimeCon
         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);
             }
@@ -284,7 +284,7 @@ public abstract class AbstractBindingRuntimeContext implements BindingRuntimeCon
             childSchema, origSchema);
 
         try {
-            return getStrategy().loadClass(clazzType.get());
+            return loadClass(clazzType.get());
         } catch (final ClassNotFoundException e) {
             throw new IllegalStateException(e);
         }
index f375c134268be6f85a7eb62c9475df7d614a8daa..99b98d1c3365b347f4c8f2dd83ccd04a3779716d 100644 (file)
@@ -45,16 +45,10 @@ import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier.Absol
  */
 @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();
diff --git a/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ClassLoadingStrategy.java b/binding/mdsal-binding-runtime-api/src/main/java/org/opendaylight/mdsal/binding/runtime/api/ClassLoadingStrategy.java
deleted file mode 100644 (file)
index dc47d33..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * 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;
-}
index 0e658e884bce4339fb539e2a7bcc4d462ea64e97..a4c1da1e2b7ca01e82ba19452dc9507a6a334260 100644 (file)
@@ -11,6 +11,7 @@ import static java.util.Objects.requireNonNull;
 
 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;
 
 /**
@@ -24,38 +25,20 @@ 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());
     }
 }
index ffdbe7f8f4e2df8a7fb1df6246e76678fbaff94e..733511d47727a636ec297adc318370d5d245ec63 100644 (file)
@@ -14,7 +14,8 @@ import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 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;
 }
index e331142701ae2ce3dfb0462174480807887cf1b3..bce0e0a24bafd967513c93c02255be552f8741a0 100644 (file)
@@ -102,7 +102,7 @@ public final class OSGiBindingRuntime {
 
             instances.put(snapshot, factory.newInstance(OSGiBindingRuntimeContextImpl.props(
                 snapshot.getGeneration(), snapshot.getServiceRanking(),
-                DefaultBindingRuntimeContext.create(types, context))));
+                new DefaultBindingRuntimeContext(types, context))));
         }
 
         @Override
index eb6c0ab6a086c951dab9e88e0684b9b346ba8d3f..a2e0294cce09ed9e9537b6ce2dd4c9e542dd2a1d 100644 (file)
@@ -52,7 +52,7 @@ public final class BindingRuntimeHelpers {
     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);
     }
 
@@ -71,8 +71,7 @@ public final class BindingRuntimeHelpers {
         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")
index 4047969e8c22089459b0c461caeda208c1f06f00..8178c439ab02838771b4dfb10ad74dd430c6fd45 100644 (file)
@@ -51,12 +51,14 @@ final class DefaultModuleInfoSnapshot implements ModuleInfoSnapshot {
     }
 
     @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;
     }
 }
index fd90b05864dff6c90f894c163627c01aaec85cec..a48d44f0cabbdab084384d8328e8b81d95876660 100644 (file)
@@ -18,7 +18,6 @@ import org.opendaylight.mdsal.binding.model.api.GeneratedType;
 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;
@@ -38,11 +37,6 @@ public abstract class ForwardingBindingRuntimeContext extends ForwardingObject i
     @Override
     protected abstract BindingRuntimeContext delegate();
 
-    @Override
-    public ClassLoadingStrategy getStrategy() {
-        return delegate().getStrategy();
-    }
-
     @Override
     public BindingRuntimeTypes getTypes() {
         return delegate().getTypes();
@@ -108,4 +102,9 @@ public abstract class ForwardingBindingRuntimeContext extends ForwardingObject i
     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);
+    }
 }
index 4b3a037756db92d79a32b5e7d1073055aeacec5f..90454856ee7d5356d8af7d8afffe9901378cd5db 100644 (file)
@@ -22,7 +22,7 @@ public abstract class ForwardingModuleInfoSnapshot extends ForwardingObject impl
     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);
     }