package org.opendaylight.controller.config.yang.md.sal.binding.impl;
import com.google.common.base.Preconditions;
-import java.util.Hashtable;
+import com.google.common.base.Stopwatch;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.util.concurrent.TimeUnit;
import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.sal.binding.codegen.impl.SingletonHolder;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy;
-import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
+import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodecFactory;
import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
/**
*
**/
public final class RuntimeMappingModule extends AbstractRuntimeMappingModule {
+ private static final long WAIT_IN_MINUTES = 5;
private BundleContext bundleContext;
@Override
public java.lang.AutoCloseable createInstance() {
- final ClassLoadingStrategy classLoading = getGlobalClassLoadingStrategy();
- final BindingNormalizedNodeCodecRegistry codecRegistry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(SingletonHolder.JAVASSIST));
- final BindingToNormalizedNodeCodec instance = new BindingToNormalizedNodeCodec(classLoading, codecRegistry,getWaitForSchema());
- bundleContext.registerService(SchemaContextListener.class, instance, new Hashtable<String,String>());
- return instance;
- }
+ // This is kind of ugly - you might cringe (you've been warned). The BindingToNormalizedNodeCodec
+ // instance is advertised via blueprint so ideally we'd obtain it from the OSGi service registry.
+ // The config yang service identity declares the concrete BindingToNormalizedNodeCodec class
+ // and not an interface as the java-class so we must return a BindingToNormalizedNodeCodec instance.
+ // However we can't cast the instance obtained from the service registry to
+ // BindingToNormalizedNodeCodec b/c Aries may register a proxy if there are interceptors defined.
+ // By default karaf ships with the org.apache.aries.quiesce.api bundle which automatically adds
+ // an interceptor that adds stat tracking for service method calls. While this can be disabled, we
+ // shouldn't rely on it.
+ //
+ // Therefore we store a static instance in the BindingToNormalizedNodeCodecFactory which is created
+ // by blueprint via newInstance. We obtain the static instance here and busy wait if not yet available.
+
+ Stopwatch sw = Stopwatch.createStarted();
+ while(sw.elapsed(TimeUnit.MINUTES) <= WAIT_IN_MINUTES) {
+ BindingToNormalizedNodeCodec instance = BindingToNormalizedNodeCodecFactory.getInstance();
+ if(instance != null) {
+ return instance;
+ }
+
+ Uninterruptibles.sleepUninterruptibly(50, TimeUnit.MILLISECONDS);
+ }
- private ClassLoadingStrategy getGlobalClassLoadingStrategy() {
- final ServiceReference<ClassLoadingStrategy> ref = bundleContext.getServiceReference(ClassLoadingStrategy.class);
- return bundleContext.getService(ref);
+ throw new IllegalStateException("Could not obtain the BindingToNormalizedNodeCodec instance after " +
+ WAIT_IN_MINUTES + " minutes.");
}
public void setBundleContext(final BundleContext bundleContext) {