This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new ab8b271b4a Commons improvements
ab8b271b4a is described below

commit ab8b271b4a2a53f7159b3db7942d968bbd05a574
Author: James Bognar <[email protected]>
AuthorDate: Tue Dec 16 17:49:17 2025 -0500

    Commons improvements
---
 .../apache/juneau/commons/collections/Cache.java   |  2 +-
 .../apache/juneau/commons/collections/Cache2.java  |  2 +-
 .../apache/juneau/commons/collections/Cache3.java  |  2 +-
 .../apache/juneau/commons/collections/Cache4.java  |  2 +-
 .../apache/juneau/commons/collections/Cache5.java  |  2 +-
 .../apache/juneau/commons/settings/Settings.java   | 64 ++++++++++++------
 .../org/apache/juneau/commons/utils/Utils.java     | 54 ++-------------
 .../org/apache/juneau/config/store/FileStore.java  |  2 +-
 .../main/java/org/apache/juneau/BeanContext.java   | 12 +---
 .../org/apache/juneau/parser/ReaderParser.java     |  2 +-
 .../apache/juneau/serializer/WriterSerializer.java |  4 +-
 .../java/org/apache/juneau/rest/RestContext.java   | 15 ++--
 .../juneau/commons/settings/Settings_Test.java     | 49 ++++----------
 .../apache/juneau/commons/utils/Utils_Test.java    | 79 ----------------------
 14 files changed, 85 insertions(+), 206 deletions(-)

diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache.java
index 739dd092d0..81adbf3898 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache.java
@@ -189,7 +189,7 @@ public class Cache<K,V> {
                Function<K,V> supplier;
 
                Builder() {
-                       cacheMode = CacheMode.parse(env("juneau.cache.mode", 
"FULL"));
+                       cacheMode = env("juneau.cache.mode", CacheMode.FULL);
                        maxSize = env("juneau.cache.maxSize", 1000);
                        logOnExit = env("juneau.cache.logOnExit", false);
                        id = "Cache";
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache2.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache2.java
index 3d89e434cb..f13a22d663 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache2.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache2.java
@@ -165,7 +165,7 @@ public class Cache2<K1,K2,V> {
                Function2<K1,K2,V> supplier;
 
                Builder() {
-                       cacheMode = CacheMode.parse(env("juneau.cache.mode", 
"FULL"));
+                       cacheMode = env("juneau.cache.mode", CacheMode.FULL);
                        maxSize = env("juneau.cache.maxSize", 1000);
                        logOnExit = env("juneau.cache.logOnExit", false);
                        id = "Cache2";
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache3.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache3.java
index 2b9344c64d..ddf8f32a63 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache3.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache3.java
@@ -96,7 +96,7 @@ public class Cache3<K1,K2,K3,V> {
                Function3<K1,K2,K3,V> supplier;
 
                Builder() {
-                       cacheMode = CacheMode.parse(env("juneau.cache.mode", 
"FULL"));
+                       cacheMode = env("juneau.cache.mode", CacheMode.FULL);
                        maxSize = env("juneau.cache.maxSize", 1000);
                        logOnExit = env("juneau.cache.logOnExit", false);
                        id = "Cache3";
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache4.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache4.java
index 1ada67f2a7..7a56eb3a30 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache4.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache4.java
@@ -83,7 +83,7 @@ public class Cache4<K1,K2,K3,K4,V> {
                Function4<K1,K2,K3,K4,V> supplier;
 
                Builder() {
-                       cacheMode = CacheMode.parse(env("juneau.cache.mode", 
"FULL"));
+                       cacheMode = env("juneau.cache.mode", CacheMode.FULL);
                        maxSize = env("juneau.cache.maxSize", 1000);
                        logOnExit = env("juneau.cache.logOnExit", false);
                        id = "Cache4";
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache5.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache5.java
index 7980b088d4..4f854e12bd 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache5.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/Cache5.java
@@ -86,7 +86,7 @@ public class Cache5<K1,K2,K3,K4,K5,V> {
                Function5<K1,K2,K3,K4,K5,V> supplier;
 
                Builder() {
-                       cacheMode = CacheMode.parse(env("juneau.cache.mode", 
"FULL"));
+                       cacheMode = env("juneau.cache.mode", CacheMode.FULL);
                        maxSize = env("juneau.cache.maxSize", 1000);
                        logOnExit = env("juneau.cache.logOnExit", false);
                        id = "Cache5";
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/settings/Settings.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/settings/Settings.java
index 909d974e9e..187645e70a 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/settings/Settings.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/settings/Settings.java
@@ -16,6 +16,7 @@
  */
 package org.apache.juneau.commons.settings;
 
+import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
@@ -26,6 +27,7 @@ import java.util.concurrent.*;
 import java.util.function.*;
 
 import org.apache.juneau.commons.function.*;
+import org.apache.juneau.commons.reflect.*;
 
 /**
  * Encapsulates Java system properties with support for global and per-thread 
overrides for unit testing.
@@ -134,6 +136,8 @@ public class Settings {
         */
        public static final SettingSource SYSTEM_PROPERTY_SOURCE = 
FunctionalSource.of(System::getProperty);
 
+       private static final Set<String> FROM_STRING_METHOD_NAMES = new 
LinkedHashSet<>(Arrays.asList("fromString", "parse", "forName", "valueOf"));
+
        /**
         * System environment variable source that delegates to {@link 
System#getenv(String)}.
         */
@@ -143,13 +147,6 @@ public class Settings {
        private static final String MSG_globalDisabled = "Global settings not 
enabled";
        private static final String MSG_localDisabled = "Local settings not 
enabled";
 
-       private static final Map<Class<?>,Function<String,?>> 
DEFAULT_TYPE_FUNCTIONS = new IdentityHashMap<>();
-
-       static {
-               DEFAULT_TYPE_FUNCTIONS.put(Boolean.class, Boolean::valueOf);
-               DEFAULT_TYPE_FUNCTIONS.put(Charset.class, Charset::forName);
-       }
-
        /**
         * Returns properties for this Settings object itself.
         * Note that these are initialized at startup and not changeable 
through System.setProperty().
@@ -158,7 +155,7 @@ public class Settings {
                var v = SYSTEM_PROPERTY_SOURCE.get(property);
                if (v != null)
                        return v;  // Not testable
-               v = SYSTEM_ENV_SOURCE.get(uc(property.replace('.', '_')));
+               v = SYSTEM_ENV_SOURCE.get(property.replace('.', 
'_').toUpperCase());
                if (v != null)
                        return v;  // Not testable
                return opte();
@@ -317,7 +314,7 @@ public class Settings {
        private final ResettableSupplier<SettingStore> globalStore;
        private final ThreadLocal<SettingStore> localStore;
        private final List<SettingSource> sources;
-       private final Map<Class<?>,Function<String,?>> customTypeFunctions;
+       private final Map<Class<?>,Function<String,?>> toTypeFunctions;
 
        /**
         * Constructor.
@@ -326,7 +323,7 @@ public class Settings {
                this.globalStore = 
memoizeResettable(builder.globalStoreSupplier);
                this.localStore = 
ThreadLocal.withInitial(builder.localStoreSupplier);
                this.sources = new CopyOnWriteArrayList<>(builder.sources);
-               this.customTypeFunctions = new 
IdentityHashMap<>(builder.customTypeFunctions);
+               this.toTypeFunctions = new 
ConcurrentHashMap<>(builder.customTypeFunctions);
        }
 
        /**
@@ -380,8 +377,9 @@ public class Settings {
         *
         * <p>
         * This method searches for a value using the same lookup order as 
{@link #get(String)}.
-        * If a value is found, it is converted to the type of the default 
value using {@link #toType(String, Object)}.
-        * Supported types include {@link Boolean}, {@link Charset}, and other 
common types.
+        * If a value is found, it is converted to the type of the default 
value using {@link #toType(String, Class)}.
+        * Supported types include any type that has a static method with 
signature <c>public static &lt;T&gt; T anyName(String arg)</c>
+        * or a public constructor with signature <c>public T(String arg)</c>, 
such as {@link Boolean}, {@link Integer}, {@link Charset}, {@link File}, etc.
         *
         * <h5 class='section'>Example:</h5>
         * <p class='bjava'>
@@ -400,7 +398,7 @@ public class Settings {
         * @param def The default value to return if not found.
         * @return The found value (converted to type T), or the default value 
if not found.
         * @see #get(String)
-        * @see #toType(String, Object)
+        * @see #toType(String, Class)
         */
        @SuppressWarnings("unchecked")
        public <T> T get(String name, T def) {
@@ -533,29 +531,55 @@ public class Settings {
        }
 
        /**
-        * Converts a string to the specified type using registered conversion 
functions.
+        * Converts a string to the specified type using reflection to find 
conversion methods or constructors.
+        *
+        * <p>
+        * This method attempts to convert a string to the specified type using 
the following lookup order:
+        * <ol>
+        *      <li>Custom type functions registered via {@link 
Builder#addTypeFunction(Class, Function)}</li>
+        *      <li>Special handling for {@link String} (returns the string 
as-is)</li>
+        *      <li>Special handling for {@link Enum} types (uses {@link 
Enum#valueOf(Class, String)})</li>
+        *      <li>Reflection lookup for static methods with signature 
<c>public static &lt;T&gt; T anyName(String arg)</c>
+        *              on the target class</li>
+        *      <li>Reflection lookup for static methods on the superclass (for 
abstract classes like {@link Charset}
+        *              where concrete implementations need to use the abstract 
class's static method)</li>
+        *      <li>Reflection lookup for public constructors with signature 
<c>public T(String arg)</c></li>
+        * </ol>
+        *
+        * <p>
+        * When a conversion method or constructor is found via reflection, it 
is cached in the
+        * <c>toTypeFunctions</c> map for future use.
+        *
+        * <h5 class='section'>Examples:</h5>
+        * <ul class='spaced-list'>
+        *      <li><c>Boolean</c> - Uses <c>Boolean.valueOf(String)</c> static 
method
+        *      <li><c>Integer</c> - Uses <c>Integer.valueOf(String)</c> static 
method
+        *      <li><c>Charset</c> - Uses <c>Charset.forName(String)</c> static 
method (even for concrete implementations)
+        *      <li><c>File</c> - Uses <c>File(String)</c> constructor
+        * </ul>
         *
         * @param <T> The target type.
         * @param s The string to convert. Must not be <jk>null</jk>.
         * @param c The target class. Must not be <jk>null</jk>.
         * @return The converted value.
-        * @throws RuntimeException If the type is not supported for conversion.
+        * @throws RuntimeException If the type is not supported for conversion 
(no static method or constructor found).
         */
        @SuppressWarnings({ "unchecked", "rawtypes" })
        protected <T> T toType(String s, Class<T> c) {
                assertArgNotNull("s", s);
                assertArgNotNull("c", c);
-               var f = (Function<String,T>)customTypeFunctions.get(c);
+               var f = (Function<String,T>)toTypeFunctions.get(c);
                if (f == null) {
                        if (c == String.class)
                                return (T)s;
                        if (c.isEnum())
                                return (T)Enum.valueOf((Class<? extends 
Enum>)c, s);
-                       f = (Function<String,T>)DEFAULT_TYPE_FUNCTIONS.get(c);
-                       if (f == null)
-                               f = 
customTypeFunctions.entrySet().stream().filter(x -> 
x.getKey().isAssignableFrom(c)).map(x -> 
(Function<String,T>)x.getValue()).findFirst().orElse(null);
+                       ClassInfoTyped<T> ci = info(c);
+                       f = ci.getDeclaredMethod(x -> x.isStatic() && 
x.hasParameterTypes(String.class) && x.hasReturnType(c) && 
FROM_STRING_METHOD_NAMES.contains(x.getName())).map(x -> (Function<String,T>)s2 
-> x.invoke(null, s2)).orElse(null);
                        if (f == null)
-                               f = 
DEFAULT_TYPE_FUNCTIONS.entrySet().stream().filter(x -> 
x.getKey().isAssignableFrom(c)).map(x -> 
(Function<String,T>)x.getValue()).findFirst().orElse(null);
+                               f = ci.getPublicConstructor(x -> 
x.hasParameterTypes(String.class)).map(x -> (Function<String,T>)s2 -> 
x.newInstance(s2)).orElse(null);
+                       if (f != null)
+                               toTypeFunctions.putIfAbsent(c, f);
                }
                if (f == null)
                        throw rex("Invalid env type: {0}", c);
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
index 88fc940286..8e16f77dc5 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
@@ -23,12 +23,12 @@ import java.lang.reflect.*;
 import java.nio.charset.*;
 import java.text.*;
 import java.util.*;
-import java.util.concurrent.*;
 import java.util.concurrent.atomic.*;
 import java.util.function.*;
 
 import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.function.*;
+import org.apache.juneau.commons.settings.*;
 
 /**
  * Common utility methods.
@@ -54,15 +54,6 @@ import org.apache.juneau.commons.function.*;
  */
 public class Utils {
 
-       private static final Map<Class<?>,Function<String,?>> ENV_FUNCTIONS = 
new IdentityHashMap<>();
-
-       static {
-               ENV_FUNCTIONS.put(Boolean.class, Boolean::valueOf);
-               ENV_FUNCTIONS.put(Charset.class, Charset::forName);
-       }
-
-       private static final ConcurrentHashMap<String,String> PROPERTY_TO_ENV = 
new ConcurrentHashMap<>();
-
        /**
         * Converts an object to a boolean.
         *
@@ -362,11 +353,8 @@ public class Utils {
         * @see System#getProperty(String)
         * @see System#getenv(String)
         */
-       public static Optional<String> env(String name) {
-               var s = System.getProperty(name);
-               if (s == null)
-                       s = System.getenv(envName(name));
-               return opt(s);
+       public static StringSetting env(String name) {
+               return Settings.get().get(name);
        }
 
        /**
@@ -404,7 +392,7 @@ public class Utils {
         * @see #toType(String, Object)
         */
        public static <T> T env(String name, T def) {
-               return env(name).map(x -> toType(x, def)).orElse(def);
+               return Settings.get().get(name, def);
        }
 
        /**
@@ -1779,40 +1767,6 @@ public class Utils {
                return o;
        }
 
-       /**
-        * Converts a property name to an environment variable name.
-        *
-        * @param name The property name to convert.
-        * @return The environment variable name (uppercase with dots replaced 
by underscores).
-        */
-       private static String envName(String name) {
-               return PROPERTY_TO_ENV.computeIfAbsent(name, x -> 
x.toUpperCase().replace(".", "_"));
-       }
-
-       /**
-        * Converts a string to the specified type using registered conversion 
functions.
-        *
-        * @param <T> The target type.
-        * @param s The string to convert.
-        * @param def The default value (used to determine the target type).
-        * @return The converted value, or <jk>null</jk> if the string or 
default is <jk>null</jk>.
-        * @throws RuntimeException If the type is not supported for conversion.
-        */
-       @SuppressWarnings({ "unchecked", "rawtypes" })
-       private static <T> T toType(String s, T def) {
-               if (s == null || def == null)
-                       return null;
-               var c = (Class<T>)def.getClass();
-               if (c == String.class)
-                       return (T)s;
-               if (c.isEnum())
-                       return (T)Enum.valueOf((Class<? extends Enum>)c, s);
-               var f = (Function<String,T>)ENV_FUNCTIONS.get(c);
-               if (f == null)
-                       throw rex("Invalid env type: {0}", c);
-               return f.apply(s);
-       }
-
        /** Constructor - This class is meant to be subclasses. */
        protected Utils() {}
 
diff --git 
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/FileStore.java
 
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/FileStore.java
index d8edf7f108..871f594331 100644
--- 
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/FileStore.java
+++ 
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/store/FileStore.java
@@ -64,7 +64,7 @@ public class FileStore extends ConfigStore {
                 */
                protected Builder() {
                        directory = env("ConfigFileStore.directory", ".");
-                       charset = env("ConfigFileStore.charset", 
Charset.defaultCharset());
+                       charset = env("ConfigFileStore.charset").map(x -> 
Charset.forName(x)).orElse(Charset.defaultCharset());
                        enableWatcher = env("ConfigFileStore.enableWatcher", 
false);
                        watcherSensitivity = 
env("ConfigFileStore.watcherSensitivity", WatcherSensitivity.MEDIUM);
                        updateOnWrite = env("ConfigFileStore.updateOnWrite", 
false);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 1b8eea0473..739d00c361 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -38,7 +38,6 @@ import org.apache.juneau.commons.collections.FluentMap;
 import org.apache.juneau.commons.function.*;
 import org.apache.juneau.commons.reflect.*;
 import org.apache.juneau.commons.reflect.Visibility;
-import org.apache.juneau.commons.settings.*;
 import org.apache.juneau.cp.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.marshaller.*;
@@ -173,11 +172,6 @@ public class BeanContext extends Context {
        public static class Builder extends Context.Builder {
 
                private static final Cache<HashKey,BeanContext> CACHE = 
Cache.of(HashKey.class, BeanContext.class).build();
-               private static final Settings SETTINGS = Settings.get();
-
-//             private static <T> T env(String property, T def) {
-//                     return SETTINGS.get(property, def);
-//             }
 
                private static Set<Class<?>> classSet() {
                        return new TreeSet<>(comparing(Class::getName));
@@ -254,9 +248,9 @@ public class BeanContext extends Context {
                        useEnumNames = env("BeanContext.useEnumNames", false);
                        useJavaBeanIntrospector = 
env("BeanContext.useJavaBeanIntrospector", false);
                        typePropertyName = env("BeanContext.typePropertyName", 
"_type");
-                       mediaType = env("BeanContext.mediaType", 
(MediaType)null);
-                       timeZone = env("BeanContext.timeZone", (TimeZone)null);
-                       locale = env("BeanContext.locale", Locale.getDefault());
+                       mediaType = env("BeanContext.mediaType").map(x -> 
MediaType.of(x)).orElse(null);
+                       timeZone = env("BeanContext.timeZone").map(x -> 
TimeZone.getTimeZone(x)).orElse(null);
+                       locale = env("BeanContext.locale").map(x -> 
Locale.forLanguageTag(x)).orElse(Locale.getDefault());
                        propertyNamer = null;
                }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
index c55ddeadbf..b70c176b97 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
@@ -61,7 +61,7 @@ public class ReaderParser extends Parser {
                 * Constructor, default settings.
                 */
                protected Builder() {
-                       fileCharset = env("ReaderParser.fileCharset", 
Charset.defaultCharset());
+                       fileCharset = env("ReaderParser.fileCharset").map(x -> 
Charset.forName(x)).orElse(Charset.defaultCharset());
                        streamCharset = env("ReaderParser.streamCharset", UTF8);
                }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index d1a705a262..200f132b85 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -61,8 +61,8 @@ public class WriterSerializer extends Serializer {
                        fileCharset = Charset.defaultCharset();
                        streamCharset = UTF8;
                        maxIndent = env("WriterSerializer.maxIndent", 100);
-                       quoteChar = env("WriterSerializer.quoteChar", 
(Character)null);
-                       quoteCharOverride = 
env("WriterSerializer.quoteCharOverride", (Character)null);
+                       quoteChar = env("WriterSerializer.quoteChar").map(x -> 
(x.length() > 0 ? x.charAt(0) : null)).orElse(null);
+                       quoteCharOverride = 
env("WriterSerializer.quoteCharOverride").map(x -> (x.length() > 0 ? 
x.charAt(0) : null)).orElse(null);
                        useWhitespace = env("WriterSerializer.useWhitespace", 
false);
                }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 35c538a2dc..4be670b961 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -260,13 +260,18 @@ public class RestContext extends Context {
                private EncoderSet.Builder encoders;
                private SerializerSet.Builder serializers;
                private ParserSet.Builder parsers;
-               String allowedHeaderParams = 
env("RestContext.allowedHeaderParams", "Accept,Content-Type"), 
allowedMethodHeaders = env("RestContext.allowedMethodHeaders", ""),
-                       allowedMethodParams = 
env("RestContext.allowedMethodParams", "HEAD,OPTIONS"), clientVersionHeader = 
env("RestContext.clientVersionHeader", "Client-Version"),
-                       debugOn = env("RestContext.debugOn", null), path = 
null, uriAuthority = env("RestContext.uriAuthority", (String)null), uriContext 
= env("RestContext.uriContext", (String)null);
+               String allowedHeaderParams = 
env("RestContext.allowedHeaderParams", "Accept,Content-Type");
+               String allowedMethodHeaders = 
env("RestContext.allowedMethodHeaders", "");
+               String allowedMethodParams = 
env("RestContext.allowedMethodParams", "HEAD,OPTIONS");
+               String clientVersionHeader = 
env("RestContext.clientVersionHeader", "Client-Version");
+               String debugOn = env("RestContext.debugOn").orElse(null);
+               String path = null;
+               String uriAuthority = 
env("RestContext.uriAuthority").orElse(null);
+               String uriContext = env("RestContext.uriContext").orElse(null);
                UriRelativity uriRelativity = env("RestContext.uriRelativity", 
UriRelativity.RESOURCE);
                UriResolution uriResolution = env("RestContext.uriResolution", 
UriResolution.ROOT_RELATIVE);
-               Charset defaultCharset = env("RestContext.defaultCharset", 
UTF8);
-               long maxInput = parseLongWithSuffix(env("RestContext.maxInput", 
"100M"));
+               Charset defaultCharset = 
env("RestContext.defaultCharset").map(Charset::forName).orElse(UTF8);
+               long maxInput = 
env("RestContext.maxInput").map(StringUtils::parseLongWithSuffix).orElse(100_000_000l);
 
                List<MediaType> consumes, produces;
                boolean disableContentParam = 
env("RestContext.disableContentParam", false);
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/settings/Settings_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/settings/Settings_Test.java
index fb5acc07db..cb46804781 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/settings/Settings_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/settings/Settings_Test.java
@@ -908,15 +908,6 @@ class Settings_Test extends TestBase {
                assertFalse(result);
        }
 
-       @Test
-       void u06_get_withDefaultCharset_found() {
-               System.setProperty(TEST_PROP, "ISO-8859-1");
-               // Use Charset.forName to get a Charset instance (not a 
concrete implementation)
-               var defaultCharset = Charset.forName("UTF-8");
-               var result = Settings.get().get(TEST_PROP, defaultCharset);
-               assertEquals(Charset.forName("ISO-8859-1"), result);
-       }
-
        @Test
        void u07_get_withDefaultCharset_notFound() {
                // Use Charset.forName to get a Charset instance (not a 
concrete implementation)
@@ -1053,7 +1044,14 @@ class Settings_Test extends TestBase {
 
        @Test
        void v08_addTypeFunction_unsupportedType() {
-               // Try to use a type that hasn't been registered
+               // Try to use a type that doesn't have a static method or 
constructor
+               // Custom class without static method or String constructor
+               class UnsupportedType {
+                       @SuppressWarnings("unused")
+                       private final int value;
+                       UnsupportedType(int value) { this.value = value; }
+               }
+
                var settings = Settings.create()
                        .addSource(Settings.SYSTEM_PROPERTY_SOURCE)
                        .addSource(Settings.SYSTEM_ENV_SOURCE)
@@ -1061,44 +1059,27 @@ class Settings_Test extends TestBase {
 
                System.setProperty(TEST_PROP, "123");
                assertThrows(RuntimeException.class, () -> {
-                       settings.get(TEST_PROP, 0); // Integer not registered
+                       settings.get(TEST_PROP, new UnsupportedType(0)); // No 
static method or String constructor
                });
        }
 
        @Test
-       void v09_addTypeFunction_usesDefaultWhenCustomNotRegistered() {
-               // Custom settings without Integer registered should fall back 
to default functions
-               // But Integer is not in DEFAULT_TYPE_FUNCTIONS, so it should 
throw
+       void v09_addTypeFunction_usesReflectionWhenCustomNotRegistered() {
+               // Types with static methods or String constructors work via 
reflection
                var settings = Settings.create()
                        .addSource(Settings.SYSTEM_PROPERTY_SOURCE)
                        .addSource(Settings.SYSTEM_ENV_SOURCE)
                        .build();
 
-               // Boolean is in DEFAULT_TYPE_FUNCTIONS, so it should work
+               // Boolean has Boolean.valueOf(String) static method, so it 
should work
                System.setProperty(TEST_PROP, "true");
                var result = settings.get(TEST_PROP, false);
                assertTrue(result);
 
-               // Integer is not in DEFAULT_TYPE_FUNCTIONS, so it should throw
+               // Integer has Integer.valueOf(String) static method, so it 
should work
                System.setProperty(TEST_PROP_2, "123");
-               assertThrows(RuntimeException.class, () -> {
-                       settings.get(TEST_PROP_2, 0);
-               });
-       }
-
-       @Test
-       void v10_addTypeFunction_charsetUsesDefault() {
-               // Charset is in DEFAULT_TYPE_FUNCTIONS, so it should work 
without registration
-               // Use Charset.forName to get a Charset instance (not a 
concrete implementation)
-               var settings = Settings.create()
-                       .addSource(Settings.SYSTEM_PROPERTY_SOURCE)
-                       .addSource(Settings.SYSTEM_ENV_SOURCE)
-                       .build();
-
-               System.setProperty(TEST_PROP, "UTF-8");
-               var defaultCharset = Charset.forName("ISO-8859-1");
-               var result = settings.get(TEST_PROP, defaultCharset);
-               assertEquals(Charset.forName("UTF-8"), result);
+               var intResult = settings.get(TEST_PROP_2, 0);
+               assertEquals(123, intResult.intValue());
        }
 
        
//====================================================================================================
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/utils/Utils_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/commons/utils/Utils_Test.java
index 946b73b131..f66ef1559f 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/commons/utils/Utils_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/commons/utils/Utils_Test.java
@@ -206,85 +206,6 @@ class Utils_Test extends TestBase {
                assertFalse(missing.isPresent());
        }
 
-       
//====================================================================================================
-       // env(String, T)
-       
//====================================================================================================
-       @Test
-       void a011_env_withDefault() {
-               // Test with system property - covers toType line 1618-1619 
(String)
-               System.setProperty("test.property2", "testValue2");
-               var result = env("test.property2", "default");
-               assertEquals("testValue2", result);
-               System.clearProperty("test.property2");
-
-               // Test with default value
-               var defaultValue = env("nonexistent.property.xyz2", "default");
-               assertEquals("default", defaultValue);
-
-               // Test with Boolean type - covers toType line 1622-1625 
(ENV_FUNCTIONS)
-               System.setProperty("test.boolean", "true");
-               var boolResult = env("test.boolean", false);
-               assertTrue(boolResult);
-               System.clearProperty("test.boolean");
-
-               // Test with Enum type - covers toType line 1620-1621 (Enum)
-               enum TestEnum { VALUE1, VALUE2 }
-               System.setProperty("test.enum", "VALUE1");
-               var enumResult = env("test.enum", TestEnum.VALUE2);
-               assertEquals(TestEnum.VALUE1, enumResult);
-               System.clearProperty("test.enum");
-
-               // Test null default - covers toType line 1615-1616 (def == 
null)
-               // When property doesn't exist, toType is never called, so test 
via reflection
-               // Also test with property set to ensure toType is called with 
s != null && def == null
-               System.setProperty("test.null.def", "value");
-               var nullResult = env("test.null.def", (String)null);
-               assertNull(nullResult); // toType returns null when def is null
-               System.clearProperty("test.null.def");
-               
-               // Also test when property doesn't exist (returns def directly 
without calling toType)
-               var nullResult2 = env("nonexistent.property.null", 
(String)null);
-               assertNull(nullResult2);
-
-               // Test null string - covers toType line 1615-1616 (s == null, 
def != null)
-               // Use reflection to call private toType method directly
-               try {
-                       var toTypeMethod = 
Utils.class.getDeclaredMethod("toType", String.class, Object.class);
-                       toTypeMethod.setAccessible(true);
-                       var nullStringResult = 
(String)toTypeMethod.invoke(null, (String)null, "default");
-                       assertNull(nullStringResult);
-               } catch (Exception e) {
-                       fail("Failed to test toType with null string: " + 
e.getMessage());
-               }
-
-               // Test both null - covers toType line 1615-1616 (s == null && 
def == null)
-               // Use reflection to call private toType method directly
-               try {
-                       var toTypeMethod = 
Utils.class.getDeclaredMethod("toType", String.class, Object.class);
-                       toTypeMethod.setAccessible(true);
-                       var bothNullResult = (String)toTypeMethod.invoke(null, 
(String)null, (String)null);
-                       assertNull(bothNullResult);
-               } catch (Exception e) {
-                       fail("Failed to test toType with both null: " + 
e.getMessage());
-               }
-               
-               // Test s != null && def == null via reflection to ensure line 
1615 is fully covered
-               try {
-                       var toTypeMethod = 
Utils.class.getDeclaredMethod("toType", String.class, Object.class);
-                       toTypeMethod.setAccessible(true);
-                       var nonNullStringNullDef = 
(String)toTypeMethod.invoke(null, "value", (String)null);
-                       assertNull(nonNullStringNullDef); // toType returns 
null when def is null
-               } catch (Exception e) {
-                       fail("Failed to test toType with non-null string and 
null def: " + e.getMessage());
-               }
-
-               // Test invalid type - covers toType line 1623-1624 (exception)
-               // Note: Charset doesn't work because def.getClass() returns 
concrete implementation class
-               System.setProperty("test.invalid", "value");
-               assertThrows(RuntimeException.class, () -> env("test.invalid", 
123)); // Integer not in ENV_FUNCTIONS
-               System.clearProperty("test.invalid");
-       }
-
        
//====================================================================================================
        // eq(boolean, String, String)
        
//====================================================================================================

Reply via email to