BUG-4367: Use SchemaSourceProvider to retrieve sources for yang 54/27654/8
authorMaros Marsalek <mmarsale@cisco.com>
Wed, 30 Sep 2015 13:28:23 +0000 (15:28 +0200)
committerTony Tkacik <ttkacik@cisco.com>
Sat, 3 Oct 2015 08:30:37 +0000 (08:30 +0000)
- Not using schema context to provide the sources anymore.
- Transform the modules into capabilities in YangStoreService instead
  of requiring the listeners to do so

Change-Id: I39a144c7472f7944cca01eeff273058aa2fe7d7a
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreActivator.java
opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreService.java
opendaylight/config/config-manager-facade-xml/src/main/java/org/opendaylight/controller/config/facade/xml/osgi/YangStoreSnapshot.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ConfigManagerActivator.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RefreshingSCPModuleInfoRegistry.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java
opendaylight/config/config-util/src/main/java/org/opendaylight/controller/config/util/capability/ModuleListener.java

index 1df85391abdbaf492701304269414dc93295ac1b..57ebfb2b10ae0637f40491797aa0a51fec951fc6 100644 (file)
@@ -8,6 +8,7 @@
 
 package org.opendaylight.controller.config.facade.xml.osgi;
 
+import com.google.common.base.Preconditions;
 import java.lang.management.ManagementFactory;
 import java.util.Hashtable;
 import java.util.concurrent.atomic.AtomicBoolean;
@@ -16,6 +17,8 @@ import org.opendaylight.controller.config.facade.xml.ConfigSubsystemFacadeFactor
 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
@@ -51,6 +54,11 @@ public class YangStoreActivator implements BundleActivator {
             @Override
             public YangStoreService addingService(ServiceReference<SchemaContextProvider> reference) {
                 LOG.debug("Got addingService(SchemaContextProvider) event");
+                if(reference.getProperty(SchemaSourceProvider.class.getName()) == null &&
+                    reference.getProperty(BindingRuntimeContext.class.getName()) == null) {
+                    LOG.debug("SchemaContextProvider not from config-manager. Ignoring");
+                    return null;
+                }
 
                 // Yang store service should not be registered multiple times
                 if(!alreadyStarted.compareAndSet(false, true)) {
@@ -58,7 +66,13 @@ public class YangStoreActivator implements BundleActivator {
                     throw new RuntimeException("Starting yang store service multiple times");
                 }
                 SchemaContextProvider schemaContextProvider = reference.getBundle().getBundleContext().getService(reference);
-                final YangStoreService yangStoreService = new YangStoreService(schemaContextProvider);
+                final Object sourceProvider = Preconditions.checkNotNull(
+                    reference.getProperty(SchemaSourceProvider.class.getName()), "Source provider not found");
+                Preconditions.checkArgument(sourceProvider instanceof SchemaSourceProvider);
+
+                // TODO avoid cast
+                final YangStoreService yangStoreService = new YangStoreService(schemaContextProvider,
+                    ((SchemaSourceProvider<YangTextSchemaSource>) sourceProvider));
                 yangStoreServiceServiceRegistration = context.registerService(YangStoreService.class, yangStoreService, new Hashtable<String, Object>());
                 configRegistryLookup = new ConfigRegistryLookupThread(yangStoreService);
                 configRegistryLookup.start();
@@ -67,14 +81,23 @@ public class YangStoreActivator implements BundleActivator {
 
             @Override
             public void modifiedService(ServiceReference<SchemaContextProvider> reference, YangStoreService service) {
+                if (service == null) {
+                    return;
+                }
+
                 LOG.debug("Got modifiedService(SchemaContextProvider) event");
-                final BindingRuntimeContext runtimeContext = (BindingRuntimeContext) reference.getProperty(BindingRuntimeContext.class.getName());
+                final BindingRuntimeContext runtimeContext = (BindingRuntimeContext) reference
+                    .getProperty(BindingRuntimeContext.class.getName());
                 LOG.debug("BindingRuntimeContext retrieved as {}", runtimeContext);
                 service.refresh(runtimeContext);
             }
 
             @Override
             public void removedService(ServiceReference<SchemaContextProvider> reference, YangStoreService service) {
+                if(service == null) {
+                    return;
+                }
+
                 LOG.debug("Got removedService(SchemaContextProvider) event");
                 alreadyStarted.set(false);
                 configRegistryLookup.interrupt();
index b6b1869937dda15dd99de854999c46b9167f5971..ebdfe550da894af319348c40e35c566ac6a41f10 100644 (file)
@@ -8,6 +8,8 @@
 
 package org.opendaylight.controller.config.facade.xml.osgi;
 
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
 import com.google.common.collect.Sets;
 import java.lang.ref.SoftReference;
 import java.util.Collections;
@@ -18,13 +20,18 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.atomic.AtomicReference;
+import javax.annotation.Nullable;
+import org.opendaylight.controller.config.util.capability.Capability;
 import org.opendaylight.controller.config.util.capability.ModuleListener;
+import org.opendaylight.controller.config.util.capability.YangModuleCapability;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -59,6 +66,7 @@ public class YangStoreService implements YangStoreContext {
             new AtomicReference<>(new SoftReference<BindingRuntimeContext>(null));
 
     private final SchemaContextProvider schemaContextProvider;
+    private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
 
     private final ExecutorService notificationExecutor = Executors.newSingleThreadExecutor(new ThreadFactory() {
         @Override
@@ -69,8 +77,10 @@ public class YangStoreService implements YangStoreContext {
 
     private final Set<ModuleListener> listeners = Collections.synchronizedSet(new HashSet<ModuleListener>());
 
-    public YangStoreService(final SchemaContextProvider schemaContextProvider) {
+    public YangStoreService(final SchemaContextProvider schemaContextProvider,
+        final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
         this.schemaContextProvider = schemaContextProvider;
+        this.sourceProvider = sourceProvider;
     }
 
     private synchronized YangStoreContext getYangStoreSnapshot() {
@@ -79,7 +89,8 @@ public class YangStoreService implements YangStoreContext {
 
         while (ret == null) {
             // We need to be compute a new value
-            ret = new YangStoreSnapshot(schemaContextProvider.getSchemaContext(), refBindingContext.get().get());
+            // TODO sourceProvider is not a snapshot
+            ret = new YangStoreSnapshot(schemaContextProvider.getSchemaContext(), refBindingContext.get().get(), sourceProvider);
 
             if (!ref.compareAndSet(r, new SoftReference<>(ret))) {
                 LOG.debug("Concurrent refresh detected, recomputing snapshot");
@@ -135,7 +146,7 @@ public class YangStoreService implements YangStoreContext {
         }
 
         this.listeners.add(listener);
-        listener.onCapabilitiesChanged(context.getModules(), Collections.<Module>emptySet());
+        listener.onCapabilitiesChanged(toCapabilities(context.getModules(), context), Collections.<Capability>emptySet());
 
         return new AutoCloseable() {
             @Override
@@ -145,6 +156,14 @@ public class YangStoreService implements YangStoreContext {
         };
     }
 
+    private Set<Capability> toCapabilities(final Set<Module> modules, final YangStoreContext current) {
+        return Sets.newHashSet(Collections2.transform(modules, new Function<Module, Capability>() {
+            @Nullable @Override public Capability apply(final Module input) {
+                return new YangModuleCapability(input, current.getModuleSource(input));
+            }
+        }));
+    }
+
     private final class CapabilityChangeNotifier implements Runnable {
 
         private final YangStoreSnapshot previous;
@@ -162,9 +181,10 @@ public class YangStoreService implements YangStoreContext {
                 final Set<Module> added = Sets.difference(current.getModules(), previous.getModules());
 
                 for (final ModuleListener listener : listeners) {
-                    listener.onCapabilitiesChanged(added, removed);
+                    listener.onCapabilitiesChanged(toCapabilities(added, current), toCapabilities(removed, current));
                 }
             }
         }
+
     }
 }
index a5c7ca8cc69450aaf3dba474c3ec157d98b5c0b6..8babb867b24016f0349856501a63599d5232a760 100644 (file)
@@ -8,18 +8,18 @@
 
 package org.opendaylight.controller.config.facade.xml.osgi;
 
-import com.google.common.base.Optional;
+import com.google.common.base.Charsets;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
 import com.google.common.collect.BiMap;
-import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 import com.google.common.collect.Sets;
+import com.google.common.io.ByteStreams;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.io.IOException;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.NoSuchElementException;
 import java.util.Set;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator;
@@ -31,7 +31,10 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceException;
+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.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -47,9 +50,13 @@ final class YangStoreSnapshot implements YangStoreContext, EnumResolver {
 
     private final SchemaContext schemaContext;
     private final BindingRuntimeContext bindingContextProvider;
+    private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
 
-    public YangStoreSnapshot(final SchemaContext resolveSchemaContext, final BindingRuntimeContext bindingContextProvider) {
+    public YangStoreSnapshot(final SchemaContext resolveSchemaContext,
+        final BindingRuntimeContext bindingContextProvider,
+        final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
         this.bindingContextProvider = bindingContextProvider;
+        this.sourceProvider = sourceProvider;
         LOG.trace("Resolved modules:{}", resolveSchemaContext.getModules());
         this.schemaContext = resolveSchemaContext;
         // JMX generator
@@ -119,21 +126,18 @@ final class YangStoreSnapshot implements YangStoreContext, EnumResolver {
 
     @Override
     public String getModuleSource(final org.opendaylight.yangtools.yang.model.api.ModuleIdentifier moduleIdentifier) {
-        final Optional<String> moduleSource = schemaContext.getModuleSource(moduleIdentifier);
-        if(moduleSource.isPresent()) {
-            return moduleSource.get();
-        } else {
-            try {
-                return Iterables.find(getModules(), new Predicate<Module>() {
-                    @Override
-                    public boolean apply(final Module input) {
-                        final ModuleIdentifierImpl id = new ModuleIdentifierImpl(input.getName(), Optional.fromNullable(input.getNamespace()), Optional.fromNullable(input.getRevision()));
-                        return id.equals(moduleIdentifier);
-                    }
-                }).getSource();
-            } catch (final NoSuchElementException e) {
-                throw new IllegalArgumentException("Source for yang module " + moduleIdentifier + " not found", e);
-            }
+        final CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> source = sourceProvider.getSource(
+            moduleIdentifier.getRevision() == null ?
+                new SourceIdentifier(moduleIdentifier.getName()) :
+                new SourceIdentifier(moduleIdentifier.getName(),
+                    QName.formattedRevision(moduleIdentifier.getRevision())));
+
+        try {
+            final YangTextSchemaSource yangTextSchemaSource = source.checkedGet();
+            return new String(ByteStreams.toByteArray(yangTextSchemaSource.openStream()), Charsets.UTF_8);
+        } catch (SchemaSourceException | IOException e) {
+            LOG.warn("Unable to provide source for {}", moduleIdentifier, e);
+            throw new IllegalArgumentException("Unable to provide source for " + moduleIdentifier, e);
         }
     }
 
index 128399563aeb808e906f58e522dce0ef48f1548d..7966b8983aab814ca310be6d660b5f8e1ba4fc1c 100644 (file)
@@ -47,7 +47,7 @@ public class ConfigManagerActivator implements BundleActivator {
             BindingContextProvider bindingContextProvider = new BindingContextProvider();
 
             RefreshingSCPModuleInfoRegistry moduleInfoRegistryWrapper = new RefreshingSCPModuleInfoRegistry(
-                    moduleInfoBackedContext, moduleInfoBackedContext, moduleInfoBackedContext, bindingContextProvider, context);
+                    moduleInfoBackedContext, moduleInfoBackedContext, moduleInfoBackedContext, moduleInfoBackedContext, bindingContextProvider, context);
 
             ModuleInfoBundleTracker moduleInfoBundleTracker = new ModuleInfoBundleTracker(moduleInfoRegistryWrapper);
 
index b62e60382c09210c6e24f6fc7be7db95b1c73944..8bc1a58ccc0069f75421288dac0ae8b8deb75a1c 100644 (file)
@@ -15,6 +15,8 @@ import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
@@ -25,24 +27,31 @@ public class RefreshingSCPModuleInfoRegistry implements ModuleInfoRegistry, Auto
 
     private final ModuleInfoRegistry moduleInfoRegistry;
     private final SchemaContextProvider schemaContextProvider;
+    private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
     private final BindingContextProvider bindingContextProvider;
     private final ClassLoadingStrategy classLoadingStrat;
 
     private final ServiceRegistration<SchemaContextProvider> osgiReg;
 
     public RefreshingSCPModuleInfoRegistry(final ModuleInfoRegistry moduleInfoRegistry,
-                                           final SchemaContextProvider schemaContextProvider, final ClassLoadingStrategy classLoadingStrat, final BindingContextProvider bindingContextProvider, final BundleContext bundleContext) {
+        final SchemaContextProvider schemaContextProvider, final ClassLoadingStrategy classLoadingStrat,
+        final SchemaSourceProvider<YangTextSchemaSource> sourceProvider, final BindingContextProvider bindingContextProvider,
+        final BundleContext bundleContext) {
+
         this.moduleInfoRegistry = moduleInfoRegistry;
         this.schemaContextProvider = schemaContextProvider;
         this.classLoadingStrat = classLoadingStrat;
+        this.sourceProvider = sourceProvider;
         this.bindingContextProvider = bindingContextProvider;
-        osgiReg = bundleContext.registerService(SchemaContextProvider.class, schemaContextProvider, new Hashtable<String, String>());
+        osgiReg = bundleContext
+            .registerService(SchemaContextProvider.class, schemaContextProvider, new Hashtable<String, String>());
     }
 
     private void updateService() {
         bindingContextProvider.update(classLoadingStrat, schemaContextProvider);
         osgiReg.setProperties(new Hashtable<String, Object>() {{
                 put(BindingRuntimeContext.class.getName(), bindingContextProvider.getBindingContext());
+                put(SchemaSourceProvider.class.getName(), sourceProvider);
             }
         }); // send modifiedService event
     }
index 00214f6ba7b54b1d6acb58b28816ccd7c9bb4daf..8613eeba6bca39f998edea21bc6eba6d6d73127d 100644 (file)
@@ -15,8 +15,11 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 
 import java.util.Dictionary;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.config.manager.impl.osgi.mapping.BindingContextProvider;
 import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSCPModuleInfoRegistry;
 import org.opendaylight.yangtools.concepts.ObjectRegistration;
@@ -25,10 +28,20 @@ import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
 public class RefreshingSCPModuleInfoRegistryTest {
+
+    @Mock
+    SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
+
+    @Before public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+    }
+
     @Test
     public void testConstructor() throws Exception {
         ModuleInfoRegistry reg = mock(ModuleInfoRegistry.class);
@@ -47,7 +60,7 @@ public class RefreshingSCPModuleInfoRegistryTest {
         doReturn("B-runtime-context").when(bindingRuntimeContext).toString();
         doReturn(bindingRuntimeContext).when(codecRegistryProvider).getBindingContext();
 
-        RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, classLoadingStrat, codecRegistryProvider, ctxt);
+        RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, classLoadingStrat, sourceProvider, codecRegistryProvider, ctxt);
 
         doNothing().when(servReg).unregister();
 
index eebbe7f01bffe52503058741c45b032fd6164c59..f2624c06b18551e4a3bae0af59d52157353802c9 100644 (file)
@@ -9,9 +9,8 @@
 package org.opendaylight.controller.config.util.capability;
 
 import java.util.Set;
-import org.opendaylight.yangtools.yang.model.api.Module;
 
 public interface ModuleListener {
 
-    void onCapabilitiesChanged(Set<Module> added, Set<Module> removed);
+    void onCapabilitiesChanged(Set<Capability> added, Set<Capability> removed);
 }