TAP5-223: Allow properties files (on classpath or in the context) to be used as SymbolProviders

git-svn-id: https://svn.apache.org/repos/asf/tapestry/tapestry5/trunk@769554 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/internal/ContextResourceSymbolProvider.java b/tapestry-core/src/main/java/org/apache/tapestry5/internal/ContextResourceSymbolProvider.java
new file mode 100644
index 0000000..8199dc0
--- /dev/null
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/internal/ContextResourceSymbolProvider.java
@@ -0,0 +1,33 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.internal;
+
+import org.apache.tapestry5.internal.services.ContextResource;
+import org.apache.tapestry5.ioc.internal.services.ResourceSymbolProvider;
+import org.apache.tapestry5.services.Context;
+
+/**
+ * Makes a {@link org.apache.tapestry5.ioc.Resource} in the {@link org.apache.tapestry5.services.Context} available as a
+ * {@link org.apache.tapestry5.ioc.services.SymbolProvider}
+ *
+ * @since 5.1.0.5
+ */
+public class ContextResourceSymbolProvider extends ResourceSymbolProvider
+{
+    public ContextResourceSymbolProvider(Context context, String path)
+    {
+        super(new ContextResource(context, path));
+    }
+}
diff --git a/tapestry-core/src/test/java/org/apache/tapestry5/internal/ContextResourceSymbolProviderTest.java b/tapestry-core/src/test/java/org/apache/tapestry5/internal/ContextResourceSymbolProviderTest.java
new file mode 100644
index 0000000..483658e
--- /dev/null
+++ b/tapestry-core/src/test/java/org/apache/tapestry5/internal/ContextResourceSymbolProviderTest.java
@@ -0,0 +1,70 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.internal;
+
+import org.apache.tapestry5.internal.test.InternalBaseTestCase;
+import org.apache.tapestry5.services.Context;
+import org.testng.annotations.Test;
+
+import java.io.File;
+import java.io.FileOutputStream;
+
+public class ContextResourceSymbolProviderTest extends InternalBaseTestCase
+{
+    private static final String CONTENT = "homer=simpson\r\nmonty=burns";
+
+    private static final String PATH = "bar/foo.properties";
+
+    @Test
+    public void access() throws Exception
+    {
+        File f = File.createTempFile("foo", ".properties");
+
+        setupFile(f);
+
+        Context context = mockContext();
+
+        expect(context.getRealFile("/" + PATH)).andReturn(f);
+
+        replay();
+
+        ContextResourceSymbolProvider provider = new ContextResourceSymbolProvider(context, PATH);
+
+        /* test general access */
+        assertEquals(provider.valueForSymbol("homer"), "simpson");
+        assertEquals(provider.valueForSymbol("monty"), "burns");
+
+        /* check for case-insensitivity */
+        assertEquals(provider.valueForSymbol("HOMER"), "simpson");
+
+        /* non-existent keys should return null */
+        assertNull(provider.valueForSymbol("marge"));
+
+        verify();
+
+        f.delete();
+    }
+
+    private void setupFile(File f) throws Exception
+    {
+        FileOutputStream fos = new FileOutputStream(f);
+
+        fos.write(CONTENT.getBytes());
+
+        fos.close();
+
+        fos = null;
+    }
+}
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProvider.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProvider.java
new file mode 100644
index 0000000..0bf89e0
--- /dev/null
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProvider.java
@@ -0,0 +1,31 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.internal.util.ClasspathResource;
+
+/**
+ * Makes a {@link org.apache.tapestry5.ioc.Resource} on the classpath available as a {@link
+ * org.apache.tapestry5.ioc.services.SymbolProvider}
+ *
+ * @since 5.1.0.5
+ */
+public class ClasspathResourceSymbolProvider extends ResourceSymbolProvider
+{
+    public ClasspathResourceSymbolProvider(String path)
+    {
+        super(new ClasspathResource(path));
+    }
+}
diff --git a/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProvider.java b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProvider.java
new file mode 100644
index 0000000..0222ab7
--- /dev/null
+++ b/tapestry-ioc/src/main/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProvider.java
@@ -0,0 +1,82 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.services.SymbolProvider;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Makes a {@link org.apache.tapestry5.ioc.Resource} available as a {@link org.apache.tapestry5.ioc.services.SymbolProvider}
+ *
+ * @since 5.1.0.5
+ */
+public class ResourceSymbolProvider implements SymbolProvider
+{
+    private final Resource resource;
+
+    private final Map<String, String> properties = CollectionFactory.newCaseInsensitiveMap();
+
+    public ResourceSymbolProvider(final Resource resource)
+    {
+        this.resource = resource;
+
+        readProperties();
+    }
+
+    private void readProperties()
+    {
+        Properties p = new Properties();
+
+        InputStream is = null;
+
+        try
+        {
+            is = resource.openStream();
+
+            p.load(is);
+
+            is.close();
+
+            is = null;
+
+            for (Map.Entry<Object, Object> entry : p.entrySet())
+            {
+                String key = entry.getKey().toString();
+
+                properties.put(key, p.getProperty(key));
+            }
+        }
+        catch (IOException ex)
+        {
+            throw new RuntimeException(ex);
+        }
+        finally
+        {
+            InternalUtils.close(is);
+        }
+    }
+
+    public String valueForSymbol(String symbolName)
+    {
+        return properties.get(symbolName);
+    }
+}
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProviderTest.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProviderTest.java
new file mode 100644
index 0000000..4896d38
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ClasspathResourceSymbolProviderTest.java
@@ -0,0 +1,39 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.ioc.internal.services;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+public class ClasspathResourceSymbolProviderTest extends Assert
+{
+    private static final String PATH = "org/apache/tapestry5/ioc/internal/services/foo.properties";
+
+    @Test
+    public void access()
+    {
+        ClasspathResourceSymbolProvider provider = new ClasspathResourceSymbolProvider(PATH);
+
+        /* test general access */
+        assertEquals(provider.valueForSymbol("homer"), "simpson");
+        assertEquals(provider.valueForSymbol("monty"), "burns");
+
+        /* check for case-insensitivity */
+        assertEquals(provider.valueForSymbol("HOMER"), "simpson");
+
+        /* non-existent keys should return null */
+        assertNull(provider.valueForSymbol("marge"));
+    }
+}
diff --git a/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProviderTest.java b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProviderTest.java
new file mode 100644
index 0000000..587e6f7
--- /dev/null
+++ b/tapestry-ioc/src/test/java/org/apache/tapestry5/ioc/internal/services/ResourceSymbolProviderTest.java
@@ -0,0 +1,53 @@
+// Copyright 2009 The Apache Software Foundation
+//
+// Licensed 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.tapestry5.ioc.internal.services;
+
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.test.IOCTestCase;
+import org.testng.annotations.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+public class ResourceSymbolProviderTest extends IOCTestCase
+{
+    private static final String CONTENT = "homer=simpson\r\nmonty=burns";
+
+    @Test
+    public void access() throws Exception
+    {
+        Resource resource = mockResource();
+
+        InputStream is = new ByteArrayInputStream(CONTENT.getBytes());
+
+        expect(resource.openStream()).andReturn(is);
+
+        replay();
+
+        ResourceSymbolProvider provider = new ResourceSymbolProvider(resource);
+
+        /* test general access */
+        assertEquals(provider.valueForSymbol("homer"), "simpson");
+        assertEquals(provider.valueForSymbol("monty"), "burns");
+
+        /* check for case-insensitivity */
+        assertEquals(provider.valueForSymbol("HOMER"), "simpson");
+
+        /* non-existent keys should return null */
+        assertNull(provider.valueForSymbol("marge"));
+
+        verify();
+    }
+}
diff --git a/tapestry-ioc/src/test/resources/org/apache/tapestry5/ioc/internal/services/foo.properties b/tapestry-ioc/src/test/resources/org/apache/tapestry5/ioc/internal/services/foo.properties
new file mode 100644
index 0000000..b6fe6a8
--- /dev/null
+++ b/tapestry-ioc/src/test/resources/org/apache/tapestry5/ioc/internal/services/foo.properties
@@ -0,0 +1,2 @@
+homer=simpson
+monty=burns