Add blacklist capability to yang-store-impl. 80/2880/2
authorTomas Olvecky <tolvecky@cisco.com>
Tue, 19 Nov 2013 17:13:07 +0000 (18:13 +0100)
committerTomas Olvecky <tolvecky@cisco.com>
Wed, 20 Nov 2013 09:29:38 +0000 (10:29 +0100)
Add blacklist to overcome yuma problems when parsing buggy yang files in md-sal.

Change-Id: Iaf222ac627317a48619beadaebb2a16073edac9d
Signed-off-by: Tomas Olvecky <tolvecky@cisco.com>
12 files changed:
opendaylight/config/yang-store-api/pom.xml
opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/api/YangStoreListenerRegistration.java [deleted file]
opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/api/YangStoreService.java
opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/spi/YangStoreListener.java [deleted file]
opendaylight/config/yang-store-impl/pom.xml
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTracker.java [moved from opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTrackerCustomizer.java with 51% similarity]
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/MbeParser.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreActivator.java
opendaylight/config/yang-store-impl/src/main/java/org/opendaylight/controller/config/yang/store/impl/YangStoreSnapshotImpl.java
opendaylight/config/yang-store-impl/src/test/java/org/opendaylight/controller/config/yang/store/impl/ExtenderYangTrackerCustomizerTest.java
opendaylight/config/yang-store-impl/src/test/java/org/opendaylight/controller/config/yang/store/impl/HardcodedYangStoreService.java
opendaylight/distribution/opendaylight/src/main/resources/configuration/config.ini

index 9b103df8d7f8900e7e474bf0e777ec30805670f4..382dced3e754b08e8f4c593b3fca2ae9bcb11eaf 100644 (file)
@@ -13,7 +13,7 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.opendaylight.controller</groupId>
+            <groupId>${project.groupId}</groupId>
             <artifactId>yang-jmx-generator</artifactId>
         </dependency>
     </dependencies>
@@ -31,7 +31,6 @@
                         </Import-Package>
                         <Export-Package>
                             org.opendaylight.controller.config.yang.store.api,
-                            org.opendaylight.controller.config.yang.store.spi
                         </Export-Package>
                     </instructions>
                 </configuration>
diff --git a/opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/api/YangStoreListenerRegistration.java b/opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/api/YangStoreListenerRegistration.java
deleted file mode 100644 (file)
index 8101595..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.controller.config.yang.store.api;
-
-public interface YangStoreListenerRegistration extends AutoCloseable {
-
-    @Override
-    void close();
-}
index 3ac4b84fdb2e1b203d9508dfb01f16b0db76af08..15619a88cc41b3ac88e59469b3e72563de0e1b5c 100644 (file)
@@ -7,8 +7,6 @@
  */
 package org.opendaylight.controller.config.yang.store.api;
 
-import org.opendaylight.controller.config.yang.store.spi.YangStoreListener;
-
 /**
  * Yang store OSGi service
  */
@@ -21,10 +19,4 @@ public interface YangStoreService {
      */
     YangStoreSnapshot getYangStoreSnapshot() throws YangStoreException;
 
-
-    /**
-     * Allows for registering for change notifications.
-     */
-    YangStoreListenerRegistration registerListener(YangStoreListener listener);
-
 }
diff --git a/opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/spi/YangStoreListener.java b/opendaylight/config/yang-store-api/src/main/java/org/opendaylight/controller/config/yang/store/spi/YangStoreListener.java
deleted file mode 100644 (file)
index 72c3d34..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.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);
-
-}
index ae59dde26ca461ee844df5486ae50fd6367a76b9..7b79c831f84477253bdcf647303631ebdc8e2f13 100644 (file)
             <artifactId>mockito-configuration</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.findbugs</groupId>
+            <artifactId>jsr305</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
                 <artifactId>maven-bundle-plugin</artifactId>
                 <configuration>
                     <instructions>
-                        <Bundle-Activator>org.opendaylight.controller.config.yang.store.impl.YangStoreActivator
-                        </Bundle-Activator>
-                        <Private-Package>
-                            org.opendaylight.controller.config.yang.store.impl,
-                        </Private-Package>
-
+                        <Bundle-Activator>org.opendaylight.controller.config.yang.store.impl.YangStoreActivator</Bundle-Activator>
                         <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,
@@ -76,7 +74,7 @@
                             org.opendaylight.yangtools.yang.common,
                             org.opendaylight.yangtools.yang.model.api,
                             org.opendaylight.yangtools.sal.binding.generator.spi,
-                            org.opendaylight.yangtools.yang.parser.impl
+                            org.opendaylight.yangtools.yang.parser.impl,
                         </Import-Package>
                         <Export-Package>
                         </Export-Package>
@@ -16,24 +16,27 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Sets;
 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;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.osgi.util.tracker.BundleTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.concurrent.GuardedBy;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
 import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Note on consistency:
@@ -41,10 +44,9 @@ import java.util.Set;
  * is not preserved. We thus maintain two maps, one containing consistent snapshot, other inconsistent. The
  * container should eventually send all events and thus making the inconsistent map redundant.
  */
-public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Object>, YangStoreService {
+public class ExtenderYangTracker extends BundleTracker<Object> implements YangStoreService, AutoCloseable {
 
-    private static final Logger logger = LoggerFactory
-            .getLogger(ExtenderYangTrackerCustomizer.class);
+    private static final Logger logger = LoggerFactory.getLogger(ExtenderYangTracker.class);
 
     private final Multimap<Bundle, URL> consistentBundlesToYangURLs = HashMultimap.create();
 
@@ -55,20 +57,25 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
 
     private final YangStoreCache cache = new YangStoreCache();
     private final MbeParser mbeParser;
-    private final List<YangStoreListener> listeners = new ArrayList<>();
 
-    public ExtenderYangTrackerCustomizer() {
-        this(new MbeParser());
 
+    public ExtenderYangTracker(Optional<Pattern> maybeBlacklist, BundleContext bundleContext) {
+        this(new MbeParser(), maybeBlacklist, bundleContext);
     }
 
+    @GuardedBy("this")
+    private Optional<Pattern> maybeBlacklist;
+
     @VisibleForTesting
-    ExtenderYangTrackerCustomizer(MbeParser mbeParser) {
+    ExtenderYangTracker(MbeParser mbeParser, Optional<Pattern> maybeBlacklist, BundleContext bundleContext) {
+        super(bundleContext, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, null);
         this.mbeParser = mbeParser;
+        this.maybeBlacklist = maybeBlacklist;
+        open();
     }
 
     @Override
-    public Object addingBundle(Bundle bundle, BundleEvent event) {
+    public synchronized Object addingBundle(Bundle bundle, BundleEvent event) {
 
         // Ignore system bundle:
         // system bundle might have config-api on classpath &&
@@ -77,6 +84,14 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
         if (bundle.getBundleId() == 0)
             return bundle;
 
+        if (maybeBlacklist.isPresent()) {
+            Matcher m = maybeBlacklist.get().matcher(bundle.getSymbolicName());
+            if (m.matches()) {
+                logger.debug("Ignoring {} because it is in blacklist {}", bundle, maybeBlacklist);
+                return bundle;
+            }
+        }
+
         Enumeration<URL> enumeration = bundle.findEntries("META-INF/yang", "*.yang", false);
         if (enumeration != null && enumeration.hasMoreElements()) {
             synchronized (this) {
@@ -90,8 +105,32 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
                 Multimap<Bundle, URL> proposedNewState = HashMultimap.create(consistentBundlesToYangURLs);
                 proposedNewState.putAll(inconsistentBundlesToYangURLs);
                 proposedNewState.putAll(bundle, addedURLs);
-                boolean adding = true;
-                if (tryToUpdateState(addedURLs, proposedNewState, adding) == false) {
+
+                Preconditions.checkArgument(addedURLs.size() > 0, "No change can occur when no URLs are changed");
+                boolean success;
+                String failureReason = null;
+                try(YangStoreSnapshotImpl snapshot = createSnapshot(mbeParser, proposedNewState)) {
+                    updateCache(snapshot);
+                    success = true;
+                } catch(YangStoreException e) {
+                    failureReason = e.toString();
+                    success = false;
+                }
+                if (success){
+                    // consistent state
+                    // merge into
+                    consistentBundlesToYangURLs.clear();
+                    consistentBundlesToYangURLs.putAll(proposedNewState);
+                    inconsistentBundlesToYangURLs.clear();
+
+                    logger.info("Yang store updated to new consistent state containing {} yang files", consistentBundlesToYangURLs.size());
+                    logger.trace("Yang store updated to new consistent state containing {}", consistentBundlesToYangURLs);
+                } else {
+                    // inconsistent state
+                    logger.debug("Yang store is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
+                            consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, failureReason);
+                    logger.warn("Yang store is falling back on last consistent state containing {} files, inconsistent yang files size is {}, reason {}",
+                            consistentBundlesToYangURLs.size(), inconsistentBundlesToYangURLs.size(), failureReason);
                     inconsistentBundlesToYangURLs.putAll(bundle, addedURLs);
                 }
             }
@@ -99,30 +138,7 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
         return bundle;
     }
 
-    private synchronized boolean tryToUpdateState(Collection<URL> changedURLs, Multimap<Bundle, URL> proposedNewState, boolean adding) {
-        Preconditions.checkArgument(changedURLs.size() > 0, "No change can occur when no URLs are changed");
-        try(YangStoreSnapshot snapshot = createSnapshot(mbeParser, proposedNewState)) {
-            // consistent state
-            // merge into
-            consistentBundlesToYangURLs.clear();
-            consistentBundlesToYangURLs.putAll(proposedNewState);
-            inconsistentBundlesToYangURLs.clear();
-            // update cache
-            updateCache(snapshot);
-            logger.info("Yang store updated to new consistent state");
-            logger.trace("Yang store updated to new consistent state containing {}", consistentBundlesToYangURLs);
-
-            notifyListeners(changedURLs, adding);
-            return true;
-        } catch(YangStoreException e) {
-            // inconsistent state
-            logger.debug("Yang store is falling back on last consistent state containing {}, inconsistent yang files {}, reason {}",
-                    consistentBundlesToYangURLs, inconsistentBundlesToYangURLs, e.toString());
-            return false;
-        }
-    }
-
-    private void updateCache(YangStoreSnapshot snapshot) {
+    private void updateCache(YangStoreSnapshotImpl snapshot) {
         cache.cacheYangStore(consistentBundlesToYangURLs, snapshot);
     }
 
@@ -131,31 +147,6 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
         logger.debug("Modified bundle {} {} {}", bundle, event, object);
     }
 
-    /**
-     * Notifiers get only notified when consistent snapshot has changed.
-     */
-    private void notifyListeners(Collection<URL> changedURLs, boolean adding) {
-        Preconditions.checkArgument(changedURLs.size() > 0, "Cannot notify when no URLs changed");
-        if (changedURLs.size() > 0) {
-            RuntimeException potential = new RuntimeException("Error while notifying listeners");
-            for (YangStoreListener listener : listeners) {
-                try {
-                    if (adding) {
-                        listener.onAddedYangURL(changedURLs);
-                    } else {
-                        listener.onRemovedYangURL(changedURLs);
-                    }
-                } catch(RuntimeException e) {
-                    potential.addSuppressed(e);
-                }
-            }
-            if (potential.getSuppressed().length > 0) {
-                throw potential;
-            }
-        }
-    }
-
-
     /**
      * If removing YANG files makes yang store inconsistent, method {@link #getYangStoreSnapshot()}
      * will throw exception. There is no rollback.
@@ -163,31 +154,25 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
     @Override
     public synchronized void removedBundle(Bundle bundle, BundleEvent event, Object object) {
         inconsistentBundlesToYangURLs.removeAll(bundle);
-        Collection<URL> consistentURLsToBeRemoved = consistentBundlesToYangURLs.removeAll(bundle);
-
-        if (consistentURLsToBeRemoved.isEmpty()){
-            return; // no change
-        }
-        boolean adding = false;
-        notifyListeners(consistentURLsToBeRemoved, adding);
+        consistentBundlesToYangURLs.removeAll(bundle);
     }
 
     @Override
     public synchronized YangStoreSnapshot getYangStoreSnapshot()
             throws YangStoreException {
-        Optional<YangStoreSnapshot> yangStoreOpt = cache.getCachedYangStore(consistentBundlesToYangURLs);
+        Optional<YangStoreSnapshot> yangStoreOpt = cache.getSnapshotIfPossible(consistentBundlesToYangURLs);
         if (yangStoreOpt.isPresent()) {
             logger.trace("Returning cached yang store {}", yangStoreOpt.get());
             return yangStoreOpt.get();
         }
-        YangStoreSnapshot snapshot = createSnapshot(mbeParser, consistentBundlesToYangURLs);
+        YangStoreSnapshotImpl snapshot = createSnapshot(mbeParser, consistentBundlesToYangURLs);
         updateCache(snapshot);
         return snapshot;
     }
 
-    private static YangStoreSnapshot createSnapshot(MbeParser mbeParser, Multimap<Bundle, URL> multimap) throws YangStoreException {
+    private static YangStoreSnapshotImpl createSnapshot(MbeParser mbeParser, Multimap<Bundle, URL> multimap) throws YangStoreException {
         try {
-            YangStoreSnapshot yangStoreSnapshot = mbeParser.parseYangFiles(fromUrlsToInputStreams(multimap));
+            YangStoreSnapshotImpl yangStoreSnapshot = mbeParser.parseYangFiles(fromUrlsToInputStreams(multimap));
             logger.trace("{} module entries parsed successfully from {} yang files",
                     yangStoreSnapshot.countModuleMXBeanEntries(), multimap.values().size());
             return yangStoreSnapshot;
@@ -213,44 +198,46 @@ public class ExtenderYangTrackerCustomizer implements BundleTrackerCustomizer<Ob
                 });
     }
 
-    @Override
-    public synchronized YangStoreListenerRegistration registerListener(final YangStoreListener listener) {
-        listeners.add(listener);
-        return new YangStoreListenerRegistration() {
-            @Override
-            public void close() {
-                listeners.remove(listener);
-            }
-        };
+    public synchronized void setMaybeBlacklist(Optional<Pattern> maybeBlacklistPattern) {
+        maybeBlacklist = maybeBlacklistPattern;
+        cache.invalidate();
     }
+}
 
-    private static final class YangStoreCache {
-
-        Set<URL> cachedUrls;
-        YangStoreSnapshot cachedYangStoreSnapshot;
-
-        Optional<YangStoreSnapshot> getCachedYangStore(
-                Multimap<Bundle, URL> bundlesToYangURLs) {
-            Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
-            if (cachedUrls != null && cachedUrls.equals(urls)) {
-                Preconditions.checkState(cachedYangStoreSnapshot != null);
-                return Optional.of(cachedYangStoreSnapshot);
-            }
-            return Optional.absent();
+class YangStoreCache {
+    @GuardedBy("this")
+    private Set<URL> cachedUrls = Collections.emptySet();
+    @GuardedBy("this")
+    private Optional<YangStoreSnapshotImpl> cachedYangStoreSnapshot = Optional.absent();
+
+    synchronized Optional<YangStoreSnapshot> getSnapshotIfPossible(Multimap<Bundle, URL> bundlesToYangURLs) {
+        Set<URL> urls = setFromMultimapValues(bundlesToYangURLs);
+        if (cachedUrls != null && cachedUrls.equals(urls)) {
+            Preconditions.checkState(cachedYangStoreSnapshot.isPresent());
+            YangStoreSnapshot freshSnapshot = new YangStoreSnapshotImpl(cachedYangStoreSnapshot.get());
+            return Optional.of(freshSnapshot);
         }
+        return Optional.absent();
+    }
 
-        private static Set<URL> setFromMultimapValues(
-                Multimap<Bundle, URL> bundlesToYangURLs) {
-            Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
-            Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
-            return urls;
-        }
+    private static Set<URL> setFromMultimapValues(
+            Multimap<Bundle, URL> bundlesToYangURLs) {
+        Set<URL> urls = Sets.newHashSet(bundlesToYangURLs.values());
+        Preconditions.checkState(bundlesToYangURLs.size() == urls.size());
+        return urls;
+    }
 
-        void cacheYangStore(Multimap<Bundle, URL> urls,
-                YangStoreSnapshot yangStoreSnapshot) {
-            this.cachedUrls = setFromMultimapValues(urls);
-            this.cachedYangStoreSnapshot = yangStoreSnapshot;
-        }
+    synchronized void cacheYangStore(Multimap<Bundle, URL> urls,
+                        YangStoreSnapshotImpl yangStoreSnapshot) {
+        this.cachedUrls = setFromMultimapValues(urls);
+        this.cachedYangStoreSnapshot = Optional.of(yangStoreSnapshot);
+    }
 
+    synchronized void invalidate() {
+        cachedUrls.clear();
+        if (cachedYangStoreSnapshot.isPresent()){
+            cachedYangStoreSnapshot.get().close();
+            cachedYangStoreSnapshot = Optional.absent();
+        }
     }
 }
index fc895eb51dcb25ba4e381ef3cac7d7b7d49d0479..211da6bfefdc62df10906eff27b30655e90eb790 100644 (file)
@@ -7,19 +7,11 @@
  */
 package org.opendaylight.controller.config.yang.store.impl;
 
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.commons.io.IOUtils;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
-import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator;
 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry;
@@ -30,13 +22,19 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
 public class MbeParser {
 
-    public YangStoreSnapshot parseYangFiles(
+    public YangStoreSnapshotImpl parseYangFiles(
             Collection<? extends InputStream> allInput)
             throws YangStoreException {
         YangParserImpl parser = new YangParserImpl();
index a358e5f7c1e0bc7080fd674effe18d24ffc9703d..a25b05ab8aa92225df6d1ec1f7782a70efef640b 100644 (file)
@@ -7,50 +7,40 @@
  */
 package org.opendaylight.controller.config.yang.store.impl;
 
-import java.util.Dictionary;
-import java.util.Hashtable;
-
+import com.google.common.base.Optional;
 import org.opendaylight.controller.config.yang.store.api.YangStoreService;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.util.tracker.BundleTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class YangStoreActivator implements BundleActivator {
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.regex.Pattern;
 
-    private BundleTracker bundleTracker;
-    private ServiceRegistration<YangStoreService> registration;
-    private static final Logger logger = LoggerFactory
-            .getLogger(YangStoreActivator.class);
+public class YangStoreActivator implements BundleActivator {
+    private static final Logger logger = LoggerFactory.getLogger(YangStoreActivator.class);
 
     @Override
     public void start(BundleContext context) throws Exception {
-        ExtenderYangTrackerCustomizer customizerAndService = new ExtenderYangTrackerCustomizer();
-        bundleTracker = new BundleTracker(context, BundleEvent.RESOLVED | BundleEvent.UNRESOLVED, customizerAndService);
-        bundleTracker.open();
-
+        // get blacklist
+        Optional<Pattern> maybeBlacklistPattern = Optional.absent();
+        String blacklist = context.getProperty("yangstore.blacklist");
+        if (blacklist != null) {
+            try {
+                maybeBlacklistPattern = Optional.of(Pattern.compile(blacklist));
+            } catch (RuntimeException e) {
+                logger.error("Cannot parse blacklist regex " + blacklist, e);
+                throw e;
+            }
+        }
+        ExtenderYangTracker extenderYangTracker = new ExtenderYangTracker(maybeBlacklistPattern, context);
         Dictionary<String, ?> properties = new Hashtable<>();
-        registration = context.registerService(YangStoreService.class,
-                customizerAndService, properties);
+        context.registerService(YangStoreService.class, extenderYangTracker, properties);
     }
 
     @Override
     public void stop(BundleContext context) throws Exception {
-        try {
-            bundleTracker.close();
-        } catch (Exception e) {
-            logger.warn("Exception while closing bundleTracker", e);
-        }
-        if (registration != null) {
-            try {
-                registration.unregister();
-            } catch (Exception e) {
-                logger.warn("Exception while unregistring yang store service",
-                        e);
-            }
-        }
+
     }
 }
index d5169eac38b2d97982ef6a9227933662450687c3..7a5ca7debe8c3d4379e1c03812afcabac3ee1390 100644 (file)
@@ -7,32 +7,31 @@
  */
 package org.opendaylight.controller.config.yang.store.impl;
 
-import java.util.Map;
-import java.util.Map.Entry;
-
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry;
 import org.opendaylight.yangtools.yang.model.api.Module;
 
+import java.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+
 public class YangStoreSnapshotImpl implements YangStoreSnapshot {
 
-    private final Map<String /* Namespace from yang file */, Map<String /*
-                                                                         * Name
-                                                                         * of
-                                                                         * module
-                                                                         * entry
-                                                                         * from
-                                                                         * yang
-                                                                         * file
-                                                                         */, ModuleMXBeanEntry>> moduleMXBeanEntryMap;
+    private final Map<String /* Namespace from yang file */,
+            Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> moduleMXBeanEntryMap;
 
     private final Map<String, Entry<Module, String>> moduleMap;
 
     public YangStoreSnapshotImpl(
             Map<String, Map<String, ModuleMXBeanEntry>> moduleMXBeanEntryMap,
             Map<String, Entry<Module, String>> moduleMap) {
-        this.moduleMXBeanEntryMap = moduleMXBeanEntryMap;
-        this.moduleMap = moduleMap;
+        this.moduleMXBeanEntryMap = Collections.unmodifiableMap(moduleMXBeanEntryMap);
+        this.moduleMap = Collections.unmodifiableMap(moduleMap);
+    }
+
+    public YangStoreSnapshotImpl(YangStoreSnapshotImpl yangStoreSnapshot) {
+        this.moduleMXBeanEntryMap = yangStoreSnapshot.moduleMXBeanEntryMap;
+        this.moduleMap = yangStoreSnapshot.moduleMap;
     }
 
     @Override
index 427da1f634cd6c3ac657bf71b6ef4926f3b5b023..c4c523992f271391b33f6220b9f49fc28a4fc4ca 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.controller.config.yang.store.impl;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.Lists;
 import org.junit.Before;
 import org.junit.Test;
@@ -15,14 +16,19 @@ import org.mockito.MockitoAnnotations;
 import org.opendaylight.controller.config.yang.store.api.YangStoreException;
 import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleListener;
 
 import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.List;
+import java.util.regex.Pattern;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyCollectionOf;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
@@ -34,22 +40,26 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
 public class ExtenderYangTrackerCustomizerTest {
 
 
-    private ExtenderYangTrackerCustomizer tested;
+    private ExtenderYangTracker tested;
     @Mock
     private MbeParser parser;
     @Mock
-    private YangStoreSnapshot yangStoreSnapshot;
+    private YangStoreSnapshotImpl yangStoreSnapshot;
+    @Mock
+    private BundleContext bundleContext;
 
     @Before
     public void setUp() throws YangStoreException {
         MockitoAnnotations.initMocks(this);
-
-        tested = new ExtenderYangTrackerCustomizer(parser);
+        doNothing().when(bundleContext).addBundleListener(any(BundleListener.class));
+        doReturn(new Bundle[0]).when(bundleContext).getBundles();
+        tested = new ExtenderYangTracker(parser, Optional.<Pattern>absent(), bundleContext);
         doReturn(yangStoreSnapshot).when(parser).parseYangFiles(
                 anyCollectionOf(InputStream.class));
         doReturn(22).when(yangStoreSnapshot).countModuleMXBeanEntries();
         doReturn("mock yang store").when(yangStoreSnapshot).toString();
         doNothing().when(yangStoreSnapshot).close();
+        doReturn(Collections.emptyMap()).when(yangStoreSnapshot).getModuleMap();
     }
 
     @Test
@@ -73,17 +83,15 @@ public class ExtenderYangTrackerCustomizerTest {
         bundle = getMockedBundle(10, false);
         tested.addingBundle(bundle, null);
 
-        for(int i = 0; i< 10; i++){
+        for(int i = 0; i< 20; i++){
             tested.getYangStoreSnapshot();
         }
 
-        verify(parser, times(5)).parseYangFiles(
-                anyCollectionOf(InputStream.class));
+        verify(parser, times(7)).parseYangFiles(anyCollectionOf(InputStream.class));
 
         returnedStore = tested.getYangStoreSnapshot();
 
         verifyNoMoreInteractions(parser);
-        assertEquals(yangStoreSnapshot, returnedStore);
     }
 
     int bundleCounter = 1;
@@ -106,6 +114,7 @@ public class ExtenderYangTrackerCustomizerTest {
             doReturn(1L).when(mock).getBundleId();
 
         doReturn("mockedBundle").when(mock).toString();
+        doReturn("mockedBundle").when(mock).getSymbolicName();
 
         return mock;
     }
index 844f682b7a6348a2e86cecceb35e010772e5074e..6221682147e86eea464e3f25abb066d0bfa4d3aa 100644 (file)
@@ -7,7 +7,10 @@
  */
 package org.opendaylight.controller.config.yang.store.impl;
 
-import static org.junit.Assert.assertNotNull;
+import org.apache.commons.io.IOUtils;
+import org.opendaylight.controller.config.yang.store.api.YangStoreException;
+import org.opendaylight.controller.config.yang.store.api.YangStoreService;
+import org.opendaylight.controller.config.yang.store.api.YangStoreSnapshot;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -15,12 +18,7 @@ import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.Collection;
 
-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;
+import static org.junit.Assert.assertNotNull;
 
 public class HardcodedYangStoreService implements YangStoreService {
 
@@ -50,9 +48,4 @@ 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");
-    }
 }
index caf9d095914413477ef2888501e0dd53e473559e..8347bf1e447eef876f3941e71ffc2af4c8890254 100644 (file)
@@ -23,6 +23,7 @@ netconf.tcp.port=8383
 #netconf.tls.keystore.password=
 
 netconf.config.persister.storageAdapterClass=org.opendaylight.controller.netconf.persist.impl.NoOpStorageAdapter
+yangstore.blacklist=.*controller.model.*
 
 # Set Default start level for framework
 osgi.bundles.defaultStartLevel=4