X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=dom%2Fmdsal-dom-broker%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fmdsal%2Fdom%2Fbroker%2Fosgi%2FOsgiBundleScanningSchemaService.java;h=87e5c4d23e4e770fef87883f68188b1526b5df0d;hb=14f04995729708e2ac192df2bdfce6fe6a5a9aaf;hp=caec7cc7851b9982a450eded533782085deb4d80;hpb=c2c61de266b41416a11f381d3dba79d5866d7e76;p=mdsal.git diff --git a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaService.java b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaService.java index caec7cc785..87e5c4d23e 100644 --- a/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaService.java +++ b/dom/mdsal-dom-broker/src/main/java/org/opendaylight/mdsal/dom/broker/osgi/OsgiBundleScanningSchemaService.java @@ -13,19 +13,30 @@ 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.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; @@ -39,42 +50,49 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class OsgiBundleScanningSchemaService implements SchemaContextProvider, DOMSchemaService, - ServiceTrackerCustomizer, AutoCloseable { + ServiceTrackerCustomizer, DOMYangTextSourceProvider, + AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(OsgiBundleScanningSchemaService.class); + private static final AtomicReference GLOBAL_INSTANCE = new AtomicReference<>(); + + private static final long FRAMEWORK_BUNDLE_ID = 0; + + @GuardedBy("lock") private final ListenerRegistry 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 listenerTracker; private BundleTracker> bundleTracker; private boolean starting = true; + private volatile boolean stopping; - private static OsgiBundleScanningSchemaService instance; private OsgiBundleScanningSchemaService(final BundleContext context) { this.context = Preconditions.checkNotNull(context); } - public static synchronized OsgiBundleScanningSchemaService createInstance(final BundleContext ctx) { - Preconditions.checkState(instance == null); - instance = new OsgiBundleScanningSchemaService(ctx); + public static @Nonnull OsgiBundleScanningSchemaService createInstance(final BundleContext ctx) { + OsgiBundleScanningSchemaService instance = new OsgiBundleScanningSchemaService(ctx); + Preconditions.checkState(GLOBAL_INSTANCE.compareAndSet(null, instance)); instance.start(); return instance; } - public static synchronized OsgiBundleScanningSchemaService getInstance() { + public static OsgiBundleScanningSchemaService getInstance() { + OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.get(); Preconditions.checkState(instance != null, "Global Instance was not instantiated"); return instance; } @VisibleForTesting - public static synchronized void destroyInstance() { - try { + public static void destroyInstance() { + OsgiBundleScanningSchemaService instance = GLOBAL_INSTANCE.getAndSet(null); + if (instance != null) { instance.close(); - } finally { - instance = null; } } @@ -86,18 +104,22 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D checkState(context != null); LOG.debug("start() starting"); - listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, - OsgiBundleScanningSchemaService.this); + listenerTracker = new ServiceTracker<>(context, SchemaContextListener.class, this); bundleTracker = new BundleTracker<>(context, Bundle.RESOLVED | Bundle.STARTING - | - Bundle.STOPPING | Bundle.ACTIVE, scanner); - bundleTracker.open(); + | Bundle.STOPPING | Bundle.ACTIVE, scanner); + + synchronized (lock) { + bundleTracker.open(); - LOG.debug("BundleTracker.open() complete"); + LOG.debug("BundleTracker.open() complete"); + + if (Iterables.size(listeners.getListeners()) > 0) { + tryToUpdateSchemaContext(); + } + } listenerTracker.open(); starting = false; - tryToUpdateSchemaContext(); LOG.debug("start() complete"); } @@ -118,32 +140,40 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D } @Override - public synchronized ListenerRegistration - registerSchemaContextListener(final SchemaContextListener listener) { - final Optional potentialCtx = contextResolver.getSchemaContext(); - if (potentialCtx.isPresent()) { - listener.onGlobalContextUpdated(potentialCtx.get()); + public ListenerRegistration registerSchemaContextListener( + final SchemaContextListener listener) { + synchronized (lock) { + final Optional potentialCtx = contextResolver.getSchemaContext(); + if (potentialCtx.isPresent()) { + listener.onGlobalContextUpdated(potentialCtx.get()); + } + return listeners.register(listener); } - return listeners.register(listener); } @Override public void close() { - stopping = true; - if (bundleTracker != null) { - bundleTracker.close(); - } - if (listenerTracker != null) { - listenerTracker.close(); - } + synchronized (lock) { + stopping = true; + if (bundleTracker != null) { + bundleTracker.close(); + bundleTracker = null; + } + if (listenerTracker != null) { + listenerTracker.close(); + listenerTracker = null; + } - for (final ListenerRegistration l : listeners.getListeners()) { - l.close(); + for (final ListenerRegistration l : listeners.getListeners()) { + l.close(); + } } } @SuppressWarnings("checkstyle:IllegalCatch") - private synchronized void updateContext(final SchemaContext snapshot) { + @VisibleForTesting + @GuardedBy("lock") + void notifyListeners(final SchemaContext snapshot) { final Object[] services = listenerTracker.getServices(); for (final ListenerRegistration listener : listeners) { try { @@ -169,7 +199,7 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D @Override public Iterable addingBundle(final Bundle bundle, final BundleEvent event) { - if (bundle.getBundleId() == 0) { + if (bundle.getBundleId() == FRAMEWORK_BUNDLE_ID) { return Collections.emptyList(); } @@ -200,6 +230,13 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D @Override public void modifiedBundle(final Bundle bundle, final BundleEvent event, final Iterable object) { + if (bundle.getBundleId() == FRAMEWORK_BUNDLE_ID) { + LOG.debug("Framework bundle {} got event {}", bundle, event.getType()); + if ((event.getType() & BundleEvent.STOPPING) != 0) { + LOG.info("OSGi framework is being stopped, halting bundle scanning"); + stopping = true; + } + } } /** @@ -209,8 +246,7 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D */ @SuppressWarnings("checkstyle:IllegalCatch") @Override - public synchronized void removedBundle(final Bundle bundle, final BundleEvent event, - final Iterable urls) { + public void removedBundle(final Bundle bundle, final BundleEvent event, final Iterable urls) { for (final Registration url : urls) { try { url.close(); @@ -232,7 +268,7 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D } @Override - public synchronized SchemaContextListener addingService(final ServiceReference reference) { + public SchemaContextListener addingService(final ServiceReference reference) { final SchemaContextListener listener = context.getService(reference); final SchemaContext _ctxContext = getGlobalContext(); @@ -242,17 +278,20 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D return listener; } - public synchronized void tryToUpdateSchemaContext() { + public void tryToUpdateSchemaContext() { if (starting || stopping) { return; } - final Optional schema = contextResolver.getSchemaContext(); - if (schema.isPresent()) { - if (LOG.isDebugEnabled()) { - LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getAllModuleIdentifiers().size()); - } - updateContext(schema.get()); + synchronized (lock) { + final Optional schema = contextResolver.getSchemaContext(); + if (schema.isPresent()) { + if (LOG.isDebugEnabled()) { + LOG.debug("Got new SchemaContext: # of modules {}", schema.get().getAllModuleIdentifiers().size()); + } + + notifyListeners(schema.get()); + } } } @@ -267,4 +306,15 @@ public class OsgiBundleScanningSchemaService implements SchemaContextProvider, D final SchemaContextListener service) { context.ungetService(reference); } + + @Override + public Map, DOMSchemaServiceExtension> getSupportedExtensions() { + return ImmutableMap.of(DOMYangTextSourceProvider.class, this); + } + + @Override + public CheckedFuture getSource( + final SourceIdentifier sourceIdentifier) { + return contextResolver.getSource(sourceIdentifier); + } }