BUG-8360: add mdsal-binding-dom-codec-osgi 80/56480/8
authorRobert Varga <robert.varga@pantheon.tech>
Wed, 3 May 2017 11:21:54 +0000 (13:21 +0200)
committerMartin Ciglan <mciglan@cisco.com>
Tue, 9 May 2017 07:43:32 +0000 (07:43 +0000)
This is an OSGi binding producing all context needed required
to implement binding/dom/external serialization. It is similar
to how the config-manager service operates, except associated
services are explicitly covered instead of sneaking them through
properties.

Change-Id: I31f2bdb11153d6e514dacf2b070b073d768c1ff3
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
12 files changed:
binding/mdsal-binding-dom-codec-osgi/pom.xml [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextListener.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextService.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/Activator.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/ModuleInfoBundleTracker.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OsgiModuleInfoRegistry.java [new file with mode: 0644]
binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/SimpleBindingRuntimeContextService.java [new file with mode: 0644]
binding/pom.xml
common/artifacts/pom.xml
common/features/features-mdsal/pom.xml
common/features/features-mdsal/src/main/features/features.xml
common/features/odl-mdsal-binding-runtime/pom.xml

diff --git a/binding/mdsal-binding-dom-codec-osgi/pom.xml b/binding/mdsal-binding-dom-codec-osgi/pom.xml
new file mode 100644 (file)
index 0000000..1785cda
--- /dev/null
@@ -0,0 +1,102 @@
+<?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">
+
+    <parent>
+        <groupId>org.opendaylight.odlparent</groupId>
+        <artifactId>bundle-parent</artifactId>
+        <version>1.9.0-SNAPSHOT</version>
+        <relativePath/>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.opendaylight.mdsal</groupId>
+    <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+    <version>0.11.0-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-artifacts</artifactId>
+                <version>2.3.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.opendaylight.mdsal</groupId>
+            <artifactId>mdsal-binding-dom-codec</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>mockito-configuration</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-test-util</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>${project.groupId}.${project.artifactId}</Bundle-Name>
+                        <Activator>org.opendaylight.mdsal.binding.dom.codec.osgi.impl.Activator</Activator>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+  <!--
+      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>
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextListener.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextListener.java
new file mode 100644 (file)
index 0000000..7537e25
--- /dev/null
@@ -0,0 +1,17 @@
+/*
+ * 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.binding.dom.codec.osgi;
+
+import java.util.EventListener;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+
+@Deprecated
+public interface BindingRuntimeContextListener extends EventListener {
+
+    void onBindingRuntimeContextUpdated(BindingRuntimeContext context);
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextService.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/BindingRuntimeContextService.java
new file mode 100644 (file)
index 0000000..86ba87b
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * 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.binding.dom.codec.osgi;
+
+import com.google.common.annotations.Beta;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceProvider;
+
+/**
+ * A {@link BindingRuntimeContext} enriched with the ability to look up {@link YangTextSchemaSource}s.
+ *
+ * @author Robert Varga
+ *
+ * @deprecated This service is exposed for transition purposes only.
+ */
+@Deprecated
+@Beta
+public interface BindingRuntimeContextService extends SchemaSourceProvider<YangTextSchemaSource> {
+    /**
+     * Return the current {@link BindingRuntimeContext}.
+     *
+     * @return Current BindingRuntimeContext.
+     */
+    BindingRuntimeContext getBindingRuntimeContext();
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/Activator.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/Activator.java
new file mode 100644 (file)
index 0000000..dd51b15
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * 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.binding.dom.codec.osgi.impl;
+
+import java.util.Collection;
+import org.opendaylight.mdsal.binding.dom.codec.osgi.BindingRuntimeContextService;
+import org.opendaylight.mdsal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.BundleTracker;
+
+public final class Activator implements BundleActivator {
+    private BundleTracker<Collection<ObjectRegistration<YangModuleInfo>>> moduleInfoResolvedBundleTracker;
+    private SimpleBindingRuntimeContextService service;
+    private ServiceRegistration<?> registration;
+
+    @Override
+    public void start(final BundleContext context) {
+        // XXX: this will use thread-context class loader, which is probably appropriate
+        final ModuleInfoBackedContext moduleInfoBackedContext = ModuleInfoBackedContext.create();
+
+        service = new SimpleBindingRuntimeContextService(context, moduleInfoBackedContext, moduleInfoBackedContext);
+
+        final OsgiModuleInfoRegistry registry = new OsgiModuleInfoRegistry(moduleInfoBackedContext,
+            moduleInfoBackedContext, service);
+
+        final ModuleInfoBundleTracker moduleInfoTracker = new ModuleInfoBundleTracker(registry);
+        moduleInfoResolvedBundleTracker = new BundleTracker<>(context, Bundle.RESOLVED | Bundle.STARTING
+                | Bundle.STOPPING | Bundle.ACTIVE, moduleInfoTracker);
+        moduleInfoResolvedBundleTracker.open();
+        moduleInfoTracker.finishStart();
+
+        service.open();
+        registration = context.registerService(BindingRuntimeContextService.class, service, null);
+    }
+
+    @Override
+    public void stop(final BundleContext context) {
+        moduleInfoResolvedBundleTracker.close();
+        service.close();
+        registration.unregister();
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/ModuleInfoBundleTracker.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/ModuleInfoBundleTracker.java
new file mode 100644 (file)
index 0000000..fd93e31
--- /dev/null
@@ -0,0 +1,165 @@
+/*
+ * 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.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.io.Resources;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.regex.Pattern;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.YangModelBindingProvider;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tracks bundles and attempts to retrieve YangModuleInfo, which is then fed into ModuleInfoRegistry
+ */
+final class ModuleInfoBundleTracker implements BundleTrackerCustomizer<Collection<ObjectRegistration<YangModuleInfo>>> {
+    private static final Logger LOG = LoggerFactory.getLogger(ModuleInfoBundleTracker.class);
+    // FIXME: this should be in a place shared with maven-sal-api-gen-plugin
+    private static final String MODULE_INFO_PROVIDER_PATH_PREFIX = "META-INF/services/";
+
+    private static final String YANG_MODLE_BINDING_PROVIDER_SERVICE = MODULE_INFO_PROVIDER_PATH_PREFIX
+            + YangModelBindingProvider.class.getName();
+
+    private static final Pattern BRACE_PATTERN = Pattern.compile("{}", Pattern.LITERAL);
+
+    private final OsgiModuleInfoRegistry moduleInfoRegistry;
+
+    private volatile boolean starting = true;
+
+    ModuleInfoBundleTracker(final OsgiModuleInfoRegistry moduleInfoRegistry) {
+        this.moduleInfoRegistry = checkNotNull(moduleInfoRegistry);
+    }
+
+    void finishStart() {
+        starting = false;
+        moduleInfoRegistry.updateService();
+    }
+
+    @Override
+    public Collection<ObjectRegistration<YangModuleInfo>> addingBundle(final Bundle bundle, final BundleEvent event) {
+        final URL resource = bundle.getEntry(YANG_MODLE_BINDING_PROVIDER_SERVICE);
+        if (resource == null) {
+            LOG.debug("Bundle {} does not have an entry for {}", bundle, YANG_MODLE_BINDING_PROVIDER_SERVICE);
+            return ImmutableList.of();
+        }
+
+        LOG.debug("Got addingBundle({}) with YangModelBindingProvider resource {}", bundle, resource);
+        final List<String> lines;
+        try {
+            lines = Resources.readLines(resource, StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            LOG.error("Error while reading {} from bundle {}", resource, bundle, e);
+            return ImmutableList.of();
+        }
+
+        if (lines.isEmpty()) {
+            LOG.debug("Bundle {} has empty services for {}", bundle, YANG_MODLE_BINDING_PROVIDER_SERVICE);
+            return ImmutableList.of();
+        }
+
+        final List<ObjectRegistration<YangModuleInfo>> registrations = new ArrayList<>(lines.size());
+        for (String moduleInfoName : lines) {
+            LOG.trace("Retrieve ModuleInfo({}, {})", moduleInfoName, bundle);
+            final YangModuleInfo moduleInfo;
+            try {
+                moduleInfo = retrieveModuleInfo(moduleInfoName, bundle);
+            } catch (RuntimeException e) {
+                LOG.warn("Failed to acquire {} from bundle {}, ignoring it", moduleInfoName, bundle, e);
+                continue;
+            }
+
+            registrations.add(moduleInfoRegistry.registerModuleInfo(moduleInfo));
+        }
+
+        if (!starting) {
+            moduleInfoRegistry.updateService();
+        }
+
+        LOG.trace("Bundle {} resultend in registrations {}", registrations);
+        return registrations;
+    }
+
+    @Override
+    public void modifiedBundle(final Bundle bundle, final BundleEvent event,
+            final Collection<ObjectRegistration<YangModuleInfo>> object) {
+        // No-op
+    }
+
+    @Override
+    public void removedBundle(final Bundle bundle, final BundleEvent event,
+            final Collection<ObjectRegistration<YangModuleInfo>> regs) {
+        if (regs == null) {
+            return;
+        }
+
+        for (ObjectRegistration<YangModuleInfo> reg : regs) {
+            try {
+                reg.close();
+            } catch (Exception e) {
+                LOG.warn("Unable to unregister YangModuleInfo {}", reg.getInstance(), e);
+            }
+        }
+    }
+
+    private static YangModuleInfo retrieveModuleInfo(final String moduleInfoClass, final Bundle bundle) {
+        final Class<?> clazz = loadClass(moduleInfoClass, bundle);
+        if (!YangModelBindingProvider.class.isAssignableFrom(clazz)) {
+            String errorMessage = logMessage("Class {} does not implement {} in bundle {}", clazz,
+                YangModelBindingProvider.class, bundle);
+            throw new IllegalStateException(errorMessage);
+        }
+
+        final YangModelBindingProvider instance;
+        try {
+            Object instanceObj = clazz.newInstance();
+            instance = YangModelBindingProvider.class.cast(instanceObj);
+        } catch (InstantiationException e) {
+            String errorMessage = logMessage("Could not instantiate {} in bundle {}, reason {}", moduleInfoClass,
+                bundle, e);
+            throw new IllegalStateException(errorMessage, e);
+        } catch (IllegalAccessException e) {
+            String errorMessage = logMessage("Illegal access during instantiation of class {} in bundle {}, reason {}",
+                    moduleInfoClass, bundle, e);
+            throw new IllegalStateException(errorMessage, e);
+        }
+
+        try {
+            return instance.getModuleInfo();
+        } catch (NoClassDefFoundError | ExceptionInInitializerError e) {
+            throw new IllegalStateException("Error while executing getModuleInfo on " + instance, e);
+        }
+    }
+
+    private static Class<?> loadClass(final String moduleInfoClass, final Bundle bundle) {
+        try {
+            return bundle.loadClass(moduleInfoClass);
+        } catch (ClassNotFoundException e) {
+            String errorMessage = logMessage("Could not find class {} in bundle {}, reason {}", moduleInfoClass, bundle,
+                e);
+            throw new IllegalStateException(errorMessage);
+        }
+    }
+
+    private static String logMessage(final String slfMessage, final Object... params) {
+        LOG.info(slfMessage, params);
+        return String.format(BRACE_PATTERN.matcher(slfMessage).replaceAll("%s"), params);
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OsgiModuleInfoRegistry.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/OsgiModuleInfoRegistry.java
new file mode 100644 (file)
index 0000000..6b63cf8
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.mdsal.binding.generator.api.ModuleInfoRegistry;
+import org.opendaylight.yangtools.concepts.ObjectRegistration;
+import org.opendaylight.yangtools.yang.binding.YangModuleInfo;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Update SchemaContext service in Service Registry each time new YangModuleInfo is added or removed.
+ */
+final class OsgiModuleInfoRegistry implements ModuleInfoRegistry {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiModuleInfoRegistry.class);
+
+    private final SimpleBindingRuntimeContextService runtimeContext;
+    private final SchemaContextProvider schemaContextProvider;
+    private final ModuleInfoRegistry moduleInfoRegistry;
+
+    @GuardedBy("this")
+    private ServiceRegistration<?> registration;
+    @GuardedBy("this")
+    private long generation;
+
+    OsgiModuleInfoRegistry(final ModuleInfoRegistry moduleInfoRegistry,
+        final SchemaContextProvider schemaContextProvider, final SimpleBindingRuntimeContextService runtimeContext) {
+
+        this.moduleInfoRegistry = checkNotNull(moduleInfoRegistry);
+        this.schemaContextProvider = checkNotNull(schemaContextProvider);
+        this.runtimeContext = checkNotNull(runtimeContext);
+    }
+
+    synchronized void updateService() {
+        final SchemaContext context;
+        try {
+            context = schemaContextProvider.getSchemaContext();
+        } catch (final RuntimeException e) {
+            // The ModuleInfoBackedContext throws a RuntimeException if it can't create the schema context.
+            LOG.error("Error updating the schema context", e);
+            return;
+        }
+
+        try {
+            runtimeContext.updateBindingRuntimeContext(context);
+        } catch (final RuntimeException e) {
+            LOG.error("Error updating binding runtime context", e);
+            return;
+        }
+    }
+
+    @Override
+    public ObjectRegistration<YangModuleInfo> registerModuleInfo(final YangModuleInfo yangModuleInfo) {
+        return new ObjectRegistrationWrapper(moduleInfoRegistry.registerModuleInfo(yangModuleInfo));
+    }
+
+    private class ObjectRegistrationWrapper implements ObjectRegistration<YangModuleInfo> {
+        private final ObjectRegistration<YangModuleInfo> inner;
+
+        ObjectRegistrationWrapper(final ObjectRegistration<YangModuleInfo> inner) {
+            this.inner = checkNotNull(inner);
+        }
+
+        @Override
+        public YangModuleInfo getInstance() {
+            return inner.getInstance();
+        }
+
+        @Override
+        public void close() throws Exception {
+            try {
+                inner.close();
+            } finally {
+                // send modify event when a bundle disappears
+                updateService();
+            }
+        }
+
+        @Override
+        public String toString() {
+            return inner.toString();
+        }
+    }
+}
diff --git a/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/SimpleBindingRuntimeContextService.java b/binding/mdsal-binding-dom-codec-osgi/src/main/java/org/opendaylight/mdsal/binding/dom/codec/osgi/impl/SimpleBindingRuntimeContextService.java
new file mode 100644 (file)
index 0000000..3ebdbcb
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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.binding.dom.codec.osgi.impl;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.base.Verify.verifyNotNull;
+
+import com.google.common.util.concurrent.CheckedFuture;
+import javax.annotation.concurrent.GuardedBy;
+import org.opendaylight.mdsal.binding.dom.codec.osgi.BindingRuntimeContextListener;
+import org.opendaylight.mdsal.binding.dom.codec.osgi.BindingRuntimeContextService;
+import org.opendaylight.mdsal.binding.generator.api.ClassLoadingStrategy;
+import org.opendaylight.mdsal.binding.generator.util.BindingRuntimeContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+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.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+@Deprecated
+final class SimpleBindingRuntimeContextService extends
+        ServiceTracker<BindingRuntimeContextListener, BindingRuntimeContextListener>
+        implements BindingRuntimeContextService {
+    private final SchemaSourceProvider<YangTextSchemaSource> sourceProvider;
+    private final ClassLoadingStrategy strategy;
+    private final Object lock = new Object();
+
+    @GuardedBy("lock")
+    private BindingRuntimeContext current;
+
+    SimpleBindingRuntimeContextService(final BundleContext context, final ClassLoadingStrategy strategy,
+        final SchemaSourceProvider<YangTextSchemaSource> sourceProvider) {
+        super(context, BindingRuntimeContextListener.class, null);
+        this.sourceProvider = checkNotNull(sourceProvider);
+        this.strategy = checkNotNull(strategy);
+    }
+
+    @Override
+    public CheckedFuture<? extends YangTextSchemaSource, SchemaSourceException> getSource(
+            final SourceIdentifier sourceIdentifier) {
+        return sourceProvider.getSource(sourceIdentifier);
+    }
+
+    @Override
+    public BindingRuntimeContext getBindingRuntimeContext() {
+        synchronized (lock) {
+            checkState(current != null, "Runtime context is not initialized yet");
+            return current;
+        }
+    }
+
+    void updateBindingRuntimeContext(final SchemaContext schemaContext) {
+        final BindingRuntimeContext next = verifyNotNull(BindingRuntimeContext.create(strategy, schemaContext));
+
+        final BindingRuntimeContextListener[] listeners;
+        synchronized (lock) {
+            current = next;
+            listeners = this.getServices(new BindingRuntimeContextListener[0]);
+        }
+
+        for (BindingRuntimeContextListener l : listeners) {
+            l.onBindingRuntimeContextUpdated(next);
+        }
+    }
+
+    @Override
+    public BindingRuntimeContextListener addingService(
+            final ServiceReference<BindingRuntimeContextListener> reference) {
+        final BindingRuntimeContextListener listener = super.addingService(reference);
+
+        synchronized (lock) {
+            listener.onBindingRuntimeContextUpdated(current);
+        }
+
+        return listener;
+    }
+}
index dfd516e481752394a06f718592901f285c1ff6f5..4699bf3f49e607534419f999322efde7ff04a087 100644 (file)
@@ -35,6 +35,7 @@
 
         <module>mdsal-binding-test-model</module>
         <module>mdsal-binding-dom-codec</module>
+        <module>mdsal-binding-dom-codec-osgi</module>
 
         <module>mdsal-binding-api</module>
         <module>mdsal-binding-util</module>
index d8cb9acdb1e0ccbab5aef4042d5c35c886223079..1844e878bd55deff15e987bdb40c75b06633e2e9 100644 (file)
                 <artifactId>mdsal-binding-dom-codec</artifactId>
                 <version>0.11.0-SNAPSHOT</version>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.mdsal</groupId>
+                <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+                <version>0.11.0-SNAPSHOT</version>
+            </dependency>
 
             <dependency>
                 <groupId>org.opendaylight.mdsal</groupId>
index 11dd745603ed01507225a515afece2f78dde38aa..7428c275de86247664c8e5bad5fb80d28a7022cd 100644 (file)
             <groupId>${project.groupId}</groupId>
             <artifactId>mdsal-binding-dom-codec</artifactId>
         </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>${project.groupId}</groupId>
index 43311d60711d966dc30291ead39a8b3ee20ef84a..e4cc848bc8e0aaadaa684655cb6a229c3b55258a 100644 (file)
@@ -58,6 +58,7 @@
         <bundle>mvn:org.opendaylight.mdsal/mdsal-binding-generator-impl/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.mdsal/mdsal-binding-generator-util/{{VERSION}}</bundle>
         <bundle>mvn:org.opendaylight.mdsal/mdsal-binding-dom-codec/{{VERSION}}</bundle>
+        <bundle>mvn:org.opendaylight.mdsal/mdsal-binding-dom-codec-osgi/{{VERSION}}</bundle>
     </feature>
 
     <feature name='odl-mdsal-binding-api' version='${project.version}' description='OpenDaylight :: MD-SAL :: Binding Base Concepts'>
index b171cd9532e355ac92adb7c4c88232fb85dfa42a..4d2096f077ca4928f6378e32471eda14d9b4b389 100644 (file)
@@ -71,7 +71,7 @@
         </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
-            <artifactId>mdsal-binding-dom-codec</artifactId>
+            <artifactId>mdsal-binding-dom-codec-osgi</artifactId>
         </dependency>
     </dependencies>
 
@@ -91,4 +91,4 @@
         </site>
     </distributionManagement>
 
-</project>
\ No newline at end of file
+</project>