diff --git a/common/src/main/java/io/netty/util/internal/DetectionUtil.java b/common/src/main/java/io/netty/util/internal/DetectionUtil.java index 47199904f4..0717d4b39f 100644 --- a/common/src/main/java/io/netty/util/internal/DetectionUtil.java +++ b/common/src/main/java/io/netty/util/internal/DetectionUtil.java @@ -40,7 +40,7 @@ public final class DetectionUtil { private static final boolean IS_ROOT; static { - String os = System.getProperty("os.name").toLowerCase(); + String os = SystemPropertyUtil.get("os.name").toLowerCase(); // windows IS_WINDOWS = os.contains("win"); @@ -104,17 +104,20 @@ public final class DetectionUtil { } private static boolean hasUnsafe(ClassLoader loader) { - String value = SystemPropertyUtil.get("io.netty.noUnsafe"); - if (value != null) { + boolean noUnsafe = SystemPropertyUtil.getBoolean("io.netty.noUnsafe", false); + if (noUnsafe) { return false; } // Legacy properties - value = SystemPropertyUtil.get("io.netty.tryUnsafe"); - if (value == null) { - value = SystemPropertyUtil.get("org.jboss.netty.tryUnsafe", "true"); + boolean tryUnsafe = false; + if (SystemPropertyUtil.contains("io.netty.tryUnsafe")) { + tryUnsafe = SystemPropertyUtil.getBoolean("io.netty.tryUnsafe", true); + } else { + tryUnsafe = SystemPropertyUtil.getBoolean("org.jboss.netty.tryUnsafe", true); } - if (!"true".equalsIgnoreCase(value)) { + + if (!tryUnsafe) { return false; } @@ -124,6 +127,7 @@ public final class DetectionUtil { } catch (Exception e) { // Ignore } + return false; } diff --git a/common/src/main/java/io/netty/util/internal/SystemPropertyUtil.java b/common/src/main/java/io/netty/util/internal/SystemPropertyUtil.java index 977e28918e..4614401a96 100644 --- a/common/src/main/java/io/netty/util/internal/SystemPropertyUtil.java +++ b/common/src/main/java/io/netty/util/internal/SystemPropertyUtil.java @@ -15,27 +15,56 @@ */ package io.netty.util.internal; -import java.util.regex.Pattern; +import io.netty.logging.InternalLogger; +import io.netty.logging.InternalLoggerFactory; + +import java.util.Properties; /** - * Accesses the system property swallowing a {@link SecurityException}. + * A collection of utility methods to retrieve and parse the values of the Java system properties. */ -final class SystemPropertyUtil { +public final class SystemPropertyUtil { + + private static final InternalLogger logger = + InternalLoggerFactory.getInstance(SystemPropertyUtil.class); + + private static final Properties props; + + // Retrieve all system properties at once so that there's no need to deal with + // security exceptions from next time. Otherwise, we might end up with logging every + // security exceptions on every system property access or introducing more complexity + // just because of less verbose logging. + static { + Properties newProps = null; + try { + newProps = System.getProperties(); + } catch (SecurityException e) { + logger.warn("Unable to access the system properties; default values will be used.", e); + newProps = new Properties(); + } + + props = newProps; + } + + /** + * Returns {@code true} if and only if the system property with the specified {@code key} + * exists. + */ + public static boolean contains(String key) { + if (key == null) { + throw new NullPointerException("key"); + } + return props.containsKey(key); + } /** * Returns the value of the Java system property with the specified - * {@code key}. + * {@code key}, while falling back to {@code null} if the property access fails. * - * @return the property value. - * {@code null} if there's no such property or if an access to the - * specified property is not allowed. + * @return the property value or {@code null} */ public static String get(String key) { - try { - return System.getProperty(key); - } catch (Exception e) { - return null; - } + return get(key, null); } /** @@ -48,10 +77,15 @@ final class SystemPropertyUtil { * specified property is not allowed. */ public static String get(String key, String def) { - String value = get(key); - if (value == null) { - value = def; + if (key == null) { + throw new NullPointerException("key"); } + + String value = props.getProperty(key); + if (value == null) { + return def; + } + return value; } @@ -64,17 +98,104 @@ final class SystemPropertyUtil { * {@code def} if there's no such property or if an access to the * specified property is not allowed. */ - public static int get(String key, int def) { - String value = get(key); + public static boolean getBoolean(String key, boolean def) { + if (key == null) { + throw new NullPointerException("key"); + } + + String value = props.getProperty(key); if (value == null) { return def; } - if (Pattern.matches("-?[0-9]+", value)) { - return Integer.parseInt(value); - } else { + value = value.trim().toLowerCase(); + if (value.length() == 0) { + return true; + } + + if (value.equals("true") || value.equals("yes") || value.equals("1")) { + return true; + } + + if (value.equals("false") || value.equals("no") || value.equals("0")) { + return false; + } + + logger.warn( + "Unable to parse the boolean system property '" + key + "':" + value + " - " + + "using the default value: " + def); + + return def; + } + + /** + * Returns the value of the Java system property with the specified + * {@code key}, while falling back to the specified default value if + * the property access fails. + * + * @return the property value. + * {@code def} if there's no such property or if an access to the + * specified property is not allowed. + */ + public static int getInt(String key, int def) { + if (key == null) { + throw new NullPointerException("key"); + } + + String value = props.getProperty(key); + if (value == null) { return def; } + + value = value.trim().toLowerCase(); + if (value.matches("-?[0-9]+")) { + try { + return Integer.parseInt(value); + } catch (Exception e) { + // Ignore + } + } + + logger.warn( + "Unable to parse the integer system property '" + key + "':" + value + " - " + + "using the default value: " + def); + + return def; + } + + /** + * Returns the value of the Java system property with the specified + * {@code key}, while falling back to the specified default value if + * the property access fails. + * + * @return the property value. + * {@code def} if there's no such property or if an access to the + * specified property is not allowed. + */ + public static long getLong(String key, long def) { + if (key == null) { + throw new NullPointerException("key"); + } + + String value = props.getProperty(key); + if (value == null) { + return def; + } + + value = value.trim().toLowerCase(); + if (value.matches("-?[0-9]+")) { + try { + return Long.parseLong(value); + } catch (Exception e) { + // Ignore + } + } + + logger.warn( + "Unable to parse the long integer system property '" + key + "':" + value + " - " + + "using the default value: " + def); + + return def; } private SystemPropertyUtil() { diff --git a/transport/src/main/java/io/netty/channel/socket/nio/SelectorUtil.java b/transport/src/main/java/io/netty/channel/socket/nio/SelectorUtil.java index b22bbba492..feb4b167b3 100644 --- a/transport/src/main/java/io/netty/channel/socket/nio/SelectorUtil.java +++ b/transport/src/main/java/io/netty/channel/socket/nio/SelectorUtil.java @@ -17,6 +17,7 @@ package io.netty.channel.socket.nio; import io.netty.logging.InternalLogger; import io.netty.logging.InternalLoggerFactory; +import io.netty.util.internal.SystemPropertyUtil; import java.io.IOException; import java.nio.channels.CancelledKeyException; @@ -27,8 +28,9 @@ final class SelectorUtil { private static final InternalLogger logger = InternalLoggerFactory.getInstance(SelectorUtil.class); static final long DEFAULT_SELECT_TIMEOUT = 10; - static final long SELECT_TIMEOUT; - static final long SELECT_TIMEOUT_NANOS; + static final long SELECT_TIMEOUT = + SystemPropertyUtil.getLong("io.netty.selectTimeout", DEFAULT_SELECT_TIMEOUT); + static final long SELECT_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(SELECT_TIMEOUT); // Workaround for JDK NIO bug. // @@ -47,15 +49,7 @@ final class SelectorUtil { logger.debug("Unable to get/set System Property '" + key + "'", e); } } - long selectTimeout; - try { - selectTimeout = Long.parseLong(System.getProperty("io.netty.selectTimeout", - String.valueOf(DEFAULT_SELECT_TIMEOUT))); - } catch (NumberFormatException e) { - selectTimeout = DEFAULT_SELECT_TIMEOUT; - } - SELECT_TIMEOUT = selectTimeout; - SELECT_TIMEOUT_NANOS = TimeUnit.MILLISECONDS.toNanos(SELECT_TIMEOUT); + logger.debug("Using select timeout of " + SELECT_TIMEOUT); }