Add restart-dependents-on-update blueprint extension
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / ext / OpendaylightNamespaceHandler.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 java.net.URL;
11 import java.util.Collections;
12 import java.util.Set;
13 import org.apache.aries.blueprint.ComponentDefinitionRegistry;
14 import org.apache.aries.blueprint.NamespaceHandler;
15 import org.apache.aries.blueprint.ParserContext;
16 import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
17 import org.apache.aries.blueprint.mutable.MutableRefMetadata;
18 import org.apache.aries.blueprint.mutable.MutableReferenceMetadata;
19 import org.apache.aries.blueprint.mutable.MutableValueMetadata;
20 import org.opendaylight.controller.blueprint.BlueprintContainerRestartService;
21 import org.osgi.service.blueprint.container.ComponentDefinitionException;
22 import org.osgi.service.blueprint.reflect.BeanMetadata;
23 import org.osgi.service.blueprint.reflect.ComponentMetadata;
24 import org.osgi.service.blueprint.reflect.Metadata;
25 import org.osgi.service.blueprint.reflect.RefMetadata;
26 import org.osgi.service.blueprint.reflect.ReferenceMetadata;
27 import org.osgi.service.blueprint.reflect.ValueMetadata;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30 import org.w3c.dom.Attr;
31 import org.w3c.dom.Element;
32 import org.w3c.dom.Node;
33
34 /**
35  * The NamespaceHandler for Opendaylight blueprint extensions.
36  *
37  * @author Thomas Pantelis
38  */
39 public class OpendaylightNamespaceHandler implements NamespaceHandler {
40     public static final String NAMESPACE_1_0_0 = "http://opendaylight.org/xmlns/blueprint/v1.0.0";
41
42     private static final Logger LOG = LoggerFactory.getLogger(OpendaylightNamespaceHandler.class);
43     private static final String COMPONENT_PROCESSOR_NAME = ComponentProcessor.class.getName();
44     private static final String RESTART_DEPENDENTS_ON_UPDATES = "restart-dependents-on-updates";
45
46     @SuppressWarnings("rawtypes")
47     @Override
48     public Set<Class> getManagedClasses() {
49         return Collections.emptySet();
50     }
51
52     @Override
53     public URL getSchemaLocation(String namespace) {
54         if(NAMESPACE_1_0_0.equals(namespace)) {
55             URL url = getClass().getResource("/opendaylight-blueprint-ext-1.0.0.xsd");
56             LOG.debug("getSchemaLocation for {} returning URL {}", namespace, url);
57             return url;
58         }
59
60         return null;
61     }
62
63     @Override
64     public Metadata parse(Element element, ParserContext context) {
65         LOG.debug("In parse for {}", element);
66         throw new ComponentDefinitionException("Unsupported standalone element: " + element.getNodeName());
67     }
68
69     @Override
70     public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
71         if(node instanceof Attr) {
72             if (nodeNameEquals(node, RESTART_DEPENDENTS_ON_UPDATES)) {
73                 return decorateRestartDependentsOnUpdates((Attr)node, component, context);
74             }
75
76             throw new ComponentDefinitionException("Unsupported attribute: " + node.getNodeName());
77         } else {
78             throw new ComponentDefinitionException("Unsupported node type: " + node);
79         }
80     }
81
82     private static ComponentMetadata decorateRestartDependentsOnUpdates(Attr attr, ComponentMetadata component,
83             ParserContext context) {
84         if(component != null) {
85             throw new ComponentDefinitionException("Attribute " + attr.getNodeName() +
86                     " can only be used on the root <blueprint> element");
87         }
88
89         LOG.debug("decorateRestartDependentsOnUpdates: {}", attr.getValue());
90
91         if(!Boolean.TRUE.equals(Boolean.valueOf(attr.getValue()))) {
92             return component;
93         }
94
95         MutableBeanMetadata metadata = registerComponentProcessor(context);
96         metadata.addProperty("restartDependentsOnUpdates", createValue(context, "true"));
97
98         return component;
99     }
100
101     private static MutableBeanMetadata registerComponentProcessor(ParserContext context) {
102         ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
103         MutableBeanMetadata metadata = (MutableBeanMetadata) registry.getComponentDefinition(COMPONENT_PROCESSOR_NAME);
104         if(metadata == null) {
105             metadata = context.createMetadata(MutableBeanMetadata.class);
106             metadata.setProcessor(true);
107             metadata.setId(COMPONENT_PROCESSOR_NAME);
108             metadata.setActivation(BeanMetadata.ACTIVATION_EAGER);
109             metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
110             metadata.setRuntimeClass(ComponentProcessor.class);
111             metadata.setDestroyMethod("destroy");
112             metadata.addProperty("bundle", createRef(context, "blueprintBundle"));
113             metadata.addProperty("blueprintContainerRestartService", createServiceRef(context,
114                     BlueprintContainerRestartService.class, null));
115
116             LOG.debug("Registering ComponentProcessor bean: {}", metadata);
117
118             registry.registerComponentDefinition(metadata);
119         }
120
121         return metadata;
122     }
123
124     private static ValueMetadata createValue(ParserContext context, String value) {
125         MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
126         m.setStringValue(value);
127         return m;
128     }
129
130     private static MutableReferenceMetadata createServiceRef(ParserContext context, Class<?> cls, String filter) {
131         MutableReferenceMetadata m = context.createMetadata(MutableReferenceMetadata.class);
132         m.setRuntimeInterface(cls);
133         m.setInterface(cls.getName());
134         m.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
135         m.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY);
136
137         if(filter != null) {
138             m.setFilter(filter);
139         }
140
141         return m;
142     }
143
144     private static RefMetadata createRef(ParserContext context, String value) {
145         MutableRefMetadata metadata = context.createMetadata(MutableRefMetadata.class);
146         metadata.setComponentId(value);
147         return metadata;
148     }
149
150     private static boolean nodeNameEquals(Node node, String name) {
151         return name.equals(node.getNodeName()) || name.equals(node.getLocalName());
152     }
153 }