Configurable update-strategy for clusteredAppConfig
[controller.git] / opendaylight / blueprint / src / main / java / org / opendaylight / controller / blueprint / ext / OpendaylightNamespaceHandler.java
index 80417e8bd076fb39fd8b7db1a02090bf5ae8567c..47b2c2b238320f711d428208728608b49ee92e7f 100644 (file)
@@ -8,9 +8,11 @@
 package org.opendaylight.controller.blueprint.ext;
 
 import com.google.common.base.Strings;
+import java.io.StringReader;
 import java.net.URL;
 import java.util.Collections;
 import java.util.Set;
+import javax.xml.parsers.DocumentBuilderFactory;
 import org.apache.aries.blueprint.ComponentDefinitionRegistry;
 import org.apache.aries.blueprint.NamespaceHandler;
 import org.apache.aries.blueprint.ParserContext;
@@ -38,6 +40,8 @@ import org.slf4j.LoggerFactory;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
 
 /**
  * The NamespaceHandler for Opendaylight blueprint extensions.
@@ -49,16 +53,20 @@ public class OpendaylightNamespaceHandler implements NamespaceHandler {
     static final String ROUTED_RPC_REG_CONVERTER_NAME = "org.opendaylight.blueprint.RoutedRpcRegConverter";
     static final String RPC_REGISTRY_NAME = "org.opendaylight.blueprint.RpcRegistry";
     static final String NOTIFICATION_SERVICE_NAME = "org.opendaylight.blueprint.NotificationService";
+    static final String TYPE_ATTR = "type";
+    static final String UPDATE_STRATEGY_ATTR = "update-strategy";
 
     private static final Logger LOG = LoggerFactory.getLogger(OpendaylightNamespaceHandler.class);
     private static final String COMPONENT_PROCESSOR_NAME = ComponentProcessor.class.getName();
     private static final String RESTART_DEPENDENTS_ON_UPDATES = "restart-dependents-on-updates";
     private static final String USE_DEFAULT_FOR_REFERENCE_TYPES = "use-default-for-reference-types";
-    private static final String TYPE_ATTR = "type";
+    private static final String CLUSTERED_APP_CONFIG = "clustered-app-config";
     private static final String INTERFACE = "interface";
     private static final String REF_ATTR = "ref";
     private static final String ID_ATTR = "id";
     private static final String RPC_SERVICE = "rpc-service";
+    private static final String SPECIFIC_SERVICE_REF_LIST = "specific-reference-list";
+    private static final String STATIC_REFERENCE = "static-reference";
 
     @SuppressWarnings("rawtypes")
     @Override
@@ -89,6 +97,12 @@ public class OpendaylightNamespaceHandler implements NamespaceHandler {
             return parseRpcService(element, context);
         } else if (nodeNameEquals(element, NotificationListenerBean.NOTIFICATION_LISTENER)) {
             return parseNotificationListener(element, context);
+        } else if (nodeNameEquals(element, CLUSTERED_APP_CONFIG)) {
+            return parseClusteredAppConfig(element, context);
+        } else if (nodeNameEquals(element, SPECIFIC_SERVICE_REF_LIST)) {
+            return parseSpecificReferenceList(element, context);
+        } else if (nodeNameEquals(element, STATIC_REFERENCE)) {
+            return parseStaticReference(element, context);
         }
 
         throw new ComponentDefinitionException("Unsupported standalone element: " + element.getNodeName());
@@ -250,8 +264,6 @@ public class OpendaylightNamespaceHandler implements NamespaceHandler {
     }
 
     private Metadata parseRpcService(Element element, ParserContext context) {
-        registerRpcRegistryServiceRefBean(context);
-
         ComponentFactoryMetadata metadata = new RpcServiceMetadata(getId(context, element),
                 element.getAttribute(INTERFACE));
 
@@ -300,7 +312,7 @@ public class OpendaylightNamespaceHandler implements NamespaceHandler {
         return metadata;
     }
 
-     private void registerNotificationServiceRefBean(ParserContext context) {
+    private void registerNotificationServiceRefBean(ParserContext context) {
         ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
         if(registry.getComponentDefinition(NOTIFICATION_SERVICE_NAME) == null) {
             MutableReferenceMetadata metadata = createServiceRef(context, NotificationService.class, null);
@@ -309,6 +321,84 @@ public class OpendaylightNamespaceHandler implements NamespaceHandler {
         }
     }
 
+    private Metadata parseClusteredAppConfig(Element element, ParserContext context) {
+        LOG.debug("parseClusteredAppConfig");
+
+        // Find the default-config child element representing the default app config XML, if present.
+        Element defaultConfigElement = null;
+        NodeList children = element.getChildNodes();
+        for(int i = 0; i < children.getLength(); i++) {
+            Node child = children.item(i);
+            if(nodeNameEquals(child, DataStoreAppConfigMetadata.DEFAULT_CONFIG)) {
+                defaultConfigElement = (Element) child;
+                break;
+            }
+        }
+
+        Element defaultAppConfigElement = null;
+        if(defaultConfigElement != null) {
+            // Find the CDATA element containing the default app config XML.
+            children = defaultConfigElement.getChildNodes();
+            for(int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+                if(child.getNodeType() == Node.CDATA_SECTION_NODE) {
+                    defaultAppConfigElement = parseXML(DataStoreAppConfigMetadata.DEFAULT_CONFIG, child.getTextContent());
+                    break;
+                }
+            }
+        }
+
+        return new DataStoreAppConfigMetadata(getId(context, element), element.getAttribute(
+                DataStoreAppConfigMetadata.BINDING_CLASS), element.getAttribute(
+                        DataStoreAppConfigMetadata.LIST_KEY_VALUE), element.getAttribute(
+                        DataStoreAppConfigMetadata.DEFAULT_CONFIG_FILE_NAME), parseUpdateStrategy(
+                        element.getAttribute(UPDATE_STRATEGY_ATTR)), defaultAppConfigElement);
+    }
+
+    private UpdateStrategy parseUpdateStrategy(String updateStrategyValue) {
+        if (Strings.isNullOrEmpty(updateStrategyValue) ||
+                updateStrategyValue.equalsIgnoreCase(UpdateStrategy.RELOAD.name())) {
+            return UpdateStrategy.RELOAD;
+        } else if(updateStrategyValue.equalsIgnoreCase(UpdateStrategy.NONE.name())){
+            return UpdateStrategy.NONE;
+        } else {
+            LOG.warn("update-strategy {} not supported, using reload", updateStrategyValue);
+            return UpdateStrategy.RELOAD;
+        }
+    }
+
+    private Metadata parseSpecificReferenceList(Element element, ParserContext context) {
+        ComponentFactoryMetadata metadata = new SpecificReferenceListMetadata(getId(context, element),
+                element.getAttribute(INTERFACE));
+
+        LOG.debug("parseSpecificReferenceList returning {}", metadata);
+
+        return metadata;
+    }
+
+    private Metadata parseStaticReference(Element element, ParserContext context) {
+        ComponentFactoryMetadata metadata = new StaticReferenceMetadata(getId(context, element),
+                element.getAttribute(INTERFACE));
+
+        LOG.debug("parseStaticReference returning {}", metadata);
+
+        return metadata;
+    }
+
+    private Element parseXML(String name, String xml) {
+        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
+        builderFactory.setNamespaceAware(true);
+        builderFactory.setCoalescing(true);
+        builderFactory.setIgnoringElementContentWhitespace(true);
+        builderFactory.setIgnoringComments(true);
+
+        try {
+            return builderFactory.newDocumentBuilder().parse(new InputSource(new StringReader(xml))).getDocumentElement();
+        } catch(Exception e) {
+            throw new ComponentDefinitionException(String.format("Error %s parsing XML: %s", name, xml));
+        }
+    }
+
     private static ValueMetadata createValue(ParserContext context, String value) {
         MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
         m.setStringValue(value);