You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/10/16 17:06:17 UTC

[23/23] knox git commit: KNOX-998 - package name refactoring

KNOX-998 - package name refactoring


Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/7d0bff16
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/7d0bff16
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/7d0bff16

Branch: refs/heads/KNOX-998-Package_Restructuring
Commit: 7d0bff16e7128e5f2e10b54237cbc93f45932ffc
Parents: 78d35f1
Author: Sandeep More <mo...@apache.org>
Authored: Mon Oct 16 13:05:28 2017 -0400
Committer: Sandeep More <mo...@apache.org>
Committed: Mon Oct 16 13:05:28 2017 -0400

----------------------------------------------------------------------
 .../ambari/AmbariDynamicServiceURLCreator.java  | 151 ----
 .../ambari/ConditionalValueHandler.java         |  24 -
 .../discovery/ambari/PropertyEqualsHandler.java |  76 --
 .../ambari/ServiceURLPropertyConfig.java        | 324 -------
 .../discovery/ambari/SimpleValueHandler.java    |  32 -
 .../ambari/AmbariDynamicServiceURLCreator.java  | 151 ++++
 .../ambari/AmbariServiceURLCreator.java         |   0
 .../ambari/ConditionalValueHandler.java         |  24 +
 .../discovery/ambari/PropertyEqualsHandler.java |  76 ++
 .../ambari/ServiceURLPropertyConfig.java        | 324 +++++++
 .../discovery/ambari/SimpleValueHandler.java    |  32 +
 .../AmbariDynamicServiceURLCreatorTest.java     | 876 -------------------
 .../AmbariDynamicServiceURLCreatorTest.java     | 876 +++++++++++++++++++
 .../gateway/websockets/ProxyInboundClient.java  | 107 ---
 .../gateway/websockets/ProxyInboundClient.java  | 107 +++
 .../websockets/ProxyInboundClientTest.java      | 374 --------
 .../websockets/ProxyInboundClientTest.java      | 374 ++++++++
 17 files changed, 1964 insertions(+), 1964 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
deleted file mode 100644
index ed5d3e7..0000000
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.hadoop.gateway.topology.discovery.ambari;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-
-class AmbariDynamicServiceURLCreator {
-
-    static final String MAPPING_CONFIG_OVERRIDE_PROPERTY = "org.apache.gateway.topology.discovery.ambari.config";
-
-    private AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
-
-    private AmbariCluster cluster = null;
-    private ServiceURLPropertyConfig config;
-
-    AmbariDynamicServiceURLCreator(AmbariCluster cluster) {
-        this.cluster = cluster;
-
-        String mappingConfiguration = System.getProperty(MAPPING_CONFIG_OVERRIDE_PROPERTY);
-        if (mappingConfiguration != null) {
-            File mappingConfigFile = new File(mappingConfiguration);
-            if (mappingConfigFile.exists()) {
-                try {
-                    config = new ServiceURLPropertyConfig(mappingConfigFile);
-                    log.loadedComponentConfigMappings(mappingConfigFile.getAbsolutePath());
-                } catch (Exception e) {
-                    log.failedToLoadComponentConfigMappings(mappingConfigFile.getAbsolutePath(), e);
-                }
-            }
-        }
-
-        // If there is no valid override configured, fall-back to the internal mapping configuration
-        if (config == null) {
-            config = new ServiceURLPropertyConfig();
-        }
-    }
-
-    AmbariDynamicServiceURLCreator(AmbariCluster cluster, File mappingConfiguration) throws IOException {
-        this.cluster = cluster;
-        config = new ServiceURLPropertyConfig(new FileInputStream(mappingConfiguration));
-    }
-
-    AmbariDynamicServiceURLCreator(AmbariCluster cluster, String mappings) {
-        this.cluster = cluster;
-        config = new ServiceURLPropertyConfig(new ByteArrayInputStream(mappings.getBytes()));
-    }
-
-    List<String> create(String serviceName) {
-        List<String> urls = new ArrayList<>();
-
-        Map<String, String> placeholderValues = new HashMap<>();
-        List<String> componentHostnames = new ArrayList<>();
-        String hostNamePlaceholder = null;
-
-        ServiceURLPropertyConfig.URLPattern pattern = config.getURLPattern(serviceName);
-        if (pattern != null) {
-            for (String propertyName : pattern.getPlaceholders()) {
-                ServiceURLPropertyConfig.Property configProperty = config.getConfigProperty(serviceName, propertyName);
-
-                String propertyValue = null;
-                String propertyType = configProperty.getType();
-                if (ServiceURLPropertyConfig.Property.TYPE_SERVICE.equals(propertyType)) {
-                    log.lookingUpServiceConfigProperty(configProperty.getService(), configProperty.getServiceConfig(), configProperty.getValue());
-                    AmbariCluster.ServiceConfiguration svcConfig =
-                        cluster.getServiceConfiguration(configProperty.getService(), configProperty.getServiceConfig());
-                    if (svcConfig != null) {
-                        propertyValue = svcConfig.getProperties().get(configProperty.getValue());
-                    }
-                } else if (ServiceURLPropertyConfig.Property.TYPE_COMPONENT.equals(propertyType)) {
-                    String compName = configProperty.getComponent();
-                    if (compName != null) {
-                        AmbariComponent component = cluster.getComponent(compName);
-                        if (component != null) {
-                            if (ServiceURLPropertyConfig.Property.PROP_COMP_HOSTNAME.equals(configProperty.getValue())) {
-                                log.lookingUpComponentHosts(compName);
-                                componentHostnames.addAll(component.getHostNames());
-                                hostNamePlaceholder = propertyName; // Remember the host name placeholder
-                            } else {
-                                log.lookingUpComponentConfigProperty(compName, configProperty.getValue());
-                                propertyValue = component.getConfigProperty(configProperty.getValue());
-                            }
-                        }
-                    }
-                } else { // Derived property
-                    log.handlingDerivedProperty(serviceName, configProperty.getType(), configProperty.getName());
-                    ServiceURLPropertyConfig.Property p = config.getConfigProperty(serviceName, configProperty.getName());
-                    propertyValue = p.getValue();
-                    if (propertyValue == null) {
-                        if (p.getConditionHandler() != null) {
-                            propertyValue = p.getConditionHandler().evaluate(config, cluster);
-                        }
-                    }
-                }
-
-                log.determinedPropertyValue(configProperty.getName(), propertyValue);
-                placeholderValues.put(configProperty.getName(), propertyValue);
-            }
-
-            // For patterns with a placeholder value for the hostname (e.g., multiple URL scenarios)
-            if (!componentHostnames.isEmpty()) {
-                for (String componentHostname : componentHostnames) {
-                    String url = pattern.get().replace("{" + hostNamePlaceholder + "}", componentHostname);
-                    urls.add(createURL(url, placeholderValues));
-                }
-            } else { // Single URL result case
-                urls.add(createURL(pattern.get(), placeholderValues));
-            }
-        }
-
-        return urls;
-    }
-
-    private String createURL(String pattern, Map<String, String> placeholderValues) {
-        String url = null;
-        if (pattern != null) {
-            url = pattern;
-            for (String placeHolder : placeholderValues.keySet()) {
-                String value = placeholderValues.get(placeHolder);
-                if (value != null) {
-                    url = url.replace("{" + placeHolder + "}", value);
-                }
-            }
-        }
-        return url;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ConditionalValueHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ConditionalValueHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ConditionalValueHandler.java
deleted file mode 100644
index d76a161..0000000
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ConditionalValueHandler.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.hadoop.gateway.topology.discovery.ambari;
-
-
-interface ConditionalValueHandler {
-
-    String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster);
-
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/PropertyEqualsHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
deleted file mode 100644
index 642a676..0000000
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.hadoop.gateway.topology.discovery.ambari;
-
-
-class PropertyEqualsHandler implements ConditionalValueHandler {
-
-    private String serviceName                        = null;
-    private String propertyName                       = null;
-    private String propertyValue                      = null;
-    private ConditionalValueHandler affirmativeResult = null;
-    private ConditionalValueHandler negativeResult    = null;
-
-    PropertyEqualsHandler(String                  serviceName,
-                          String                  propertyName,
-                          String                  propertyValue,
-                          ConditionalValueHandler affirmativeResult,
-                          ConditionalValueHandler negativeResult) {
-        this.serviceName       = serviceName;
-        this.propertyName      = propertyName;
-        this.propertyValue     = propertyValue;
-        this.affirmativeResult = affirmativeResult;
-        this.negativeResult    = negativeResult;
-    }
-
-    @Override
-    public String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster) {
-        String result = null;
-
-        ServiceURLPropertyConfig.Property p = config.getConfigProperty(serviceName, propertyName);
-        if (p != null) {
-            String value = getActualPropertyValue(cluster, p);
-            if (propertyValue.equals(value)) {
-                result = affirmativeResult.evaluate(config, cluster);
-            } else if (negativeResult != null) {
-                result = negativeResult.evaluate(config, cluster);
-            }
-
-            // Check if the result is a reference to a local derived property
-            ServiceURLPropertyConfig.Property derived = config.getConfigProperty(serviceName, result);
-            if (derived != null) {
-                result = getActualPropertyValue(cluster, derived);
-            }
-        }
-
-        return result;
-    }
-
-    private String getActualPropertyValue(AmbariCluster cluster, ServiceURLPropertyConfig.Property property) {
-        String value = null;
-        String propertyType = property.getType();
-        if (ServiceURLPropertyConfig.Property.TYPE_COMPONENT.equals(propertyType)) {
-            AmbariComponent component = cluster.getComponent(property.getComponent());
-            if (component != null) {
-                value = component.getConfigProperty(property.getValue());
-            }
-        } else if (ServiceURLPropertyConfig.Property.TYPE_SERVICE.equals(propertyType)) {
-            value = cluster.getServiceConfiguration(property.getService(), property.getServiceConfig()).getProperties().get(property.getValue());
-        }
-        return value;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
deleted file mode 100644
index 3330cc3..0000000
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
+++ /dev/null
@@ -1,324 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.hadoop.gateway.topology.discovery.ambari;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.util.XmlUtils;
-import org.w3c.dom.Document;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpression;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-/**
- * Service URL pattern mapping configuration model.
- */
-class ServiceURLPropertyConfig {
-
-    private static final AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
-
-    private static final String ATTR_NAME = "name";
-
-    private static XPathExpression SERVICE_URL_PATTERN_MAPPINGS;
-    private static XPathExpression URL_PATTERN;
-    private static XPathExpression PROPERTIES;
-    static {
-        XPath xpath = XPathFactory.newInstance().newXPath();
-        try {
-            SERVICE_URL_PATTERN_MAPPINGS = xpath.compile("/service-discovery-url-mappings/service");
-            URL_PATTERN                  = xpath.compile("url-pattern/text()");
-            PROPERTIES                   = xpath.compile("properties/property");
-        } catch (XPathExpressionException e) {
-            e.printStackTrace();
-        }
-    }
-
-    private static final String DEFAULT_SERVICE_URL_MAPPINGS = "ambari-service-discovery-url-mappings.xml";
-
-    private Map<String, URLPattern> urlPatterns = new HashMap<>();
-
-    private Map<String, Map<String, Property>> properties = new HashMap<>();
-
-
-    /**
-     * The default service URL pattern to property mapping configuration will be used.
-     */
-    ServiceURLPropertyConfig() {
-        this(ServiceURLPropertyConfig.class.getClassLoader().getResourceAsStream(DEFAULT_SERVICE_URL_MAPPINGS));
-    }
-
-    /**
-     * The default service URL pattern to property mapping configuration will be used.
-     */
-    ServiceURLPropertyConfig(File mappingConfigurationFile) throws Exception {
-        this(new FileInputStream(mappingConfigurationFile));
-    }
-
-    /**
-     *
-     * @param source An InputStream for the XML content
-     */
-    ServiceURLPropertyConfig(InputStream source) {
-        // Parse the XML, and build the model
-        try {
-            Document doc = XmlUtils.readXml(source);
-
-            NodeList serviceNodes =
-                    (NodeList) SERVICE_URL_PATTERN_MAPPINGS.evaluate(doc, XPathConstants.NODESET);
-            for (int i=0; i < serviceNodes.getLength(); i++) {
-                Node serviceNode = serviceNodes.item(i);
-                String serviceName = serviceNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
-                properties.put(serviceName, new HashMap<String, Property>());
-
-                Node urlPatternNode = (Node) URL_PATTERN.evaluate(serviceNode, XPathConstants.NODE);
-                if (urlPatternNode != null) {
-                    urlPatterns.put(serviceName, new URLPattern(urlPatternNode.getNodeValue()));
-                }
-
-                NodeList propertiesNode = (NodeList) PROPERTIES.evaluate(serviceNode, XPathConstants.NODESET);
-                if (propertiesNode != null) {
-                    processProperties(serviceName, propertiesNode);
-                }
-            }
-        } catch (Exception e) {
-            log.failedToLoadServiceDiscoveryConfiguration(e);
-        } finally {
-            try {
-                source.close();
-            } catch (IOException e) {
-                // Ignore
-            }
-        }
-    }
-
-    private void processProperties(String serviceName, NodeList propertyNodes) {
-        for (int i = 0; i < propertyNodes.getLength(); i++) {
-            Property p = Property.createProperty(serviceName, propertyNodes.item(i));
-            properties.get(serviceName).put(p.getName(), p);
-        }
-    }
-
-    URLPattern getURLPattern(String service) {
-        return urlPatterns.get(service);
-    }
-
-    Property getConfigProperty(String service, String property) {
-        return properties.get(service).get(property);
-    }
-
-    static class URLPattern {
-        String pattern;
-        List<String> placeholders = new ArrayList<>();
-
-        URLPattern(String pattern) {
-            this.pattern = pattern;
-
-            final Pattern regex = Pattern.compile("\\{(.*?)}", Pattern.DOTALL);
-            final Matcher matcher = regex.matcher(pattern);
-            while( matcher.find() ){
-                placeholders.add(matcher.group(1));
-            }
-        }
-
-        String get() {return pattern; }
-        List<String> getPlaceholders() {
-            return placeholders;
-        }
-    }
-
-    static class Property {
-        static final String TYPE_SERVICE   = "SERVICE";
-        static final String TYPE_COMPONENT = "COMPONENT";
-        static final String TYPE_DERIVED   = "DERIVED";
-
-        static final String PROP_COMP_HOSTNAME = "component.host.name";
-
-        static final String ATTR_NAME     = "name";
-        static final String ATTR_PROPERTY = "property";
-        static final String ATTR_VALUE    = "value";
-
-        static XPathExpression HOSTNAME;
-        static XPathExpression SERVICE_CONFIG;
-        static XPathExpression COMPONENT;
-        static XPathExpression CONFIG_PROPERTY;
-        static XPathExpression IF;
-        static XPathExpression THEN;
-        static XPathExpression ELSE;
-        static XPathExpression TEXT;
-        static {
-            XPath xpath = XPathFactory.newInstance().newXPath();
-            try {
-                HOSTNAME        = xpath.compile("hostname");
-                SERVICE_CONFIG  = xpath.compile("service-config");
-                COMPONENT       = xpath.compile("component");
-                CONFIG_PROPERTY = xpath.compile("config-property");
-                IF              = xpath.compile("if");
-                THEN            = xpath.compile("then");
-                ELSE            = xpath.compile("else");
-                TEXT            = xpath.compile("text()");
-            } catch (XPathExpressionException e) {
-                e.printStackTrace();
-            }
-        }
-
-
-        String type;
-        String name;
-        String component;
-        String service;
-        String serviceConfig;
-        String value;
-        ConditionalValueHandler conditionHandler = null;
-
-        private Property(String type,
-                         String propertyName,
-                         String component,
-                         String service,
-                         String configType,
-                         String value,
-                         ConditionalValueHandler pch) {
-            this.type = type;
-            this.name = propertyName;
-            this.service = service;
-            this.component = component;
-            this.serviceConfig = configType;
-            this.value = value;
-            conditionHandler = pch;
-        }
-
-        static Property createProperty(String serviceName, Node propertyNode) {
-            String propertyName = propertyNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
-            String propertyType = null;
-            String serviceType = null;
-            String configType = null;
-            String componentType = null;
-            String value = null;
-            ConditionalValueHandler pch = null;
-
-            try {
-                Node hostNameNode = (Node) HOSTNAME.evaluate(propertyNode, XPathConstants.NODE);
-                if (hostNameNode != null) {
-                    value = PROP_COMP_HOSTNAME;
-                }
-
-                // Check for a service-config node
-                Node scNode = (Node) SERVICE_CONFIG.evaluate(propertyNode, XPathConstants.NODE);
-                if (scNode != null) {
-                    // Service config property
-                    propertyType = Property.TYPE_SERVICE;
-                    serviceType = scNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
-                    Node scTextNode = (Node) TEXT.evaluate(scNode, XPathConstants.NODE);
-                    configType = scTextNode.getNodeValue();
-                } else { // If not service-config node, check for a component config node
-                    Node cNode = (Node) COMPONENT.evaluate(propertyNode, XPathConstants.NODE);
-                    if (cNode != null) {
-                        // Component config property
-                        propertyType = Property.TYPE_COMPONENT;
-                        componentType = cNode.getFirstChild().getNodeValue();
-                        Node cTextNode = (Node) TEXT.evaluate(cNode, XPathConstants.NODE);
-                        configType = cTextNode.getNodeValue();
-                        componentType = cTextNode.getNodeValue();
-                    }
-                }
-
-                // Check for a config property node
-                Node cpNode = (Node) CONFIG_PROPERTY.evaluate(propertyNode, XPathConstants.NODE);
-                if (cpNode != null) {
-                    // Check for a condition element
-                    Node ifNode = (Node) IF.evaluate(cpNode, XPathConstants.NODE);
-                    if (ifNode != null) {
-                        propertyType = TYPE_DERIVED;
-                        pch = getConditionHandler(serviceName, ifNode);
-                    } else {
-                        Node cpTextNode = (Node) TEXT.evaluate(cpNode, XPathConstants.NODE);
-                        value = cpTextNode.getNodeValue();
-                    }
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
-
-            // Create and return the property representation
-            return new Property(propertyType, propertyName, componentType, serviceType, configType, value, pch);
-        }
-
-        private static ConditionalValueHandler getConditionHandler(String serviceName, Node ifNode) throws Exception {
-            ConditionalValueHandler result = null;
-
-            if (ifNode != null) {
-                NamedNodeMap attrs = ifNode.getAttributes();
-                String comparisonPropName = attrs.getNamedItem(ATTR_PROPERTY).getNodeValue();
-                String comparisonValue = attrs.getNamedItem(ATTR_VALUE).getNodeValue();
-
-                ConditionalValueHandler affirmativeResult = null;
-                Node thenNode = (Node) THEN.evaluate(ifNode, XPathConstants.NODE);
-                if (thenNode != null) {
-                    Node subIfNode = (Node) IF.evaluate(thenNode, XPathConstants.NODE);
-                    if (subIfNode != null) {
-                        affirmativeResult = getConditionHandler(serviceName, subIfNode);
-                    } else {
-                        affirmativeResult = new SimpleValueHandler(thenNode.getFirstChild().getNodeValue());
-                    }
-                }
-
-                ConditionalValueHandler negativeResult = null;
-                Node elseNode = (Node) ELSE.evaluate(ifNode, XPathConstants.NODE);
-                if (elseNode != null) {
-                    Node subIfNode = (Node) IF.evaluate(elseNode, XPathConstants.NODE);
-                    if (subIfNode != null) {
-                        negativeResult = getConditionHandler(serviceName, subIfNode);
-                    } else {
-                        negativeResult = new SimpleValueHandler(elseNode.getFirstChild().getNodeValue());
-                    }
-                }
-
-                result = new PropertyEqualsHandler(serviceName,
-                        comparisonPropName,
-                        comparisonValue,
-                        affirmativeResult,
-                        negativeResult);
-            }
-
-            return result;
-        }
-
-        String getType() { return type; }
-        String getName() { return name; }
-        String getComponent() { return component; }
-        String getService() { return service; }
-        String getServiceConfig() { return serviceConfig; }
-        String getValue() {
-            return value;
-        }
-        ConditionalValueHandler getConditionHandler() { return conditionHandler; }
-    }
-}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/SimpleValueHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/SimpleValueHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/SimpleValueHandler.java
deleted file mode 100644
index 8e0cd75..0000000
--- a/gateway-discovery-ambari/src/main/java/org/apache/hadoop/gateway/topology/discovery/ambari/SimpleValueHandler.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * <p>
- * http://www.apache.org/licenses/LICENSE-2.0
- * <p>
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations under
- * the License.
- */
-package org.apache.hadoop.gateway.topology.discovery.ambari;
-
-
-class SimpleValueHandler implements ConditionalValueHandler {
-    private String value;
-
-    SimpleValueHandler(String value) {
-        this.value = value;
-    }
-
-    @Override
-    public String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster) {
-        return value;
-    }
-}
-

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
new file mode 100644
index 0000000..3c2269d
--- /dev/null
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariDynamicServiceURLCreator.java
@@ -0,0 +1,151 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.ambari;
+
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+class AmbariDynamicServiceURLCreator {
+
+    static final String MAPPING_CONFIG_OVERRIDE_PROPERTY = "org.apache.gateway.topology.discovery.ambari.config";
+
+    private AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
+
+    private AmbariCluster cluster = null;
+    private ServiceURLPropertyConfig config;
+
+    AmbariDynamicServiceURLCreator(AmbariCluster cluster) {
+        this.cluster = cluster;
+
+        String mappingConfiguration = System.getProperty(MAPPING_CONFIG_OVERRIDE_PROPERTY);
+        if (mappingConfiguration != null) {
+            File mappingConfigFile = new File(mappingConfiguration);
+            if (mappingConfigFile.exists()) {
+                try {
+                    config = new ServiceURLPropertyConfig(mappingConfigFile);
+                    log.loadedComponentConfigMappings(mappingConfigFile.getAbsolutePath());
+                } catch (Exception e) {
+                    log.failedToLoadComponentConfigMappings(mappingConfigFile.getAbsolutePath(), e);
+                }
+            }
+        }
+
+        // If there is no valid override configured, fall-back to the internal mapping configuration
+        if (config == null) {
+            config = new ServiceURLPropertyConfig();
+        }
+    }
+
+    AmbariDynamicServiceURLCreator(AmbariCluster cluster, File mappingConfiguration) throws IOException {
+        this.cluster = cluster;
+        config = new ServiceURLPropertyConfig(new FileInputStream(mappingConfiguration));
+    }
+
+    AmbariDynamicServiceURLCreator(AmbariCluster cluster, String mappings) {
+        this.cluster = cluster;
+        config = new ServiceURLPropertyConfig(new ByteArrayInputStream(mappings.getBytes()));
+    }
+
+    List<String> create(String serviceName) {
+        List<String> urls = new ArrayList<>();
+
+        Map<String, String> placeholderValues = new HashMap<>();
+        List<String> componentHostnames = new ArrayList<>();
+        String hostNamePlaceholder = null;
+
+        ServiceURLPropertyConfig.URLPattern pattern = config.getURLPattern(serviceName);
+        if (pattern != null) {
+            for (String propertyName : pattern.getPlaceholders()) {
+                ServiceURLPropertyConfig.Property configProperty = config.getConfigProperty(serviceName, propertyName);
+
+                String propertyValue = null;
+                String propertyType = configProperty.getType();
+                if (ServiceURLPropertyConfig.Property.TYPE_SERVICE.equals(propertyType)) {
+                    log.lookingUpServiceConfigProperty(configProperty.getService(), configProperty.getServiceConfig(), configProperty.getValue());
+                    AmbariCluster.ServiceConfiguration svcConfig =
+                        cluster.getServiceConfiguration(configProperty.getService(), configProperty.getServiceConfig());
+                    if (svcConfig != null) {
+                        propertyValue = svcConfig.getProperties().get(configProperty.getValue());
+                    }
+                } else if (ServiceURLPropertyConfig.Property.TYPE_COMPONENT.equals(propertyType)) {
+                    String compName = configProperty.getComponent();
+                    if (compName != null) {
+                        AmbariComponent component = cluster.getComponent(compName);
+                        if (component != null) {
+                            if (ServiceURLPropertyConfig.Property.PROP_COMP_HOSTNAME.equals(configProperty.getValue())) {
+                                log.lookingUpComponentHosts(compName);
+                                componentHostnames.addAll(component.getHostNames());
+                                hostNamePlaceholder = propertyName; // Remember the host name placeholder
+                            } else {
+                                log.lookingUpComponentConfigProperty(compName, configProperty.getValue());
+                                propertyValue = component.getConfigProperty(configProperty.getValue());
+                            }
+                        }
+                    }
+                } else { // Derived property
+                    log.handlingDerivedProperty(serviceName, configProperty.getType(), configProperty.getName());
+                    ServiceURLPropertyConfig.Property p = config.getConfigProperty(serviceName, configProperty.getName());
+                    propertyValue = p.getValue();
+                    if (propertyValue == null) {
+                        if (p.getConditionHandler() != null) {
+                            propertyValue = p.getConditionHandler().evaluate(config, cluster);
+                        }
+                    }
+                }
+
+                log.determinedPropertyValue(configProperty.getName(), propertyValue);
+                placeholderValues.put(configProperty.getName(), propertyValue);
+            }
+
+            // For patterns with a placeholder value for the hostname (e.g., multiple URL scenarios)
+            if (!componentHostnames.isEmpty()) {
+                for (String componentHostname : componentHostnames) {
+                    String url = pattern.get().replace("{" + hostNamePlaceholder + "}", componentHostname);
+                    urls.add(createURL(url, placeholderValues));
+                }
+            } else { // Single URL result case
+                urls.add(createURL(pattern.get(), placeholderValues));
+            }
+        }
+
+        return urls;
+    }
+
+    private String createURL(String pattern, Map<String, String> placeholderValues) {
+        String url = null;
+        if (pattern != null) {
+            url = pattern;
+            for (String placeHolder : placeholderValues.keySet()) {
+                String value = placeholderValues.get(placeHolder);
+                if (value != null) {
+                    url = url.replace("{" + placeHolder + "}", value);
+                }
+            }
+        }
+        return url;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/AmbariServiceURLCreator.java
deleted file mode 100644
index e69de29..0000000

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ConditionalValueHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ConditionalValueHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ConditionalValueHandler.java
new file mode 100644
index 0000000..168fce6
--- /dev/null
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ConditionalValueHandler.java
@@ -0,0 +1,24 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.ambari;
+
+
+interface ConditionalValueHandler {
+
+    String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster);
+
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/PropertyEqualsHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
new file mode 100644
index 0000000..4044d56
--- /dev/null
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/PropertyEqualsHandler.java
@@ -0,0 +1,76 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.ambari;
+
+
+class PropertyEqualsHandler implements ConditionalValueHandler {
+
+    private String serviceName                        = null;
+    private String propertyName                       = null;
+    private String propertyValue                      = null;
+    private ConditionalValueHandler affirmativeResult = null;
+    private ConditionalValueHandler negativeResult    = null;
+
+    PropertyEqualsHandler(String                  serviceName,
+                          String                  propertyName,
+                          String                  propertyValue,
+                          ConditionalValueHandler affirmativeResult,
+                          ConditionalValueHandler negativeResult) {
+        this.serviceName       = serviceName;
+        this.propertyName      = propertyName;
+        this.propertyValue     = propertyValue;
+        this.affirmativeResult = affirmativeResult;
+        this.negativeResult    = negativeResult;
+    }
+
+    @Override
+    public String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster) {
+        String result = null;
+
+        ServiceURLPropertyConfig.Property p = config.getConfigProperty(serviceName, propertyName);
+        if (p != null) {
+            String value = getActualPropertyValue(cluster, p);
+            if (propertyValue.equals(value)) {
+                result = affirmativeResult.evaluate(config, cluster);
+            } else if (negativeResult != null) {
+                result = negativeResult.evaluate(config, cluster);
+            }
+
+            // Check if the result is a reference to a local derived property
+            ServiceURLPropertyConfig.Property derived = config.getConfigProperty(serviceName, result);
+            if (derived != null) {
+                result = getActualPropertyValue(cluster, derived);
+            }
+        }
+
+        return result;
+    }
+
+    private String getActualPropertyValue(AmbariCluster cluster, ServiceURLPropertyConfig.Property property) {
+        String value = null;
+        String propertyType = property.getType();
+        if (ServiceURLPropertyConfig.Property.TYPE_COMPONENT.equals(propertyType)) {
+            AmbariComponent component = cluster.getComponent(property.getComponent());
+            if (component != null) {
+                value = component.getConfigProperty(property.getValue());
+            }
+        } else if (ServiceURLPropertyConfig.Property.TYPE_SERVICE.equals(propertyType)) {
+            value = cluster.getServiceConfiguration(property.getService(), property.getServiceConfig()).getProperties().get(property.getValue());
+        }
+        return value;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
new file mode 100644
index 0000000..ed07873
--- /dev/null
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/ServiceURLPropertyConfig.java
@@ -0,0 +1,324 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.ambari;
+
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.util.XmlUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Service URL pattern mapping configuration model.
+ */
+class ServiceURLPropertyConfig {
+
+    private static final AmbariServiceDiscoveryMessages log = MessagesFactory.get(AmbariServiceDiscoveryMessages.class);
+
+    private static final String ATTR_NAME = "name";
+
+    private static XPathExpression SERVICE_URL_PATTERN_MAPPINGS;
+    private static XPathExpression URL_PATTERN;
+    private static XPathExpression PROPERTIES;
+    static {
+        XPath xpath = XPathFactory.newInstance().newXPath();
+        try {
+            SERVICE_URL_PATTERN_MAPPINGS = xpath.compile("/service-discovery-url-mappings/service");
+            URL_PATTERN                  = xpath.compile("url-pattern/text()");
+            PROPERTIES                   = xpath.compile("properties/property");
+        } catch (XPathExpressionException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static final String DEFAULT_SERVICE_URL_MAPPINGS = "ambari-service-discovery-url-mappings.xml";
+
+    private Map<String, URLPattern> urlPatterns = new HashMap<>();
+
+    private Map<String, Map<String, Property>> properties = new HashMap<>();
+
+
+    /**
+     * The default service URL pattern to property mapping configuration will be used.
+     */
+    ServiceURLPropertyConfig() {
+        this(ServiceURLPropertyConfig.class.getClassLoader().getResourceAsStream(DEFAULT_SERVICE_URL_MAPPINGS));
+    }
+
+    /**
+     * The default service URL pattern to property mapping configuration will be used.
+     */
+    ServiceURLPropertyConfig(File mappingConfigurationFile) throws Exception {
+        this(new FileInputStream(mappingConfigurationFile));
+    }
+
+    /**
+     *
+     * @param source An InputStream for the XML content
+     */
+    ServiceURLPropertyConfig(InputStream source) {
+        // Parse the XML, and build the model
+        try {
+            Document doc = XmlUtils.readXml(source);
+
+            NodeList serviceNodes =
+                    (NodeList) SERVICE_URL_PATTERN_MAPPINGS.evaluate(doc, XPathConstants.NODESET);
+            for (int i=0; i < serviceNodes.getLength(); i++) {
+                Node serviceNode = serviceNodes.item(i);
+                String serviceName = serviceNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
+                properties.put(serviceName, new HashMap<String, Property>());
+
+                Node urlPatternNode = (Node) URL_PATTERN.evaluate(serviceNode, XPathConstants.NODE);
+                if (urlPatternNode != null) {
+                    urlPatterns.put(serviceName, new URLPattern(urlPatternNode.getNodeValue()));
+                }
+
+                NodeList propertiesNode = (NodeList) PROPERTIES.evaluate(serviceNode, XPathConstants.NODESET);
+                if (propertiesNode != null) {
+                    processProperties(serviceName, propertiesNode);
+                }
+            }
+        } catch (Exception e) {
+            log.failedToLoadServiceDiscoveryConfiguration(e);
+        } finally {
+            try {
+                source.close();
+            } catch (IOException e) {
+                // Ignore
+            }
+        }
+    }
+
+    private void processProperties(String serviceName, NodeList propertyNodes) {
+        for (int i = 0; i < propertyNodes.getLength(); i++) {
+            Property p = Property.createProperty(serviceName, propertyNodes.item(i));
+            properties.get(serviceName).put(p.getName(), p);
+        }
+    }
+
+    URLPattern getURLPattern(String service) {
+        return urlPatterns.get(service);
+    }
+
+    Property getConfigProperty(String service, String property) {
+        return properties.get(service).get(property);
+    }
+
+    static class URLPattern {
+        String pattern;
+        List<String> placeholders = new ArrayList<>();
+
+        URLPattern(String pattern) {
+            this.pattern = pattern;
+
+            final Pattern regex = Pattern.compile("\\{(.*?)}", Pattern.DOTALL);
+            final Matcher matcher = regex.matcher(pattern);
+            while( matcher.find() ){
+                placeholders.add(matcher.group(1));
+            }
+        }
+
+        String get() {return pattern; }
+        List<String> getPlaceholders() {
+            return placeholders;
+        }
+    }
+
+    static class Property {
+        static final String TYPE_SERVICE   = "SERVICE";
+        static final String TYPE_COMPONENT = "COMPONENT";
+        static final String TYPE_DERIVED   = "DERIVED";
+
+        static final String PROP_COMP_HOSTNAME = "component.host.name";
+
+        static final String ATTR_NAME     = "name";
+        static final String ATTR_PROPERTY = "property";
+        static final String ATTR_VALUE    = "value";
+
+        static XPathExpression HOSTNAME;
+        static XPathExpression SERVICE_CONFIG;
+        static XPathExpression COMPONENT;
+        static XPathExpression CONFIG_PROPERTY;
+        static XPathExpression IF;
+        static XPathExpression THEN;
+        static XPathExpression ELSE;
+        static XPathExpression TEXT;
+        static {
+            XPath xpath = XPathFactory.newInstance().newXPath();
+            try {
+                HOSTNAME        = xpath.compile("hostname");
+                SERVICE_CONFIG  = xpath.compile("service-config");
+                COMPONENT       = xpath.compile("component");
+                CONFIG_PROPERTY = xpath.compile("config-property");
+                IF              = xpath.compile("if");
+                THEN            = xpath.compile("then");
+                ELSE            = xpath.compile("else");
+                TEXT            = xpath.compile("text()");
+            } catch (XPathExpressionException e) {
+                e.printStackTrace();
+            }
+        }
+
+
+        String type;
+        String name;
+        String component;
+        String service;
+        String serviceConfig;
+        String value;
+        ConditionalValueHandler conditionHandler = null;
+
+        private Property(String type,
+                         String propertyName,
+                         String component,
+                         String service,
+                         String configType,
+                         String value,
+                         ConditionalValueHandler pch) {
+            this.type = type;
+            this.name = propertyName;
+            this.service = service;
+            this.component = component;
+            this.serviceConfig = configType;
+            this.value = value;
+            conditionHandler = pch;
+        }
+
+        static Property createProperty(String serviceName, Node propertyNode) {
+            String propertyName = propertyNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
+            String propertyType = null;
+            String serviceType = null;
+            String configType = null;
+            String componentType = null;
+            String value = null;
+            ConditionalValueHandler pch = null;
+
+            try {
+                Node hostNameNode = (Node) HOSTNAME.evaluate(propertyNode, XPathConstants.NODE);
+                if (hostNameNode != null) {
+                    value = PROP_COMP_HOSTNAME;
+                }
+
+                // Check for a service-config node
+                Node scNode = (Node) SERVICE_CONFIG.evaluate(propertyNode, XPathConstants.NODE);
+                if (scNode != null) {
+                    // Service config property
+                    propertyType = Property.TYPE_SERVICE;
+                    serviceType = scNode.getAttributes().getNamedItem(ATTR_NAME).getNodeValue();
+                    Node scTextNode = (Node) TEXT.evaluate(scNode, XPathConstants.NODE);
+                    configType = scTextNode.getNodeValue();
+                } else { // If not service-config node, check for a component config node
+                    Node cNode = (Node) COMPONENT.evaluate(propertyNode, XPathConstants.NODE);
+                    if (cNode != null) {
+                        // Component config property
+                        propertyType = Property.TYPE_COMPONENT;
+                        componentType = cNode.getFirstChild().getNodeValue();
+                        Node cTextNode = (Node) TEXT.evaluate(cNode, XPathConstants.NODE);
+                        configType = cTextNode.getNodeValue();
+                        componentType = cTextNode.getNodeValue();
+                    }
+                }
+
+                // Check for a config property node
+                Node cpNode = (Node) CONFIG_PROPERTY.evaluate(propertyNode, XPathConstants.NODE);
+                if (cpNode != null) {
+                    // Check for a condition element
+                    Node ifNode = (Node) IF.evaluate(cpNode, XPathConstants.NODE);
+                    if (ifNode != null) {
+                        propertyType = TYPE_DERIVED;
+                        pch = getConditionHandler(serviceName, ifNode);
+                    } else {
+                        Node cpTextNode = (Node) TEXT.evaluate(cpNode, XPathConstants.NODE);
+                        value = cpTextNode.getNodeValue();
+                    }
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+
+            // Create and return the property representation
+            return new Property(propertyType, propertyName, componentType, serviceType, configType, value, pch);
+        }
+
+        private static ConditionalValueHandler getConditionHandler(String serviceName, Node ifNode) throws Exception {
+            ConditionalValueHandler result = null;
+
+            if (ifNode != null) {
+                NamedNodeMap attrs = ifNode.getAttributes();
+                String comparisonPropName = attrs.getNamedItem(ATTR_PROPERTY).getNodeValue();
+                String comparisonValue = attrs.getNamedItem(ATTR_VALUE).getNodeValue();
+
+                ConditionalValueHandler affirmativeResult = null;
+                Node thenNode = (Node) THEN.evaluate(ifNode, XPathConstants.NODE);
+                if (thenNode != null) {
+                    Node subIfNode = (Node) IF.evaluate(thenNode, XPathConstants.NODE);
+                    if (subIfNode != null) {
+                        affirmativeResult = getConditionHandler(serviceName, subIfNode);
+                    } else {
+                        affirmativeResult = new SimpleValueHandler(thenNode.getFirstChild().getNodeValue());
+                    }
+                }
+
+                ConditionalValueHandler negativeResult = null;
+                Node elseNode = (Node) ELSE.evaluate(ifNode, XPathConstants.NODE);
+                if (elseNode != null) {
+                    Node subIfNode = (Node) IF.evaluate(elseNode, XPathConstants.NODE);
+                    if (subIfNode != null) {
+                        negativeResult = getConditionHandler(serviceName, subIfNode);
+                    } else {
+                        negativeResult = new SimpleValueHandler(elseNode.getFirstChild().getNodeValue());
+                    }
+                }
+
+                result = new PropertyEqualsHandler(serviceName,
+                        comparisonPropName,
+                        comparisonValue,
+                        affirmativeResult,
+                        negativeResult);
+            }
+
+            return result;
+        }
+
+        String getType() { return type; }
+        String getName() { return name; }
+        String getComponent() { return component; }
+        String getService() { return service; }
+        String getServiceConfig() { return serviceConfig; }
+        String getValue() {
+            return value;
+        }
+        ConditionalValueHandler getConditionHandler() { return conditionHandler; }
+    }
+}

http://git-wip-us.apache.org/repos/asf/knox/blob/7d0bff16/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/SimpleValueHandler.java
----------------------------------------------------------------------
diff --git a/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/SimpleValueHandler.java b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/SimpleValueHandler.java
new file mode 100644
index 0000000..d1678d8
--- /dev/null
+++ b/gateway-discovery-ambari/src/main/java/org/apache/knox/gateway/topology/discovery/ambari/SimpleValueHandler.java
@@ -0,0 +1,32 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.apache.knox.gateway.topology.discovery.ambari;
+
+
+class SimpleValueHandler implements ConditionalValueHandler {
+    private String value;
+
+    SimpleValueHandler(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String evaluate(ServiceURLPropertyConfig config, AmbariCluster cluster) {
+        return value;
+    }
+}
+