Author: rgodfrey
Date: Fri Jul 18 14:01:19 2014
New Revision: 1611657

URL: http://svn.apache.org/r1611657
Log:
QPID-5903 : [Java Broker] allow character escaping for JSON in configured 
object attribute interpolation

Added:
    
qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/util/StringsTest.java
Modified:
    
qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
    qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/Strings.java

Modified: 
qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java?rev=1611657&r1=1611656&r2=1611657&view=diff
==============================================================================
--- 
qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
 (original)
+++ 
qpid/trunk/qpid/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java
 Fri Jul 18 14:01:19 2014
@@ -1361,6 +1361,7 @@ public abstract class AbstractConfigured
         Map<String,String> inheritedContext = new HashMap<String, String>();
         generateInheritedContext(object.getModel(), object, inheritedContext);
         return Strings.expand(value, false,
+                              JSON_SUBSTITUTION_RESOLVER,
                               getOwnAttributeResolver(object),
                               new Strings.MapResolver(inheritedContext),
                               Strings.JAVA_SYS_PROPS_RESOLVER,
@@ -1395,6 +1396,16 @@ public abstract class AbstractConfigured
     }
 
 
+    private static final Strings.Resolver JSON_SUBSTITUTION_RESOLVER =
+            Strings.createSubstitutionResolver("json:",
+                                               new LinkedHashMap<String, 
String>()
+                                               {
+                                                   {
+                                                       put("\\","\\\\");
+                                                       put("\"","\\\"");
+                                                   }
+                                               });
+
     private static class OwnAttributeResolver implements Strings.Resolver
     {
         private static final Module _module;
@@ -1432,7 +1443,7 @@ public abstract class AbstractConfigured
         }
 
         @Override
-        public String resolve(final String variable)
+        public String resolve(final String variable, final Strings.Resolver 
resolver)
         {
             boolean clearStack = false;
             Set<String> currentStack = _stack.get();

Modified: 
qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/Strings.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/Strings.java?rev=1611657&r1=1611656&r2=1611657&view=diff
==============================================================================
--- qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/Strings.java 
(original)
+++ qpid/trunk/qpid/java/common/src/main/java/org/apache/qpid/util/Strings.java 
Fri Jul 18 14:01:19 2014
@@ -22,8 +22,11 @@ package org.apache.qpid.util;
 
 import java.io.UnsupportedEncodingException;
 import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.Stack;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -122,14 +125,14 @@ public final class Strings
 
     public static interface Resolver
     {
-        String resolve(String variable);
+        String resolve(String variable, final Resolver resolver);
     }
 
     private static final Resolver NULL_RESOLVER =
             new Resolver()
             {
                 @Override
-                public String resolve(final String variable)
+                public String resolve(final String variable, final Resolver 
resolver)
                 {
                     return null;
                 }
@@ -145,7 +148,7 @@ public final class Strings
             this.map = map;
         }
 
-        public String resolve(String variable)
+        public String resolve(String variable, final Resolver resolver)
         {
             return map.get(variable);
         }
@@ -161,7 +164,7 @@ public final class Strings
             this.properties = properties;
         }
 
-        public String resolve(String variable)
+        public String resolve(String variable, final Resolver resolver)
         {
             return properties.getProperty(variable);
         }
@@ -178,12 +181,12 @@ public final class Strings
             this.secondary = secondary;
         }
 
-        public String resolve(String variable)
+        public String resolve(String variable, final Resolver resolver)
         {
-            String result = primary.resolve(variable);
+            String result = primary.resolve(variable, resolver);
             if (result == null)
             {
-                result = secondary.resolve(variable);
+                result = secondary.resolve(variable, resolver);
             }
             return result;
         }
@@ -192,7 +195,7 @@ public final class Strings
     public static final Resolver ENV_VARS_RESOLVER = new Resolver()
         {
             @Override
-            public String resolve(final String variable)
+            public String resolve(final String variable, final Resolver 
resolver)
             {
                 return System.getenv(variable);
             }
@@ -202,7 +205,7 @@ public final class Strings
     public static final Resolver JAVA_SYS_PROPS_RESOLVER = new Resolver()
     {
         @Override
-        public String resolve(final String variable)
+        public String resolve(final String variable, final Resolver resolver)
         {
             return System.getProperty(variable);
         }
@@ -269,7 +272,7 @@ public final class Strings
                                stack));
         }
 
-        String result = resolver.resolve(var);
+        String result = resolver.resolve(var, resolver);
         if (result == null)
         {
             if(failOnUnresolved)
@@ -329,4 +332,75 @@ public final class Strings
         return sb.toString();
     }
 
+
+    public static Resolver createSubstitutionResolver(String prefix, 
LinkedHashMap<String,String> substitutions)
+    {
+        return new StringSubstitutionResolver(prefix, substitutions);
+    }
+
+    private static class StringSubstitutionResolver implements Resolver
+    {
+
+        private final ThreadLocal<Set<String>> _stack = new ThreadLocal<>();
+
+        private final LinkedHashMap<String, String> _substitutions;
+        private final String _prefix;
+
+        private StringSubstitutionResolver(String prefix, 
LinkedHashMap<String, String> substitutions)
+        {
+            _prefix = prefix;
+            _substitutions = substitutions;
+        }
+
+        @Override
+        public String resolve(final String variable, final Resolver resolver)
+        {
+            boolean clearStack = false;
+            Set<String> currentStack = _stack.get();
+            if(currentStack == null)
+            {
+                currentStack = new HashSet<>();
+                _stack.set(currentStack);
+                clearStack = true;
+            }
+
+            try
+            {
+                if(currentStack.contains(variable))
+                {
+                    throw new IllegalArgumentException("The value of attribute 
" + variable + " is defined recursively");
+
+                }
+
+
+                if (variable.startsWith(_prefix))
+                {
+                    currentStack.add(variable);
+                    String expanded = 
resolver.resolve(variable.substring(_prefix.length()), resolver);
+                    currentStack.remove(variable);
+                    if(expanded != null)
+                    {
+                        for(Map.Entry<String,String> entry : 
_substitutions.entrySet())
+                        {
+                            expanded = expanded.replace(entry.getKey(), 
entry.getValue());
+                        }
+                    }
+                    return expanded;
+                }
+                else
+                {
+                    return null;
+                }
+
+            }
+            finally
+            {
+
+                if(clearStack)
+                {
+                    _stack.remove();
+                }
+            }
+        }
+    }
 }

Added: 
qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/util/StringsTest.java
URL: 
http://svn.apache.org/viewvc/qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/util/StringsTest.java?rev=1611657&view=auto
==============================================================================
--- 
qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/util/StringsTest.java 
(added)
+++ 
qpid/trunk/qpid/java/common/src/test/java/org/apache/qpid/util/StringsTest.java 
Fri Jul 18 14:01:19 2014
@@ -0,0 +1,48 @@
+/*
+ *
+ * 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
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * 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.qpid.util;
+
+import java.util.Collections;
+import java.util.LinkedHashMap;
+
+import junit.framework.TestCase;
+
+public class StringsTest extends TestCase
+{
+    public void testSubstitutionResolver()
+    {
+        Strings.MapResolver mapResolver =
+                new Strings.MapResolver(Collections.singletonMap("test", 
"C:\\TEMP\\\"Hello World\""));
+
+        Strings.Resolver jsonResolver = 
Strings.createSubstitutionResolver("json:",
+                                                                           new 
LinkedHashMap<String, String>()
+                                                                           {
+                                                                               
{
+                                                                               
    put("\\", "\\\\");
+                                                                               
    put("\"", "\\\"");
+                                                                               
}
+                                                                           });
+
+        assertEquals("{ \"path\" : \"C:\\\\TEMP\\\\\\\"Hello World\\\"\\foo\" 
}",
+                     Strings.expand("{ \"path\" : \"${json:test}\\foo\" 
}",Strings.chain(jsonResolver,mapResolver)));
+
+    }
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to