diff --git a/src/main/java/com/zaxxer/hikari/util/PropertyElf.java b/src/main/java/com/zaxxer/hikari/util/PropertyElf.java index 7797be02..219cb2c8 100644 --- a/src/main/java/com/zaxxer/hikari/util/PropertyElf.java +++ b/src/main/java/com/zaxxer/hikari/util/PropertyElf.java @@ -31,6 +31,8 @@ import java.util.regex.Pattern; */ public final class PropertyElf { + private static final char ESCAPE_CHAR = '\\'; + private static final char SEPARATOR_CHAR = ','; private static final Pattern DURATION_PATTERN = Pattern.compile("^(?\\d+)(?ms|s|m|h|d)$"); private PropertyElf() { @@ -160,6 +162,12 @@ public final class PropertyElf else if (paramClass.isArray() && char.class.isAssignableFrom(paramClass.getComponentType())) { writeMethod.invoke(target, value.toCharArray()); } + else if( paramClass.isArray() && int.class.isAssignableFrom(paramClass.getComponentType())) { + writeMethod.invoke(target, parseIntArray(value)); + } + else if( paramClass.isArray() && String.class.isAssignableFrom(paramClass.getComponentType())) { + writeMethod.invoke(target, new Object[]{parseStringArray(value)}); + } else if (paramClass == String.class) { writeMethod.invoke(target, value); } @@ -186,6 +194,54 @@ public final class PropertyElf return propertyName.substring(0, 1).toUpperCase(Locale.ENGLISH) + propertyName.substring(1); } + private static int[] parseIntArray(String value) + { + if( value == null || value.isEmpty() ) { + return new int[0]; + } + + var split = value.split(","); + var intArray = new int[split.length]; + for (int i = 0; i < split.length; i++) { + intArray[i] = Integer.parseInt(split[i]); + } + return intArray; + } + + private static String[] parseStringArray(String value) + { + if(value == null || value.isEmpty()) { + return new String[0]; + } + + var resultList = new ArrayList(); + var inEscape = false; + var currentField = new StringBuilder(); + for(var c : value.toCharArray()) + { + if(inEscape) { + currentField.append(c); + inEscape = false; + } + else if( c == ESCAPE_CHAR) { + inEscape = true; + } else if( c == SEPARATOR_CHAR) { + resultList.add(currentField.toString()); + currentField.setLength(0); + } + else { + currentField.append(c); + } + } + + if( inEscape ) { + throw new IllegalArgumentException("Unterminated escape sequence in property value: " + value); + } + + resultList.add(currentField.toString()); + return resultList.toArray(new String[0]); + } + private static Optional parseDuration(String value) { var matcher = DURATION_PATTERN.matcher(value); diff --git a/src/test/java/com/zaxxer/hikari/mocks/TestObject.java b/src/test/java/com/zaxxer/hikari/mocks/TestObject.java index 1cbb5222..21f64f98 100644 --- a/src/test/java/com/zaxxer/hikari/mocks/TestObject.java +++ b/src/test/java/com/zaxxer/hikari/mocks/TestObject.java @@ -6,6 +6,8 @@ public class TestObject private String string; private short shortRaw; private char[] charArray; + private String[] stringArray; + private int[] intArray; public void setTestObject(TestObject testObject) { @@ -44,4 +46,24 @@ public class TestObject { return charArray; } + + public void setStringArray(String[] stringArray) + { + this.stringArray = stringArray; + } + + public String[] getStringArray() + { + return stringArray; + } + + public void setIntArray(int[] intArray) + { + this.intArray = intArray; + } + + public int[] getIntArray() + { + return intArray; + } } diff --git a/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java b/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java index 3f957dda..fef9f4e7 100644 --- a/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java +++ b/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java @@ -5,10 +5,7 @@ import com.zaxxer.hikari.mocks.TestObject; import java.util.Properties; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotSame; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; public class PropertyElfTest { @@ -44,4 +41,49 @@ public class PropertyElfTest assertEquals("argument type mismatch", e.getCause().getMessage()); } } + + @Test + public void setStringArray() + { + Properties properties = new Properties(); + TestObject testObject = new TestObject(); + + properties.setProperty("stringArray", "abc,123"); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new String[] {"abc", "123"}, testObject.getStringArray()); + + properties.setProperty("stringArray", "abc\\,123"); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new String[] {"abc,123"}, testObject.getStringArray()); + + properties.setProperty("stringArray", "abc\\\\,123"); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new String[] {"abc\\","123"}, testObject.getStringArray()); + + properties.setProperty("stringArray", ""); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new String[] {}, testObject.getStringArray()); + + properties.setProperty("stringArray", "abc,12\\3"); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new String[] {"abc","123"}, testObject.getStringArray()); + + properties.setProperty("stringArray", "abc,123\\"); + assertThrows(RuntimeException.class, () -> PropertyElf.setTargetFromProperties(testObject, properties)); + } + + @Test + public void setIntArray() + { + Properties properties = new Properties(); + TestObject testObject = new TestObject(); + + properties.setProperty("intArray", "1,2,3"); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new int[] {1,2,3}, testObject.getIntArray()); + + properties.setProperty("intArray", ""); + PropertyElf.setTargetFromProperties(testObject, properties); + assertArrayEquals(new int[] {}, testObject.getIntArray()); + } }