Repository: brettwooldridge/HikariCP (Java)

Issue:
argument type mismatch (PropertyElf does not handle char array)
Environment: HikariCP-5.0.1.jar and jt400-jdk9-11.1.jar
Cannot initialize pool because of this exception:
```
Failed to set property password on target class com.ibm.as400.access.AS400JDBCDataSource
	java.lang.IllegalArgumentException: argument type mismatch
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
		at java.base/java.lang.reflect.Method.invoke(Unknown Source)
		at com.zaxxer.hikari.util.PropertyElf.setProperty(PropertyElf.java:154)
		at com.zaxxer.hikari.util.PropertyElf.lambda$setTargetFromProperties$0(PropertyElf.java:51)
		at java.base/java.util.concurrent.ConcurrentHashMap.forEach(Unknown Source)
		at java.base/java.util.Properties.forEach(Unknown Source)
		at com.zaxxer.hikari.util.PropertyElf.setTargetFromProperties(PropertyElf.java:46)
		at com.zaxxer.hikari.pool.PoolBase.initializeDataSource(PoolBase.java:323)
		at com.zaxxer.hikari.pool.PoolBase.<init>(PoolBase.java:112)
		at com.zaxxer.hikari.pool.HikariPool.<init>(HikariPool.java:93)
		at com.zaxxer.hikari.HikariDataSource.<init>(HikariDataSource.java:81)
		at com.zaxxer.hikari.HikariJNDIFactory.createDataSource(HikariJNDIFactory.java:63)
		at com.zaxxer.hikari.HikariJNDIFactory.getObjectInstance(HikariJNDIFactory.java:51)
		at org.apache.naming.factory.FactoryBase.getObjectInstance(FactoryBase.java:96)
		at java.naming/javax.naming.spi.NamingManager.getObjectInstance(Unknown Source)
		at org.apache.naming.NamingContext.lookup(NamingContext.java:864)
		at org.apache.naming.NamingContext.lookup(NamingContext.java:158)
		at org.apache.naming.NamingContextBindingsEnumeration.nextElementInternal(NamingContextBindingsEnumeration.java:115)
		at org.apache.naming.NamingContextBindingsEnumeration.next(NamingContextBindingsEnumeration.java:69)
		at org.apache.naming.NamingContextBindingsEnumeration.next(NamingContextBindingsEnumeration.java:32)
		at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:133)
		at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:140)
		at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.createMBeans(GlobalResourcesLifecycleListener.java:107)
		at org.apache.catalina.mbeans.GlobalResourcesLifecycleListener.lifecycleEvent(GlobalResourcesLifecycleListener.java:82)
		at org.apache.catalina.util.LifecycleBase.fireLifecycleEvent(LifecycleBase.java:123)
		at org.apache.catalina.util.LifecycleBase.setStateInternal(LifecycleBase.java:423)
		at org.apache.catalina.util.LifecycleBase.setState(LifecycleBase.java:366)
		at org.apache.catalina.core.StandardServer.startInternal(StandardServer.java:906)
		at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:183)
		at org.apache.catalina.startup.Catalina.start(Catalina.java:795)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
		at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
		at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
		at java.base/java.lang.reflect.Method.invoke(Unknown Source)
		at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:347)
		at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:478)
```
jt400 guys have added a new [setPassword(char[]) method](https://javadoc.io/static/net.sf.jt400/jt400/11.2/com/ibm/as400/access/AS400JDBCDataSource.html#setPassword(char[])) so I think PropertyElf need tho handle char[] as a possible argument...


Discussion:
Similar issue in OpenLiberty: https://github.com/OpenLiberty/open-liberty/issues/23690



Patch:
diff --git a/src/main/java/com/zaxxer/hikari/util/PropertyElf.java b/src/main/java/com/zaxxer/hikari/util/PropertyElf.java
index 9cebdfbab..edf117dd2 100644
--- a/src/main/java/com/zaxxer/hikari/util/PropertyElf.java
+++ b/src/main/java/com/zaxxer/hikari/util/PropertyElf.java
@@ -141,6 +141,9 @@ else if (paramClass == short.class) {
          else if (paramClass == boolean.class || paramClass == Boolean.class) {
             writeMethod.invoke(target, Boolean.parseBoolean(propValue.toString()));
          }
+         else if (paramClass.isArray() && char.class.isAssignableFrom(paramClass.getComponentType())) {
+            writeMethod.invoke(target, propValue.toString().toCharArray());
+         }
          else if (paramClass == String.class) {
             writeMethod.invoke(target, propValue.toString());
          }


Test patch:
diff --git a/src/test/java/com/zaxxer/hikari/mocks/TestObject.java b/src/test/java/com/zaxxer/hikari/mocks/TestObject.java
index 91cfe8688..1cbb52220 100644
--- a/src/test/java/com/zaxxer/hikari/mocks/TestObject.java
+++ b/src/test/java/com/zaxxer/hikari/mocks/TestObject.java
@@ -5,6 +5,7 @@ public class TestObject
    private TestObject testObject;
    private String string;
    private short shortRaw;
+   private char[] charArray;
 
    public void setTestObject(TestObject testObject)
    {
@@ -33,4 +34,14 @@ public short getShortRaw() {
    public void setShortRaw(short shortRaw) {
       this.shortRaw = shortRaw;
    }
+
+   public void setCharArray(char[] charArray)
+   {
+      this.charArray = charArray;
+   }
+
+   public char[] getCharArray()
+   {
+      return charArray;
+   }
 }
diff --git a/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java b/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java
index 983ef0bf9..3f957dda3 100644
--- a/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java
+++ b/src/test/java/com/zaxxer/hikari/util/PropertyElfTest.java
@@ -5,6 +5,7 @@
 
 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;
@@ -18,10 +19,12 @@ public void setTargetFromProperties() throws Exception
       properties.setProperty("string", "aString");
       properties.setProperty("testObject", "com.zaxxer.hikari.mocks.TestObject");
       properties.setProperty("shortRaw", "1");
+      properties.setProperty("charArray", "aCharArray");
       TestObject testObject = new TestObject();
       PropertyElf.setTargetFromProperties(testObject, properties);
       assertEquals("aString", testObject.getString());
       assertEquals((short) 1, testObject.getShortRaw());
+      assertArrayEquals("aCharArray".toCharArray(), testObject.getCharArray());
       assertEquals(com.zaxxer.hikari.mocks.TestObject.class, testObject.getTestObject().getClass());
       assertNotSame(testObject, testObject.getTestObject());
    }