2 * Copyright (c) 2016 Brocade Communications Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.blueprint.ext;
10 import com.google.common.base.Strings;
11 import java.util.ArrayList;
12 import java.util.Dictionary;
13 import java.util.Hashtable;
14 import java.util.List;
15 import org.apache.aries.blueprint.ComponentDefinitionRegistry;
16 import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor;
17 import org.apache.aries.blueprint.ext.AbstractPropertyPlaceholder;
18 import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
19 import org.apache.aries.blueprint.mutable.MutableServiceReferenceMetadata;
20 import org.apache.aries.util.AriesFrameworkUtil;
21 import org.opendaylight.controller.blueprint.BlueprintContainerRestartService;
22 import org.osgi.framework.Bundle;
23 import org.osgi.framework.Constants;
24 import org.osgi.framework.ServiceRegistration;
25 import org.osgi.service.blueprint.reflect.BeanProperty;
26 import org.osgi.service.blueprint.reflect.ComponentMetadata;
27 import org.osgi.service.blueprint.reflect.ValueMetadata;
28 import org.osgi.service.cm.ManagedService;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
33 * The singleton component processor that is invoked by the blueprint container to perform operations on
34 * various component definitions prior to component creation.
36 * @author Thomas Pantelis
38 public class ComponentProcessor implements ComponentDefinitionRegistryProcessor {
39 private static final Logger LOG = LoggerFactory.getLogger(ComponentProcessor.class);
40 private static final String CM_PERSISTENT_ID_PROPERTY = "persistentId";
42 private final List<ServiceRegistration<?>> managedServiceRegs = new ArrayList<>();
43 private Bundle bundle;
44 private BlueprintContainerRestartService blueprintContainerRestartService;
45 private boolean restartDependentsOnUpdates;
46 private boolean useDefaultForReferenceTypes;
48 public void setBundle(Bundle bundle) {
52 public void setBlueprintContainerRestartService(BlueprintContainerRestartService restartService) {
53 this.blueprintContainerRestartService = restartService;
56 public void setRestartDependentsOnUpdates(boolean restartDependentsOnUpdates) {
57 this.restartDependentsOnUpdates = restartDependentsOnUpdates;
60 public void setUseDefaultForReferenceTypes(boolean useDefaultForReferenceTypes) {
61 this.useDefaultForReferenceTypes = useDefaultForReferenceTypes;
64 public void destroy() {
65 for(ServiceRegistration<?> reg: managedServiceRegs) {
66 AriesFrameworkUtil.safeUnregisterService(reg);
71 public void process(ComponentDefinitionRegistry registry) {
72 LOG.debug("{}: In process", logName());
74 for(String name : registry.getComponentDefinitionNames()) {
75 ComponentMetadata component = registry.getComponentDefinition(name);
76 if(component instanceof MutableBeanMetadata) {
77 processMutableBeanMetadata((MutableBeanMetadata)component);
78 } else if(component instanceof MutableServiceReferenceMetadata) {
79 processServiceReferenceMetadata((MutableServiceReferenceMetadata)component);
84 private void processServiceReferenceMetadata(MutableServiceReferenceMetadata serviceRef) {
85 if(!useDefaultForReferenceTypes) {
89 String filter = serviceRef.getFilter();
90 String extFilter = serviceRef.getExtendedFilter() == null ? null :
91 serviceRef.getExtendedFilter().getStringValue();
93 LOG.debug("{}: processServiceReferenceMetadata for {}, filter: {}, ext filter: {}", logName(),
94 serviceRef.getId(), filter, extFilter);
96 if(Strings.isNullOrEmpty(filter) && Strings.isNullOrEmpty(extFilter)) {
97 serviceRef.setFilter("(|(type=default)(!(type=*)))");
99 LOG.debug("{}: processServiceReferenceMetadata for {} set filter to {}", logName(),
100 serviceRef.getId(), serviceRef.getFilter());
104 private void processMutableBeanMetadata(MutableBeanMetadata bean) {
105 if(restartDependentsOnUpdates && bean.getRuntimeClass() != null &&
106 AbstractPropertyPlaceholder.class.isAssignableFrom(bean.getRuntimeClass())) {
107 LOG.debug("{}: Found PropertyPlaceholder bean: {}, runtime {}", logName(), bean.getId(),
108 bean.getRuntimeClass());
110 for(BeanProperty prop: bean.getProperties()) {
111 if(CM_PERSISTENT_ID_PROPERTY.equals(prop.getName())) {
112 if(prop.getValue() instanceof ValueMetadata) {
113 ValueMetadata persistentId = (ValueMetadata)prop.getValue();
115 LOG.debug("{}: Found {} property, value : {}", logName(),
116 CM_PERSISTENT_ID_PROPERTY, persistentId.getStringValue());
118 registerManagedService(persistentId.getStringValue());
120 LOG.debug("{}: {} property metadata {} is not instanceof ValueMetadata",
121 logName(), CM_PERSISTENT_ID_PROPERTY, prop.getValue());
130 private void registerManagedService(final String persistentId) {
131 // Register a ManagedService so we get updates from the ConfigAdmin when the cfg file corresponding
132 // to the persistentId changes.
133 ManagedService managedService = new ManagedService() {
134 private volatile boolean initialUpdate = true;
137 public void updated(Dictionary<String, ?> properties) {
138 LOG.debug("{}: ManagedService updated for persistentId {}, properties: {}, initialUpdate: {}",
139 logName(), persistentId, properties, initialUpdate);
141 // The first update occurs when the service is registered so ignore it as we want subsequent
142 // updates when it changes. The ConfigAdmin will send an update even if the cfg file doesn't
145 initialUpdate = false;
147 blueprintContainerRestartService.restartContainerAndDependents(bundle);
152 Dictionary<String, Object> props = new Hashtable<>();
153 props.put(Constants.SERVICE_PID, persistentId);
154 props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
155 props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
156 managedServiceRegs.add(bundle.getBundleContext().registerService(ManagedService.class.getName(),
157 managedService, props));
160 private String logName() {
161 return bundle.getSymbolicName();