Add ability to listen for change notifications to yang-store. Listeners get notified when
new yang files are found in bundles and also when bundle with yang files is stopped.
Change-Id: I7c665a57ba7face18bf128d6a7db17c1a23526ce
Signed-off-by: Tomas Olvecky <tolvecky@cisco.com>
<controller.version>0.4.1-SNAPSHOT</controller.version>
<config.version>0.2.1-SNAPSHOT</config.version>
<netconf.version>0.2.2-SNAPSHOT</netconf.version>
+ <config.yangstore.version>0.2.2-SNAPSHOT</config.yangstore.version>
<mdsal.version>1.0-SNAPSHOT</mdsal.version>
<containermanager.version>0.5.1-SNAPSHOT</containermanager.version>
<switchmanager.api.version>0.5.1-SNAPSHOT</switchmanager.api.version>
<artifactId>yang-store-api</artifactId>
<name>${project.artifactId}</name>
<packaging>bundle</packaging>
+ <version>${config.yangstore.version}</version>
<dependencies>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-jmx-generator</artifactId>
- <version>0.2.1-SNAPSHOT</version>
+ <version>${config.version}</version>
</dependency>
</dependencies>
<artifactId>maven-bundle-plugin</artifactId>
<configuration>
<instructions>
-
- <Private-Package>
- </Private-Package>
-
<Import-Package>
org.opendaylight.controller.config.yangjmxgenerator,
org.opendaylight.yangtools.yang.model.api
</Import-Package>
<Export-Package>
- org.opendaylight.controller.config.yang.store.api
+ org.opendaylight.controller.config.yang.store.api,
+ org.opendaylight.controller.config.yang.store.spi
</Export-Package>
</instructions>
</configuration>
</plugin>
- <!-- test jar -->
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- </plugin>
</plugins>
</build>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.store.api;
+
+public interface YangStoreListenerRegistration extends AutoCloseable {
+
+ @Override
+ void close();
+}
*/
package org.opendaylight.controller.config.yang.store.api;
+import org.opendaylight.controller.config.yang.store.spi.YangStoreListener;
+
/**
* Yang store OSGi service
*/
*/
YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException;
+
+ /**
+ * Allows for registering for change notifications.
+ */
+ YangStoreListenerRegistration registerListener(YangStoreListener listener);
+
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yang.store.spi;
+
+import java.net.URL;
+import java.util.Collection;
+
+/**
+ * Implementation of this interface gets notified when bundle containing yang files in META-INF/yang has been
+ * added or removed. One notification is sent per one bundle.
+ */
+public interface YangStoreListener {
+
+ void onAddedYangURL(Collection<URL> url);
+
+ void onRemovedYangURL(Collection<URL> url);
+
+}
<artifactId>yang-store-impl</artifactId>
<name>${project.artifactId}</name>
<packaging>bundle</packaging>
+ <version>${config.yangstore.version}</version>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-store-api</artifactId>
- <version>0.2.1-SNAPSHOT</version>
+ <version>${config.yangstore.version}</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-jmx-generator</artifactId>
- <version>0.2.1-SNAPSHOT</version>
+ <version>${config.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<Import-Package>
org.opendaylight.controller.config.yang.store.api,
+ org.opendaylight.controller.config.yang.store.spi,
org.opendaylight.controller.config.yangjmxgenerator,
com.google.common.base,
com.google.common.collect,
org.osgi.framework,
org.osgi.util.tracker,
org.slf4j,
- javax.*,
<!-- YANGTOOLS -->
org.opendaylight.yangtools.sal.binding.yang.types,
org.opendaylight.yangtools.yang.common,
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.Set;
+import java.util.*;
import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.api.YangStoreListenerRegistration;
import org.opendaylight.controller.config.yang.store.api.YangStoreService;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yang.store.spi.YangStoreListener;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
.create();
private final YangStoreCache cache = new YangStoreCache();
private final MbeParser mbeParser;
+ private final List<YangStoreListener> listeners = new ArrayList<>();
public ExtenderYangTracker(BundleContext context) {
this(context, new MbeParser());
@Override
public Object addingBundle(Bundle bundle, BundleEvent event) {
- // Ignore system bundle
- //
- // system bundle has config-api on classpath &&
+ // Ignore system bundle:
+ // system bundle might have config-api on classpath &&
// config-api contains yang files =>
- // system bundle contains yang files from that bundle
+ // system bundle might contain yang files from that bundle
if (bundle.getBundleId() == 0)
return bundle;
- Enumeration<URL> yangURLs = bundle.findEntries("META-INF/yang",
- "*.yang", false);
-
- if (yangURLs == null)
- return bundle;
-
- synchronized (this) {
- while (yangURLs.hasMoreElements()) {
- URL yang = yangURLs.nextElement();
- logger.debug("Bundle {} found yang file {}", bundle, yang);
- bundlesToYangURLs.put(bundle, yang);
+ Enumeration<URL> yangURLs = bundle.findEntries("META-INF/yang", "*.yang", false);
+ if (yangURLs != null) {
+ synchronized (this) {
+ while (yangURLs.hasMoreElements()) {
+ URL url = yangURLs.nextElement();
+ logger.debug("Bundle {} found yang file {}", bundle, url);
+ bundlesToYangURLs.put(bundle, url);
+ }
+ Collection<URL> urls = bundlesToYangURLs.get(bundle);
+ notifyListeners(urls, true);
}
}
-
return bundle;
}
+ private void notifyListeners(Collection<URL> urls, boolean adding) {
+ if (urls.size() > 0) {
+ RuntimeException potential = new RuntimeException("Error while notifying listeners");
+ for (YangStoreListener listener : listeners) {
+ try {
+ if (adding) {
+ listener.onAddedYangURL(urls);
+ } else {
+ listener.onRemovedYangURL(urls);
+ }
+ } catch(RuntimeException e) {
+ potential.addSuppressed(e);
+ }
+ }
+ if (potential.getSuppressed().length > 0) {
+ throw potential;
+ }
+ }
+ }
+
@Override
- public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
- synchronized (this) {
- Collection<URL> urls = bundlesToYangURLs.removeAll(bundle);
- logger.debug(
- "Removed following yang URLs {} because of removed bundle {}",
- urls, bundle);
+ public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+ Collection<URL> urls = bundlesToYangURLs.removeAll(bundle);
+ if (urls.size() > 0) {
+ logger.debug("Removed following yang URLs {} because of removed bundle {}", urls, bundle);
+ notifyListeners(urls, false);
}
}
});
}
+ @Override
+ public synchronized YangStoreListenerRegistration registerListener(final YangStoreListener listener) {
+ listeners.add(listener);
+ return new YangStoreListenerRegistration() {
+ @Override
+ public void close() {
+ listeners.remove(listener);
+ }
+ };
+ }
+
private static final class YangStoreCache {
Set<URL> cachedUrls;
import org.apache.commons.io.IOUtils;
import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.api.YangStoreListenerRegistration;
import org.opendaylight.controller.config.yang.store.api.YangStoreService;
import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
+import org.opendaylight.controller.config.yang.store.spi.YangStoreListener;
public class HardcodedYangStoreService implements YangStoreService {
}
return new MbeParser().parseYangFiles(byteArrayInputStreams);
}
+
+ @Override
+ public YangStoreListenerRegistration registerListener(YangStoreListener listener){
+ throw new UnsupportedOperationException("Cannot register for changes on this service");
+ }
}
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-store-api</artifactId>
- <version>${config.version}</version>
+ <version>${config.yangstore.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<artifactId>yang-store-impl</artifactId>
- <version>${config.version}</version>
+ <version>${config.yangstore.version}</version>
</dependency>
<dependency>
<groupId>org.opendaylight.controller</groupId>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-store-api</artifactId>
- <version>${config.version}</version>
+ <version>${config.yangstore.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>yang-store-impl</artifactId>
- <version>${config.version}</version>
+ <version>${config.yangstore.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>