Fix CS warnings in blueprint and enable enforcement
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / ext / ComponentProcessor.java
1 /*
2  * Copyright (c) 2016 Brocade Communications Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.blueprint.ext;
9
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;
31
32 /**
33  * The singleton component processor that is invoked by the blueprint container to perform operations on
34  * various component definitions prior to component creation.
35  *
36  * @author Thomas Pantelis
37  */
38 public class ComponentProcessor implements ComponentDefinitionRegistryProcessor {
39     static final String DEFAULT_TYPE_FILTER = "(|(type=default)(!(type=*)))";
40
41     private static final Logger LOG = LoggerFactory.getLogger(ComponentProcessor.class);
42     private static final String CM_PERSISTENT_ID_PROPERTY = "persistentId";
43
44     private final List<ServiceRegistration<?>> managedServiceRegs = new ArrayList<>();
45     private Bundle bundle;
46     private BlueprintContainerRestartService blueprintContainerRestartService;
47     private boolean restartDependentsOnUpdates;
48     private boolean useDefaultForReferenceTypes;
49
50     public void setBundle(Bundle bundle) {
51         this.bundle = bundle;
52     }
53
54     public void setBlueprintContainerRestartService(BlueprintContainerRestartService restartService) {
55         this.blueprintContainerRestartService = restartService;
56     }
57
58     public void setRestartDependentsOnUpdates(boolean restartDependentsOnUpdates) {
59         this.restartDependentsOnUpdates = restartDependentsOnUpdates;
60     }
61
62     public void setUseDefaultForReferenceTypes(boolean useDefaultForReferenceTypes) {
63         this.useDefaultForReferenceTypes = useDefaultForReferenceTypes;
64     }
65
66     public void destroy() {
67         for (ServiceRegistration<?> reg: managedServiceRegs) {
68             AriesFrameworkUtil.safeUnregisterService(reg);
69         }
70     }
71
72     @Override
73     public void process(ComponentDefinitionRegistry registry) {
74         LOG.debug("{}: In process",  logName());
75
76         for (String name : registry.getComponentDefinitionNames()) {
77             ComponentMetadata component = registry.getComponentDefinition(name);
78             if (component instanceof MutableBeanMetadata) {
79                 processMutableBeanMetadata((MutableBeanMetadata) component);
80             } else if (component instanceof MutableServiceReferenceMetadata) {
81                 processServiceReferenceMetadata((MutableServiceReferenceMetadata)component);
82             }
83         }
84     }
85
86     private void processServiceReferenceMetadata(MutableServiceReferenceMetadata serviceRef) {
87         if (!useDefaultForReferenceTypes) {
88             return;
89         }
90
91         String filter = serviceRef.getFilter();
92         String extFilter = serviceRef.getExtendedFilter() == null ? null :
93             serviceRef.getExtendedFilter().getStringValue();
94
95         LOG.debug("{}: processServiceReferenceMetadata for {}, filter: {}, ext filter: {}", logName(),
96                 serviceRef.getId(), filter, extFilter);
97
98         if (Strings.isNullOrEmpty(filter) && Strings.isNullOrEmpty(extFilter)) {
99             serviceRef.setFilter(DEFAULT_TYPE_FILTER);
100
101             LOG.debug("{}: processServiceReferenceMetadata for {} set filter to {}", logName(),
102                     serviceRef.getId(), serviceRef.getFilter());
103         }
104     }
105
106     private void processMutableBeanMetadata(MutableBeanMetadata bean) {
107         if (restartDependentsOnUpdates && bean.getRuntimeClass() != null
108                 && AbstractPropertyPlaceholder.class.isAssignableFrom(bean.getRuntimeClass())) {
109             LOG.debug("{}: Found PropertyPlaceholder bean: {}, runtime {}", logName(), bean.getId(),
110                     bean.getRuntimeClass());
111
112             for (BeanProperty prop : bean.getProperties()) {
113                 if (CM_PERSISTENT_ID_PROPERTY.equals(prop.getName())) {
114                     if (prop.getValue() instanceof ValueMetadata) {
115                         ValueMetadata persistentId = (ValueMetadata)prop.getValue();
116
117                         LOG.debug("{}: Found {} property, value : {}", logName(),
118                                 CM_PERSISTENT_ID_PROPERTY, persistentId.getStringValue());
119
120                         registerManagedService(persistentId.getStringValue());
121                     } else {
122                         LOG.debug("{}: {} property metadata {} is not instanceof ValueMetadata",
123                                 logName(), CM_PERSISTENT_ID_PROPERTY, prop.getValue());
124                     }
125
126                     break;
127                 }
128             }
129         }
130     }
131
132     private void registerManagedService(final String persistentId) {
133         // Register a ManagedService so we get updates from the ConfigAdmin when the cfg file corresponding
134         // to the persistentId changes.
135         final ManagedService managedService = new ManagedService() {
136             private volatile boolean initialUpdate = true;
137
138             @Override
139             public void updated(Dictionary<String, ?> properties) {
140                 LOG.debug("{}: ManagedService updated for persistentId {}, properties: {}, initialUpdate: {}",
141                         logName(), persistentId, properties, initialUpdate);
142
143                 // The first update occurs when the service is registered so ignore it as we want subsequent
144                 // updates when it changes. The ConfigAdmin will send an update even if the cfg file doesn't
145                 // yet exist.
146                 if (initialUpdate) {
147                     initialUpdate = false;
148                 } else {
149                     blueprintContainerRestartService.restartContainerAndDependents(bundle);
150                 }
151             }
152         };
153
154         Dictionary<String, Object> props = new Hashtable<>();
155         props.put(Constants.SERVICE_PID, persistentId);
156         props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
157         props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
158         managedServiceRegs.add(bundle.getBundleContext().registerService(ManagedService.class.getName(),
159                 managedService, props));
160     }
161
162     private String logName() {
163         return bundle.getSymbolicName();
164     }
165 }