import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
+import javax.annotation.Nullable;
import org.apache.aries.blueprint.NamespaceHandler;
import org.apache.aries.blueprint.services.BlueprintExtenderService;
import org.apache.aries.quiesce.participant.QuiesceParticipant;
@Override
public BlueprintExtenderService addingService(
final ServiceReference<BlueprintExtenderService> reference) {
- blueprintExtenderService = reference.getBundle().getBundleContext().getService(reference);
- bundleTracker.open();
-
- context.addBundleListener(BlueprintBundleTracker.this);
-
- LOG.debug("Got BlueprintExtenderService");
-
- restartService.setBlueprintExtenderService(blueprintExtenderService);
-
- blueprintContainerRestartReg = context.registerService(
- BlueprintContainerRestartService.class.getName(), restartService, new Hashtable<>());
-
- return blueprintExtenderService;
+ return onBlueprintExtenderServiceAdded(reference);
}
@Override
@Override
public QuiesceParticipant addingService(
final ServiceReference<QuiesceParticipant> reference) {
- quiesceParticipant = reference.getBundle().getBundleContext().getService(reference);
-
- LOG.debug("Got QuiesceParticipant");
-
- restartService.setQuiesceParticipant(quiesceParticipant);
-
- return quiesceParticipant;
+ return onQuiesceParticipantAdded(reference);
}
@Override
quiesceParticipantTracker.open();
}
+ private QuiesceParticipant onQuiesceParticipantAdded(final ServiceReference<QuiesceParticipant> reference) {
+ quiesceParticipant = reference.getBundle().getBundleContext().getService(reference);
+
+ LOG.debug("Got QuiesceParticipant");
+
+ restartService.setQuiesceParticipant(quiesceParticipant);
+
+ return quiesceParticipant;
+ }
+
+ private BlueprintExtenderService onBlueprintExtenderServiceAdded(
+ final ServiceReference<BlueprintExtenderService> reference) {
+ blueprintExtenderService = reference.getBundle().getBundleContext().getService(reference);
+ bundleTracker.open();
+
+ bundleContext.addBundleListener(BlueprintBundleTracker.this);
+
+ LOG.debug("Got BlueprintExtenderService");
+
+ restartService.setBlueprintExtenderService(blueprintExtenderService);
+
+ blueprintContainerRestartReg = bundleContext.registerService(
+ BlueprintContainerRestartService.class.getName(), restartService, new Hashtable<>());
+
+ return blueprintExtenderService;
+ }
+
private void registerNamespaceHandler(final BundleContext context) {
Dictionary<String, Object> props = new Hashtable<>();
props.put("osgi.service.blueprint.namespace", OpendaylightNamespaceHandler.NAMESPACE_1_0_0);
if (EventConstants.TOPIC_CREATED.equals(event.getTopic())) {
LOG.info("Blueprint container for bundle {} was successfully created",
event.getProperty(EventConstants.BUNDLE));
- } else if (EventConstants.TOPIC_FAILURE.equals(event.getTopic())) {
- // If the container timed out waiting for dependencies, we'll destroy it and start it again. This
- // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
- // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
- // be set at the bundle level in the manifest - there's no way to set it globally.
- if (event.getProperty(EventConstants.DEPENDENCIES) != null) {
- Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
-
- List<Object> paths = findBlueprintPaths(bundle);
- if (!paths.isEmpty()) {
- LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
- event.getProperty(EventConstants.BUNDLE));
-
- restartService.restartContainer(bundle, paths);
- }
+ return;
+ }
+
+ // If the container timed out waiting for dependencies, we'll destroy it and start it again. This
+ // is indicated via a non-null DEPENDENCIES property containing the missing dependencies. The
+ // default timeout is 5 min and ideally we would set this to infinite but the timeout can only
+ // be set at the bundle level in the manifest - there's no way to set it globally.
+ if (EventConstants.TOPIC_FAILURE.equals(event.getTopic())
+ && event.getProperty(EventConstants.DEPENDENCIES) != null) {
+ Bundle bundle = (Bundle) event.getProperty(EventConstants.BUNDLE);
+
+ List<Object> paths = findBlueprintPaths(bundle);
+ if (!paths.isEmpty()) {
+ LOG.warn("Blueprint container for bundle {} timed out waiting for dependencies - restarting it",
+ event.getProperty(EventConstants.BUNDLE));
+
+ restartService.restartContainer(bundle, paths);
}
}
}
// ID, we're picking the bundle that was (likely) started after all the others and thus
// is likely the safest to destroy at this point.
- ServiceReference<?> ref = null;
- for (Bundle bundle : containerBundles) {
- ServiceReference<?>[] references = bundle.getRegisteredServices();
- if (references == null) {
- continue;
- }
-
- for (ServiceReference<?> reference : references) {
- // We did check the service usage above but it's possible the usage has changed since
- // then,
- if (getServiceUsage(reference) == 0) {
- continue;
- }
-
- // Choose 'reference' if it has a lower service ranking or, if the rankings are equal
- // which is usually the case, if it has a higher service ID. For the latter the < 0
- // check looks backwards but that's how ServiceReference#compareTo is documented to work.
- if (ref == null || reference.compareTo(ref) < 0) {
- LOG.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
- ref = reference;
- }
- }
- }
-
- if (ref != null) {
- bundlesToDestroy.add(ref.getBundle());
+ Bundle bundle = findBundleWithHighestUsedServiceId(containerBundles);
+ if (bundle != null) {
+ bundlesToDestroy.add(bundle);
}
LOG.debug("Selected bundle {} for destroy (lowest ranking service or highest service ID)",
return bundlesToDestroy;
}
+ @Nullable
+ private Bundle findBundleWithHighestUsedServiceId(final Collection<Bundle> containerBundles) {
+ ServiceReference<?> highestServiceRef = null;
+ for (Bundle bundle : containerBundles) {
+ ServiceReference<?>[] references = bundle.getRegisteredServices();
+ if (references == null) {
+ continue;
+ }
+
+ for (ServiceReference<?> reference : references) {
+ // We did check the service usage previously but it's possible the usage has changed since then.
+ if (getServiceUsage(reference) == 0) {
+ continue;
+ }
+
+ // Choose 'reference' if it has a lower service ranking or, if the rankings are equal
+ // which is usually the case, if it has a higher service ID. For the latter the < 0
+ // check looks backwards but that's how ServiceReference#compareTo is documented to work.
+ if (highestServiceRef == null || reference.compareTo(highestServiceRef) < 0) {
+ LOG.debug("Currently selecting bundle {} for destroy (with reference {})", bundle, reference);
+ highestServiceRef = reference;
+ }
+ }
+ }
+
+ return highestServiceRef == null ? null : highestServiceRef.getBundle();
+ }
+
private static int getServiceUsage(final ServiceReference<?> ref) {
Bundle[] usingBundles = ref.getUsingBundles();
return usingBundles != null ? usingBundles.length : 0;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcService;
import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
rpcRegistry = (RpcProviderRegistry)service;
// Now acquire SchemaService...
- retrieveService("SchemaService", SchemaService.class, this::onSchemaService);
+ retrieveService("SchemaService", DOMSchemaService.class, this::onSchemaService);
}
private void onSchemaService(final Object service) {
log.debug("{}: Retrieved SchemaService {}", logName(), service);
// Now get the SchemaContext and trigger RPC resolution
- retrievedSchemaContext(((SchemaService)service).getGlobalContext());
+ retrievedSchemaContext(((DOMSchemaService)service).getGlobalContext());
}
private void retrievedSchemaContext(final SchemaContext schemaContext) {
import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
import org.opendaylight.controller.md.sal.dom.broker.spi.rpc.RpcRoutingStrategy;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.yangtools.concepts.Registration;
import org.opendaylight.yangtools.yang.binding.RpcService;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
private DOMRpcProviderService rpcProviderService;
private RpcProviderRegistry rpcRegistry;
- private SchemaService schemaService;
+ private DOMSchemaService schemaService;
private RpcService implementation;
private String interfaceName;
private Registration reg;
this.rpcRegistry = rpcRegistry;
}
- public void setSchemaService(final SchemaService schemaService) {
+ public void setSchemaService(final DOMSchemaService schemaService) {
this.schemaService = schemaService;
}
import java.net.URL;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLStreamException;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.yangtools.util.xml.UntrustedXML;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.common.QName;
private final String logName;
private final String defaultAppConfigFileName;
- private final SchemaService schemaService;
+ private final DOMSchemaService schemaService;
private final BindingNormalizedNodeSerializer bindingSerializer;
private final BindingContext bindingContext;
private final ConfigURLProvider inputStreamProvider;
public DataStoreAppConfigDefaultXMLReader(
final String logName,
final String defaultAppConfigFileName,
- final SchemaService schemaService,
+ final DOMSchemaService schemaService,
final BindingNormalizedNodeSerializer bindingSerializer,
final BindingContext bindingContext,
final ConfigURLProvider inputStreamProvider) {
public DataStoreAppConfigDefaultXMLReader(
final Class<?> testClass,
final String defaultAppConfigFileName,
- final SchemaService schemaService,
+ final DOMSchemaService schemaService,
final BindingNormalizedNodeSerializer bindingSerializer,
final Class<T> klass) {
this(testClass.getName(), defaultAppConfigFileName, schemaService, bindingSerializer,
LOG.debug("{}: Creating app config instance from path {}, Qname: {}", logName, yangPath,
bindingContext.bindingQName);
- if (schemaService == null) {
- throw new ConfigXMLReaderException(
- String.format("%s: Could not obtain the SchemaService OSGi service", logName));
- }
+ checkNotNull(schemaService, "%s: Could not obtain the SchemaService OSGi service", logName);
SchemaContext schemaContext = schemaService.getGlobalContext();
Module module = schemaContext.findModuleByNamespaceAndRevision(bindingContext.bindingQName.getNamespace(),
bindingContext.bindingQName.getRevision());
- if (module == null) {
- throw new ConfigXMLReaderException(
- String.format("%s: Could not obtain the module schema for namespace %s, revision %s",
- logName, bindingContext.bindingQName.getNamespace(), bindingContext.bindingQName.getRevision()));
- }
+ checkNotNull(module, "%s: Could not obtain the module schema for namespace %s, revision %s",
+ logName, bindingContext.bindingQName.getNamespace(), bindingContext.bindingQName.getRevision());
DataSchemaNode dataSchema = module.getDataChildByName(bindingContext.bindingQName);
- if (dataSchema == null) {
- throw new ConfigXMLReaderException(
- String.format("%s: Could not obtain the schema for %s", logName,
- bindingContext.bindingQName));
- }
+ checkNotNull(dataSchema, "%s: Could not obtain the schema for %s", logName, bindingContext.bindingQName);
- if (!bindingContext.schemaType.isAssignableFrom(dataSchema.getClass())) {
- throw new ConfigXMLReaderException(
- String.format("%s: Expected schema type %s for %s but actual type is %s", logName,
- bindingContext.schemaType, bindingContext.bindingQName, dataSchema.getClass()));
- }
+ checkCondition(bindingContext.schemaType.isAssignableFrom(dataSchema.getClass()),
+ "%s: Expected schema type %s for %s but actual type is %s", logName,
+ bindingContext.schemaType, bindingContext.bindingQName, dataSchema.getClass());
NormalizedNode<?, ?> dataNode = parsePossibleDefaultAppConfigXMLFile(schemaContext, dataSchema);
if (dataNode == null) {
}
DataObject appConfig = bindingSerializer.fromNormalizedNode(yangPath, dataNode).getValue();
- if (appConfig == null) {
- // This shouldn't happen but need to handle it in case...
- throw new ConfigXMLReaderException(
- String.format("%s: Could not create instance for app config binding %s",
- logName, bindingContext.appConfigBindingClass));
- } else {
- return (T) appConfig;
+
+ // This shouldn't happen but need to handle it in case...
+ checkNotNull(appConfig, "%s: Could not create instance for app config binding %s", logName,
+ bindingContext.appConfigBindingClass);
+
+ return (T) appConfig;
+ }
+
+ private static void checkNotNull(Object reference, String errorMessageFormat, Object... formatArgs)
+ throws ConfigXMLReaderException {
+ checkCondition(reference != null, errorMessageFormat, formatArgs);
+ }
+
+ private static void checkCondition(boolean expression, String errorMessageFormat, Object... formatArgs)
+ throws ConfigXMLReaderException {
+ if (!expression) {
+ throw new ConfigXMLReaderException(String.format(errorMessageFormat, formatArgs));
}
}
package org.opendaylight.controller.blueprint.ext;
import com.google.common.base.Optional;
-import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import com.google.common.util.concurrent.MoreExecutors;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import org.opendaylight.controller.md.sal.binding.api.DataTreeModification;
import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
-import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
import org.opendaylight.mdsal.binding.dom.codec.api.BindingNormalizedNodeSerializer;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.yangtools.concepts.ListenerRegistration;
import org.opendaylight.yangtools.yang.binding.DataObject;
import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
}
private void readInitialAppConfig(final DataBroker dataBroker) {
- @SuppressWarnings("resource") // it's closed in the callback
final ReadOnlyTransaction readOnlyTx = dataBroker.newReadOnlyTransaction();
- CheckedFuture<Optional<DataObject>, ReadFailedException> future = readOnlyTx.read(
+ ListenableFuture<Optional<DataObject>> future = readOnlyTx.read(
LogicalDatastoreType.CONFIGURATION, bindingContext.appConfigPath);
Futures.addCallback(future, new FutureCallback<Optional<DataObject>>() {
@Override
readInitialAppConfig(dataBroker);
}
}
- });
+ }, MoreExecutors.directExecutor());
}
private void onAppConfigChanged(final Collection<DataTreeModification<DataObject>> changes) {
private DataObject createDefaultInstance() {
try {
- @SuppressWarnings("resource")
ConfigURLProvider inputStreamProvider = appConfigFileName -> {
File appConfigFile = new File(DEFAULT_APP_CONFIG_FILE_PATH, appConfigFileName);
LOG.debug("{}: parsePossibleDefaultAppConfigXMLFile looking for file {}", logName(),
return Optional.of(appConfigFile.toURI().toURL());
};
- DataStoreAppConfigDefaultXMLReader<?> reader = new DataStoreAppConfigDefaultXMLReader(logName(),
- defaultAppConfigFileName, getOSGiService(SchemaService.class), bindingSerializer, bindingContext,
+ DataStoreAppConfigDefaultXMLReader<?> reader = new DataStoreAppConfigDefaultXMLReader<>(logName(),
+ defaultAppConfigFileName, getOSGiService(DOMSchemaService.class), bindingSerializer, bindingContext,
inputStreamProvider);
return reader.createDefaultInstance((schemaContext, dataSchema) -> {
// Fallback if file cannot be read, try XML from Config
import org.opendaylight.controller.md.sal.binding.api.NotificationService;
import org.opendaylight.controller.md.sal.dom.api.DOMRpcProviderService;
import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.controller.sal.core.api.model.SchemaService;
+import org.opendaylight.mdsal.dom.api.DOMSchemaService;
import org.opendaylight.yangtools.util.xml.UntrustedXML;
import org.osgi.service.blueprint.container.ComponentDefinitionException;
import org.osgi.service.blueprint.reflect.BeanMetadata;
ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
MutableBeanMetadata metadata = (MutableBeanMetadata) registry.getComponentDefinition(COMPONENT_PROCESSOR_NAME);
if (metadata == null) {
- metadata = context.createMetadata(MutableBeanMetadata.class);
+ metadata = createBeanMetadata(context, COMPONENT_PROCESSOR_NAME, ComponentProcessor.class, false, true);
metadata.setProcessor(true);
- metadata.setId(COMPONENT_PROCESSOR_NAME);
- metadata.setActivation(BeanMetadata.ACTIVATION_EAGER);
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- metadata.setRuntimeClass(ComponentProcessor.class);
- metadata.setDestroyMethod("destroy");
- metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
+ addBlueprintBundleRefProperty(context, metadata);
metadata.addProperty("blueprintContainerRestartService", createServiceRef(context,
BlueprintContainerRestartService.class, null));
registerRpcRegistryServiceRefBean(context);
registerSchemaServiceRefBean(context);
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setId(context.generateId());
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- metadata.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
- metadata.setRuntimeClass(ActionProviderBean.class);
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
+ MutableBeanMetadata metadata = createBeanMetadata(context, context.generateId(), ActionProviderBean.class,
+ true, true);
+ addBlueprintBundleRefProperty(context, metadata);
metadata.addProperty("rpcProviderService", createRef(context, RPC_PROVIDER_SERVICE_NAME));
metadata.addProperty("rpcRegistry", createRef(context, RPC_REGISTRY_NAME));
metadata.addProperty("schemaService", createRef(context, SCHEMA_SERVICE_NAME));
return metadata;
}
+
private static Metadata parseRpcImplementation(final Element element, final ParserContext context) {
registerRpcRegistryServiceRefBean(context);
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setId(context.generateId());
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- metadata.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
- metadata.setRuntimeClass(RpcImplementationBean.class);
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
+ MutableBeanMetadata metadata = createBeanMetadata(context, context.generateId(), RpcImplementationBean.class,
+ true, true);
+ addBlueprintBundleRefProperty(context, metadata);
metadata.addProperty("rpcRegistry", createRef(context, RPC_REGISTRY_NAME));
metadata.addProperty("implementation", createRef(context, element.getAttribute(REF_ATTR)));
private static void registerRoutedRpcRegistrationConverter(final ParserContext context) {
ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
if (registry.getComponentDefinition(ROUTED_RPC_REG_CONVERTER_NAME) == null) {
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setId(ROUTED_RPC_REG_CONVERTER_NAME);
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
+ MutableBeanMetadata metadata = createBeanMetadata(context, ROUTED_RPC_REG_CONVERTER_NAME,
+ RoutedRpcRegistrationConverter.class, false, false);
metadata.setActivation(ReferenceMetadata.ACTIVATION_LAZY);
- metadata.setRuntimeClass(RoutedRpcRegistrationConverter.class);
registry.registerTypeConverter(metadata);
}
}
}
private static void registerSchemaServiceRefBean(final ParserContext context) {
- registerRefBean(context, SCHEMA_SERVICE_NAME, SchemaService.class);
+ registerRefBean(context, SCHEMA_SERVICE_NAME, DOMSchemaService.class);
}
private static void registerRefBean(final ParserContext context, final String name, final Class<?> clazz) {
private static Metadata parseNotificationListener(final Element element, final ParserContext context) {
registerNotificationServiceRefBean(context);
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setId(context.generateId());
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- metadata.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
- metadata.setRuntimeClass(NotificationListenerBean.class);
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
+ MutableBeanMetadata metadata = createBeanMetadata(context, context.generateId(), NotificationListenerBean.class,
+ true, true);
+ addBlueprintBundleRefProperty(context, metadata);
metadata.addProperty("notificationService", createRef(context, NOTIFICATION_SERVICE_NAME));
metadata.addProperty("notificationListener", createRef(context, element.getAttribute(REF_ATTR)));
private static boolean nodeNameEquals(final Node node, final String name) {
return name.equals(node.getNodeName()) || name.equals(node.getLocalName());
}
+
+ private static void addBlueprintBundleRefProperty(final ParserContext context, final MutableBeanMetadata metadata) {
+ metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
+ }
+
+ private static MutableBeanMetadata createBeanMetadata(final ParserContext context, final String id,
+ final Class<?> runtimeClass, final boolean initMethod, final boolean destroyMethod) {
+ MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
+ metadata.setId(id);
+ metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
+ metadata.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
+ metadata.setRuntimeClass(runtimeClass);
+
+ if (initMethod) {
+ metadata.setInitMethod("init");
+ }
+
+ if (destroyMethod) {
+ metadata.setDestroyMethod("destroy");
+ }
+
+ return metadata;
+ }
}
private static final Logger LOG = LoggerFactory.getLogger(StaticServiceReferenceRecipe.class);
private static final SatisfactionListener NOOP_LISTENER = satisfiable -> {
-
+ // Intentional NOOP
};
private volatile ServiceReference<?> trackedServiceReference;
}
@Override
+ // Disables "Either log or rethrow this exception" sonar warning
+ @SuppressWarnings("squid:S1166")
protected void doStop() {
LOG.debug("{}: In doStop", getName());