diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2014-07-18 14:01:19 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2014-07-18 14:01:19 +0000 |
commit | 94cb657202acbbe5e45f1377ad40f29a1c6858ae (patch) | |
tree | 31a4170adfa846e3135ad1bbe357d54e97472261 /java | |
parent | d2cd7a13bbf24069dc2177af0001d44b68f4e33f (diff) | |
download | qpid-python-94cb657202acbbe5e45f1377ad40f29a1c6858ae.tar.gz |
QPID-5903 : [Java Broker] allow character escaping for JSON in configured object attribute interpolation
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1611657 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'java')
3 files changed, 144 insertions, 11 deletions
diff --git a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java index baf20da486..41578272f7 100644 --- a/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java +++ b/java/broker-core/src/main/java/org/apache/qpid/server/model/AbstractConfiguredObject.java @@ -1361,6 +1361,7 @@ public abstract class AbstractConfiguredObject<X extends ConfiguredObject<X>> im 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 AbstractConfiguredObject<X extends ConfiguredObject<X>> im } + 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 AbstractConfiguredObject<X extends ConfiguredObject<X>> im } @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(); diff --git a/java/common/src/main/java/org/apache/qpid/util/Strings.java b/java/common/src/main/java/org/apache/qpid/util/Strings.java index 5b544014a3..b7b9bf8c6e 100644 --- a/java/common/src/main/java/org/apache/qpid/util/Strings.java +++ b/java/common/src/main/java/org/apache/qpid/util/Strings.java @@ -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(); + } + } + } + } } diff --git a/java/common/src/test/java/org/apache/qpid/util/StringsTest.java b/java/common/src/test/java/org/apache/qpid/util/StringsTest.java new file mode 100644 index 0000000000..e513b488e6 --- /dev/null +++ b/java/common/src/test/java/org/apache/qpid/util/StringsTest.java @@ -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))); + + } +} |