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 93eb4b264 Test modernization, clean up utility classes.
93eb4b264 is described below

commit 93eb4b264c1b062b8ac03ff0df6a4e3e947686a0
Author: James Bognar <james.bog...@salesforce.com>
AuthorDate: Mon Aug 25 15:43:50 2025 -0400

    Test modernization, clean up utility classes.
---
 .../apache/juneau/common/internal/StringUtils.java |   14 +-
 .../juneau/common/internal/ThrowableLogger.java    |   21 -
 .../org/apache/juneau/common/internal/Utils.java   | 1502 ++++++++++----------
 .../main/java/org/apache/juneau/config/Entry.java  |    2 +-
 .../java/org/apache/juneau/AnnotationApplier.java  |    2 +-
 .../org/apache/juneau/BeanTraverseSession.java     |    2 +-
 .../java/org/apache/juneau/PropertyNamerDLC.java   |    2 +-
 .../java/org/apache/juneau/PropertyNamerDUCS.java  |    2 +-
 .../java/org/apache/juneau/PropertyNamerULC.java   |    2 +-
 .../src/main/java/org/apache/juneau/Version.java   |    2 +-
 .../org/apache/juneau/collections/JsonList.java    |    2 +-
 .../org/apache/juneau/collections/JsonMap.java     |    4 +-
 .../java/org/apache/juneau/cp/BasicFileFinder.java |    2 +-
 .../main/java/org/apache/juneau/cp/BeanStore.java  |    2 +-
 .../java/org/apache/juneau/internal/DateUtils.java |    4 +-
 .../java/org/apache/juneau/internal/FileUtils.java |    2 +-
 .../org/apache/juneau/internal/VersionRange.java   |    2 +-
 .../juneau/swaps/XMLGregorianCalendarSwap.java     |    2 +-
 .../org/apache/juneau/utils/ReflectionMap.java     |    2 +-
 .../juneau/utils/StringExpressionMatcher.java      |    2 +-
 .../org/apache/juneau/rest/client/RestRequest.java |   30 +-
 .../apache/juneau/rest/client/RestResponse.java    |    2 +-
 .../juneau/http/header/BasicBooleanHeader.java     |    2 +-
 .../apache/juneau/http/header/BasicDateHeader.java |    2 +-
 .../apache/juneau/http/header/BasicUriHeader.java  |    2 +-
 .../org/apache/juneau/http/header/EntityTags.java  |    2 +-
 .../juneau/http/header/SerializedHeader.java       |    2 +-
 .../apache/juneau/http/part/BasicBooleanPart.java  |    6 +-
 .../apache/juneau/http/part/BasicCsvArrayPart.java |    4 +-
 .../org/apache/juneau/http/part/BasicDatePart.java |    6 +-
 .../apache/juneau/http/part/BasicIntegerPart.java  |    6 +-
 .../org/apache/juneau/http/part/BasicLongPart.java |    6 +-
 .../apache/juneau/http/part/BasicStringPart.java   |    4 +-
 .../org/apache/juneau/http/part/BasicUriPart.java  |    6 +-
 .../apache/juneau/http/part/SerializedPart.java    |    2 +-
 .../org/apache/juneau/rest/guard/RoleMatcher.java  |    2 +-
 .../juneau/rest/httppart/RequestContent.java       |    2 +-
 .../juneau/rest/httppart/RequestFormParams.java    |    2 +-
 .../juneau/rest/httppart/RequestHeaders.java       |    2 +-
 .../juneau/rest/httppart/RequestPathParams.java    |    2 +-
 .../juneau/rest/httppart/RequestQueryParams.java   |    2 +-
 .../juneau/rest/logger/CallLoggingDetail.java      |    2 +-
 .../juneau/rest/matcher/ClientVersionMatcher.java  |    2 +-
 .../rest/processor/PlainTextPojoProcessor.java     |    4 +-
 .../rest/swagger/BasicSwaggerProviderSession.java  |    6 +-
 .../org/apache/juneau/rest/util/RestUtils.java     |    2 +-
 .../org/apache/juneau/rest/util/UrlPathMatch.java  |    2 +-
 .../test/java/org/apache/juneau/ComboInput.java    |    2 +-
 .../apache/juneau/utils/StringVarResolverTest.java |    2 +-
 49 files changed, 824 insertions(+), 867 deletions(-)

diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
index e7c2ea458..044bc15a6 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/StringUtils.java
@@ -761,7 +761,7 @@ public final class StringUtils {
         * @throws IllegalArgumentException Value was not a valid date.
         */
        public static Date parseIsoDate(String date) throws 
IllegalArgumentException {
-               if (Utils.isEmpty3(date))
+               if (Utils.isEmpty(date))
                        return null;
                return parseIsoCalendar(date).getTime();  // NOSONAR - NPE not 
possible.
        }
@@ -778,7 +778,7 @@ public final class StringUtils {
         * @throws IllegalArgumentException Value was not a valid date.
         */
        public static Calendar parseIsoCalendar(String date) throws 
IllegalArgumentException {
-               if (Utils.isEmpty3(date))
+               if (Utils.isEmpty(date))
                        return null;
                date = date.trim().replace(' ', 'T');  // Convert to 'standard' 
ISO8601
                if (date.indexOf(',') != -1)  // Trim milliseconds
@@ -1380,7 +1380,7 @@ public final class StringUtils {
         */
        public static boolean isAbsoluteUri(String s) {  // NOSONAR - False 
positive.
 
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return false;
 
                // Use a state machine for maximum performance.
@@ -1437,7 +1437,7 @@ public final class StringUtils {
         */
        public static boolean isUri(String s) {  // NOSONAR - False positive.
 
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return false;
 
                // Use a state machine for maximum performance.
@@ -1647,7 +1647,7 @@ public final class StringUtils {
        }
 
        private static int multiplier(String s) {
-               char c = Utils.isEmpty3(s) ? null : s.charAt(s.length()-1);  // 
NOSONAR - NPE not possible.
+               char c = Utils.isEmpty(s) ? null : s.charAt(s.length()-1);  // 
NOSONAR - NPE not possible.
                if (c == 'G') return 1024*1024*1024;
                if (c == 'M') return 1024*1024;
                if (c == 'K') return 1024;
@@ -1687,7 +1687,7 @@ public final class StringUtils {
        }
 
        private static long multiplier2(String s) {
-               char c = Utils.isEmpty3(s) ? null : s.charAt(s.length()-1);  // 
NOSONAR - NPE not possible.
+               char c = Utils.isEmpty(s) ? null : s.charAt(s.length()-1);  // 
NOSONAR - NPE not possible.
                if (c == 'P') return 1024*1024*1024*1024*1024l;
                if (c == 'T') return 1024*1024*1024*1024l;
                if (c == 'G') return 1024*1024*1024l;
@@ -1913,7 +1913,7 @@ public final class StringUtils {
         */
        public static long getDuration(String s) {
                s = trim(s);
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return -1;
                int i;
                for (i = 0; i < s.length(); i++) {
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowableLogger.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowableLogger.java
deleted file mode 100644
index 813f5f29d..000000000
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/ThrowableLogger.java
+++ /dev/null
@@ -1,21 +0,0 @@
-// 
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
-// * to you 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.juneau.common.internal;
-
-/**
- * Interface for an object that logs thrown exceptions.
- */
-public interface ThrowableLogger {
-
-       void log(Throwable t);
-}
diff --git 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
index f18b5ac2e..ad45b0728 100644
--- 
a/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
+++ 
b/juneau-core/juneau-common/src/main/java/org/apache/juneau/common/internal/Utils.java
@@ -30,8 +30,14 @@ import java.util.stream.*;
 
 public class Utils {
 
-       /** Constructor */
-       protected 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<>();
 
        /**
         * Creates an array of objects.
@@ -54,14 +60,91 @@ public class Utils {
                return (List<T>) l;
        }
 
+       /**
+        * Shortcut for creating an unmodifiable list out of an array of values.
+        */
+       @SafeVarargs
+       public static <T> List<T> alist(T...values) {  // NOSONAR
+               return Arrays.asList(values);
+       }
+
+       /**
+        * Converts the specified collection to an array.
+        *
+        * @param <E> The element type.
+        * @param value The collection to convert.
+        * @param componentType The component type of the array.
+        * @return A new array.
+        */
+       public static <E> E[] array(Collection<E> value, Class<E> 
componentType) {
+               if (value == null)
+                       return null;
+               E[] array = (E[])Array.newInstance(componentType, value.size());
+               return value.toArray(array);
+       }
+
+       /**
+        * Casts an object to a specific type if it's an instance of that type.
+        *
+        * @param <T> The type to cast to.
+        * @param c The type to cast to.
+        * @param o The object to cast to.
+        * @return The cast object, or <jk>null</jk> if the object wasn't the 
specified type.
+        */
+       public static <T> T cast(Class<T> c, Object o) {
+               return o != null && c.isInstance(o) ? c.cast(o) : null;
+       }
+
+       /**
+        * If the specified object is an instance of the specified class, casts 
it to that type.
+        *
+        * @param <T> The class to cast to.
+        * @param o The object to cast.
+        * @param c The class to cast to.
+        * @return The cast object, or <jk>null</jk> if the object wasn't an 
instance of the specified class.
+        */
+       public static <T> T castOrNull(Object o, Class<T> c) {
+               if (c.isInstance(o))
+                       return c.cast(o);
+               return null;
+       }
+
+       /**
+        * Compares two objects for equality.
+        *
+        * <p>
+        * Nulls are always considered less-than unless both are null.
+        *
+        * @param o1 Object 1.
+        * @param o2 Object 2.
+        * @return
+        *      <c>-1</c>, <c>0</c>, or <c>1</c> if <c>o1</c> is less-than, 
equal, or greater-than <c>o2</c>.
+        *      <br><c>0</c> if objects are not of the same type or do not 
implement the {@link Comparable} interface.
+        */
+       @SuppressWarnings({ "rawtypes", "unchecked" })
+       public static int compare(Object o1, Object o2) {
+               if (o1 == null) {
+                       if (o2 == null)
+                               return 0;
+                       return -1;
+               } else if (o2 == null) {
+                       return 1;
+               }
+
+               if (o1.getClass() == o2.getClass() && o1 instanceof Comparable)
+                       return ((Comparable)o1).compareTo(o2);
+
+               return 0;
+       }
+
        /**
         * Null-safe {@link String#contains(CharSequence)} operation.
         */
-       public static boolean contains(String s, String...values) {
+       public static boolean contains(String s, char...values) {
                if (s == null || values == null || values.length == 0)
                        return false;
                for (var v : values) {
-                       if (s.contains(v))
+                       if (s.indexOf(v) >= 0)
                                return true;
                }
                return false;
@@ -70,16 +153,26 @@ public class Utils {
        /**
         * Null-safe {@link String#contains(CharSequence)} operation.
         */
-       public static boolean contains(String s, char...values) {
+       public static boolean contains(String s, String...values) {
                if (s == null || values == null || values.length == 0)
                        return false;
                for (var v : values) {
-                       if (s.indexOf(v) >= 0)
+                       if (s.contains(v))
                                return true;
                }
                return false;
        }
 
+       /**
+        * Returns an empty {@link Optional}.
+        *
+        * @param <T> The component type.
+        * @return An empty {@link Optional}.
+        */
+       public static <T> Optional<T> empty() {
+               return Optional.empty();
+       }
+
        /**
         * Returns the specified string, or blank if that string is null.
         */
@@ -94,13 +187,14 @@ public class Utils {
         * First looks in system properties.  Then converts the name to 
env-safe and looks in the system environment.
         * Then returns the default if it can't be found.
         *
-        * @param <T> The type to convert the value to.
         * @param name The property name.
-        * @param def The default value if not found.
-        * @return The default value.
+        * @return The value if found.
         */
-       public static <T> T env(String name, T def) {
-               return env(name).map(x -> toType(x, def)).orElse(def);
+       public static Optional<String> env(String name) {
+               var s = System.getProperty(name);
+               if (s == null)
+                       s = System.getenv(envName(name));
+               return opt(s);
        }
 
        /**
@@ -110,14 +204,29 @@ public class Utils {
         * First looks in system properties.  Then converts the name to 
env-safe and looks in the system environment.
         * Then returns the default if it can't be found.
         *
+        * @param <T> The type to convert the value to.
         * @param name The property name.
-        * @return The value if found.
+        * @param def The default value if not found.
+        * @return The default value.
         */
-       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 <T> T env(String name, T def) {
+               return env(name).map(x -> toType(x, def)).orElse(def);
+       }
+
+       private static String envName(String name) {
+               return PROPERTY_TO_ENV.computeIfAbsent(name, 
x->x.toUpperCase().replace(".", "_"));
+       }
+
+       /**
+        * Tests two strings for equality, but gracefully handles nulls.
+        *
+        * @param caseInsensitive Use case-insensitive matching.
+        * @param s1 String 1.
+        * @param s2 String 2.
+        * @return <jk>true</jk> if the strings are equal.
+        */
+       public static boolean eq(boolean caseInsensitive, String s1, String s2) 
{
+               return caseInsensitive ? eqic(s1, s2) : eq(s1, s2);
        }
 
        /**
@@ -141,10 +250,6 @@ public class Utils {
                return Objects.equals(o1, o2);
        }
 
-       private static boolean isArray(Object o) {
-               return o != null && o.getClass().isArray();
-       }
-
        /**
         * Tests two objects for equality, gracefully handling nulls.
         *
@@ -171,6 +276,21 @@ public class Utils {
                return test.test(o1, o2);
        }
 
+       /**
+        * Tests two strings for case-insensitive equality, but gracefully 
handles nulls.
+        *
+        * @param s1 String 1.
+        * @param s2 String 2.
+        * @return <jk>true</jk> if the strings are equal.
+        */
+       public static boolean eqic(String s1, String s2) {
+               if (s1 == null)
+                       return s2 == null;
+               if (s2 == null)
+                       return false;
+               return s1.equalsIgnoreCase(s2);
+       }
+
        /**
         * Same as MessageFormat.format().
         */
@@ -181,372 +301,125 @@ public class Utils {
        }
 
        /**
-        * Shortcut for calling {@link Objects#hash(Object...)}.
+        * Returns the first non-null value in the specified array
+        *
+        * @param <T> The value types.
+        * @param t The values to check.
+        * @return The first non-null value, or <jk>null</jk> if the array is 
null or empty or contains only <jk>null</jk> values.
         */
-       public static final int hash(Object...values) {
-               return Objects.hash(values);
+       @SafeVarargs
+       public static <T> T firstNonNull(T... t) {
+               if (t != null)
+                       for (T tt : t)
+                               if (tt != null)
+                                       return tt;
+               return null;
        }
 
        /**
-        * Creates an {@link IllegalArgumentException}.
+        * Simplified formatted string supplier with message arguments.
         */
-       public static IllegalArgumentException illegalArg(String msg, 
Object...args) {
-               return new IllegalArgumentException(args.length == 0 ? msg : 
f(msg, args));
+       public static Supplier<String> fs(String pattern, Object...args) {
+               return ()->StringUtils.format(pattern, args);
        }
 
        /**
-        * @return True if string is null or empty.
+        * Converts a string containing <js>"*"</js> meta characters with a 
regular expression pattern.
+        *
+        * @param s The string to create a pattern from.
+        * @return A regular expression pattern.
         */
-       public static boolean isEmpty(String o) {
-               return o == null || o.isEmpty();
+       public static Pattern getMatchPattern3(String s) {
+               return getMatchPattern3(s, 0);
        }
 
        /**
-        * @return True if string is not null or empty.
+        * Converts a string containing <js>"*"</js> meta characters with a 
regular expression pattern.
+        *
+        * @param s The string to create a pattern from.
+        * @param flags Regular expression flags.
+        * @return A regular expression pattern.
         */
-       public static boolean isNotEmpty(String o) {
-               return ! isEmpty(o);
+       public static Pattern getMatchPattern3(String s, int flags) {
+               if (s == null)
+                       return null;
+               var sb = new StringBuilder();
+               sb.append("\\Q");
+               for (var i = 0; i < s.length(); i++) {
+                       var c = s.charAt(i);
+                       if (c == '*')
+                               sb.append("\\E").append(".*").append("\\Q");
+                       else if (c == '?')
+                               sb.append("\\E").append(".").append("\\Q");
+                       else
+                               sb.append(c);
+               }
+               sb.append("\\E");
+               return Pattern.compile(sb.toString(), flags);
        }
 
        /**
-        * Shortcut for creating a modifiable list out of an array of values.
+        * Shortcut for calling {@link Objects#hash(Object...)}.
         */
-       @SafeVarargs
-       public static <T> List<T> list(T...values) {  // NOSONAR
-               return new ArrayList<>(Arrays.asList(values));
+       public static final int hash(Object...values) {
+               return Objects.hash(values);
        }
 
        /**
-        * Shortcut for creating a modifiable set out of an array of values.
+        * Creates an {@link IllegalArgumentException}.
         */
-       @SafeVarargs
-       public static <K,V> LinkedHashMap<K,V> map(Object...values) {  // 
NOSONAR
-               var m = new LinkedHashMap<K,V>();
-               for (var i = 0; i < values.length; i+=2) {
-                       m.put((K)values[i], (V)values[i+1]);
-               }
-               return m;
+       public static IllegalArgumentException illegalArg(String msg, 
Object...args) {
+               return new IllegalArgumentException(args.length == 0 ? msg : 
f(msg, args));
        }
 
-       /** Not equals */
-       public static <T> boolean ne(T s1, T s2) {
-               return ! eq(s1, s2);
+       private static boolean isArray(Object o) {
+               return o != null && o.getClass().isArray();
        }
 
        /**
-        * Null-safe {@link String#contains(CharSequence)} operation.
+        * Returns <jk>true</jk> if the specified object is empty.
+        *
+        * <p>
+        * Return <jk>true</jk> if the value is any of the following:
+        * <ul>
+        *      <li><jk>null</jk>
+        *      <li>An empty Collection
+        *      <li>An empty Map
+        *      <li>An empty array
+        *      <li>An empty CharSequence
+        *      <li>An empty String when serialized to a string using {@link 
Object#toString()}.
+        * </ul>
+        *
+        * @param o The object to test.
+        * @return <jk>true</jk> if the specified object is empty.
         */
-       public static boolean notContains(String s, char...values) {
-               return ! contains(s, values);
-       }
-
-       /**
-        * Returns the specified string, or null if that string is null or 
empty.
-        */
-       public static String nullIfEmpty(String value) {
-               return isEmpty(value) ? null : value;
-       }
-
-       /**
-        * Returns an obfuscated version of the specified string.
-        */
-       public static String obfuscate(String s) {
-               if (s == null || s.length() < 2)
-                       return "*";
-               return s.substring(0, 1) + s.substring(1).replaceAll(".", "*"); 
 // NOSONAR
-       }
-
-       /**
-        * Shortcut for calling {@link Optional#ofNullable(Object)}.
-        */
-       public static final <T> Optional<T> opt(T t) {
-               return Optional.ofNullable(t);
-       }
-
-       public static final <T> Optional<T> opte() {
-               return Optional.empty();
-       }
-
-       /**
-        * Prints all the specified lines to System.out.
-        */
-       public static final void printLines(String[] lines) {
-               for (var i = 0; i < lines.length; i++)
-                       System.out.println(String.format("%4s:" + lines[i], 
i+1)); // NOSONAR - NOT DEBUG
-       }
-
-       /**
-        * Shortcut for {@link #readable(Object)}
-        */
-       public static String r(Object o) {
-               if (o instanceof Optional<?> o2)
-                       return r(o2.orElse(null));
-               if (o instanceof Collection<?> o2)
-                       return 
o2.stream().map(Utils::r).collect(joining(",","[","]"));
-               if (o instanceof Map<?,?> o2)
-                       return 
o2.entrySet().stream().map(Utils::r).collect(joining(",","{","}"));
-               if (o instanceof Map.Entry<?,?> o2)
-                       return r(o2.getKey()) + '=' + r(o2.getValue());
-               if (o instanceof GregorianCalendar o2)
-                       return 
o2.toZonedDateTime().format(DateTimeFormatter.ISO_INSTANT);
-               if (o instanceof Date o2)
-                       return o2.toInstant().toString();
-               if (o instanceof InputStream o2)
-                       return toHex(o2);
-               if (o instanceof Reader o2)
-                       return safe(()->IOUtils.read(o2));
-               if (o instanceof File o2)
-                       return safe(()->IOUtils.read(o2));
-               if (o instanceof byte[] o2)
-                       return toHex(o2);
-               if (o != null && o.getClass().isArray()) {
-                       var l = list();
-                       for (var i = 0; i < Array.getLength(o); i++) {
-                               l.add(Array.get(o, i));
-                       }
-                       return r(l);
-               }
-               return s(o);
-       }
-
-       /**
-        * Creates a {@link RuntimeException}.
-        */
-       public static RuntimeException runtimeException(String msg, 
Object...args) {
-               return new RuntimeException(args.length == 0 ? msg : f(msg, 
args));
-       }
-
-       /**
-        * Shortcut for converting an object to a string.
-        */
-       public static String s(Object val) {
-               return val == null ? null : val.toString();
-       }
-
-       /**
-        * Used to wrap code that returns a value but throws an exception.
-        * Useful in cases where you're trying to execute code in a fluent 
method call
-        * or are trying to eliminate untestable catch blocks in code.
-        */
-       public static <T> T safe(ThrowingSupplier<T> s) {
-               try {
-                       return s.get();
-               } catch (RuntimeException e) {
-                       throw e;
-               } catch (Exception e) {
-                       throw new RuntimeException(e);
-               }
-       }
-
-       /**
-        * Shortcut for creating a modifiable set out of an array of values.
-        */
-       @SafeVarargs
-       public static <T> LinkedHashSet<T> set(T...values) {  // NOSONAR
-               return new LinkedHashSet<>(Arrays.asList(values));
-       }
-
-       /**
-        * Splits a comma-delimited list into a list of strings.
-        */
-       public static List<String> split(String s) {
-               return s == null ? Collections.emptyList() : Utils.split2(s);
-       }
-
-       /**
-        * Splits a comma-delimited list into an array of strings.
-        */
-       public static String[] splita(String s) {
-               return s == null ? new String[0] : Utils.split3(s);
-       }
-
-       /**
-        * Converts an array to a stream of objects.
-        * @param array The array to convert.
-        * @return A new stream.
-        */
-       public static Stream<Object> toStream(Object array) {
-               if (array == null || ! array.getClass().isArray()) {
-                       throw illegalArg("Not an array: " + array);
-               }
-               var length = Array.getLength(array);
-               return IntStream.range(0, length).mapToObj(i -> 
Array.get(array, i));
-       }
-
-       /**
-        * Traverses all elements in the specified object and executes a 
consumer for it.
-        *
-        * @param <T> The element type.
-        * @param o The object to traverse.
-        * @param c The consumer of the objects.
-        */
-       public static <T> void traverse(Object o, Consumer<T> c) {
-               if (o == null)
-                       return;
-               if (o instanceof Iterable<?> o2)
-                       o2.forEach(x -> traverse(x, c));
-               else if (o instanceof Stream<?> o2)
-                       o2.forEach(x -> traverse(x, c));
-               else if (o.getClass().isArray())
-                       toStream(o).forEach(x -> traverse(x, c));
-               else
-                       c.accept((T)o);
-       }
-
-       /**
-        * Shortcut for creating an unmodifiable list out of an array of values.
-        */
-       @SafeVarargs
-       public static <T> List<T> alist(T...values) {  // NOSONAR
-               return Arrays.asList(values);
-       }
-
-       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<>();
-
-       private static String envName(String name) {
-               return PROPERTY_TO_ENV.computeIfAbsent(name, 
x->x.toUpperCase().replace(".", "_"));
-       }
-
-       @SuppressWarnings("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 runtimeException("Invalid env type: {0}", c);
-               return f.apply(s);
-       }
-
-       /**
-        * Simplified formatted string supplier with message arguments.
-        */
-       public static Supplier<String> fs(String pattern, Object...args) {
-               return ()->StringUtils.format(pattern, args);
-       }
-
-       /**
-        * Returns an empty {@link Optional}.
-        *
-        * @param <T> The component type.
-        * @return An empty {@link Optional}.
-        */
-       public static <T> Optional<T> empty() {
-               return Optional.empty();
-       }
-
-       /**
-        * Returns the first non-null value in the specified array
-        *
-        * @param <T> The value types.
-        * @param t The values to check.
-        * @return The first non-null value, or <jk>null</jk> if the array is 
null or empty or contains only <jk>null</jk> values.
-        */
-       @SafeVarargs
-       public static <T> T firstNonNull(T... t) {
-               if (t != null)
-                       for (T tt : t)
-                               if (tt != null)
-                                       return tt;
-               return null;
-       }
-
-       /**
-        * Casts an object to a specific type if it's an instance of that type.
-        *
-        * @param <T> The type to cast to.
-        * @param c The type to cast to.
-        * @param o The object to cast to.
-        * @return The cast object, or <jk>null</jk> if the object wasn't the 
specified type.
-        */
-       public static <T> T cast(Class<T> c, Object o) {
-               return o != null && c.isInstance(o) ? c.cast(o) : null;
-       }
-
-       /**
-        * Returns <jk>true</jk> if the specified object is empty.
-        *
-        * <p>
-        * Return <jk>true</jk> if the value is any of the following:
-        * <ul>
-        *      <li><jk>null</jk>
-        *      <li>An empty Collection
-        *      <li>An empty Map
-        *      <li>An empty array
-        *      <li>An empty CharSequence
-        *      <li>An empty String when serialized to a string using {@link 
Object#toString()}.
-        * </ul>
-        *
-        * @param o The object to test.
-        * @return <jk>true</jk> if the specified object is empty.
-        */
-       @SuppressWarnings("rawtypes")
        public static boolean isEmpty(Object o) {
                if (o == null)
                        return true;
-               if (o instanceof Collection)
-                       return ((Collection)o).isEmpty();
-               if (o instanceof Map)
-                       return ((Map)o).isEmpty();
+               if (o instanceof Collection<?> o2)
+                       return  o2.isEmpty();
+               if (o instanceof Map<?,?> o2)
+                       return o2.isEmpty();
                if (o.getClass().isArray())
                        return (Array.getLength(o) == 0);
                return o.toString().isEmpty();
        }
 
        /**
-        * Returns <jk>true</jk> if the specified object is not <jk>null</jk>.
-        *
-        * @param <T> The value type.
-        * @param value The value being checked.
-        * @return <jk>true</jk> if the specified object is not <jk>null</jk>.
-        */
-       public static <T> boolean isNotNull(T value) {
-               return value != null;
-       }
-
-       /**
-        * If the specified object is an instance of the specified class, casts 
it to that type.
-        *
-        * @param <T> The class to cast to.
-        * @param o The object to cast.
-        * @param c The class to cast to.
-        * @return The cast object, or <jk>null</jk> if the object wasn't an 
instance of the specified class.
-        */
-       public static <T> T castOrNull(Object o, Class<T> c) {
-               if (c.isInstance(o))
-                       return c.cast(o);
-               return null;
-       }
-
-       /**
-        * Returns <jk>true</jk> if the specified boolean is not <jk>null</jk> 
and is <jk>true</jk>.
-        *
-        * @param value The value being checked.
-        * @return <jk>true</jk> if the specified boolean is not <jk>null</jk> 
and is <jk>true</jk>.
+        * @return True if string is null or empty.
         */
-       public static boolean isTrue(Boolean value) {
-               return value != null && value;
+       public static boolean isEmpty(String o) {
+               return o == null || o.isEmpty();
        }
 
        /**
-        * Returns <jk>true</jk> if the specified number is not <jk>null</jk> 
and not <c>-1</c>.
+        * Returns <jk>true</jk> if specified string is <jk>null</jk> or empty 
or consists of only blanks.
         *
-        * @param <T> The value types.
-        * @param value The value being checked.
-        * @return <jk>true</jk> if the specified number is not <jk>null</jk> 
and not <c>-1</c>.
+        * @param s The string to check.
+        * @return <jk>true</jk> if specified string is <jk>null</jk> or 
emptyor consists of only blanks.
         */
-       public static <T extends Number> boolean isNotMinusOne(T value) {
-               return value != null && value.intValue() != -1;
+       public static boolean isEmptyOrBlank(String s) {
+               return s == null || s.trim().isEmpty();
        }
 
        /**
@@ -568,65 +441,11 @@ public class Utils {
        }
 
        /**
-        * Compares two objects for equality.
-        *
-        * <p>
-        * Nulls are always considered less-than unless both are null.
-        *
-        * @param o1 Object 1.
-        * @param o2 Object 2.
-        * @return
-        *      <c>-1</c>, <c>0</c>, or <c>1</c> if <c>o1</c> is less-than, 
equal, or greater-than <c>o2</c>.
-        *      <br><c>0</c> if objects are not of the same type or do not 
implement the {@link Comparable} interface.
-        */
-       @SuppressWarnings({ "rawtypes", "unchecked" })
-       public static int compare(Object o1, Object o2) {
-               if (o1 == null) {
-                       if (o2 == null)
-                               return 0;
-                       return -1;
-               } else if (o2 == null) {
-                       return 1;
-               }
-
-               if (o1.getClass() == o2.getClass() && o1 instanceof Comparable)
-                       return ((Comparable)o1).compareTo(o2);
-
-               return 0;
-       }
-
-       /**
-        * Tests two objects for inequality, gracefully handling nulls.
-        *
-        * @param <T> Object 1 type.
-        * @param <U> Object 2 type.
-        * @param o1 Object 1.
-        * @param o2 Object 2.
-        * @param test The test to use for equality.
-        * @return <jk>false</jk> if both objects are equal based on the test.
+        * @return True if string is not null or empty.
         */
-       public static <T,U> boolean ne(T o1, U o2, BiPredicate<T,U> test) {
-               if (o1 == null)
-                       return o2 != null;
-               if (o2 == null)
-                       return true;
-               if (o1 == o2)
-                       return false;
-               return ! test.test(o1, o2);
-       }
-
-       public static <K,V> Map<K,V> u(Map<? extends K, ? extends V> value) {
-               return value == null ? null : 
Collections.unmodifiableMap(value);
-       }
-
-       public static <T> List<T> u(List<? extends T> value) {
-               return value == null ? null : 
Collections.unmodifiableList(value);
-       }
-
-       public static <T> Set<T> u(Set<? extends T> value) {
-               return value == null ? null : 
Collections.unmodifiableSet(value);
+       public static boolean isNotEmpty(String o) {
+               return ! isEmpty(o);
        }
-
        /**
         * Returns <jk>true</jk> if the specified collection is not 
<jk>null</jk> and not empty.
         *
@@ -651,110 +470,123 @@ public class Utils {
        }
 
        /**
-        * Converts the specified collection to an array.
+        * Returns <jk>true</jk> if specified string is not <jk>null</jk> or 
empty.
         *
-        * @param <E> The element type.
-        * @param value The collection to convert.
-        * @param componentType The component type of the array.
-        * @return A new array.
+        * @param s The string to check.
+        * @return <jk>true</jk> if specified string is not <jk>null</jk> or 
empty.
         */
-       @SuppressWarnings("unchecked")
-       public static <E> E[] array(Collection<E> value, Class<E> 
componentType) {
-               if (value == null)
-                       return null;
-               E[] array = (E[])Array.newInstance(componentType, value.size());
-               return value.toArray(array);
+       public static boolean isNotEmpty3(String s) {
+               return ! isEmpty(s);
        }
 
        /**
-        * Convenience method for creating an unmodifiable list.
+        * Returns <jk>true</jk> if either of the specified strings are not 
<jk>null</jk> or empty.
         *
-        * @param <E> The element type.
-        * @param values The values to initialize the list with.
-        * @return A new unmodifiable list, or <jk>null</jk> if the array was 
<jk>null</jk>.
+        * @param s1 The string to check.
+        * @param s2 The string to check.
+        * @return <jk>true</jk> if either of the specified strings are not 
<jk>null</jk> or empty.
         */
-       @SafeVarargs
-       public static <E> List<E> ulist2(E...values) {
-               if (values == null)
-                       return null;
-               return u(alist(values));
+       public static boolean isNotEmpty3(String s1, String s2) {
+               return isNotEmpty3(s1) || isNotEmpty3(s2);
        }
 
        /**
-        * Convenience method for creating an unmodifiable {@link 
LinkedHashSet}.
+        * Returns <jk>true</jk> if the specified number is not <jk>null</jk> 
and not <c>-1</c>.
         *
-        * @param <E> The element type.
-        * @param values The values to initialize the set with.
-        * @return A new unmodifiable set.
+        * @param <T> The value types.
+        * @param value The value being checked.
+        * @return <jk>true</jk> if the specified number is not <jk>null</jk> 
and not <c>-1</c>.
         */
-       @SafeVarargs
-       public static <E> Set<E> uset2(E...values) {
-               return u(set(values));
+       public static <T extends Number> boolean isNotMinusOne(T value) {
+               return value != null && value.intValue() != -1;
+       }
+
+       /**
+        * Returns <jk>true</jk> if the specified object is not <jk>null</jk>.
+        *
+        * @param <T> The value type.
+        * @param value The value being checked.
+        * @return <jk>true</jk> if the specified object is not <jk>null</jk>.
+        */
+       public static <T> boolean isNotNull(T value) {
+               return value != null;
        }
 
        /**
-        * Convenience method for creating an {@link ArrayList} of the 
specified size.
+        * Returns <jk>true</jk> if the specified boolean is not <jk>null</jk> 
and is <jk>true</jk>.
         *
-        * @param <E> The element type.
-        * @param size The initial size of the list.
-        * @return A new modifiable list.
+        * @param value The value being checked.
+        * @return <jk>true</jk> if the specified boolean is not <jk>null</jk> 
and is <jk>true</jk>.
         */
-       public static <E> ArrayList<E> listOfSize(int size) {
-               return new ArrayList<>(size);
+       public static boolean isTrue(Boolean value) {
+               return value != null && value;
        }
 
        /**
-        * Tests two strings for equality, but gracefully handles nulls.
+        * Join the specified tokens into a delimited string.
         *
-        * @param caseInsensitive Use case-insensitive matching.
-        * @param s1 String 1.
-        * @param s2 String 2.
-        * @return <jk>true</jk> if the strings are equal.
+        * @param tokens The tokens to join.
+        * @param d The delimiter.
+        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
         */
-       public static boolean eq(boolean caseInsensitive, String s1, String s2) 
{
-               return caseInsensitive ? eqic(s1, s2) : eq(s1, s2);
+       public static String join(Collection<?> tokens, char d) {
+               if (tokens == null)
+                       return null;
+               var sb = new StringBuilder();
+               for (var iter = tokens.iterator(); iter.hasNext();) {
+                       sb.append(iter.next());
+                       if (iter.hasNext())
+                               sb.append(d);
+               }
+               return sb.toString();
        }
 
        /**
-        * Tests two strings for case-insensitive equality, but gracefully 
handles nulls.
+        * Join the specified tokens into a delimited string.
         *
-        * @param s1 String 1.
-        * @param s2 String 2.
-        * @return <jk>true</jk> if the strings are equal.
+        * @param tokens The tokens to join.
+        * @param d The delimiter.
+        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
         */
-       public static boolean eqic(String s1, String s2) {
-               if (s1 == null)
-                       return s2 == null;
-               if (s2 == null)
-                       return false;
-               return s1.equalsIgnoreCase(s2);
+       public static String join(Collection<?> tokens, String d) {
+               if (tokens == null)
+                       return null;
+               return join(tokens, d, new StringBuilder()).toString();
        }
 
        /**
-        * Tests two strings for non-equality ignoring case, but gracefully 
handles nulls.
+        * Joins the specified tokens into a delimited string and writes the 
output to the specified string builder.
         *
-        * @param s1 String 1.
-        * @param s2 String 2.
-        * @return <jk>true</jk> if the strings are not equal ignoring case.
+        * @param tokens The tokens to join.
+        * @param d The delimiter.
+        * @param sb The string builder to append the response to.
+        * @return The same string builder passed in as <c>sb</c>.
         */
-       public static boolean neic(String s1, String s2) {
-               return ! eqic(s1, s2);
+       public static StringBuilder join(Collection<?> tokens, String d, 
StringBuilder sb) {
+               if (tokens == null)
+                       return sb;
+               for (var iter = tokens.iterator(); iter.hasNext();) {
+                       sb.append(iter.next());
+                       if (iter.hasNext())
+                               sb.append(d);
+               }
+               return sb;
        }
 
        /**
         * Join the specified tokens into a delimited string.
         *
         * @param tokens The tokens to join.
-        * @param separator The delimiter.
+        * @param d The delimiter.
         * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
         */
-       public static String join(Object[] tokens, String separator) {
+       public static String join(int[] tokens, char d) {
                if (tokens == null)
                        return null;
                var sb = new StringBuilder();
                for (var i = 0; i < tokens.length; i++) {
                        if (i > 0)
-                               sb.append(separator);
+                               sb.append(d);
                        sb.append(tokens[i]);
                }
                return sb.toString();
@@ -767,10 +599,16 @@ public class Utils {
         * @param d The delimiter.
         * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
         */
-       public static String join(Collection<?> tokens, String d) {
+       public static String join(List<?> tokens, char d) {
                if (tokens == null)
                        return null;
-               return join(tokens, d, new StringBuilder()).toString();
+               var sb = new StringBuilder();
+               for (int i = 0, j = tokens.size(); i < j; i++) {
+                       if (i > 0)
+                               sb.append(d);
+                       sb.append(tokens.get(i));
+               }
+               return sb.toString();
        }
 
        /**
@@ -794,145 +632,277 @@ public class Utils {
         * @param sb The string builder to append the response to.
         * @return The same string builder passed in as <c>sb</c>.
         */
-       public static StringBuilder join(Collection<?> tokens, String d, 
StringBuilder sb) {
+       public static StringBuilder join(List<?> tokens, String d, 
StringBuilder sb) {
                if (tokens == null)
                        return sb;
-               for (var iter = tokens.iterator(); iter.hasNext();) {
-                       sb.append(iter.next());
-                       if (iter.hasNext())
+               for (int i = 0, j = tokens.size(); i < j; i++) {
+                       if (i > 0)
                                sb.append(d);
+                       sb.append(tokens.get(i));
                }
                return sb;
        }
 
        /**
-        * Joins the specified tokens into a delimited string and writes the 
output to the specified string builder.
+        * Joins the specified tokens into a delimited string.
+        *
+        * @param tokens The tokens to join.
+        * @param d The delimiter.
+        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        */
+       public static String join(Object[] tokens, char d) {
+               if (tokens == null)
+                       return null;
+               if (tokens.length == 1)
+                       return emptyIfNull(s(tokens[0]));
+               return join(tokens, d, new StringBuilder()).toString();
+       }
+
+       /**
+        * Join the specified tokens into a delimited string and writes the 
output to the specified string builder.
         *
         * @param tokens The tokens to join.
         * @param d The delimiter.
         * @param sb The string builder to append the response to.
         * @return The same string builder passed in as <c>sb</c>.
         */
-       public static StringBuilder join(List<?> tokens, String d, 
StringBuilder sb) {
+       public static StringBuilder join(Object[] tokens, char d, StringBuilder 
sb) {
                if (tokens == null)
                        return sb;
-               for (int i = 0, j = tokens.size(); i < j; i++) {
+               for (var i = 0; i < tokens.length; i++) {
                        if (i > 0)
                                sb.append(d);
-                       sb.append(tokens.get(i));
+                       sb.append(tokens[i]);
                }
                return sb;
        }
 
        /**
-        * Joins the specified tokens into a delimited string.
-        *
-        * @param tokens The tokens to join.
-        * @param d The delimiter.
-        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        * Join the specified tokens into a delimited string.
+        *
+        * @param tokens The tokens to join.
+        * @param separator The delimiter.
+        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        */
+       public static String join(Object[] tokens, String separator) {
+               if (tokens == null)
+                       return null;
+               var sb = new StringBuilder();
+               for (var i = 0; i < tokens.length; i++) {
+                       if (i > 0)
+                               sb.append(separator);
+                       sb.append(tokens[i]);
+               }
+               return sb.toString();
+       }
+
+       /**
+        * Joins tokens with newlines.
+        *
+        * @param tokens The tokens to concatenate.
+        * @return A string with the specified tokens contatenated with 
newlines.
+        */
+       public static String joinnl(Object[] tokens) {
+               return join(tokens, '\n');
+       }
+
+       /**
+        * Shortcut for creating a modifiable list out of an array of values.
+        */
+       @SafeVarargs
+       public static <T> List<T> list(T...values) {  // NOSONAR
+               return new ArrayList<>(Arrays.asList(values));
+       }
+
+       /**
+        * Convenience method for creating an {@link ArrayList} of the 
specified size.
+        *
+        * @param <E> The element type.
+        * @param size The initial size of the list.
+        * @return A new modifiable list.
+        */
+       public static <E> ArrayList<E> listOfSize(int size) {
+               return new ArrayList<>(size);
+       }
+
+       /**
+        * Shortcut for creating a modifiable set out of an array of values.
+        */
+       @SafeVarargs
+       public static <K,V> LinkedHashMap<K,V> map(Object...values) {  // 
NOSONAR
+               var m = new LinkedHashMap<K,V>();
+               for (var i = 0; i < values.length; i+=2) {
+                       m.put((K)values[i], (V)values[i+1]);
+               }
+               return m;
+       }
+
+       /** Not equals */
+       public static <T> boolean ne(T s1, T s2) {
+               return ! eq(s1, s2);
+       }
+
+       /**
+        * Tests two objects for inequality, gracefully handling nulls.
+        *
+        * @param <T> Object 1 type.
+        * @param <U> Object 2 type.
+        * @param o1 Object 1.
+        * @param o2 Object 2.
+        * @param test The test to use for equality.
+        * @return <jk>false</jk> if both objects are equal based on the test.
+        */
+       public static <T,U> boolean ne(T o1, U o2, BiPredicate<T,U> test) {
+               if (o1 == null)
+                       return o2 != null;
+               if (o2 == null)
+                       return true;
+               if (o1 == o2)
+                       return false;
+               return ! test.test(o1, o2);
+       }
+
+       /**
+        * Tests two strings for non-equality ignoring case, but gracefully 
handles nulls.
+        *
+        * @param s1 String 1.
+        * @param s2 String 2.
+        * @return <jk>true</jk> if the strings are not equal ignoring case.
+        */
+       public static boolean neic(String s1, String s2) {
+               return ! eqic(s1, s2);
+       }
+
+       /**
+        * Null-safe {@link String#contains(CharSequence)} operation.
+        */
+       public static boolean notContains(String s, char...values) {
+               return ! contains(s, values);
+       }
+
+       /**
+        * Returns the specified string, or null if that string is null or 
empty.
+        */
+       public static String nullIfEmpty(String value) {
+               return isEmpty(value) ? null : value;
+       }
+
+       /**
+        * Returns <jk>null</jk> if the specified string is <jk>null</jk> or 
empty.
+        *
+        * @param s The string to check.
+        * @return <jk>null</jk> if the specified string is <jk>null</jk> or 
empty, or the same string if not.
+        */
+       public static String nullIfEmpty3(String s) {
+               if (s == null || s.isEmpty())
+                       return null;
+               return s;
+       }
+
+       /**
+        * Returns an obfuscated version of the specified string.
+        */
+       public static String obfuscate(String s) {
+               if (s == null || s.length() < 2)
+                       return "*";
+               return s.substring(0, 1) + s.substring(1).replaceAll(".", "*"); 
 // NOSONAR
+       }
+
+       /**
+        * Shortcut for calling {@link Optional#ofNullable(Object)}.
+        */
+       public static final <T> Optional<T> opt(T t) {
+               return Optional.ofNullable(t);
+       }
+
+       public static final <T> Optional<T> opte() {
+               return Optional.empty();
+       }
+
+       /**
+        * Prints all the specified lines to System.out.
         */
-       public static String join(Object[] tokens, char d) {
-               if (tokens == null)
-                       return null;
-               if (tokens.length == 1)
-                       return emptyIfNull(s(tokens[0]));
-               return join(tokens, d, new StringBuilder()).toString();
+       public static final void printLines(String[] lines) {
+               for (var i = 0; i < lines.length; i++)
+                       System.out.println(String.format("%4s:" + lines[i], 
i+1)); // NOSONAR - NOT DEBUG
        }
 
        /**
-        * Join the specified tokens into a delimited string and writes the 
output to the specified string builder.
-        *
-        * @param tokens The tokens to join.
-        * @param d The delimiter.
-        * @param sb The string builder to append the response to.
-        * @return The same string builder passed in as <c>sb</c>.
+        * Shortcut for {@link #readable(Object)}
         */
-       public static StringBuilder join(Object[] tokens, char d, StringBuilder 
sb) {
-               if (tokens == null)
-                       return sb;
-               for (var i = 0; i < tokens.length; i++) {
-                       if (i > 0)
-                               sb.append(d);
-                       sb.append(tokens[i]);
+       public static String r(Object o) {
+               if (o instanceof Optional<?> o2)
+                       return r(o2.orElse(null));
+               if (o instanceof Collection<?> o2)
+                       return 
o2.stream().map(Utils::r).collect(joining(",","[","]"));
+               if (o instanceof Map<?,?> o2)
+                       return 
o2.entrySet().stream().map(Utils::r).collect(joining(",","{","}"));
+               if (o instanceof Map.Entry<?,?> o2)
+                       return r(o2.getKey()) + '=' + r(o2.getValue());
+               if (o instanceof GregorianCalendar o2)
+                       return 
o2.toZonedDateTime().format(DateTimeFormatter.ISO_INSTANT);
+               if (o instanceof Date o2)
+                       return o2.toInstant().toString();
+               if (o instanceof InputStream o2)
+                       return toHex(o2);
+               if (o instanceof Reader o2)
+                       return safe(()->IOUtils.read(o2));
+               if (o instanceof File o2)
+                       return safe(()->IOUtils.read(o2));
+               if (o instanceof byte[] o2)
+                       return toHex(o2);
+               if (o != null && o.getClass().isArray()) {
+                       var l = list();
+                       for (var i = 0; i < Array.getLength(o); i++) {
+                               l.add(Array.get(o, i));
+                       }
+                       return r(l);
                }
-               return sb;
+               return s(o);
        }
 
        /**
-        * Join the specified tokens into a delimited string.
-        *
-        * @param tokens The tokens to join.
-        * @param d The delimiter.
-        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        * Creates a {@link RuntimeException}.
         */
-       public static String join(int[] tokens, char d) {
-               if (tokens == null)
-                       return null;
-               var sb = new StringBuilder();
-               for (var i = 0; i < tokens.length; i++) {
-                       if (i > 0)
-                               sb.append(d);
-                       sb.append(tokens[i]);
-               }
-               return sb.toString();
+       public static RuntimeException runtimeException(String msg, 
Object...args) {
+               return new RuntimeException(args.length == 0 ? msg : f(msg, 
args));
        }
 
        /**
-        * Join the specified tokens into a delimited string.
-        *
-        * @param tokens The tokens to join.
-        * @param d The delimiter.
-        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        * Shortcut for converting an object to a string.
         */
-       public static String join(Collection<?> tokens, char d) {
-               if (tokens == null)
-                       return null;
-               var sb = new StringBuilder();
-               for (var iter = tokens.iterator(); iter.hasNext();) {
-                       sb.append(iter.next());
-                       if (iter.hasNext())
-                               sb.append(d);
-               }
-               return sb.toString();
+       public static String s(Object val) {
+               return val == null ? null : val.toString();
        }
 
        /**
-        * Join the specified tokens into a delimited string.
-        *
-        * @param tokens The tokens to join.
-        * @param d The delimiter.
-        * @return The delimited string.  If <c>tokens</c> is <jk>null</jk>, 
returns <jk>null</jk>.
+        * Used to wrap code that returns a value but throws an exception.
+        * Useful in cases where you're trying to execute code in a fluent 
method call
+        * or are trying to eliminate untestable catch blocks in code.
         */
-       public static String join(List<?> tokens, char d) {
-               if (tokens == null)
-                       return null;
-               var sb = new StringBuilder();
-               for (int i = 0, j = tokens.size(); i < j; i++) {
-                       if (i > 0)
-                               sb.append(d);
-                       sb.append(tokens.get(i));
+       public static <T> T safe(ThrowingSupplier<T> s) {
+               try {
+                       return s.get();
+               } catch (RuntimeException e) {
+                       throw e;
+               } catch (Exception e) {
+                       throw new RuntimeException(e);
                }
-               return sb.toString();
        }
 
        /**
-        * Joins tokens with newlines.
-        *
-        * @param tokens The tokens to concatenate.
-        * @return A string with the specified tokens contatenated with 
newlines.
+        * Shortcut for creating a modifiable set out of an array of values.
         */
-       public static String joinnl(Object[] tokens) {
-               return join(tokens, '\n');
+       @SafeVarargs
+       public static <T> LinkedHashSet<T> set(T...values) {  // NOSONAR
+               return new LinkedHashSet<>(Arrays.asList(values));
        }
 
        /**
-        * Shortcut for calling <code>split(s, <js>','</js>)</code>
-        *
-        * @param s The string to split.  Can be <jk>null</jk>.
-        * @return The tokens, or <jk>null</jk> if the string was null.
+        * Splits a comma-delimited list into a list of strings.
         */
-       public static String[] split3(String s) {
-               return split3(s, ',');
+       public static List<String> split(String s) {
+               return s == null ? Collections.emptyList() : Utils.split2(s);
        }
 
        /**
@@ -945,16 +915,6 @@ public class Utils {
                return split2(s, ',');
        }
 
-       /**
-        * Same as {@link #split3(String)} but consumes the tokens instead of 
creating an array.
-        *
-        * @param s The string to split.
-        * @param consumer The consumer of the tokens.
-        */
-       public static void split3(String s, Consumer<String> consumer) {
-               split3(s, ',', consumer);
-       }
-
        /**
         * Splits a character-delimited string into a string array.
         *
@@ -978,8 +938,62 @@ public class Utils {
         * @param c The character to split on.
         * @return The tokens, or <jk>null</jk> if the string was null.
         */
-       public static String[] split3(String s, char c) {
-               return split3(s, c, Integer.MAX_VALUE);
+       public static List<String> split2(String s, char c) {
+               return split2(s, c, Integer.MAX_VALUE);
+       }
+
+       /**
+        * Same as {@link #split3(String, char)} but limits the number of 
tokens returned.
+        *
+        * @param s The string to split.  Can be <jk>null</jk>.
+        * @param c The character to split on.
+        * @param limit The maximum number of tokens to return.
+        * @return The tokens, or <jk>null</jk> if the string was null.
+        */
+       public static List<String> split2(String s, char c, int limit) {
+
+               var escapeChars = StringUtils.getEscapeSet(c);
+
+               if (s == null)
+                       return null;  // NOSONAR - Intentional.
+               if (isEmpty(s))
+                       return Collections.emptyList();
+               if (s.indexOf(c) == -1)
+                       return Collections.singletonList(s);
+
+               var l = new LinkedList<String>();
+               var sArray = s.toCharArray();
+               var x1 = 0;
+               var escapeCount = 0;
+               limit--;
+               for (var i = 0; i < sArray.length && limit > 0; i++) {
+                       if (sArray[i] == '\\')
+                               escapeCount++;
+                       else if (sArray[i]==c && escapeCount % 2 == 0) {
+                               var s2 = new String(sArray, x1, i-x1);
+                               var s3 = StringUtils.unEscapeChars(s2, 
escapeChars);
+                               l.add(s3.trim());
+                               limit--;
+                               x1 = i+1;
+                       }
+                       if (sArray[i] != '\\')
+                               escapeCount = 0;
+               }
+               var s2 = new String(sArray, x1, sArray.length-x1);
+               var s3 = StringUtils.unEscapeChars(s2, escapeChars);
+               l.add(s3.trim());
+
+               return l;
+       }
+
+       /**
+        * Shortcut for calling <code>split(s, <js>','</js>)</code>
+        *
+        * @param s The string to split.  Can be <jk>null</jk>.
+        * @return The tokens, or <jk>null</jk> if the string was null.
+        */
+       public static String[] split3(String s) {
+               return split3(s, ',');
        }
 
        /**
@@ -1005,8 +1019,8 @@ public class Utils {
         * @param c The character to split on.
         * @return The tokens, or <jk>null</jk> if the string was null.
         */
-       public static List<String> split2(String s, char c) {
-               return split2(s, c, Integer.MAX_VALUE);
+       public static String[] split3(String s, char c) {
+               return split3(s, c, Integer.MAX_VALUE);
        }
 
        /**
@@ -1018,17 +1032,17 @@ public class Utils {
         */
        public static void split3(String s, char c, Consumer<String> consumer) {
                var escapeChars = StringUtils.getEscapeSet(c);
-       
-               if (Utils.isEmpty3(s))
+
+               if (isEmpty(s))
                        return;
                if (s.indexOf(c) == -1) {
                        consumer.accept(s);
                        return;
                }
-       
+
                var x1 = 0;
                var escapeCount = 0;
-       
+
                for (var i = 0; i < s.length(); i++) {
                        if (s.charAt(i) == '\\')
                                escapeCount++;
@@ -1060,47 +1074,13 @@ public class Utils {
        }
 
        /**
-        * Same as {@link #split3(String, char)} but limits the number of 
tokens returned.
+        * Same as {@link #split3(String)} but consumes the tokens instead of 
creating an array.
         *
-        * @param s The string to split.  Can be <jk>null</jk>.
-        * @param c The character to split on.
-        * @param limit The maximum number of tokens to return.
-        * @return The tokens, or <jk>null</jk> if the string was null.
+        * @param s The string to split.
+        * @param consumer The consumer of the tokens.
         */
-       public static List<String> split2(String s, char c, int limit) {
-       
-               var escapeChars = StringUtils.getEscapeSet(c);
-       
-               if (s == null)
-                       return null;  // NOSONAR - Intentional.
-               if (Utils.isEmpty3(s))
-                       return Collections.emptyList();
-               if (s.indexOf(c) == -1)
-                       return Collections.singletonList(s);
-       
-               var l = new LinkedList<String>();
-               var sArray = s.toCharArray();
-               var x1 = 0;
-               var escapeCount = 0;
-               limit--;
-               for (var i = 0; i < sArray.length && limit > 0; i++) {
-                       if (sArray[i] == '\\')
-                               escapeCount++;
-                       else if (sArray[i]==c && escapeCount % 2 == 0) {
-                               var s2 = new String(sArray, x1, i-x1);
-                               var s3 = StringUtils.unEscapeChars(s2, 
escapeChars);
-                               l.add(s3.trim());
-                               limit--;
-                               x1 = i+1;
-                       }
-                       if (sArray[i] != '\\')
-                               escapeCount = 0;
-               }
-               var s2 = new String(sArray, x1, sArray.length-x1);
-               var s3 = StringUtils.unEscapeChars(s2, escapeChars);
-               l.add(s3.trim());
-       
-               return l;
+       public static void split3(String s, Consumer<String> consumer) {
+               split3(s, ',', consumer);
        }
 
        /**
@@ -1123,6 +1103,13 @@ public class Utils {
                return l.toArray(new String[l.size()]);
        }
 
+       /**
+        * Splits a comma-delimited list into an array of strings.
+        */
+       public static String[] splita(String s) {
+               return s == null ? new String[0] : Utils.split3(s);
+       }
+
        /**
         * Splits a list of key-value pairs into an ordered map.
         *
@@ -1138,20 +1125,20 @@ public class Utils {
         * @return The parsed map, or null if the string was null.
         */
        public static Map<String,String> splitMap(String s, boolean trim) {
-       
+
                if (s == null)
                        return null;  // NOSONAR - Intentional.
-               if (Utils.isEmpty3(s))
+               if (isEmpty(s))
                        return Collections.emptyMap();
-       
+
                var m = new LinkedHashMap<String,String>();
-       
+
                final int
                        S1 = 1,  // Found start of key, looking for equals.
                        S2 = 2;  // Found equals, looking for delimiter (or 
end).
-       
+
                var state = S1;
-       
+
                var sArray = s.toCharArray();
                var x1 = 0;
                var escapeCount = 0;
@@ -1194,31 +1181,47 @@ public class Utils {
                        if (c != '\\')
                                escapeCount = 0;
                }
-       
+
                return m;
        }
 
        /**
-        * Splits a space-delimited string with optionally quoted arguments.
-        *
-        * <p>
-        * Examples:
-        * <ul>
-        *      <li><js>"foo"</js> =&gt; <c>["foo"]</c>
-        *      <li><js>" foo "</js> =&gt; <c>["foo"]</c>
-        *      <li><js>"foo bar baz"</js> =&gt; <c>["foo","bar","baz"]</c>
-        *      <li><js>"foo 'bar baz'"</js> =&gt; <c>["foo","bar baz"]</c>
-        *      <li><js>"foo \"bar baz\""</js> =&gt; <c>["foo","bar baz"]</c>
-        *      <li><js>"foo 'bar\'baz'"</js> =&gt; <c>["foo","bar'baz"]</c>
-        * </ul>
+        * Splits the method arguments in the signature of a method.
         *
-        * @param s The input string.
-        * @return
-        *      The results, or <jk>null</jk> if the input was <jk>null</jk>.
-        *      <br>An empty string results in an empty array.
+        * @param s The arguments to split.
+        * @return The split arguments, or null if the input string is null.
         */
-       public static String[] splitQuoted(String s) {
-               return splitQuoted(s, false);
+       public static String[] splitMethodArgs(String s) {
+
+               if (s == null)
+                       return null;  // NOSONAR - Intentional.
+               if (isEmpty(s))
+                       return new String[0];
+               if (s.indexOf(',') == -1)
+                       return new String[]{s};
+
+               var l = new LinkedList<String>();
+               var sArray = s.toCharArray();
+               var x1 = 0;
+               var paramDepth = 0;
+
+               for (var i = 0; i < sArray.length; i++) {
+                       var c = s.charAt(i);
+                       if (c == '>')
+                               paramDepth++;
+                       else if (c == '<')
+                               paramDepth--;
+                       else if (c == ',' && paramDepth == 0) {
+                               var s2 = new String(sArray, x1, i-x1);
+                               l.add(s2.trim());
+                               x1 = i+1;
+                       }
+               }
+
+               var s2 = new String(sArray, x1, sArray.length-x1);
+               l.add(s2.trim());
+
+               return l.toArray(new String[l.size()]);
        }
 
        /**
@@ -1237,17 +1240,17 @@ public class Utils {
         */
        public static List<String> splitNested(String s) {
                var escapeChars = StringUtils.getEscapeSet(',');
-       
+
                if (s == null) return null;  // NOSONAR - Intentional.
-               if (Utils.isEmpty3(s)) return Collections.emptyList();
+               if (isEmpty(s)) return Collections.emptyList();
                if (s.indexOf(',') == -1) return 
Collections.singletonList(StringUtils.trim(s));
-       
+
                var l = new LinkedList<String>();
-       
+
                var x1 = 0;
                var inEscape = false;
                var depthCount = 0;
-       
+
                for (var i = 0; i < s.length(); i++) {
                        var c = s.charAt(i);
                        if (inEscape) {
@@ -1268,7 +1271,7 @@ public class Utils {
                        }
                }
                
l.add(StringUtils.trim(StringUtils.unEscapeChars(s.substring(x1, s.length()), 
escapeChars)));
-       
+
                return l;
        }
 
@@ -1288,18 +1291,18 @@ public class Utils {
         */
        public static List<String> splitNestedInner(String s) {
                if (s == null) throw illegalArg("String was null.");
-               if (Utils.isEmpty3(s)) throw illegalArg("String was empty.");
-       
+               if (isEmpty(s)) throw illegalArg("String was empty.");
+
                final int
                        S1 = 1,  // Looking for '{'
                        S2 = 2;  // Found '{', looking for '}'
-       
+
                var start = -1;
                var end = -1;
                var state = S1;
                var depth = 0;
                var inEscape = false;
-       
+
                for (var i = 0; i < s.length(); i++) {
                        var c = s.charAt(i);
                        if (inEscape) {
@@ -1326,12 +1329,35 @@ public class Utils {
                                }
                        }
                }
-       
+
                if (start == -1) throw illegalArg("Start character '{' not 
found in string.", s);
                if (end == -1) throw illegalArg("End character '}' not found in 
string.", s);
                return splitNested(s.substring(start, end));
        }
 
+       /**
+        * Splits a space-delimited string with optionally quoted arguments.
+        *
+        * <p>
+        * Examples:
+        * <ul>
+        *      <li><js>"foo"</js> =&gt; <c>["foo"]</c>
+        *      <li><js>" foo "</js> =&gt; <c>["foo"]</c>
+        *      <li><js>"foo bar baz"</js> =&gt; <c>["foo","bar","baz"]</c>
+        *      <li><js>"foo 'bar baz'"</js> =&gt; <c>["foo","bar baz"]</c>
+        *      <li><js>"foo \"bar baz\""</js> =&gt; <c>["foo","bar baz"]</c>
+        *      <li><js>"foo 'bar\'baz'"</js> =&gt; <c>["foo","bar'baz"]</c>
+        * </ul>
+        *
+        * @param s The input string.
+        * @return
+        *      The results, or <jk>null</jk> if the input was <jk>null</jk>.
+        *      <br>An empty string results in an empty array.
+        */
+       public static String[] splitQuoted(String s) {
+               return splitQuoted(s, false);
+       }
+
        /**
         * Same as {@link #splitQuoted(String)} but allows you to optionally 
keep the quote characters.
         *
@@ -1342,34 +1368,34 @@ public class Utils {
         *      <br>An empty string results in an empty array.
         */
        public static String[] splitQuoted(String s, boolean keepQuotes) {
-       
+
                if (s == null)
                        return null;  // NOSONAR - Intentional.
-       
+
                s = s.trim();
-       
-               if (Utils.isEmpty3(s))
+
+               if (isEmpty(s))
                        return new String[0];
-       
+
                if (! StringUtils.containsAny(s, ' ', '\t', '\'', '"'))
                        return new String[]{s};
-       
+
                final int
                        S1 = 1,  // Looking for start of token.
                        S2 = 2,  // Found ', looking for end '
                        S3 = 3,  // Found ", looking for end "
                        S4 = 4;  // Found non-whitespace, looking for end 
whitespace.
-       
+
                var state = S1;
-       
+
                var isInEscape = false;
                var needsUnescape = false;
                var mark = 0;
-       
+
                var l = new ArrayList<String>();
                for (var i = 0; i < s.length(); i++) {
                        var c = s.charAt(i);
-       
+
                        if (state == S1) {
                                if (c == '\'') {
                                        state = S2;
@@ -1412,139 +1438,91 @@ public class Utils {
        }
 
        /**
-        * Splits the method arguments in the signature of a method.
-        *
-        * @param s The arguments to split.
-        * @return The split arguments, or null if the input string is null.
+        * Converts an array to a stream of objects.
+        * @param array The array to convert.
+        * @return A new stream.
         */
-       public static String[] splitMethodArgs(String s) {
-       
-               if (s == null)
-                       return null;  // NOSONAR - Intentional.
-               if (Utils.isEmpty3(s))
-                       return new String[0];
-               if (s.indexOf(',') == -1)
-                       return new String[]{s};
-       
-               var l = new LinkedList<String>();
-               var sArray = s.toCharArray();
-               var x1 = 0;
-               var paramDepth = 0;
-       
-               for (var i = 0; i < sArray.length; i++) {
-                       var c = s.charAt(i);
-                       if (c == '>')
-                               paramDepth++;
-                       else if (c == '<')
-                               paramDepth--;
-                       else if (c == ',' && paramDepth == 0) {
-                               var s2 = new String(sArray, x1, i-x1);
-                               l.add(s2.trim());
-                               x1 = i+1;
-                       }
+       public static Stream<Object> toStream(Object array) {
+               if (array == null || ! array.getClass().isArray()) {
+                       throw illegalArg("Not an array: " + array);
                }
-       
-               var s2 = new String(sArray, x1, sArray.length-x1);
-               l.add(s2.trim());
-       
-               return l.toArray(new String[l.size()]);
+               var length = Array.getLength(array);
+               return IntStream.range(0, length).mapToObj(i -> 
Array.get(array, i));
        }
 
-       /**
-        * Returns <jk>true</jk> if specified string is <jk>null</jk> or empty.
-        *
-        * @param s The string to check.
-        * @return <jk>true</jk> if specified string is <jk>null</jk> or empty.
-        */
-       public static boolean isEmpty3(String s) {
-               return s == null || s.isEmpty();
+       @SuppressWarnings("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 runtimeException("Invalid env type: {0}", c);
+               return f.apply(s);
        }
 
        /**
-        * Returns <jk>true</jk> if specified charsequence is <jk>null</jk> or 
empty.
+        * Traverses all elements in the specified object and executes a 
consumer for it.
         *
-        * @param s The string to check.
-        * @return <jk>true</jk> if specified charsequence is <jk>null</jk> or 
empty.
+        * @param <T> The element type.
+        * @param o The object to traverse.
+        * @param c The consumer of the objects.
         */
-       public static boolean isEmpty3(CharSequence s) {
-               return s == null || s.isEmpty();
+       public static <T> void traverse(Object o, Consumer<T> c) {
+               if (o == null)
+                       return;
+               if (o instanceof Iterable<?> o2)
+                       o2.forEach(x -> traverse(x, c));
+               else if (o instanceof Stream<?> o2)
+                       o2.forEach(x -> traverse(x, c));
+               else if (o.getClass().isArray())
+                       toStream(o).forEach(x -> traverse(x, c));
+               else
+                       c.accept((T)o);
        }
 
-       /**
-        * Returns <jk>true</jk> if specified string is <jk>null</jk> or empty 
or consists of only blanks.
-        *
-        * @param s The string to check.
-        * @return <jk>true</jk> if specified string is <jk>null</jk> or 
emptyor consists of only blanks.
-        */
-       public static boolean isEmptyOrBlank3(String s) {
-               return s == null || s.trim().isEmpty();
+       public static <T> List<T> u(List<? extends T> value) {
+               return value == null ? null : 
Collections.unmodifiableList(value);
        }
 
-       /**
-        * Returns <jk>true</jk> if specified string is not <jk>null</jk> or 
empty.
-        *
-        * @param s The string to check.
-        * @return <jk>true</jk> if specified string is not <jk>null</jk> or 
empty.
-        */
-       public static boolean isNotEmpty3(String s) {
-               return ! isEmpty3(s);
+       public static <K,V> Map<K,V> u(Map<? extends K, ? extends V> value) {
+               return value == null ? null : 
Collections.unmodifiableMap(value);
        }
 
-       /**
-        * Returns <jk>true</jk> if either of the specified strings are not 
<jk>null</jk> or empty.
-        *
-        * @param s1 The string to check.
-        * @param s2 The string to check.
-        * @return <jk>true</jk> if either of the specified strings are not 
<jk>null</jk> or empty.
-        */
-       public static boolean isNotEmpty3(String s1, String s2) {
-               return isNotEmpty3(s1) || isNotEmpty3(s2);
+       public static <T> Set<T> u(Set<? extends T> value) {
+               return value == null ? null : 
Collections.unmodifiableSet(value);
        }
 
        /**
-        * Returns <jk>null</jk> if the specified string is <jk>null</jk> or 
empty.
+        * Convenience method for creating an unmodifiable list.
         *
-        * @param s The string to check.
-        * @return <jk>null</jk> if the specified string is <jk>null</jk> or 
empty, or the same string if not.
+        * @param <E> The element type.
+        * @param values The values to initialize the list with.
+        * @return A new unmodifiable list, or <jk>null</jk> if the array was 
<jk>null</jk>.
         */
-       public static String nullIfEmpty3(String s) {
-               if (s == null || s.isEmpty())
+       @SafeVarargs
+       public static <E> List<E> ulist2(E...values) {
+               if (values == null)
                        return null;
-               return s;
+               return u(alist(values));
        }
 
        /**
-        * Converts a string containing <js>"*"</js> meta characters with a 
regular expression pattern.
+        * Convenience method for creating an unmodifiable {@link 
LinkedHashSet}.
         *
-        * @param s The string to create a pattern from.
-        * @return A regular expression pattern.
+        * @param <E> The element type.
+        * @param values The values to initialize the set with.
+        * @return A new unmodifiable set.
         */
-       public static Pattern getMatchPattern3(String s) {
-               return getMatchPattern3(s, 0);
+       @SafeVarargs
+       public static <E> Set<E> uset2(E...values) {
+               return u(set(values));
        }
 
-       /**
-        * Converts a string containing <js>"*"</js> meta characters with a 
regular expression pattern.
-        *
-        * @param s The string to create a pattern from.
-        * @param flags Regular expression flags.
-        * @return A regular expression pattern.
-        */
-       public static Pattern getMatchPattern3(String s, int flags) {
-               if (s == null)
-                       return null;
-               var sb = new StringBuilder();
-               sb.append("\\Q");
-               for (var i = 0; i < s.length(); i++) {
-                       var c = s.charAt(i);
-                       if (c == '*')
-                               sb.append("\\E").append(".*").append("\\Q");
-                       else if (c == '?')
-                               sb.append("\\E").append(".").append("\\Q");
-                       else
-                               sb.append(c);
-               }
-               sb.append("\\E");
-               return Pattern.compile(sb.toString(), flags);
-       }
+       /** Constructor */
+       protected Utils() {}
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java 
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
index 48f27c5e8..b48ccb290 100644
--- 
a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
+++ 
b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Entry.java
@@ -560,7 +560,7 @@ public class Entry {
        
//-----------------------------------------------------------------------------------------------------------------
 
        private boolean isEmpty() {
-               return Utils.isEmpty3(value);
+               return Utils.isEmpty(value);
        }
 
        private boolean isNull() {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationApplier.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationApplier.java
index 6a0a8f3f8..648bf1f25 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationApplier.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/AnnotationApplier.java
@@ -143,7 +143,7 @@ public abstract class AnnotationApplier<A extends 
Annotation, B> {
         */
        protected Optional<String> string(String in) {
                in = vr.resolve(in);
-               return Utils.opt(Utils.isEmpty3(in) ? null : in);
+               return Utils.opt(Utils.isEmpty(in) ? null : in);
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
index 9670e7699..d4d7371b3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseSession.java
@@ -344,7 +344,7 @@ public class BeanTraverseSession extends BeanSession {
 
                String toString(boolean simple) {
                        StringBuilder sb = new 
StringBuilder().append('[').append(depth).append(']').append(' ');
-                       sb.append(Utils.isEmpty3(name) ? "<noname>" : 
name).append(':');
+                       sb.append(Utils.isEmpty(name) ? "<noname>" : 
name).append(':');
                        sb.append(aType.toString(simple));
                        if (aType != 
aType.getSerializedClassMeta(BeanTraverseSession.this))
                                
sb.append('/').append(aType.getSerializedClassMeta(BeanTraverseSession.this).toString(simple));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDLC.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDLC.java
index eaca636b7..84d022477 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDLC.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDLC.java
@@ -35,7 +35,7 @@ public final class PropertyNamerDLC implements PropertyNamer {
 
        @Override /* PropertyNamer */
        public String getPropertyName(String name) {
-               if (Utils.isEmpty3(name))
+               if (Utils.isEmpty(name))
                        return name;
 
                int numUCs = 0;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDUCS.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDUCS.java
index d86301496..6af7f3492 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDUCS.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerDUCS.java
@@ -35,7 +35,7 @@ public final class PropertyNamerDUCS implements PropertyNamer 
{
 
        @Override /* PropertyNamer */
        public String getPropertyName(String name) {
-               if (Utils.isEmpty3(name))
+               if (Utils.isEmpty(name))
                        return name;
 
                int numUCs = 0;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerULC.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerULC.java
index a1b00f81b..90acae8b5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerULC.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/PropertyNamerULC.java
@@ -35,7 +35,7 @@ public final class PropertyNamerULC implements PropertyNamer {
 
        @Override /* PropertyNamer */
        public String getPropertyName(String name) {
-               if (Utils.isEmpty3(name))
+               if (Utils.isEmpty(name))
                        return name;
 
                int numUCs = 0;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Version.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Version.java
index 586f31937..c28ce4a3f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Version.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Version.java
@@ -66,7 +66,7 @@ public class Version implements Comparable<Version> {
         *      Any parts that are not numeric are interpreted as {@link 
Integer#MAX_VALUE}
         */
        public Version(String value) {
-               if (Utils.isEmpty3(value))
+               if (Utils.isEmpty(value))
                        value = "0";
                String[] sParts = Utils.split3(value, '.');
                parts = new int[sParts.length];
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
index d01b7a5b7..898264735 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonList.java
@@ -125,7 +125,7 @@ public class JsonList extends LinkedList<Object> {
         * @throws ParseException Malformed input encountered.
         */
        public static JsonList ofJsonOrCdl(String s) throws ParseException {
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return null;
                if (! StringUtils.isJsonArray(s, true))
                        return new JsonList((Object[])Utils.split3(s.trim(), 
','));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
index da527e7b5..1ac982bbd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/collections/JsonMap.java
@@ -326,7 +326,7 @@ public class JsonMap extends LinkedHashMap<String,Object> {
                this(p == null ? BeanContext.DEFAULT_SESSION : 
p.getBeanContext().getSession());
                if (p == null)
                        p = JsonParser.DEFAULT;
-               if (! Utils.isEmpty3(in))
+               if (! Utils.isEmpty(in))
                        p.parseIntoMap(in, this, bs().string(), bs().object());
        }
 
@@ -1309,7 +1309,7 @@ public class JsonMap extends LinkedHashMap<String,Object> 
{
                if (val == null)
                        return false;
                if (val instanceof CharSequence)
-                       return ! Utils.isEmpty3((CharSequence)val);
+                       return ! Utils.isEmpty((CharSequence)val);
                return false;
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
index 548d495f0..7b374cf0b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
@@ -238,7 +238,7 @@ public class BasicFileFinder implements FileFinder {
         * @return <jk>true</jk> if the path is invalid.
         */
        protected boolean isInvalidPath(String path) {
-               return Utils.isEmpty3(path) || path.contains("..") || 
path.contains("%");
+               return Utils.isEmpty(path) || path.contains("..") || 
path.contains("%");
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
index 6e7d3e762..95b285311 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
@@ -354,7 +354,7 @@ public class BeanStore {
                BeanStoreEntry<T> e = createEntry(beanType, bean, name);
                try (SimpleLock x = lock.write()) {
                        entries.addFirst(e);
-                       if (Utils.isEmpty3(name))
+                       if (Utils.isEmpty(name))
                                unnamedEntries.put(beanType, e);
                }
                return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
index 7f6375d02..63410f5f6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/DateUtils.java
@@ -67,7 +67,7 @@ public final class DateUtils {
         * @return The parsed value, or <jk>null</jk> if the string was 
<jk>null</jk> or empty.
         */
        public static Calendar parseISO8601Calendar(String s) {
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return null;
                return DatatypeConverter.parseDateTime(toValidISO8601DT(s));
        }
@@ -218,7 +218,7 @@ public final class DateUtils {
         * @return The formatter.
         */
        public static DateTimeFormatter getFormatter(String pattern) {
-               if (Utils.isEmpty3(pattern))
+               if (Utils.isEmpty(pattern))
                        return DateTimeFormatter.ISO_INSTANT;
                try {
                        FieldInfo fi = 
ClassInfo.of(DateTimeFormatter.class).getPublicField(x -> x.isStatic() && 
x.hasName(pattern));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileUtils.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileUtils.java
index 3919905bd..fd50f7d4d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileUtils.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/FileUtils.java
@@ -234,7 +234,7 @@ public class FileUtils {
         * @return The file name.
         */
        public static String getFileName(String path) {
-               if (Utils.isEmpty3(path))
+               if (Utils.isEmpty(path))
                        return null;
                path = trimTrailingSlashes(path);
                int i = path.lastIndexOf('/');
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/VersionRange.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/VersionRange.java
index 5dbbff986..d5681710f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/VersionRange.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/VersionRange.java
@@ -68,7 +68,7 @@ public class VersionRange {
         * @return <jk>true</jk> if the specified version string matches this 
version range.
         */
        public boolean matches(String v) {
-               if (Utils.isEmpty3(v))
+               if (Utils.isEmpty(v))
                        return (minVersion == null && maxVersion == null);
                Version ver = new Version(v);
                if ((minVersion != null && ! ver.isAtLeast(minVersion, 
minExclusive)) || (maxVersion != null && ! ver.isAtMost(maxVersion, 
maxExclusive)))
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/XMLGregorianCalendarSwap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/XMLGregorianCalendarSwap.java
index 1bdf9eae4..b3a7749ed 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/XMLGregorianCalendarSwap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/XMLGregorianCalendarSwap.java
@@ -61,7 +61,7 @@ public class XMLGregorianCalendarSwap extends 
StringSwap<XMLGregorianCalendar> {
         */
        @Override /* ObjectSwap */
        public XMLGregorianCalendar unswap(BeanSession session, String s, 
ClassMeta<?> hint) throws Exception {
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return null;
                return dtf.newXMLGregorianCalendar(s);
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ReflectionMap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ReflectionMap.java
index 0ce533761..1a18e8aef 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ReflectionMap.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ReflectionMap.java
@@ -197,7 +197,7 @@ public class ReflectionMap<V> {
                 * @return This object.
                 */
                public Builder<V> append(String key, V value) {
-                       if (Utils.isEmpty3(key))
+                       if (Utils.isEmpty(key))
                                throw new BasicRuntimeException("Invalid 
reflection signature: [{0}]", key);
                        try {
                                splitNames(key, k -> {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringExpressionMatcher.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringExpressionMatcher.java
index 423db594c..2bdbb116b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringExpressionMatcher.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/StringExpressionMatcher.java
@@ -94,7 +94,7 @@ public class StringExpressionMatcher {
        }
 
        private Exp parse(String expression) throws ParseException {
-               if (Utils.isEmptyOrBlank3(expression))
+               if (Utils.isEmptyOrBlank(expression))
                        return new Never();
 
                expression = expression.trim();
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
index 45d8af0b4..9d1a8a85e 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestRequest.java
@@ -1490,10 +1490,10 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        
//------------------------------------------------------------------------------------------------------------------
 
        RestRequest headerArg(String name, Object value, HttpPartSchema schema, 
HttpPartSerializer serializer, boolean skipIfEmpty) {
-               boolean isMulti = Utils.isEmpty3(name) || "*".equals(name) || 
value instanceof HeaderList || isHeaderArray(value);
+               boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof HeaderList || isHeaderArray(value);
 
                if (! isMulti) {
-                       if (! (skipIfEmpty && Utils.isEmpty3(Utils.s(value))))
+                       if (! (skipIfEmpty && isEmpty(Utils.s(value))))
                                return header(createHeader(name, value, 
serializer, schema, skipIfEmpty));
                        return this;
                }
@@ -1518,7 +1518,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                }
 
                if (skipIfEmpty)
-                       l.removeIf(x -> Utils.isEmpty3(x.getValue()));
+                       l.removeIf(x -> isEmpty(x.getValue()));
 
                headerData.append(l);
 
@@ -1526,10 +1526,10 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        }
 
        RestRequest queryArg(String name, Object value, HttpPartSchema schema, 
HttpPartSerializer serializer, boolean skipIfEmpty) {
-               boolean isMulti = Utils.isEmpty3(name) || "*".equals(name) || 
value instanceof PartList || isNameValuePairArray(value);
+               boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof PartList || isNameValuePairArray(value);
 
                if (! isMulti) {
-                       if (! (skipIfEmpty && Utils.isEmpty3(Utils.s(value))))
+                       if (! (skipIfEmpty && isEmpty(Utils.s(value))))
                                return queryData(createPart(name, value, QUERY, 
serializer, schema, skipIfEmpty));
                        return this;
                }
@@ -1555,7 +1555,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                }
 
                if (skipIfEmpty)
-                       l.removeIf(x -> Utils.isEmpty3(x.getValue()));
+                       l.removeIf(x -> isEmpty(x.getValue()));
 
                queryData.append(l);
 
@@ -1563,10 +1563,10 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        }
 
        RestRequest formDataArg(String name, Object value, HttpPartSchema 
schema, HttpPartSerializer serializer, boolean skipIfEmpty) {
-               boolean isMulti = Utils.isEmpty3(name) || "*".equals(name) || 
value instanceof PartList || isNameValuePairArray(value);
+               boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof PartList || isNameValuePairArray(value);
 
                if (! isMulti) {
-                       if (! (skipIfEmpty && Utils.isEmpty3(Utils.s(value))))
+                       if (! (skipIfEmpty && isEmpty(Utils.s(value))))
                                return formData(createPart(name, value, 
FORMDATA, serializer, schema, skipIfEmpty));
                        return this;
                }
@@ -1592,7 +1592,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                }
 
                if (skipIfEmpty)
-                       l.removeIf(x -> Utils.isEmpty3(x.getValue()));
+                       l.removeIf(x -> isEmpty(x.getValue()));
 
                formData.append(l);
 
@@ -1600,7 +1600,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
        }
 
        RestRequest pathArg(String name, Object value, HttpPartSchema schema, 
HttpPartSerializer serializer) {
-               boolean isMulti = Utils.isEmpty3(name) || "*".equals(name) || 
value instanceof PartList || isNameValuePairArray(value);
+               boolean isMulti = isEmpty(name) || "*".equals(name) || value 
instanceof PartList || isNameValuePairArray(value);
 
                if (! isMulti)
                        return pathData(createPart(name, value, PATH, 
serializer, schema, false));
@@ -2505,7 +2505,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                Header h = request.getFirstHeader("Content-Type");
                if (h != null) {
                        String s = h.getValue();
-                       if (! Utils.isEmpty3(s))
+                       if (! isEmpty(s))
                                return ContentType.of(s);
                }
                return def;
@@ -2527,7 +2527,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @return A new header.
         */
        protected Header createHeader(String name, Object value, 
HttpPartSerializer serializer, HttpPartSchema schema, Boolean skipIfEmpty) {
-               if (Utils.isEmpty3(name))
+               if (isEmpty(name))
                        return null;
                if (skipIfEmpty == null)
                        skipIfEmpty = client.isSkipEmptyHeaderData();
@@ -2552,7 +2552,7 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
         * @return A new part.
         */
        protected NameValuePair createPart(String name, Object value, 
HttpPartType type, HttpPartSerializer serializer, HttpPartSchema schema, 
Boolean skipIfEmpty) {
-               if (Utils.isEmpty3(name))
+               if (isEmpty(name))
                        return null;
                if (skipIfEmpty == null) {
                        if (type == QUERY)
@@ -2620,12 +2620,12 @@ public class RestRequest extends BeanSession implements 
HttpUriRequest, Configur
                                value = 
((SerializedPart)x).copyWith(getPartSerializerSession(), null).getValue();
                        } else {
                                String v = x.getValue();
-                               value = (Utils.isEmpty3(v) && skipIfEmpty) ? 
null : v;
+                               value = (isEmpty(v) && skipIfEmpty) ? null : v;
                        }
                }
 
                boolean isValid() {
-                       if (Utils.isEmpty3(name) || value == null)
+                       if (isEmpty(name) || value == null)
                                return false;
                        return true;
                }
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
index b034088a4..97ff2ff8a 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestResponse.java
@@ -197,7 +197,7 @@ public class RestResponse implements HttpResponse {
                String s = null;
                if (ct.isPresent())
                        s = getContentType().get().getParameter("charset");
-               return Utils.isEmpty3(s) ? "utf-8" : s;
+               return Utils.isEmpty(s) ? "utf-8" : s;
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
index 5f0fdf672..413649d0c 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicBooleanHeader.java
@@ -111,7 +111,7 @@ public class BasicBooleanHeader extends BasicHeader {
         */
        public BasicBooleanHeader(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : 
Boolean.valueOf(value);
+               this.value = Utils.isEmpty(value) ? null : 
Boolean.valueOf(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
index 84a905344..21ab725d9 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicDateHeader.java
@@ -110,7 +110,7 @@ public class BasicDateHeader extends BasicHeader {
         */
        public BasicDateHeader(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : 
ZonedDateTime.from(RFC_1123_DATE_TIME.parse(value.toString())).truncatedTo(SECONDS);
+               this.value = Utils.isEmpty(value) ? null : 
ZonedDateTime.from(RFC_1123_DATE_TIME.parse(value.toString())).truncatedTo(SECONDS);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
index 530710ee2..117eac1d6 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/BasicUriHeader.java
@@ -107,7 +107,7 @@ public class BasicUriHeader extends BasicHeader {
         */
        public BasicUriHeader(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null :  URI.create(value);
+               this.value = Utils.isEmpty(value) ? null :  URI.create(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/EntityTags.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/EntityTags.java
index 9fa0cabd4..76f533375 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/EntityTags.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/EntityTags.java
@@ -39,7 +39,7 @@ public class EntityTags {
         * @return A parsed header value.
         */
        public static EntityTags of(String value) {
-               return Utils.isEmpty3(value) ? EMPTY : CACHE.get(value, ()->new 
EntityTags(value));
+               return Utils.isEmpty(value) ? EMPTY : CACHE.get(value, ()->new 
EntityTags(value));
        }
 
        /**
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/SerializedHeader.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/SerializedHeader.java
index 87ceb875b..a740e496d 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/SerializedHeader.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/header/SerializedHeader.java
@@ -288,7 +288,7 @@ public class SerializedHeader extends BasicHeader {
                                if ((def == null && ! schema.isRequired()) || 
(def == null && schema.isAllowEmptyValue()))
                                        return null;
                        }
-                       if (Utils.isEmpty3(Utils.s(v)) && skipIfEmpty && def == 
null)
+                       if (Utils.isEmpty(Utils.s(v)) && skipIfEmpty && def == 
null)
                                return null;
                        return serializer == null ? Utils.s(v) : 
serializer.serialize(HttpPartType.HEADER, schema, v);
                } catch (SchemaValidationException e) {
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicBooleanPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicBooleanPart.java
index d9e277754..2ee46aef9 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicBooleanPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicBooleanPart.java
@@ -40,7 +40,7 @@ public class BasicBooleanPart extends BasicPart {
         * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if 
the name or value is <jk>null</jk>.
         */
        public static BasicBooleanPart of(String name, Boolean value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicBooleanPart(name, value);
        }
@@ -56,7 +56,7 @@ public class BasicBooleanPart extends BasicPart {
         * @return A new {@link BasicBooleanPart} object, or <jk>null</jk> if 
the name or supplier is <jk>null</jk>.
         */
        public static BasicBooleanPart of(String name, Supplier<Boolean> value) 
{
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicBooleanPart(name, value);
        }
@@ -104,7 +104,7 @@ public class BasicBooleanPart extends BasicPart {
         */
        public BasicBooleanPart(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : 
Boolean.valueOf(value);
+               this.value = Utils.isEmpty(value) ? null : 
Boolean.valueOf(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicCsvArrayPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicCsvArrayPart.java
index 953ac894a..f8c810976 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicCsvArrayPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicCsvArrayPart.java
@@ -43,7 +43,7 @@ public class BasicCsvArrayPart extends BasicPart {
         * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if 
the name or value is <jk>null</jk>.
         */
        public static BasicCsvArrayPart of(String name, String...value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicCsvArrayPart(name, value);
        }
@@ -59,7 +59,7 @@ public class BasicCsvArrayPart extends BasicPart {
         * @return A new {@link BasicCsvArrayPart} object, or <jk>null</jk> if 
the name or supplier is <jk>null</jk>.
         */
        public static BasicCsvArrayPart of(String name, Supplier<String[]> 
value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicCsvArrayPart(name, value);
        }
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicDatePart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicDatePart.java
index 6c48f3687..8acf0a6f7 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicDatePart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicDatePart.java
@@ -44,7 +44,7 @@ public class BasicDatePart extends BasicPart {
         * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the 
name or value is <jk>null</jk>.
         */
        public static BasicDatePart of(String name, ZonedDateTime value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicDatePart(name, value);
        }
@@ -60,7 +60,7 @@ public class BasicDatePart extends BasicPart {
         * @return A new {@link BasicDatePart} object, or <jk>null</jk> if the 
name or supplier is <jk>null</jk>.
         */
        public static BasicDatePart of(String name, Supplier<ZonedDateTime> 
value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicDatePart(name, value);
        }
@@ -108,7 +108,7 @@ public class BasicDatePart extends BasicPart {
         */
        public BasicDatePart(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : 
ZonedDateTime.from(ISO_DATE_TIME.parse(value)).truncatedTo(SECONDS);
+               this.value = Utils.isEmpty(value) ? null : 
ZonedDateTime.from(ISO_DATE_TIME.parse(value)).truncatedTo(SECONDS);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicIntegerPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicIntegerPart.java
index 35365d8c5..38d5ee8b3 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicIntegerPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicIntegerPart.java
@@ -40,7 +40,7 @@ public class BasicIntegerPart extends BasicPart {
         * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if 
the name or value is <jk>null</jk>.
         */
        public static BasicIntegerPart of(String name, Integer value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicIntegerPart(name, value);
        }
@@ -56,7 +56,7 @@ public class BasicIntegerPart extends BasicPart {
         * @return A new {@link BasicIntegerPart} object, or <jk>null</jk> if 
the name or supplier is <jk>null</jk>.
         */
        public static BasicIntegerPart of(String name, Supplier<Integer> value) 
{
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicIntegerPart(name, value);
        }
@@ -104,7 +104,7 @@ public class BasicIntegerPart extends BasicPart {
         */
        public BasicIntegerPart(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : 
Integer.valueOf(value);
+               this.value = Utils.isEmpty(value) ? null : 
Integer.valueOf(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicLongPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicLongPart.java
index 8a15cfcb4..47b6672a1 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicLongPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicLongPart.java
@@ -40,7 +40,7 @@ public class BasicLongPart extends BasicPart {
         * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the 
name or value is <jk>null</jk>.
         */
        public static BasicLongPart of(String name, Long value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicLongPart(name, value);
        }
@@ -56,7 +56,7 @@ public class BasicLongPart extends BasicPart {
         * @return A new {@link BasicLongPart} object, or <jk>null</jk> if the 
name or supplier is <jk>null</jk>.
         */
        public static BasicLongPart of(String name, Supplier<Long> value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicLongPart(name, value);
        }
@@ -105,7 +105,7 @@ public class BasicLongPart extends BasicPart {
         */
        public BasicLongPart(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : Long.valueOf(value);
+               this.value = Utils.isEmpty(value) ? null : Long.valueOf(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicStringPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicStringPart.java
index 4cc0dcbf9..eb57fe0dc 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicStringPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicStringPart.java
@@ -40,7 +40,7 @@ public class BasicStringPart extends BasicPart {
         * @return A new {@link BasicStringPart} object, or <jk>null</jk> if 
the name or value is <jk>null</jk>.
         */
        public static BasicStringPart of(String name, String value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicStringPart(name, value);
        }
@@ -56,7 +56,7 @@ public class BasicStringPart extends BasicPart {
         * @return A new {@link BasicStringPart} object, or <jk>null</jk> if 
the name or supplier is <jk>null</jk>.
         */
        public static BasicStringPart of(String name, Supplier<String> value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicStringPart(name, value);
        }
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicUriPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicUriPart.java
index 28588ccf9..c95d33e8e 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicUriPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/BasicUriPart.java
@@ -40,7 +40,7 @@ public class BasicUriPart extends BasicPart {
         * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the 
name or value is <jk>null</jk>.
         */
        public static BasicUriPart of(String name, URI value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicUriPart(name, value);
        }
@@ -56,7 +56,7 @@ public class BasicUriPart extends BasicPart {
         * @return A new {@link BasicUriPart} object, or <jk>null</jk> if the 
name or supplier is <jk>null</jk>.
         */
        public static BasicUriPart of(String name, Supplier<URI> value) {
-               if (Utils.isEmpty3(name) || value == null)
+               if (Utils.isEmpty(name) || value == null)
                        return null;
                return new BasicUriPart(name, value);
        }
@@ -104,7 +104,7 @@ public class BasicUriPart extends BasicPart {
         */
        public BasicUriPart(String name, String value) {
                super(name, value);
-               this.value = Utils.isEmpty3(value) ? null : URI.create(value);
+               this.value = Utils.isEmpty(value) ? null : URI.create(value);
                this.supplier = null;
        }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/SerializedPart.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/SerializedPart.java
index 0d628a4b6..a79da9a5e 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/SerializedPart.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/part/SerializedPart.java
@@ -219,7 +219,7 @@ public class SerializedPart extends BasicPart {
                                if ((def == null && ! schema.isRequired()) || 
(def == null && schema.isAllowEmptyValue()))
                                        return null;
                        }
-                       if (Utils.isEmpty3(Utils.s(v)) && skipIfEmpty && def == 
null)
+                       if (Utils.isEmpty(Utils.s(v)) && skipIfEmpty && def == 
null)
                                return null;
                        return serializer == null ? Utils.s(v) : 
serializer.serialize(type, schema, v);
                } catch (SchemaValidationException e) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/guard/RoleMatcher.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/guard/RoleMatcher.java
index cc0a5572c..cebf29866 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/guard/RoleMatcher.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/guard/RoleMatcher.java
@@ -95,7 +95,7 @@ public class RoleMatcher {
        }
 
        private Exp parse(String expression) throws ParseException {
-               if (Utils.isEmptyOrBlank3(expression))
+               if (Utils.isEmptyOrBlank(expression))
                        return new Never();
 
                expression = expression.trim();
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestContent.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestContent.java
index c067b106a..09f5723af 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestContent.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestContent.java
@@ -532,7 +532,7 @@ public class RequestContent {
 
                MediaType mt = getMediaType();
 
-               if ((Utils.isEmpty3(Utils.s(mt)) || 
mt.toString().startsWith("text/plain")) && cm.hasStringMutater())
+               if ((Utils.isEmpty(Utils.s(mt)) || 
mt.toString().startsWith("text/plain")) && cm.hasStringMutater())
                        return cm.getStringMutater().mutate(asString());
 
                Optional<ContentType> ct = req.getHeader(ContentType.class);
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
index 91eece624..e930e46c2 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
@@ -231,7 +231,7 @@ public class RequestFormParams extends 
ArrayList<RequestFormParam> {
                for (NameValuePair p : pairs) {
                        String name = p.getName();
                        Stream<RequestFormParam> l = stream(name);
-                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty3(x.getValue()));
+                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty(x.getValue()));
                        if (hasAllBlanks) {
                                removeAll(getAll(name));
                                add(new RequestFormParam(req, name, 
vs.resolve(p.getValue())));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
index 5863b5abe..dcf6aeb8a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
@@ -208,7 +208,7 @@ public class RequestHeaders extends 
ArrayList<RequestHeader> {
                for (Header p : pairs) {
                        String name = p.getName();
                        Stream<RequestHeader> l = stream(name);
-                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty3(x.getValue()));
+                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty(x.getValue()));
                        if (hasAllBlanks) {
                                removeAll(getAll(name));
                                add(new RequestHeader(req, name, 
vs.resolve(p.getValue())));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
index 8b2acafdd..587b2971b 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
@@ -204,7 +204,7 @@ public class RequestPathParams extends 
ArrayList<RequestPathParam> {
                for (NameValuePair p : pairs) {
                        String name = p.getName();
                        Stream<RequestPathParam> l = stream(name);
-                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty3(x.getValue()));
+                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty(x.getValue()));
                        if (hasAllBlanks) {
                                removeAll(getAll(name));
                                add(new RequestPathParam(req, name, 
vs.resolve(p.getValue())));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
index e5e920893..cb471eeb6 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
@@ -223,7 +223,7 @@ public class RequestQueryParams extends 
ArrayList<RequestQueryParam> {
                for (NameValuePair p : pairs) {
                        String name = p.getName();
                        Stream<RequestQueryParam> l = stream(name);
-                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty3(x.getValue()));
+                       boolean hasAllBlanks = l.allMatch(x -> 
Utils.isEmpty(x.getValue()));
                        if (hasAllBlanks) {
                                removeAll(getAll(name));
                                add(new RequestQueryParam(req, name, 
vs.resolve(p.getValue())));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggingDetail.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggingDetail.java
index 084d32f5b..95c4c63d5 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggingDetail.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggingDetail.java
@@ -52,7 +52,7 @@ public enum CallLoggingDetail {
         * @return The resolved value.
         */
        public static CallLoggingDetail fromString(String s) {
-               if (! Utils.isEmpty3(s)) {
+               if (! Utils.isEmpty(s)) {
                        try {
                                return valueOf(s.toUpperCase());
                        } catch (IllegalArgumentException  e) {}
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/matcher/ClientVersionMatcher.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/matcher/ClientVersionMatcher.java
index bc666a1c3..79a1f5690 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/matcher/ClientVersionMatcher.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/matcher/ClientVersionMatcher.java
@@ -43,7 +43,7 @@ public class ClientVersionMatcher extends RestMatcher {
         * @param mi The version string that the client version must match.
         */
        public ClientVersionMatcher(String clientVersionHeader, MethodInfo mi) {
-               this.clientVersionHeader = Utils.isEmpty3(clientVersionHeader) 
? "Client-Version" : clientVersionHeader;
+               this.clientVersionHeader = Utils.isEmpty(clientVersionHeader) ? 
"Client-Version" : clientVersionHeader;
                Value<String> clientVersion = Value.empty();
                mi.getAnnotationList(REST_OP_GROUP).forEachValue(String.class, 
"clientVersion", NOT_EMPTY, x -> clientVersion.set(x));
                range = new VersionRange(clientVersion.orElse(null));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
index d3b4e9522..77264dde6 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/processor/PlainTextPojoProcessor.java
@@ -35,12 +35,12 @@ public final class PlainTextPojoProcessor implements 
ResponseProcessor {
                RestResponse res = opSession.getResponse();
                String accept = req.getHeaderParam("Accept").orElse("*/*");
 
-               if (res.getSerializerMatch().isPresent() || ! 
(Utils.isEmpty3(accept) || accept.startsWith("text/plain") || 
accept.contains("*/*")))
+               if (res.getSerializerMatch().isPresent() || ! 
(Utils.isEmpty(accept) || accept.startsWith("text/plain") || 
accept.contains("*/*")))
                        return NEXT;
 
                Object o = res.getContent(Object.class);
 
-               if (Utils.isEmpty3(res.getContentType()))
+               if (Utils.isEmpty(res.getContentType()))
                        res.setHeader(ContentType.TEXT_PLAIN);
 
                FinishablePrintWriter w = res.getNegotiatedWriter();
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
index e1a32a0a3..ca8c71de0 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/swagger/BasicSwaggerProviderSession.java
@@ -823,7 +823,7 @@ public class BasicSwaggerProviderSession {
                                sex = schema.getString("example", 
schema.getString("example"));
                }
 
-               if (Utils.isEmpty3(sex))
+               if (Utils.isEmpty(sex))
                        return;
 
                Object example = null;
@@ -872,7 +872,7 @@ public class BasicSwaggerProviderSession {
 
                String s = piri.getString("example");
 
-               if (Utils.isEmpty3(s))
+               if (Utils.isEmpty(s))
                        return;
 
                JsonMap examples = piri.getMap("examples");
@@ -1067,7 +1067,7 @@ public class BasicSwaggerProviderSession {
                om = newMap(om);
                for (Header aa : a) {
                        String name = StringUtils.firstNonEmpty(aa.name(), 
aa.value());
-                       if (Utils.isEmpty3(name))
+                       if (Utils.isEmpty(name))
                                throw new IllegalArgumentException("@Header 
used without name or value.");
                        merge(om.getMap(name, true), aa.schema());
                }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
index 8703ee2aa..f66953f3a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/RestUtils.java
@@ -293,7 +293,7 @@ public final class RestUtils {
                        if (m == null)
                                m = map();
 
-                       if (qs == null || ((qs instanceof CharSequence) && 
Utils.isEmpty3(Utils.s(qs))))
+                       if (qs == null || ((qs instanceof CharSequence) && 
Utils.isEmpty(Utils.s(qs))))
                                return m;
 
                        try (ParserPipe p = new ParserPipe(qs)) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
index 2fc7a8a26..206262bd2 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
@@ -74,7 +74,7 @@ public class UrlPathMatch {
         */
        public boolean hasEmptyVars() {
                for (String v : vars.values())
-                       if (Utils.isEmpty3(v))
+                       if (Utils.isEmpty(v))
                                return true;
                return false;
        }
diff --git a/juneau-utest/src/test/java/org/apache/juneau/ComboInput.java 
b/juneau-utest/src/test/java/org/apache/juneau/ComboInput.java
index 1ed9f4de2..c73b6333f 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/ComboInput.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/ComboInput.java
@@ -249,7 +249,7 @@ public class ComboInput<T> {
        public void verify(T o, String testName) {
                for (Function<T,String> f : verify) {
                        String s = f.apply(o);
-                       if (! Utils.isEmpty3(s)) {
+                       if (! Utils.isEmpty(s)) {
                                throw new BasicAssertionError("Verification 
failed on test {0}/{1}: {2}", label, testName, s);
                        }
                }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java
index b1ad820a9..df68af5c1 100755
--- 
a/juneau-utest/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/utils/StringVarResolverTest.java
@@ -169,7 +169,7 @@ class StringVarResolverTest extends SimpleTestBase {
                String t;
 
                t = "$E{PATH}";
-               assertFalse(Utils.isEmpty3(VarResolver.DEFAULT.resolve(t)));
+               assertFalse(Utils.isEmpty(VarResolver.DEFAULT.resolve(t)));
        }
 
        
//====================================================================================================

Reply via email to