Bug 8326 - Split out OsgiBundleScanningSchemaService 61/62261/33
authorJakub Toth <jakub.toth@pantheon.tech>
Thu, 24 Aug 2017 10:46:16 +0000 (12:46 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 9 Oct 2017 11:36:52 +0000 (13:36 +0200)
 * move osgi part of mdsal-dom broker to new module
   mdsal-dom-schema-service-osgi (with unit tests)

Change-Id: I2eb2e4f96f50456f84982e5de6d439b0306bcc0f
Signed-off-by: Jakub Toth <jakub.toth@pantheon.tech>
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
20 files changed:
common/artifacts/pom.xml
common/features/features-mdsal/pom.xml
common/features/odl-mdsal-dom-broker/pom.xml
common/features/odl-mdsal-dom-schema-service-osgi/pom.xml [new file with mode: 0644]
common/features/odl-mdsal-dom/pom.xml
common/features/pom.xml
dom/mdsal-dom-broker/pom.xml
dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivator.java [deleted file]
dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProvider.java [new file with mode: 0644]
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivatorTest.java [deleted file]
dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProviderTest.java [new file with mode: 0644]
dom/mdsal-dom-broker/src/test/resources/empty-test1.yang [new file with mode: 0644]
dom/mdsal-dom-broker/src/test/resources/empty-test2.yang [new file with mode: 0644]
dom/mdsal-dom-schema-service-osgi/pom.xml [new file with mode: 0644]
dom/mdsal-dom-schema-service-osgi/src/main/java/org/opendaylight/mdsal/dom/schema/service/osgi/OsgiBundleScanningSchemaService.java [moved from dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaService.java with 50% similarity]
dom/mdsal-dom-schema-service-osgi/src/main/resources/org/opendaylight/blueprint/dom-osgi-schema-service.xml [new file with mode: 0644]
dom/mdsal-dom-schema-service-osgi/src/test/java/org/opendaylight/mdsal/dom/schema/service/osgi/OsgiBundleScanningSchemaServiceTest.java [moved from dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaServiceTest.java with 90% similarity]
dom/mdsal-dom-schema-service-osgi/src/test/java/org/opendaylight/mdsal/dom/schema/service/osgi/util/TestModel.java [new file with mode: 0644]
dom/mdsal-dom-schema-service-osgi/src/test/resources/odl-datastore-test.yang [new file with mode: 0644]
dom/pom.xml

index 55d2f9468b393f5e6eac7523e064aa476f534403..ed89321e696abe603232476886a5ce4a5acb8c0d 100644 (file)
                 <artifactId>mdsal-dom-broker</artifactId>
                 <version>${project.version}</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-dom-schema-service-osgi</artifactId>
+                <version>${project.version}</version>
+            </dependency>
             <dependency>
                 <groupId>org.opendaylight.mdsal</groupId>
                 <artifactId>mdsal-dom-inmemory-datastore</artifactId>
                 <classifier>features</classifier>
                 <type>xml</type>
             </dependency>
+            <dependency>
+                <groupId>${project.groupId}</groupId>
+                <artifactId>odl-mdsal-dom-schema-service-osgi</artifactId>
+                <version>${project.version}</version>
+                <classifier>features</classifier>
+                <type>xml</type>
+            </dependency>
 
             <!-- BINDING2 -->
             <dependency>
index 8041b7c10da765366da4e13eb781a07dac2a63c5..9794d8513d960fa518ed0a36556e207c2d43a2bc 100644 (file)
             <classifier>features</classifier>
             <type>xml</type>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>odl-mdsal-dom-schema-service-osgi</artifactId>
+            <classifier>features</classifier>
+            <type>xml</type>
+        </dependency>
 
         <!-- EOS -->
         <dependency>
index 6444c97b07121cddb7b48112b30cfe9ec110c55a..a77237a31b9dfc43fda5b20d4f6b55b7b00efc06 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>mdsal-dom-broker</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.mdsal</groupId>
+            <artifactId>odl-mdsal-dom-schema-service-osgi</artifactId>
+            <type>xml</type>
+            <classifier>features</classifier>
+        </dependency>
     </dependencies>
 
     <!--
diff --git a/common/features/odl-mdsal-dom-schema-service-osgi/pom.xml b/common/features/odl-mdsal-dom-schema-service-osgi/pom.xml
new file mode 100644 (file)
index 0000000..57f143b
--- /dev/null
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright © 2017 Pantheon Technologies s.r.o. 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
+ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>single-feature-parent</artifactId>
+        <version>2.0.5</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.mdsal</groupId>
+    <artifactId>odl-mdsal-dom-schema-service-osgi</artifactId>
+    <version>2.4.0-SNAPSHOT</version>
+    <packaging>feature</packaging>
+
+    <name>OpenDaylight :: MD-SAL :: DOM Schema Service OSGi</name>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>${project.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>mdsal-dom-schema-service-osgi</artifactId>
+        </dependency>
+    </dependencies>
+
+    <!--
+        Maven Site Configuration
+
+        The following configuration is necessary for maven-site-plugin to
+        correctly identify the correct deployment path for OpenDaylight Maven
+        sites.
+    -->
+    <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
+
+    <distributionManagement>
+        <site>
+            <id>opendaylight-site</id>
+            <url>${nexus.site.url}/${project.artifactId}/</url>
+        </site>
+    </distributionManagement>
+
+</project>
index e697a594b6d71804f3cc86c94c39e450080f4278..2882ac43b79570188c8ebbc60e800da19107296c 100644 (file)
@@ -62,4 +62,4 @@
         </site>
     </distributionManagement>
 
-</project>
\ No newline at end of file
+</project>
index a599b6466272e8af983138eee5fdc16e5dc7d6ca..3079b64143753e42afba13cb59c803c070f50750 100644 (file)
@@ -46,6 +46,7 @@
         <module>odl-mdsal-dom</module>
         <module>odl-mdsal-dom-api</module>
         <module>odl-mdsal-dom-broker</module>
+        <module>odl-mdsal-dom-schema-service-osgi</module>
 
         <!-- EOS -->
         <module>odl-mdsal-eos-binding</module>
index 1d6dd7ca31f33388d62639f342cf25c57704ffbd..826535c4d76ee0dd65e948a844dc678bc9c38615 100644 (file)
     </dependencyManagement>
 
   <dependencies>
-    <dependency>
-      <groupId>org.osgi</groupId>
-      <artifactId>org.osgi.core</artifactId>
-    </dependency>
     <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
@@ -53,6 +49,7 @@
       <groupId>com.lmax</groupId>
       <artifactId>disruptor</artifactId>
     </dependency>
+
     <dependency>
       <groupId>org.opendaylight.mdsal</groupId>
       <artifactId>mdsal-dom-api</artifactId>
@@ -65,6 +62,7 @@
       <groupId>org.opendaylight.mdsal</groupId>
       <artifactId>mdsal-dom-inmemory-datastore</artifactId>
     </dependency>
+
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>util</artifactId>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-parser-impl</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-model-api</artifactId>
+    </dependency>
 
     <dependency>
       <groupId>junit</groupId>
 
   <build>
     <plugins>
-      <plugin>
-        <groupId>org.apache.felix</groupId>
-        <artifactId>maven-bundle-plugin</artifactId>
-        <extensions>true</extensions>
-        <configuration>
-          <instructions>
-            <Bundle-Activator>org.opendaylight.mdsal.dom.broker.osgi.SchemaServiceActivator</Bundle-Activator>
-          </instructions>
-        </configuration>
-      </plugin>
       <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-checkstyle-plugin</artifactId>
diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivator.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivator.java
deleted file mode 100644 (file)
index 97370ba..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.dom.broker.osgi;
-
-import java.util.Hashtable;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-public class SchemaServiceActivator implements BundleActivator {
-    private ServiceRegistration<DOMSchemaService> schemaServiceReg;
-    private OsgiBundleScanningSchemaService schemaService;
-
-    @Override
-    public void start(final BundleContext context) {
-        schemaService = OsgiBundleScanningSchemaService.createInstance(context);
-        schemaServiceReg = context.registerService(DOMSchemaService.class,
-                schemaService, new Hashtable<>());
-    }
-
-    @Override
-    public void stop(final BundleContext context) {
-        schemaServiceReg.unregister();
-        schemaService.close();
-    }
-}
diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProvider.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProvider.java
new file mode 100644 (file)
index 0000000..3ea9b69
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.dom.broker.schema;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.util.concurrent.CheckedFuture;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
+import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.util.ListenerRegistry;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+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.parser.repo.YangTextSchemaContextResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ScanningSchemaServiceProvider
+        implements DOMSchemaService, SchemaContextProvider, DOMYangTextSourceProvider, AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(ScanningSchemaServiceProvider.class);
+
+    @GuardedBy("lock")
+    private final ListenerRegistry<SchemaContextListener> listeners = new ListenerRegistry<>();
+    private final Object lock = new Object();
+    private final YangTextSchemaContextResolver contextResolver = YangTextSchemaContextResolver.create("global-bundle");
+
+    public void tryToUpdateSchemaContext() {
+        synchronized (lock) {
+            final Optional<SchemaContext> schema = contextResolver.getSchemaContext();
+            if (schema.isPresent()) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getAllModuleIdentifiers().size());
+                }
+                notifyListeners(schema.get());
+            }
+        }
+    }
+
+    @VisibleForTesting
+    @SuppressWarnings("checkstyle:IllegalCatch")
+    public void notifyListeners(final SchemaContext schemaContext) {
+        synchronized (lock) {
+            for (final ListenerRegistration<SchemaContextListener> registration : listeners) {
+                try {
+                    registration.getInstance().onGlobalContextUpdated(schemaContext);
+                } catch (final Exception e) {
+                    LOG.error("Exception occured during invoking listener", e);
+                }
+            }
+        }
+    }
+
+    public List<Registration> registerAvailableYangs(final List<URL> yangs) {
+        final List<Registration> sourceRegistrator = new ArrayList<>();
+        for (final URL url : yangs) {
+            try {
+                sourceRegistrator.add(contextResolver.registerSource(url));
+            } catch (SchemaSourceException | IOException | YangSyntaxErrorException e) {
+                LOG.warn("Failed to register {}, ignoring it", url, e);
+            }
+        }
+        return sourceRegistrator;
+    }
+
+    public void removeListener(final SchemaContextListener schemaContextListener) {
+        synchronized (lock) {
+            for (final ListenerRegistration<SchemaContextListener> listenerRegistration : listeners.getListeners()) {
+                if (listenerRegistration.getInstance().equals(schemaContextListener)) {
+                    listenerRegistration.close();
+                    break;
+                }
+            }
+        }
+    }
+
+    public boolean hasListeners() {
+        boolean hasListeners;
+        synchronized (lock) {
+            if (Iterables.size(listeners.getListeners()) > 0) {
+                hasListeners = true;
+            } else {
+                hasListeners = false;
+            }
+        }
+        return hasListeners;
+    }
+
+    @Override
+    public SchemaContext getSessionContext() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public SchemaContext getGlobalContext() {
+        return contextResolver.getSchemaContext().orNull();
+    }
+
+    @Override
+    public ListenerRegistration<SchemaContextListener>
+            registerSchemaContextListener(final SchemaContextListener listener) {
+        synchronized (lock) {
+            final Optional<SchemaContext> potentialCtx = contextResolver.getSchemaContext();
+            if (potentialCtx.isPresent()) {
+                listener.onGlobalContextUpdated(potentialCtx.get());
+            }
+            return listeners.register(listener);
+        }
+    }
+
+    @Override
+    public SchemaContext getSchemaContext() {
+        return getGlobalContext();
+    }
+
+    @Override
+    public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException>
+            getSource(final SourceIdentifier sourceIdentifier) {
+        return contextResolver.getSource(sourceIdentifier);
+    }
+
+    @Override
+    public Map<Class<? extends DOMSchemaServiceExtension>, DOMSchemaServiceExtension> getSupportedExtensions() {
+        return ImmutableMap.of(DOMYangTextSourceProvider.class, this);
+    }
+
+    @Override
+    public void close() {
+        synchronized (lock) {
+            for (final ListenerRegistration<SchemaContextListener> registration : listeners) {
+                registration.close();
+            }
+        }
+    }
+}
diff --git a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivatorTest.java b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/osgi/SchemaServiceActivatorTest.java
deleted file mode 100644 (file)
index 33ac764..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright (c) 2016 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.dom.broker.osgi;
-
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Mockito.CALLS_REAL_METHODS;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-
-import java.lang.reflect.Field;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-
-public class SchemaServiceActivatorTest {
-
-    @Test
-    public void basicTest() throws Exception {
-        final BundleContext bundleContext = mock(BundleContext.class);
-        doReturn(mock(Filter.class)).when(bundleContext).createFilter(any());
-        doNothing().when(bundleContext).addBundleListener(any());
-        doReturn(new Bundle[] {}).when(bundleContext).getBundles();
-        doNothing().when(bundleContext).addServiceListener(any(), any());
-        doReturn(new ServiceReference<?>[] {}).when(bundleContext).getServiceReferences(anyString(), any());
-        doReturn(mock(ServiceRegistration.class)).when(bundleContext).registerService(any(Class.class), any(), any());
-        doNothing().when(bundleContext).removeBundleListener(any());
-        doNothing().when(bundleContext).removeServiceListener(any());
-        final SchemaServiceActivator schemaServiceActivator = new SchemaServiceActivator();
-        schemaServiceActivator.start(bundleContext);
-
-        final ServiceRegistration<?> registration = mock(ServiceRegistration.class);
-        final OsgiBundleScanningSchemaService osgiBundle =
-                mock(OsgiBundleScanningSchemaService.class, CALLS_REAL_METHODS);
-
-        final Field schemaServiceRegField = SchemaServiceActivator.class.getDeclaredField("schemaServiceReg");
-        schemaServiceRegField.setAccessible(true);
-        schemaServiceRegField.set(schemaServiceActivator, registration);
-
-        final Field schemaServiceField = SchemaServiceActivator.class.getDeclaredField("schemaService");
-        schemaServiceField.setAccessible(true);
-        schemaServiceField.set(schemaServiceActivator, osgiBundle);
-
-        doNothing().when(registration).unregister();
-        doNothing().when(osgiBundle).close();
-
-        schemaServiceActivator.stop(bundleContext);
-        verify(registration).unregister();
-        verify(osgiBundle).close();
-    }
-
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    @After
-    @Before
-    public void destroyInstance() throws Exception {
-        try {
-            OsgiBundleScanningSchemaService.getInstance();
-            OsgiBundleScanningSchemaService.destroyInstance();
-        } catch (Exception e) {
-            assertTrue(e instanceof IllegalStateException);
-        }
-    }
-}
\ No newline at end of file
diff --git a/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProviderTest.java b/dom/mdsal-dom-broker/src/test/java/org/opendaylight/mdsal/dom/broker/schema/ScanningSchemaServiceProviderTest.java
new file mode 100644 (file)
index 0000000..80c9821
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.dom.broker.schema;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.internal.util.io.IOUtil;
+import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.yangtools.yang.model.repo.api.RevisionSourceIdentifier;
+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;
+
+public class ScanningSchemaServiceProviderTest {
+
+    private ArrayList<URL> yangs;
+    private ScanningSchemaServiceProvider schemaService;
+
+    @Before
+    public void setup() {
+        yangs = new ArrayList<>();
+        addYang("/odl-datastore-test.yang");
+
+        schemaService = new ScanningSchemaServiceProvider();
+        assertNotNull(schemaService);
+        addYangs(schemaService);
+    }
+
+    @After
+    public void close() {
+        schemaService.close();
+    }
+
+    private void addYang(final String yang) {
+        yangs.add(ScanningSchemaServiceProvider.class.getResource(yang));
+    }
+
+    @Test
+    public void initJarScanningSchemaServiceTest() throws Exception {
+        assertNotNull(schemaService.getGlobalContext());
+        assertNotNull(schemaService.getSchemaContext());
+        assertEquals(schemaService.getGlobalContext(), schemaService.getSchemaContext());
+    }
+
+    @Test
+    public void listenersTests() {
+        assertFalse(schemaService.hasListeners());
+
+        final SchemaContextHolder actualSchemaCtx = new SchemaContextHolder();
+        final SchemaContextListener listener = prepareSchemaCtxListener(actualSchemaCtx);
+        final ListenerRegistration<SchemaContextListener> registerSchemaContextListener =
+                schemaService.registerSchemaContextListener(listener);
+        assertEquals(registerSchemaContextListener.getInstance(), listener);
+        assertEquals(schemaService.getSchemaContext(), actualSchemaCtx.getSchemaContext());
+    }
+
+    @Test
+    public void notifyListenersTest() {
+        final SchemaContext baseSchemaCtx = schemaService.getGlobalContext();
+        assertNotNull(baseSchemaCtx);
+        assertTrue(baseSchemaCtx.getModules().size() == 1);
+
+        final SchemaContextHolder actualSchemaCtx = new SchemaContextHolder();
+
+        final SchemaContextListener schemaCtxListener = prepareSchemaCtxListener(actualSchemaCtx);
+        final ListenerRegistration<SchemaContextListener> registerSchemaContextListener =
+                schemaService.registerSchemaContextListener(schemaCtxListener);
+        assertEquals(registerSchemaContextListener.getInstance(), schemaCtxListener);
+        assertNotNull(actualSchemaCtx.getSchemaContext());
+        assertEquals(baseSchemaCtx, actualSchemaCtx.getSchemaContext());
+
+        addYang("/empty-test1.yang");
+        addYangs(schemaService);
+
+        final SchemaContext nextSchemaCtx = schemaService.getGlobalContext();
+        assertNotNull(nextSchemaCtx);
+        assertTrue(nextSchemaCtx.getModules().size() == 2);
+
+        assertNotEquals(baseSchemaCtx, nextSchemaCtx);
+
+        schemaService.notifyListeners(nextSchemaCtx);
+        assertEquals(nextSchemaCtx, actualSchemaCtx.getSchemaContext());
+
+        addYang("/empty-test2.yang");
+        addYangs(schemaService);
+
+        final SchemaContext unregistredListenerSchemaCtx = schemaService.getGlobalContext();
+        assertNotNull(unregistredListenerSchemaCtx);
+        assertTrue(unregistredListenerSchemaCtx.getModules().size() == 3);
+
+        assertNotEquals(baseSchemaCtx, unregistredListenerSchemaCtx);
+        assertNotEquals(nextSchemaCtx, unregistredListenerSchemaCtx);
+
+        schemaService.removeListener(schemaCtxListener);
+        schemaService.notifyListeners(unregistredListenerSchemaCtx);
+
+        assertNotEquals(unregistredListenerSchemaCtx, actualSchemaCtx.getSchemaContext());
+        assertEquals(nextSchemaCtx, actualSchemaCtx.getSchemaContext());
+
+        schemaService.registerSchemaContextListener(schemaCtxListener);
+        assertEquals(unregistredListenerSchemaCtx, actualSchemaCtx.getSchemaContext());
+    }
+
+    @Test
+    public void tryToUpdateSchemaCtxTest() {
+        final SchemaContext baseSchemaContext = schemaService.getSchemaContext();
+        assertNotNull(baseSchemaContext);
+        assertTrue(baseSchemaContext.getModules().size() == 1);
+
+        final SchemaContextHolder actualSchemaCtx = new SchemaContextHolder();
+        final SchemaContextListener schemaCtxListener = prepareSchemaCtxListener(actualSchemaCtx);
+
+        schemaService.registerSchemaContextListener(schemaCtxListener);
+
+        assertEquals(baseSchemaContext, actualSchemaCtx.getSchemaContext());
+
+        addYang("/empty-test1.yang");
+        addYangs(schemaService);
+
+        final SchemaContext nextSchemaContext = schemaService.getSchemaContext();
+        assertNotNull(baseSchemaContext);
+        assertTrue(baseSchemaContext.getModules().size() == 1);
+
+        assertNotEquals(baseSchemaContext, nextSchemaContext);
+
+        schemaService.tryToUpdateSchemaContext();
+        assertEquals(nextSchemaContext, actualSchemaCtx.getSchemaContext());
+    }
+
+    @SuppressWarnings("deprecation")
+    @Test
+    public void getSourceTest() throws Exception {
+        final SourceIdentifier sourceIdentifier = RevisionSourceIdentifier.create("odl-datastore-test", "2014-03-13");
+        final CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> source =
+                schemaService.getSource(sourceIdentifier);
+        final YangTextSchemaSource yangTextSchemaSource = source.checkedGet();
+        final Collection<String> lines = IOUtil.readLines(yangTextSchemaSource.openStream());
+        assertEquals("module odl-datastore-test {", lines.iterator().next());
+    }
+
+    @Test
+    public void getSupportedExtensionsTest() {
+        assertEquals(schemaService.getSupportedExtensions().values().iterator().next(), schemaService);
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void getSessionContextTest() {
+        schemaService.getSessionContext();
+    }
+
+    private void addYangs(final ScanningSchemaServiceProvider schemaService) {
+        final List<Registration> registerAvailableYangs = schemaService.registerAvailableYangs(yangs);
+        assertTrue(!registerAvailableYangs.isEmpty());
+    }
+
+    private SchemaContextListener prepareSchemaCtxListener(final SchemaContextHolder actualSchemaCtx) {
+        return new SchemaContextListener() {
+
+            @Override
+            public void onGlobalContextUpdated(final SchemaContext context) {
+                actualSchemaCtx.setSchemaContext(context);
+            }
+        };
+    }
+
+    private class SchemaContextHolder {
+
+        private SchemaContext schemaCtx;
+
+        public void setSchemaContext(final SchemaContext ctx) {
+            schemaCtx = ctx;
+        }
+
+        public SchemaContext getSchemaContext() {
+            return schemaCtx;
+        }
+    }
+}
diff --git a/dom/mdsal-dom-broker/src/test/resources/empty-test1.yang b/dom/mdsal-dom-broker/src/test/resources/empty-test1.yang
new file mode 100644 (file)
index 0000000..002239e
--- /dev/null
@@ -0,0 +1,9 @@
+module empty-test1 {
+    yang-version 1;
+    namespace "em:tst:1";
+    prefix "empty-test-1";
+
+    revision "2017-09-13" {
+        description "Initial revision.";
+    }
+}
diff --git a/dom/mdsal-dom-broker/src/test/resources/empty-test2.yang b/dom/mdsal-dom-broker/src/test/resources/empty-test2.yang
new file mode 100644 (file)
index 0000000..c6e78e8
--- /dev/null
@@ -0,0 +1,9 @@
+module empty-test2 {
+    yang-version 1;
+    namespace "em:tst:2";
+    prefix "empty-test-2";
+
+    revision "2017-09-13" {
+        description "Initial revision.";
+    }
+}
diff --git a/dom/mdsal-dom-schema-service-osgi/pom.xml b/dom/mdsal-dom-schema-service-osgi/pom.xml
new file mode 100644 (file)
index 0000000..11d7a14
--- /dev/null
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2017 Pantheon Technologies s.r.o. 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>2.0.5</version>
+        <relativePath/>
+    </parent>
+
+    <groupId>org.opendaylight.mdsal</groupId>
+    <artifactId>mdsal-dom-schema-service-osgi</artifactId>
+    <version>2.4.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>2.4.0-SNAPSHOT</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yangtools-artifacts</artifactId>
+                <version>1.2.0-SNAPSHOT</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>com.google.guava</groupId>
+      <artifactId>guava</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.mdsal</groupId>
+      <artifactId>mdsal-dom-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.mdsal</groupId>
+      <artifactId>mdsal-dom-broker</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>util</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-data-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-parser-impl</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yang-test-util</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>mockito-configuration</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Name>osgiBundleScanningSchema</Bundle-Name>
+            <Import-Package>
+              *,
+              org.opendaylight.mdsal.dom.api
+            </Import-Package>
+          </instructions>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+    <scm>
+        <connection>scm:git:http://git.opendaylight.org/gerrit/controller.git</connection>
+        <developerConnection>scm:git:ssh://git.opendaylight.org:29418/controller.git</developerConnection>
+        <tag>HEAD</tag>
+        <url>https://wiki.opendaylight.org/view/OpenDaylight_Controller:MD-SAL:Architecture:Clustering</url>
+    </scm>
+
+
+  <!--
+      Maven Site Configuration
+
+      The following configuration is necessary for maven-site-plugin to
+      correctly identify the correct deployment path for OpenDaylight Maven
+      sites.
+  -->
+  <url>${odl.site.url}/${project.groupId}/${stream}/${project.artifactId}/</url>
+
+  <distributionManagement>
+    <site>
+      <id>opendaylight-site</id>
+      <url>${nexus.site.url}/${project.artifactId}/</url>
+    </site>
+  </distributionManagement>
+
+</project>
@@ -1,43 +1,28 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.dom.broker.osgi;
+package org.opendaylight.mdsal.dom.schema.service.osgi;
 
 import static com.google.common.base.Preconditions.checkState;
-
 import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
-import com.google.common.util.concurrent.CheckedFuture;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
-import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.GuardedBy;
-import org.opendaylight.mdsal.dom.api.DOMSchemaService;
-import org.opendaylight.mdsal.dom.api.DOMSchemaServiceExtension;
-import org.opendaylight.mdsal.dom.api.DOMYangTextSourceProvider;
-import org.opendaylight.yangtools.concepts.ListenerRegistration;
+import org.opendaylight.mdsal.dom.broker.schema.ScanningSchemaServiceProvider;
 import org.opendaylight.yangtools.concepts.Registration;
-import org.opendaylight.yangtools.util.ListenerRegistry;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
-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.parser.repo.YangTextSchemaContextResolver;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.BundleEvent;
@@ -49,24 +34,21 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class OsgiBundleScanningSchemaService implements SchemaContextProvider, DOMSchemaService,
-        ServiceTrackerCustomizer<SchemaContextListener, SchemaContextListener>, DOMYangTextSourceProvider,
-        AutoCloseable {
-    private static final Logger LOG = LoggerFactory.getLogger(OsgiBundleScanningSchemaService.class);
+public class OsgiBundleScanningSchemaService extends ScanningSchemaServiceProvider
+        implements ServiceTrackerCustomizer<SchemaContextListener, SchemaContextListener> {
 
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiBundleScanningSchemaService.class);
     private static final AtomicReference<OsgiBundleScanningSchemaService> GLOBAL_INSTANCE = new AtomicReference<>();
-
     private static final long FRAMEWORK_BUNDLE_ID = 0;
 
-    @GuardedBy("lock")
-    private final ListenerRegistry<SchemaContextListener> listeners = new ListenerRegistry<>();
-    private final YangTextSchemaContextResolver contextResolver = YangTextSchemaContextResolver.create("global-bundle");
     private final BundleScanner scanner = new BundleScanner();
-    private final Object lock = new Object();
     private final BundleContext context;
 
-    private ServiceTracker<SchemaContextListener, SchemaContextListener> listenerTracker;
+    @GuardedBy("lock")
     private BundleTracker<Iterable<Registration>> bundleTracker;
+    private final Object lock = new Object();
+
+    private ServiceTracker<SchemaContextListener, SchemaContextListener> listenerTracker;
     private boolean starting = true;
 
     private volatile boolean stopping;
@@ -76,44 +58,26 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
     }
 
     public static @Nonnull OsgiBundleScanningSchemaService createInstance(final BundleContext ctx) {
-        OsgiBundleScanningSchemaService instance = new OsgiBundleScanningSchemaService(ctx);
+        final OsgiBundleScanningSchemaService instance = new OsgiBundleScanningSchemaService(ctx);
         Preconditions.checkState(GLOBAL_INSTANCE.compareAndSet(null, instance));
         instance.start();
         return instance;
     }
 
-    public static OsgiBundleScanningSchemaService getInstance() {
-        OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.get();
-        Preconditions.checkState(instance != null, "Global Instance was not instantiated");
-        return instance;
-    }
-
-    @VisibleForTesting
-    public static void destroyInstance() {
-        OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.getAndSet(null);
-        if (instance != null) {
-            instance.close();
-        }
-    }
-
-    public BundleContext getContext() {
-        return context;
-    }
-
     private void start() {
         checkState(context != null);
         LOG.debug("start() starting");
 
         listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, this);
-        bundleTracker = new BundleTracker<>(context, Bundle.RESOLVED | Bundle.STARTING
-                | Bundle.STOPPING | Bundle.ACTIVE, scanner);
+        bundleTracker = new BundleTracker<>(context,
+                Bundle.RESOLVED | Bundle.STARTING | Bundle.STOPPING | Bundle.ACTIVE, scanner);
 
         synchronized (lock) {
             bundleTracker.open();
 
             LOG.debug("BundleTracker.open() complete");
 
-            if (Iterables.size(listeners.getListeners()) > 0) {
+            if (!hasListeners()) {
                 tryToUpdateSchemaContext();
             }
         }
@@ -124,74 +88,36 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
         LOG.debug("start() complete");
     }
 
-    @Override
-    public SchemaContext getSchemaContext() {
-        return getGlobalContext();
-    }
-
-    @Override
-    public SchemaContext getGlobalContext() {
-        return contextResolver.getSchemaContext().orNull();
+    public static OsgiBundleScanningSchemaService getInstance() {
+        final OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.get();
+        Preconditions.checkState(instance != null, "Global Instance was not instantiated");
+        return instance;
     }
 
-    @Override
-    public SchemaContext getSessionContext() {
-        throw new UnsupportedOperationException();
-    }
+    @VisibleForTesting
+    public static void destroyInstance() throws Exception {
+        final OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.getAndSet(null);
+        if (instance != null) {
 
-    @Override
-    public ListenerRegistration<SchemaContextListener> registerSchemaContextListener(
-            final SchemaContextListener listener) {
-        synchronized (lock) {
-            final Optional<SchemaContext> potentialCtx = contextResolver.getSchemaContext();
-            if (potentialCtx.isPresent()) {
-                listener.onGlobalContextUpdated(potentialCtx.get());
-            }
-            return listeners.register(listener);
+            instance.closeInstance();
         }
     }
 
-    @Override
-    public void close() {
-        synchronized (lock) {
-            stopping = true;
-            if (bundleTracker != null) {
-                bundleTracker.close();
-                bundleTracker = null;
-            }
-            if (listenerTracker != null) {
-                listenerTracker.close();
-                listenerTracker = null;
-            }
-
-            for (final ListenerRegistration<SchemaContextListener> l : listeners.getListeners()) {
-                l.close();
-            }
+    private void closeInstance() {
+        stopping = true;
+        if (bundleTracker != null) {
+            bundleTracker.close();
+            bundleTracker = null;
+        }
+        if (listenerTracker != null) {
+            listenerTracker.close();
+            listenerTracker = null;
         }
+        close();
     }
 
-    @SuppressWarnings("checkstyle:IllegalCatch")
-    @VisibleForTesting
-    @GuardedBy("lock")
-    void notifyListeners(final SchemaContext snapshot) {
-        final Object[] services = listenerTracker.getServices();
-        for (final ListenerRegistration<SchemaContextListener> listener : listeners) {
-            try {
-                listener.getInstance().onGlobalContextUpdated(snapshot);
-            } catch (final Exception e) {
-                LOG.error("Exception occured during invoking listener", e);
-            }
-        }
-        if (services != null) {
-            for (final Object rawListener : services) {
-                final SchemaContextListener listener = (SchemaContextListener) rawListener;
-                try {
-                    listener.onGlobalContextUpdated(snapshot);
-                } catch (final Exception e) {
-                    LOG.error("Exception occured during invoking listener {}", listener, e);
-                }
-            }
-        }
+    public BundleContext getContext() {
+        return context;
     }
 
     @SuppressWarnings("checkstyle:IllegalCatch")
@@ -208,24 +134,26 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
                 return Collections.emptyList();
             }
 
-            final List<Registration> urls = new ArrayList<>();
+            final List<URL> urls = new ArrayList<>();
             while (enumeration.hasMoreElements()) {
                 final URL u = enumeration.nextElement();
                 try {
-                    urls.add(contextResolver.registerSource(u));
+                    urls.add(u);
                     LOG.debug("Registered {}", u);
                 } catch (final Exception e) {
                     LOG.warn("Failed to register {}, ignoring it", e);
                 }
             }
 
-            if (!urls.isEmpty()) {
+            final List<Registration> registrations = registerAvailableYangs(urls);
+            if (!registrations.isEmpty()) {
                 LOG.debug("Loaded {} new URLs from bundle {}, attempting to rebuild schema context",
-                        urls.size(), bundle.getSymbolicName());
-                tryToUpdateSchemaContext();
+                        registrations.size(), bundle.getSymbolicName());
+                if (!starting && !stopping) {
+                    tryToUpdateSchemaContext();
+                }
             }
-
-            return ImmutableList.copyOf(urls);
+            return ImmutableList.copyOf(registrations);
         }
 
         @Override
@@ -240,9 +168,8 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
         }
 
         /**
-         * If removing YANG files makes yang store inconsistent, method
-         * {@link #getYangStoreSnapshot()} will throw exception. There is no
-         * rollback.
+         * If removing YANG files makes yang store inconsistent, method {@link #getYangStoreSnapshot()} will
+         * throw exception. There is no rollback.
          */
         @SuppressWarnings("checkstyle:IllegalCatch")
         @Override
@@ -258,43 +185,23 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
             final int numUrls = Iterables.size(urls);
             if (numUrls > 0) {
                 if (LOG.isDebugEnabled()) {
-                    LOG.debug("removedBundle: {}, state: {}, # urls: {}", bundle.getSymbolicName(),
-                            bundle.getState(), numUrls);
+                    LOG.debug("removedBundle: {}, state: {}, # urls: {}", bundle.getSymbolicName(), bundle.getState(),
+                            numUrls);
+                }
+                if (!starting && !stopping) {
+                    tryToUpdateSchemaContext();
                 }
-
-                tryToUpdateSchemaContext();
             }
         }
     }
 
     @Override
     public SchemaContextListener addingService(final ServiceReference<SchemaContextListener> reference) {
-
         final SchemaContextListener listener = context.getService(reference);
-        final SchemaContext ctxContext = getGlobalContext();
-        if (getContext() != null && ctxContext != null) {
-            listener.onGlobalContextUpdated(ctxContext);
-        }
+        registerSchemaContextListener(listener);
         return listener;
     }
 
-    public void tryToUpdateSchemaContext() {
-        if (starting || stopping) {
-            return;
-        }
-
-        synchronized (lock) {
-            final Optional<SchemaContext> schema = contextResolver.getSchemaContext();
-            if (schema.isPresent()) {
-                if (LOG.isDebugEnabled()) {
-                    LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getAllModuleIdentifiers().size());
-                }
-
-                notifyListeners(schema.get());
-            }
-        }
-    }
-
     @Override
     public void modifiedService(final ServiceReference<SchemaContextListener> reference,
             final SchemaContextListener service) {
@@ -305,16 +212,6 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D
     public void removedService(final ServiceReference<SchemaContextListener> reference,
             final SchemaContextListener service) {
         context.ungetService(reference);
-    }
-
-    @Override
-    public Map<Class<? extends DOMSchemaServiceExtension>, DOMSchemaServiceExtension> getSupportedExtensions() {
-        return ImmutableMap.of(DOMYangTextSourceProvider.class, this);
-    }
-
-    @Override
-    public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> getSource(
-            final SourceIdentifier sourceIdentifier) {
-        return contextResolver.getSource(sourceIdentifier);
+        removeListener(service);
     }
 }
diff --git a/dom/mdsal-dom-schema-service-osgi/src/main/resources/org/opendaylight/blueprint/dom-osgi-schema-service.xml b/dom/mdsal-dom-schema-service-osgi/src/main/resources/org/opendaylight/blueprint/dom-osgi-schema-service.xml
new file mode 100644 (file)
index 0000000..ae3f347
--- /dev/null
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
+
+  <bean id="osgiBundleScanningSchema" class="org.opendaylight.mdsal.dom.schema.service.osgi.OsgiBundleScanningSchemaService" factory-method="createInstance" destroy-method="close">
+    <argument ref="blueprintBundleContext" />
+  </bean>
+
+  <service ref="osgiBundleScanningSchema" interface="org.opendaylight.mdsal.dom.api.DOMSchemaService" odl:type="default" />
+
+</blueprint>
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.dom.broker.osgi;
+package org.opendaylight.mdsal.dom.schema.service.osgi;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNull;
@@ -16,11 +16,11 @@ import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
-import org.opendaylight.mdsal.dom.broker.util.TestModel;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
+import org.opendaylight.mdsal.dom.schema.service.osgi.util.TestModel;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.osgi.framework.Bundle;
@@ -54,14 +54,17 @@ public class OsgiBundleScanningSchemaServiceTest {
         try {
             OsgiBundleScanningSchemaService.getInstance();
             OsgiBundleScanningSchemaService.destroyInstance();
-        } catch (Exception e) {
+        } catch (final Exception e) {
             assertTrue(e instanceof IllegalStateException);
         }
     }
 
     @Test
     public void basicTest() throws Exception {
+        assertTrue(osgiService instanceof DOMSchemaService);
+
         final SchemaContext schemaContext = TestModel.createTestContext();
+
         final SchemaContextListener schemaContextListener = mock(SchemaContextListener.class);
         doNothing().when(schemaContextListener).onGlobalContextUpdated(schemaContext);
         osgiService.registerSchemaContextListener(schemaContextListener);
@@ -85,4 +88,4 @@ public class OsgiBundleScanningSchemaServiceTest {
     public void sessionContextTest() throws Exception {
         osgiService.getSessionContext();
     }
-}
\ No newline at end of file
+}
diff --git a/dom/mdsal-dom-schema-service-osgi/src/test/java/org/opendaylight/mdsal/dom/schema/service/osgi/util/TestModel.java b/dom/mdsal-dom-schema-service-osgi/src/test/java/org/opendaylight/mdsal/dom/schema/service/osgi/util/TestModel.java
new file mode 100644 (file)
index 0000000..752329b
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2017 Pantheon Technologies s.r.o. 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.dom.schema.service.osgi.util;
+
+import java.io.InputStream;
+import java.util.Collections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class TestModel {
+
+    public static final QName TEST_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13", "test");
+    public static final QName TEST2_QNAME =
+            QName.create("urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test", "2014-03-13", "test2");
+    public static final QName OUTER_LIST_QNAME = QName.create(TEST_QNAME, "outer-list");
+    public static final QName INNER_LIST_QNAME = QName.create(TEST_QNAME, "inner-list");
+    public static final QName OUTER_CHOICE_QNAME = QName.create(TEST_QNAME, "outer-choice");
+    public static final QName ID_QNAME = QName.create(TEST_QNAME, "id");
+    public static final QName NAME_QNAME = QName.create(TEST_QNAME, "name");
+    public static final QName VALUE_QNAME = QName.create(TEST_QNAME, "value");
+    public static final QName INNER_CONTAINER = QName.create(TEST_QNAME, "inner-container");
+    public static final QName ANOTHER_SHARD_CONTAINER = QName.create(TEST_QNAME, "another-shard");
+    public static final QName NEW_SHARD_LIST = QName.create(TEST_QNAME, "new-shard-list");
+    public static final QName SHARDED_VALUE_1 = QName.create(TEST_QNAME, "sharded-value-1");
+    public static final QName SHARDED_VALUE_2 = QName.create(TEST_QNAME, "sharded-value-2");
+    public static final QName ANOTHER_SHARD_VALUE = QName.create(TEST_QNAME, "another-shard-value");
+    public static final QName TWO_QNAME = QName.create(TEST_QNAME, "two");
+    public static final QName THREE_QNAME = QName.create(TEST_QNAME, "three");
+    public static final YangInstanceIdentifier TEST_PATH = YangInstanceIdentifier.of(TEST_QNAME);
+    public static final YangInstanceIdentifier TEST2_PATH = YangInstanceIdentifier.of(TEST2_QNAME);
+    public static final YangInstanceIdentifier OUTER_LIST_PATH =
+            YangInstanceIdentifier.builder(TEST_PATH).node(OUTER_LIST_QNAME).build();
+    public static final YangInstanceIdentifier INNER_LIST_PATH =
+            YangInstanceIdentifier.builder(OUTER_LIST_PATH).node(INNER_LIST_QNAME).build();
+    public static final YangInstanceIdentifier INNER_CONTAINER_PATH =
+            YangInstanceIdentifier.builder(TEST_PATH).node(INNER_CONTAINER).build();
+    public static final YangInstanceIdentifier ANOTHER_SHARD_PATH =
+            YangInstanceIdentifier.builder(INNER_CONTAINER_PATH).node(ANOTHER_SHARD_CONTAINER).build();
+    public static final YangInstanceIdentifier NEW_SHARD_LIST_PATH =
+            YangInstanceIdentifier.builder(ANOTHER_SHARD_PATH).node(NEW_SHARD_LIST).build();
+    private static final String DATASTORE_TEST_YANG = "/odl-datastore-test.yang";
+
+    public static SchemaContext createTestContext() throws ReactorException {
+        return YangParserTestUtils.parseYangStreams(Collections.singletonList(getInputStream()));
+    }
+
+    private static InputStream getInputStream() {
+        return TestModel.class.getResourceAsStream(DATASTORE_TEST_YANG);
+    }
+}
diff --git a/dom/mdsal-dom-schema-service-osgi/src/test/resources/odl-datastore-test.yang b/dom/mdsal-dom-schema-service-osgi/src/test/resources/odl-datastore-test.yang
new file mode 100644 (file)
index 0000000..dab777d
--- /dev/null
@@ -0,0 +1,73 @@
+module odl-datastore-test {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:controller:md:sal:dom:store:test";
+    prefix "store-test";
+
+    revision "2014-03-13" {
+        description "Initial revision.";
+    }
+
+    container test {
+        presence "presence container";
+        list outer-list {
+            key id;
+            leaf id {
+                type uint16;
+            }
+            choice outer-choice {
+                case one {
+                    leaf one {
+                        type string;
+                    }
+                }
+                case two-three {
+                    leaf two {
+                        type string;
+                    }
+                    leaf three {
+                        type string;
+                    }
+               }
+           }
+           list inner-list {
+                key name;
+                leaf name {
+                    type string;
+                }
+                leaf value {
+                    type string;
+                }
+            }
+        }
+
+        container inner-container {
+
+            leaf sharded-value-1 {
+                type string;
+            }
+
+            leaf sharded-value-2 {
+                type string;
+            }
+
+            container another-shard {
+                list new-shard-list {
+                    key name;
+                    leaf name {
+                        type string;
+                    }
+                    leaf value {
+                        type string;
+                    }
+                }
+
+                leaf another-shard-value {
+                    type string;
+                }
+            }
+        }
+    }
+
+    container test2 {
+    }
+}
index 5eadc9e6a8e4f7e581fa5a2bf5d6a3390e869719..699d60bfe68aa6490739b43ae66c2fed6f7b6b58 100644 (file)
@@ -29,6 +29,7 @@
         <module>mdsal-dom-spi</module>
         <module>mdsal-dom-broker</module>
         <module>mdsal-dom-inmemory-datastore</module>
+        <module>mdsal-dom-schema-service-osgi</module>
     </modules>
 
   <!--