FELIX-6166 : Support encoding while reading properties from external file

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1872593 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Activator.java b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Activator.java
index 44ee88b..2da627d 100644
--- a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Activator.java
+++ b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/Activator.java
@@ -16,6 +16,9 @@
  */
 package org.apache.felix.configadmin.plugin.interpolation;
 
+import java.util.Dictionary;
+import java.util.Hashtable;
+
 import org.osgi.annotation.bundle.Header;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -24,12 +27,13 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Dictionary;
-import java.util.Hashtable;
-
 @Header(name=Constants.BUNDLE_ACTIVATOR, value="${@class}")
 public class Activator implements BundleActivator {
     static final String DIR_PROPERTY = "org.apache.felix.configadmin.plugin.interpolation.dir";
+    static final String ENCODING_PROPERTY = "org.apache.felix.configadmin.plugin.interpolation.file.encoding";
+
+    static final String PLUGIN_ID = "org.apache.felix.configadmin.plugin.interpolation";
+
     static final int PLUGIN_RANKING = 500;
 
     static final Logger LOG = LoggerFactory.getLogger(InterpolationConfigurationPlugin.class);
@@ -37,16 +41,23 @@
     @Override
     public void start(BundleContext context) throws Exception {
         String directory = context.getProperty(DIR_PROPERTY);
+        String encoding = context.getProperty(ENCODING_PROPERTY);
 
-        ConfigurationPlugin plugin = new InterpolationConfigurationPlugin(context, directory);
+        ConfigurationPlugin plugin = new InterpolationConfigurationPlugin(context, directory, encoding);
         Dictionary<String, Object> props = new Hashtable<>();
         props.put(ConfigurationPlugin.CM_RANKING, PLUGIN_RANKING);
-        props.put("config.plugin.id", "org.apache.felix.configadmin.plugin.interpolation");
+        props.put("config.plugin.id", PLUGIN_ID);
 
         if (directory != null)
             props.put(DIR_PROPERTY, directory);
         else
             props.put(DIR_PROPERTY, "<not configured>");
+
+        if (encoding != null)
+            props.put(ENCODING_PROPERTY, encoding);
+        else
+            props.put(ENCODING_PROPERTY, "<not configured>");
+
         context.registerService(ConfigurationPlugin.class, plugin, props);
     }
 
diff --git a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
index 61455d1..9b7824d 100644
--- a/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
+++ b/configadmin-plugins/interpolation/src/main/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPlugin.java
@@ -18,6 +18,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.nio.charset.Charset;
 import java.nio.file.Files;
 import java.util.Dictionary;
 import java.util.Enumeration;
@@ -86,7 +87,9 @@
     private final BundleContext context;
     private final File directory;
 
-    InterpolationConfigurationPlugin(BundleContext bc, String dir) {
+    private final Charset encodingCharset;
+
+    InterpolationConfigurationPlugin(BundleContext bc, String dir, String fileEncoding) {
         context = bc;
         if (dir != null) {
             directory = new File(dir);
@@ -94,6 +97,12 @@
         } else {
             directory = null;
         }
+        if (fileEncoding == null) {
+            encodingCharset = Charset.defaultCharset();
+        } else {
+            encodingCharset = Charset.forName(fileEncoding);
+        }
+
     }
 
     private Logger getLog() {
@@ -204,7 +213,7 @@
 
             return null;
         }
-        return new String(bytes).trim();
+        return new String(bytes, this.encodingCharset).trim();
     }
 
     private Object convertType(String type, String s) {
diff --git a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/ActivatorTest.java b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/ActivatorTest.java
index 79cb2b1..2d1125f 100644
--- a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/ActivatorTest.java
+++ b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/ActivatorTest.java
@@ -16,6 +16,12 @@
  */
 package org.apache.felix.configadmin.plugin.interpolation;
 
+import static org.junit.Assert.assertEquals;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
@@ -24,12 +30,6 @@
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationPlugin;
 
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import static org.junit.Assert.assertEquals;
-
 public class ActivatorTest {
     @SuppressWarnings("unchecked")
     @Test
@@ -38,6 +38,7 @@
 
         BundleContext ctx = Mockito.mock(BundleContext.class);
         Mockito.when(ctx.getProperty(Activator.DIR_PROPERTY)).thenReturn("/tmp/somewhere");
+        Mockito.when(ctx.getProperty(Activator.ENCODING_PROPERTY)).thenReturn("UTF-8");
         Mockito.when(ctx.registerService(
             Mockito.eq(ConfigurationPlugin.class),
             Mockito.isA(ConfigurationPlugin.class),
@@ -58,6 +59,7 @@
 
         Dictionary<String, Object> expected = new Hashtable<>();
         expected.put(Activator.DIR_PROPERTY, "/tmp/somewhere");
+        expected.put(Activator.ENCODING_PROPERTY, "UTF-8");
         expected.put(ConfigurationPlugin.CM_RANKING, Activator.PLUGIN_RANKING);
         expected.put("config.plugin.id", "org.apache.felix.configadmin.plugin.interpolation");
         assertEquals(expected, regProps);
diff --git a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
index cb1c451..3173128 100644
--- a/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
+++ b/configadmin-plugins/interpolation/src/test/java/org/apache/felix/configadmin/plugin/interpolation/InterpolationConfigurationPluginTest.java
@@ -43,7 +43,7 @@
         String rf = getClass().getResource("/testfile").getFile();
 
         InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
-                new File(rf).getParent());
+                new File(rf).getParent(), null);
 
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("foo", "bar");
@@ -68,7 +68,7 @@
         BundleContext bc = Mockito.mock(BundleContext.class);
         Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
 
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null);
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null, null);
 
         String envUser = System.getenv("USER");
         String userVar;
@@ -97,7 +97,7 @@
         String rf = getClass().getResource("/sub/sub2/testfile2").getFile();
 
         InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
-                new File(rf).getParentFile().getParent());
+                new File(rf).getParentFile().getParent(), null);
 
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("substed", "$[secret:sub2/testfile2]");
@@ -115,7 +115,7 @@
     public void testReplacement() throws Exception {
         String rf = getClass().getResource("/testfile.txt").getFile();
         InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
-                new File(rf).getParent());
+                new File(rf).getParent(), null);
 
         assertEquals("xxla la layy", plugin.replace("akey", "xx$[secret:testfile.txt]yy", "apid"));
         String doesNotReplace = "xx$[" + rf + "]yy";
@@ -126,14 +126,14 @@
     public void testNoReplacement() throws IOException {
         String rf = getClass().getResource("/testfile.txt").getFile();
         InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null,
-                new File(rf).getParent());
+                new File(rf).getParent(), null);
 
         assertEquals("foo", plugin.replace("akey", "foo", "apid"));
     }
 
     @Test
     public void testDefault() throws IOException {
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null, null);
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null, null, null);
 
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("defaulted", "$[env:notset;default=foo]");
@@ -145,7 +145,7 @@
 
     @Test
     public void testTypeConversion() throws IOException {
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null, null);
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(null, null, null);
 
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("defaulted", "$[env:notset;default=123;type=Integer]");
@@ -159,7 +159,7 @@
     public void testReplacementInStringArray() throws IOException {
         BundleContext bc = Mockito.mock(BundleContext.class);
         Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null);
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null, null);
 
         Dictionary<String, Object> dict = new Hashtable<>();
         dict.put("array", new String[] { "1", "$[prop:foo.bar]", "3" });
@@ -178,7 +178,8 @@
         BundleContext bc = Mockito.mock(BundleContext.class);
         Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
         String rf = getClass().getResource("/testfile.txt").getFile();
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, new File(rf).getParent());
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, new File(rf).getParent(),
+                null);
 
         assertEquals("xxhello thereyyhello therezz",
                 plugin.replace("akey", "xx$[prop:foo.bar]yy$[prop:foo.bar]zz", "apid"));
@@ -192,7 +193,7 @@
         BundleContext bc = Mockito.mock(BundleContext.class);
         Mockito.when(bc.getProperty("foo.bar")).thenReturn("hello there");
         Mockito.when(bc.getProperty("key")).thenReturn("foo.bar");
-        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null);
+        InterpolationConfigurationPlugin plugin = new InterpolationConfigurationPlugin(bc, null, null);
 
         assertEquals("hello there", plugin.replace("akey", "$[prop:$[prop:key]]", "apid"));
     }