Repository: incubator-tamaya Updated Branches: refs/heads/master c5d688bdc -> e12eacf68
TAMAYA-43: Registered ResourceResolver as service TAMAYA-47: Fixed invalid references in circular config example, fixed invalid resource references, fixed invalid Resource Module availability check. Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/e12eacf6 Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/e12eacf6 Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/e12eacf6 Branch: refs/heads/master Commit: e12eacf68df87a88f00b511d22096449257ecc39 Parents: c5d688b Author: anatole <anat...@apache.org> Authored: Sun Jan 11 17:45:58 2015 +0100 Committer: anatole <anat...@apache.org> Committed: Sun Jan 11 17:45:58 2015 +0100 ---------------------------------------------------------------------- .../resolver/internal/ClasspathResolver.java | 141 ------------------ .../internal/DefaultExpressionEvaluator.java | 68 ++++++++- .../tamaya/resolver/internal/FileResolver.java | 2 +- .../resolver/internal/ResourceResolver.java | 144 +++++++++++++++++++ ...pache.tamaya.resolver.spi.ExpressionResolver | 2 +- .../tamaya/resolver/MyTestPropertySource.java | 10 +- .../org.apache.tamaya.resource.ResourceResolver | 19 +++ .../internal/ClasspathCollectorTest.java | 4 +- .../resource/internal/FileCollectorTest.java | 12 +- 9 files changed, 239 insertions(+), 163 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ClasspathResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ClasspathResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ClasspathResolver.java deleted file mode 100644 index b0cbe9c..0000000 --- a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ClasspathResolver.java +++ /dev/null @@ -1,141 +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 - * - * 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.tamaya.resolver.internal; - -import org.apache.tamaya.resolver.spi.ExpressionResolver; -import org.apache.tamaya.resource.ResourceResolver; -import org.apache.tamaya.spi.ServiceContext; - -import javax.annotation.Priority; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Property resolver implementation that tries to load the given resource from the current classpath using the - * Thread Context classloader, and as fallback from the classloader that loaded this module and system classloader. - * <br/> - * If the {@code Resources} module is available this module is used for resolving the expression. - */ -@Priority(300) -public final class ClasspathResolver implements ExpressionResolver { - /** - * The looger used. - */ - private final Logger LOG = Logger.getLogger(ClasspathResolver.class.getName()); - - /** - * Flag that controls if the Tamaya Resource loader is available. - */ - private static final boolean IS_RESOURCE_MODULE_AVAILABLE = checkResourceModule(); - - /** - * Checks if the Tamaya ResourceLoader can be loaded from the classpath. - * - * @return true, if the module is available. - */ - private static boolean checkResourceModule() { - try { - Class.forName("org.apache.tamaya.resource.ResourceResolver.", false, ClasspathResolver.class.getClassLoader()); - return true; - } catch (Exception e) { - return false; - } - } - - @Override - public String getResolverPrefix() { - return "resource:"; - } - - @Override - public String evaluate(String expression) { - List<ClassLoader> classLoaders = new ArrayList<>(); - for (ClassLoader cl : new ClassLoader[]{Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), ClassLoader.getSystemClassLoader()}) { - if (!classLoaders.contains(cl)) { - classLoaders.add(cl); - } - } - return readURL(expression, classLoaders); - } - - private String readURL(String expression, List<ClassLoader> classLoaders) { - URL url = getUrl(expression, classLoaders); - BufferedReader in; - try { - in = new BufferedReader( - new InputStreamReader(url.openStream())); - StringBuilder builder = new StringBuilder(); - String inputLine; - while ((inputLine = in.readLine()) != null) { - builder.append(inputLine).append("\n"); - } - in.close(); - return builder.toString(); - } catch (Exception e) { - LOG.log(Level.FINEST, "Could not resolve URL: " + expression, e); - return null; - } - } - - private URL getUrl(String expression, List<ClassLoader> classLoaders) { - if (IS_RESOURCE_MODULE_AVAILABLE) { - ResourceResolver resolver = ServiceContext.getInstance().getService(ResourceResolver.class).get(); - for (ClassLoader cl : classLoaders) { - Collection<URL> resources = resolver.getResources(cl, expression); - if (!resources.isEmpty()) { - if (resources.size() != 1) { - LOG.log(Level.WARNING, "Unresolvable expression (ambiguous resource): " + expression); - return null; - } - return resources.iterator().next(); - } - } - } else { - for (ClassLoader cl : classLoaders) { - List<URL> resources = new ArrayList<>(); - Enumeration<URL> found; - try { - found = cl.getResources(expression); - } catch (Exception e) { - LOG.log(Level.SEVERE, "Error resolving expression: " + expression, e); - continue; - } - while (found.hasMoreElements()) { - resources.add(found.nextElement()); - } - if (!resources.isEmpty()) { - if (resources.size() != 1) { - LOG.log(Level.WARNING, "Unresolvable expression (ambiguous resource): " + expression); - return null; - } - return resources.get(0); - } - } - } - return null; // no such resource found - } - -} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java index 0d51753..6fc5da2 100644 --- a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/DefaultExpressionEvaluator.java @@ -110,6 +110,9 @@ public class DefaultExpressionEvaluator implements ExpressionEvaluator { */ @Override public String filterProperty(String key, String valueToBeFiltered){ + if(valueToBeFiltered==null){ + return null; + } StringTokenizer tokenizer = new StringTokenizer(valueToBeFiltered, "${}\\", true); boolean escaped = false; StringBuilder resolvedValue = new StringBuilder(); @@ -136,7 +139,11 @@ public class DefaultExpressionEvaluator implements ExpressionEvaluator { } switch (token) { case "\\": - escaped = true; + if(!escaped) { + escaped = true; + continue; + } + current.append(token); break; case "$": if (current.length() > 0) { @@ -147,17 +154,13 @@ public class DefaultExpressionEvaluator implements ExpressionEvaluator { LOG.warning("Invalid expression syntax in: " + valueToBeFiltered); return valueToBeFiltered; } - String subExpression = tokenizer.nextToken(); - if (!"}".equals(tokenizer.nextToken())) { - LOG.warning("Invalid expression syntax in: " + valueToBeFiltered); - return valueToBeFiltered; - } - // evaluate sub-expression + String subExpression = parseSubExpression(tokenizer, valueToBeFiltered); current.append(evaluateInternal(subExpression)); break; default: current.append(token); } + escaped = false; } if (current.length() > 0) { resolvedValue.append(current); @@ -166,6 +169,57 @@ public class DefaultExpressionEvaluator implements ExpressionEvaluator { } /** + * Parses subexpression from tokenizer, hereby counting all open and closed brackets, but ignoring any + * meta characters. + * @param tokenizer the current tokniezer instance + * @return the parsed sub expression + */ + private String parseSubExpression(StringTokenizer tokenizer, String valueToBeFiltered) { + StringBuilder expression = new StringBuilder(); + boolean escaped = false; + while(tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + switch (token) { + case "\\": + if(!escaped) { + escaped = true; + } + else { + expression.append(token); + continue; + } + break; + case "{": + if(!escaped) { + LOG.warning("Ignoring not escaped '{' in : " + valueToBeFiltered); + } + expression.append(token); + break; + case "$": + if(!escaped) { + LOG.warning("Ignoring not escaped '$' in : " + valueToBeFiltered); + } + expression.append(token); + break; + case "}": + if(escaped) { + expression.append(token); + } + else{ + return expression.toString(); + } + break; + default: + expression.append(token); + break; + } + escaped = false; + } + LOG.warning("Invalid expression syntax in: " + valueToBeFiltered + ", expression does not close!"); + return valueToBeFiltered; + } + + /** * Evalutes the expression parsed, hereby checking for prefixes and trying otherwise all available resolvers, * based on priority. * @param unresolvedExpression the parsed, but unresolved expression http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/FileResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/FileResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/FileResolver.java index 3459608..07db363 100644 --- a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/FileResolver.java +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/FileResolver.java @@ -65,7 +65,7 @@ public final class FileResolver implements ExpressionResolver { @Override public String getResolverPrefix() { - return "resource:"; + return "file:"; } @Override http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ResourceResolver.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ResourceResolver.java b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ResourceResolver.java new file mode 100644 index 0000000..ae8c3f4 --- /dev/null +++ b/modules/resolver/src/main/java/org/apache/tamaya/resolver/internal/ResourceResolver.java @@ -0,0 +1,144 @@ +/* + * 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.tamaya.resolver.internal; + +import org.apache.tamaya.resolver.spi.ExpressionResolver; +import org.apache.tamaya.spi.ServiceContext; + +import javax.annotation.Priority; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Enumeration; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * Property resolver implementation that tries to load the given resource from the current classpath using the + * Thread Context classloader, and as fallback from the classloader that loaded this module and system classloader. + * <br/> + * If the {@code Resources} module is available this module is used for resolving the expression. + */ +@Priority(300) +public final class ResourceResolver implements ExpressionResolver { + /** + * The looger used. + */ + private final Logger LOG = Logger.getLogger(ResourceResolver.class.getName()); + + /** + * Flag that controls if the Tamaya Resource loader is available. + */ + private static final boolean IS_RESOURCE_MODULE_AVAILABLE = checkResourceModule(); + + /** + * Checks if the Tamaya ResourceLoader can be loaded from the classpath. + * + * @return true, if the module is available. + */ + private static boolean checkResourceModule() { + try { + Class.forName("org.apache.tamaya.resource.ResourceResolver", false, ResourceResolver.class.getClassLoader()); + return true; + } catch (Exception e) { + return false; + } + } + + @Override + public String getResolverPrefix() { + return "resource:"; + } + + @Override + public String evaluate(String expression) { + List<ClassLoader> classLoaders = new ArrayList<>(); + for (ClassLoader cl : new ClassLoader[]{Thread.currentThread().getContextClassLoader(), getClass().getClassLoader(), ClassLoader.getSystemClassLoader()}) { + if (!classLoaders.contains(cl)) { + classLoaders.add(cl); + } + } + return readURL(expression, classLoaders); + } + + private String readURL(String expression, List<ClassLoader> classLoaders) { + URL url = getUrl(expression, classLoaders); + BufferedReader in; + try { + in = new BufferedReader( + new InputStreamReader(url.openStream())); + StringBuilder builder = new StringBuilder(); + String inputLine; + while ((inputLine = in.readLine()) != null) { + builder.append(inputLine).append("\n"); + } + in.close(); + return builder.toString(); + } catch (Exception e) { + LOG.log(Level.FINEST, "Could not resolve URL: " + expression, e); + return null; + } + } + + private URL getUrl(String expression, List<ClassLoader> classLoaders) { + if (IS_RESOURCE_MODULE_AVAILABLE) { + org.apache.tamaya.resource.ResourceResolver resolver = ServiceContext.getInstance().getService(org.apache.tamaya.resource.ResourceResolver.class).get(); + for (ClassLoader cl : classLoaders) { + Collection<URL> resources = resolver.getResources(cl, expression); + if (!resources.isEmpty()) { + if (resources.size() != 1) { + LOG.log(Level.WARNING, "Unresolvable expression (ambiguous resource): " + expression); + return null; + } + return resources.iterator().next(); + } + } + } else { + for (ClassLoader cl : classLoaders) { + List<URL> resources = new ArrayList<>(); + Enumeration<URL> found; + try { + found = cl.getResources(expression); + } catch (Exception e) { + LOG.log(Level.SEVERE, "Error resolving expression: " + expression, e); + continue; + } + while (found.hasMoreElements()) { + resources.add(found.nextElement()); + } + if (!resources.isEmpty()) { + if (resources.size() != 1) { + LOG.log(Level.WARNING, "Unresolvable expression (ambiguous resource): " + expression); + return null; + } + return resources.get(0); + } + } + if(expression.contains("*") || expression.contains("?")){ + LOG.warning(() -> "Rouse not found: " + expression + "(Hint: expression contains expression" + + " placeholders, but resource module is not loaded."); + } + } + return null; // no such resource found + } + +} http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/main/resources/META-INF/services/org.apache.tamaya.resolver.spi.ExpressionResolver ---------------------------------------------------------------------- diff --git a/modules/resolver/src/main/resources/META-INF/services/org.apache.tamaya.resolver.spi.ExpressionResolver b/modules/resolver/src/main/resources/META-INF/services/org.apache.tamaya.resolver.spi.ExpressionResolver index ddfbb09..cb7ced0 100644 --- a/modules/resolver/src/main/resources/META-INF/services/org.apache.tamaya.resolver.spi.ExpressionResolver +++ b/modules/resolver/src/main/resources/META-INF/services/org.apache.tamaya.resolver.spi.ExpressionResolver @@ -18,7 +18,7 @@ # org.apache.tamaya.resolver.internal.SystemPropertyResolver org.apache.tamaya.resolver.internal.EnvironmentPropertyResolver -org.apache.tamaya.resolver.internal.ClasspathResolver +org.apache.tamaya.resolver.internal.ResourceResolver org.apache.tamaya.resolver.internal.ConfigResolver org.apache.tamaya.resolver.internal.FileResolver org.apache.tamaya.resolver.internal.URLResolver \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java ---------------------------------------------------------------------- diff --git a/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java b/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java index 506e25e..674eae8 100644 --- a/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java +++ b/modules/resolver/src/test/java/org/apache/tamaya/resolver/MyTestPropertySource.java @@ -42,19 +42,19 @@ public class MyTestPropertySource implements PropertySource{ properties.put("Before and After Text (prefixed)", "My Java version is ${sys:java.version}."); properties.put("Multi-expression", "Java version ${sys:java.version} and line.separator ${line.separator}."); - properties.put("cp-ref", "${classpath:TestResource.txt}"); + properties.put("cp-ref", "${resource:Testresource.txt}"); properties.put("file-ref", "${file:"+getFileRefAsString()+"}"); properties.put("res-ref", "${resource:Test?es*ce.txt}"); properties.put("url-ref", "${url:http://www.google.com}"); - properties.put("config-ref", "Expression Only -> ${config:Expression Only}"); - properties.put("config-ref2", "Config Ref 2 -> Ref 1: ${config:config-ref}"); - properties.put("config-ref3", "Config Ref 3 -> Ref 2: ${config:config-ref2}"); + properties.put("config-ref", "Expression Only -> ${conf:Expression Only}"); + properties.put("config-ref2", "Config Ref 2 -> Ref 1: ${conf:config-ref}"); + properties.put("config-ref3", "Config Ref 3 -> Ref 2: ${conf:config-ref2}"); } private String getFileRefAsString() { try { URL res = getClass().getClassLoader().getResource("Testresource2.txt"); - return new File(res.toURI()).getAbsolutePath(); + return new File(res.toURI()).getAbsolutePath().replaceAll("\\\\","/"); } catch (URISyntaxException e) { return "Failed to evaluate file: Testresource2.txt"; } http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resources/src/main/resources/META-INF/services/org.apache.tamaya.resource.ResourceResolver ---------------------------------------------------------------------- diff --git a/modules/resources/src/main/resources/META-INF/services/org.apache.tamaya.resource.ResourceResolver b/modules/resources/src/main/resources/META-INF/services/org.apache.tamaya.resource.ResourceResolver new file mode 100644 index 0000000..aacd0d5 --- /dev/null +++ b/modules/resources/src/main/resources/META-INF/services/org.apache.tamaya.resource.ResourceResolver @@ -0,0 +1,19 @@ +# +# 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 current 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. +# +org.apache.tamaya.resource.internal.DefaultResourceResolver \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java ---------------------------------------------------------------------- diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java index 1527684..7379451 100644 --- a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java +++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/ClasspathCollectorTest.java @@ -77,9 +77,9 @@ public class ClasspathCollectorTest { @org.junit.Test public void testCollectResourcesFromLocalFSPath() throws Exception { ClasspathCollector cpc = new ClasspathCollector(ClassLoader.getSystemClassLoader()); - Collection<URL> found = cpc.collectFiles("classpath:resources_testRoot/**/*.file"); + Collection<URL> found = cpc.collectFiles("classpath:resources_testroot/**/*.file"); assertEquals(7, found.size()); - Collection<URL> found2 = cpc.collectFiles("resources_testRoot/**/*.file"); + Collection<URL> found2 = cpc.collectFiles("resources_testroot/**/*.file"); assertEquals(found, found2); } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e12eacf6/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java ---------------------------------------------------------------------- diff --git a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java index 89c1543..41c60c9 100644 --- a/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java +++ b/modules/resources/src/test/java/org/apache/tamaya/resource/internal/FileCollectorTest.java @@ -33,8 +33,8 @@ import static org.junit.Assert.assertEquals; public class FileCollectorTest { private String getResourceDir() throws URISyntaxException { - URL res = getClass().getResource("/resources_testroot/"); - return new File(res.toURI()).getParentFile().getAbsolutePath(); + URL res = getClass().getClassLoader().getResource("resources_testroot/"); + return new File(res.toURI()).getAbsolutePath(); } @Test @@ -49,18 +49,18 @@ public class FileCollectorTest { @Test public void testCollectResourcesFromLocalFSPath_WithFolderPlaceholder() throws Exception { String resDir = getResourceDir(); - Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/resources_testroot/aa?a/*.file"); + Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/aa?a/*.file"); assertEquals(5, found.size()); - Collection<URL> found2 = FileCollector.collectFiles(resDir + "/resources_testroot/aa?a/*.file"); + Collection<URL> found2 = FileCollector.collectFiles(resDir + "/aa?a/*.file"); assertEquals(found, found2); } @Test public void testCollectResourcesFromLocalFSPath_WithFolderAny() throws Exception { String resDir = getResourceDir(); - Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/resources_testroot/b*/b?/*.file"); + Collection<URL> found = FileCollector.collectFiles("file:" + resDir + "/b*/b?/*.file"); assertEquals(1, found.size()); - Collection<URL> found2 = FileCollector.collectFiles(resDir + "/resources_testroot/b*/b?/*.file"); + Collection<URL> found2 = FileCollector.collectFiles(resDir + "/b*/b?/*.file"); assertEquals(found, found2); }