From e97a39303c38eb81820f1914d217775c0badbbc7 Mon Sep 17 00:00:00 2001 From: Paulo Lopes Date: Tue, 28 May 2019 15:45:37 +0200 Subject: [PATCH] Avoid doing reflection to parse well known types (boxed primitives) Signed-off-by: Paulo Lopes --- .../vertx/core/cli/converters/Converter.java | 1 + .../vertx/core/cli/converters/Converters.java | 36 +++++++++-------- .../core/cli/converters/StringConverter.java | 40 ------------------- .../cli/converters/StringConverterTest.java | 27 ------------- 4 files changed, 21 insertions(+), 83 deletions(-) delete mode 100644 src/main/java/io/vertx/core/cli/converters/StringConverter.java delete mode 100644 src/test/java/io/vertx/core/cli/converters/StringConverterTest.java diff --git a/src/main/java/io/vertx/core/cli/converters/Converter.java b/src/main/java/io/vertx/core/cli/converters/Converter.java index bb38266ca..0dd88d1ad 100644 --- a/src/main/java/io/vertx/core/cli/converters/Converter.java +++ b/src/main/java/io/vertx/core/cli/converters/Converter.java @@ -16,6 +16,7 @@ package io.vertx.core.cli.converters; * * @author Clement Escoffier */ +@FunctionalInterface public interface Converter { T fromString(String s); diff --git a/src/main/java/io/vertx/core/cli/converters/Converters.java b/src/main/java/io/vertx/core/cli/converters/Converters.java index 761d340da..efec5e446 100644 --- a/src/main/java/io/vertx/core/cli/converters/Converters.java +++ b/src/main/java/io/vertx/core/cli/converters/Converters.java @@ -11,6 +11,7 @@ package io.vertx.core.cli.converters; +import java.lang.reflect.InvocationTargetException; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -24,6 +25,7 @@ import java.util.NoSuchElementException; public class Converters { private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + private static final Map, Converter> WELL_KNOWN_CONVERTERS; static { Map, Class> primToWrap = new HashMap<>(16); @@ -39,6 +41,19 @@ public class Converters { primToWrap.put(void.class, Void.class); PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + + Map, Converter> wellKnown = new HashMap<>(16); + wellKnown.put(Boolean.class, BooleanConverter.INSTANCE); + wellKnown.put(Byte.class, Byte::parseByte); + wellKnown.put(Character.class, CharacterConverter.INSTANCE); + wellKnown.put(Double.class, Double::parseDouble); + wellKnown.put(Float.class, Float::parseFloat); + wellKnown.put(Integer.class, Integer::parseInt); + wellKnown.put(Long.class, Long::parseLong); + wellKnown.put(Short.class, Short::parseShort); + wellKnown.put(String.class, value -> value); + + WELL_KNOWN_CONVERTERS = Collections.unmodifiableMap(wellKnown); } public static T create(Class type, String value) { @@ -68,14 +83,9 @@ public class Converters { */ @SuppressWarnings("unchecked") private static Converter getConverter(Class type) { - // check for String first - if (type == String.class) { - return (Converter) StringConverter.INSTANCE; - } - - // Boolean has a special case as they support other form of "truth" such as "yes", "on", "1"... - if (type == Boolean.class) { - return (Converter) BooleanConverter.INSTANCE; + // check for well known types first + if (WELL_KNOWN_CONVERTERS.containsKey(type)) { + return (Converter) WELL_KNOWN_CONVERTERS.get(type); } // None of them are there, try default converters in the following order: @@ -100,20 +110,14 @@ public class Converters { return converter; } - // Unlike other primitive type, characters cannot be created using the 'valueOf' method, - // so we need a specific converter. As creating characters is quite rare, this must be the last check. - if (type == Character.class) { - return (Converter) CharacterConverter.INSTANCE; - } - // running out of converters... throw new NoSuchElementException("Cannot find a converter able to create instance of " + type.getName()); } public static Converter newInstance(Class> type) throws IllegalArgumentException { try { - return type.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + return type.getDeclaredConstructor().newInstance(); + } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException("Cannot create a new instance of " + type.getName() + " - it requires an " + "public constructor without argument", e); } diff --git a/src/main/java/io/vertx/core/cli/converters/StringConverter.java b/src/main/java/io/vertx/core/cli/converters/StringConverter.java deleted file mode 100644 index e27466fe1..000000000 --- a/src/main/java/io/vertx/core/cli/converters/StringConverter.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2011-2017 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 - */ - -package io.vertx.core.cli.converters; - -/** - * Converts String to String, that's the easy one. - * - * @author Clement Escoffier - */ -public final class StringConverter implements Converter { - - /** - * The converter. - */ - public static final StringConverter INSTANCE = new StringConverter(); - - private StringConverter() { - // No direct instantiation - } - - /** - * Just returns the given input. - * - * @param input the input, can be {@literal null} - * @return the input - */ - @Override - public String fromString(String input) throws IllegalArgumentException { - return input; - } -} diff --git a/src/test/java/io/vertx/core/cli/converters/StringConverterTest.java b/src/test/java/io/vertx/core/cli/converters/StringConverterTest.java deleted file mode 100644 index 424064949..000000000 --- a/src/test/java/io/vertx/core/cli/converters/StringConverterTest.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2011-2017 Contributors to the Eclipse Foundation - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 - * which is available at https://www.apache.org/licenses/LICENSE-2.0. - * - * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 - */ - -package io.vertx.core.cli.converters; - -import org.junit.Test; - -import static org.assertj.core.api.Assertions.assertThat; - - -public class StringConverterTest { - - @Test - public void testFromString() throws Exception { - assertThat(StringConverter.INSTANCE.fromString("hello")).isEqualTo("hello"); - assertThat(StringConverter.INSTANCE.fromString("")).isEqualTo(""); - assertThat(StringConverter.INSTANCE.fromString(null)).isEqualTo(null); - } -}