This is an automated email from the ASF dual-hosted git repository.

mpapirkovskyy pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 8c9b198  AMBARI-23463. Server should support saving configs with names 
which contains slash. (mpapirkovskyy)
8c9b198 is described below

commit 8c9b19848174dfc529d55b6864cfeb8fe0f9a8ff
Author: Myroslav Papirkovskyi <[email protected]>
AuthorDate: Fri Apr 6 18:14:18 2018 +0300

    AMBARI-23463. Server should support saving configs with names which 
contains slash. (mpapirkovskyy)
---
 .../services/parsers/JsonRequestBodyParser.java    | 47 ++++++++++++++++++++--
 .../apache/ambari/server/state/ConfigHelper.java   | 27 +++++++++++++
 2 files changed, 70 insertions(+), 4 deletions(-)

diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
index eaa652e..d64b590 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/api/services/parsers/JsonRequestBodyParser.java
@@ -32,6 +32,8 @@ import org.apache.ambari.server.api.services.NamedPropertySet;
 import org.apache.ambari.server.api.services.RequestBody;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.codehaus.jackson.JsonNode;
+import org.codehaus.jackson.SerializableString;
+import org.codehaus.jackson.io.CharacterEscapes;
 import org.codehaus.jackson.map.ObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -45,6 +47,12 @@ public class JsonRequestBodyParser implements 
RequestBodyParser {
    */
   private final static Logger LOG = 
LoggerFactory.getLogger(JsonRequestBodyParser.class);
 
+  private final static ObjectMapper mapper = new ObjectMapper();
+
+  static {
+    mapper.getJsonFactory().setCharacterEscapes(new AmbariEscapes());
+  }
+
   @Override
   public Set<RequestBody> parse(String body) throws BodyParseException {
 
@@ -53,7 +61,6 @@ public class JsonRequestBodyParser implements 
RequestBodyParser {
     rootBody.setBody(body);
 
     if (body != null && body.length() != 0) {
-      ObjectMapper mapper = new ObjectMapper();
       try {
         JsonNode root = mapper.readTree(ensureArrayFormat(body));
 
@@ -110,8 +117,7 @@ public class JsonRequestBodyParser implements 
RequestBodyParser {
   }
 
   private void processNode(JsonNode node, String path, NamedPropertySet 
propertySet,
-                           Map<String, String> requestInfoProps) {
-
+                           Map<String, String> requestInfoProps) throws 
IOException {
     Iterator<String> iterator = node.getFieldNames();
     while (iterator.hasNext()) {
       String   name  = iterator.next();
@@ -160,8 +166,9 @@ public class JsonRequestBodyParser implements 
RequestBodyParser {
               path.substring(REQUEST_INFO_PATH.length() + SLASH.length()), 
name),
               value);
         } else {
+          String escapedName = AmbariEscapes.escapeValue(mapper, name);
           propertySet.getProperties().put(PropertyHelper.getPropertyId(
-              path.equals(BODY_TITLE) ? "" : path, name), value);
+              path.equals(BODY_TITLE) ? "" : path, escapedName), value);
         }
       }
     }
@@ -170,4 +177,36 @@ public class JsonRequestBodyParser implements 
RequestBodyParser {
   private String ensureArrayFormat(String s) {
     return s.startsWith("[") ? s : '[' + s + ']';
   }
+
+  static class AmbariEscapes extends CharacterEscapes {
+
+    private final int[] escapeCodesForAscii;
+
+    public AmbariEscapes() {
+      this.escapeCodesForAscii = standardAsciiEscapesForJSON();
+      escapeCodesForAscii['/'] = CharacterEscapes.ESCAPE_STANDARD;
+    }
+
+    @Override
+    public int[] getEscapeCodesForAscii() {
+      return escapeCodesForAscii;
+    }
+
+    @Override
+    public SerializableString getEscapeSequence(int ch) {
+      return null;
+    }
+
+    /**
+     * Converts string to escaped and removes first and last symbols (double 
brackets)
+     * @param mapper mapper
+     * @param value string to be escaped
+     * @return escaped string
+     * @throws IOException
+     */
+    private static String escapeValue(ObjectMapper mapper, String value) 
throws IOException {
+      String escapedString = mapper.writeValueAsString(value);
+      return escapedString.substring(1, escapedString.length() - 1);
+    }
+  }
 }
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java 
b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
index ac543b7..71d1cc4 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/state/ConfigHelper.java
@@ -58,6 +58,7 @@ import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.NumberUtils;
+import org.apache.commons.lang3.StringEscapeUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -1952,7 +1953,9 @@ public class ConfigHelper {
       LOG.info("For configs update on host {} will be used following effective 
desired tags {}", hostId, configTags.toString());
 
       getAndMergeHostConfigs(configurations, configTags, cl);
+      configurations = unescapeConfigNames(configurations);
       getAndMergeHostConfigAttributes(configurationAttributes, configTags, cl);
+      configurationAttributes = 
unescapeConfigAttributeNames(configurationAttributes);
 
       SortedMap<String, SortedMap<String, String>> configurationsTreeMap = 
sortConfigutations(configurations);
       SortedMap<String, SortedMap<String, SortedMap<String, String>>> 
configurationAttributesTreeMap =
@@ -1966,6 +1969,30 @@ public class ConfigHelper {
     return agentConfigsUpdateEvent;
   }
 
+  private Map<String, Map<String, String>> unescapeConfigNames(Map<String, 
Map<String, String>> configurations) {
+    Map<String, Map<String, String>> unescapedConfigs = new HashMap<>();
+    for (Entry<String, Map<String, String>> configTypeEntry : 
configurations.entrySet()) {
+      Map<String, String> unescapedTypeConfigs = new HashMap<>();
+      for (Entry<String, String> config : 
configTypeEntry.getValue().entrySet()) {
+        
unescapedTypeConfigs.put(StringEscapeUtils.unescapeJava(config.getKey()), 
config.getValue());
+      }
+      unescapedConfigs.put(configTypeEntry.getKey(), unescapedTypeConfigs);
+    }
+
+    return unescapedConfigs;
+  }
+
+  private Map<String, Map<String, Map<String, String>>> 
unescapeConfigAttributeNames(
+      Map<String, Map<String, Map<String, String>>> configurationAttributes) {
+    Map<String, Map<String, Map<String, String>>> unescapedConfigAttributes = 
new HashMap<>();
+
+    for (Entry<String, Map<String, Map<String, String>>> configAttrTypeEntry : 
configurationAttributes.entrySet()) {
+      unescapedConfigAttributes.put(configAttrTypeEntry.getKey(), 
unescapeConfigNames(configAttrTypeEntry.getValue()));
+    }
+
+    return unescapedConfigAttributes;
+  }
+
   public SortedMap<String, SortedMap<String, String>> 
sortConfigutations(Map<String, Map<String, String>> configurations) {
     SortedMap<String, SortedMap<String, String>> configurationsTreeMap = new 
TreeMap<>();
     configurations.forEach((k, v) -> {

-- 
To stop receiving notification emails like this one, please contact
[email protected].

Reply via email to