All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sshd.common.PropertyResolverUtils Maven / Gradle / Ivy

The newest version!
/*
 * 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.sshd.common;

import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.NavigableSet;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.MapEntryUtils;
import org.apache.sshd.common.util.ValidateUtils;

/**
 * @author Apache MINA SSHD Project
 */
public final class PropertyResolverUtils {
    public static final String NONE_VALUE = "none";

    /**
     * Case insensitive {@link NavigableSet} of values considered {@code true} by {@link #parseBoolean(String)}
     */
    public static final NavigableSet TRUE_VALUES = Collections.unmodifiableNavigableSet(
            GenericUtils.asSortedSet(
                    String.CASE_INSENSITIVE_ORDER, "true", "t", "yes", "y", "on"));

    /**
     * Case insensitive {@link NavigableSet} of values considered {@code false} by {@link #parseBoolean(String)}
     */
    public static final NavigableSet FALSE_VALUES = Collections.unmodifiableNavigableSet(
            GenericUtils.asSortedSet(
                    String.CASE_INSENSITIVE_ORDER, "false", "f", "no", "n", "off"));

    private PropertyResolverUtils() {
        throw new UnsupportedOperationException("No instance allowed");
    }

    /**
     * @param  v Value to examine
     * @return   {@code true} if equals to {@value #NONE_VALUE} - case insensitive
     */
    public static boolean isNoneValue(String v) {
        return NONE_VALUE.equalsIgnoreCase(v);
    }

    /**
     * @param  resolver              The {@link PropertyResolver} instance - ignored if {@code null}
     * @param  name                  The property name
     * @param  defaultValue          The default value to return if the specified property does not exist in the
     *                               properties map
     * @return                       The resolved property
     * @throws NumberFormatException if malformed value
     * @see                          #toLong(Object, long)
     */
    public static long getLongProperty(PropertyResolver resolver, String name, long defaultValue) {
        return toLong(resolvePropertyValue(resolver, name), defaultValue);
    }

    public static long getLongProperty(Map props, String name, long defaultValue) {
        return toLong(resolvePropertyValue(props, name), defaultValue);
    }

    /**
     * Converts a generic object value to a {@code long} if possible:
     * 
    *
  • If value is {@code null} the default is returned
  • * *
  • If value is a {@link Number} then its {@link Number#longValue()} is returned
  • * *
  • Otherwise, the value's {@code toString()} is parsed as a {@code long}
  • *
* * @param value The resolved value - may be {@code null} * @param defaultValue The default to use if {@code null} resolved value * @return The resolved value * @throws NumberFormatException if malformed value * @see Long#parseLong(String) */ public static long toLong(Object value, long defaultValue) { if (value == null) { return defaultValue; } else if (value instanceof Number) { return ((Number) value).longValue(); } else { // we parse the string in case it is not a valid long value return Long.parseLong(value.toString()); } } /** * @param resolver The {@link PropertyResolver} instance - ignored if {@code null} * @param name The property name * @return The {@link Long} value or {@code null} if property not found * @throws NumberFormatException if malformed value * @see #toLong(Object) */ public static Long getLong(PropertyResolver resolver, String name) { return toLong(resolvePropertyValue(resolver, name)); } public static Long getLong(Map props, String name) { return toLong(resolvePropertyValue(props, name)); } /** * Converts a generic object into a {@link Long}: *
    *
  • If the value is {@code null} then returns {@code null}.
  • * *
  • If the value is already a {@link Long} then it is returned as such.
  • * *
  • If value is a {@link Number} then its {@link Number#longValue()} is wrapped as a {@link Long}
  • * *
  • Otherwise, the value's {@code toString()} is parsed as a {@link Long}
  • *
* * @param value The resolved value - may be {@code null} * @return The {@link Long} value or {@code null} if property not found * @throws NumberFormatException if malformed value * @see Long#valueOf(long) * @see Long#valueOf(String) */ public static Long toLong(Object value) { if (value == null) { return null; } else if (value instanceof Long) { return (Long) value; } else if (value instanceof Number) { return ((Number) value).longValue(); } else { // we parse the string in case it is not a valid long value return Long.valueOf(value.toString()); } } /** * Converts an enumerated configuration value: *
    *

    *

  • If value is {@code null} then return {@code null}
  • *

    * *

    *

  • If value already of the expected type then simply cast and return it.
  • *

    * *

    *

  • If value is a {@link CharSequence} then convert it to a string and look for a matching enumerated value name * - case insensitive.
  • *

    * > *
* * @param Type of enumerated value * @param enumType The enumerated class type * @param value The configured value - ignored if {@code null} * @param failIfNoMatch Whether to fail if no matching name found * @param available The available values to compare the name * @return The matching enumerated value - {@code null} if no match found * @throws IllegalArgumentException If value is neither {@code null}, nor the enumerated type nor a * {@link CharSequence} * @throws NoSuchElementException If no matching string name found and failIfNoMatch is {@code true} */ public static > E toEnum( Class enumType, Object value, boolean failIfNoMatch, Collection available) { if (value == null) { return null; } else if (enumType.isInstance(value)) { return enumType.cast(value); } else if (value instanceof CharSequence) { String name = value.toString(); if (GenericUtils.size(available) > 0) { for (E v : available) { if (name.equalsIgnoreCase(v.name())) { return v; } } } if (failIfNoMatch) { throw new NoSuchElementException("No match found for " + enumType.getSimpleName() + "[" + name + "]"); } return null; } else { throw new IllegalArgumentException("Bad value type for enum conversion: " + value.getClass().getSimpleName()); } } public static Object updateProperty(PropertyResolver resolver, String name, long value) { return updateProperty(resolver.getProperties(), name, value); } public static Object updateProperty(Map props, String name, long value) { return updateProperty(props, name, Long.valueOf(value)); } public static int getIntProperty(PropertyResolver resolver, String name, int defaultValue) { return toInteger(resolvePropertyValue(resolver, name), defaultValue); } public static int getIntProperty(Map props, String name, int defaultValue) { return toInteger(resolvePropertyValue(props, name), defaultValue); } public static int toInteger(Object value, int defaultValue) { if (value == null) { return defaultValue; } else if (value instanceof Number) { return ((Number) value).intValue(); } else { // we parse the string in case this is NOT an integer return Integer.parseInt(value.toString()); } } public static Integer getInteger(PropertyResolver resolver, String name) { return toInteger(resolvePropertyValue(resolver, name)); } public static Integer getInteger(Map props, String name) { return toInteger(resolvePropertyValue(props, name)); } public static Integer toInteger(Object value) { if (value == null) { return null; } else if (value instanceof Integer) { return (Integer) value; } else if (value instanceof Number) { return ((Number) value).intValue(); } else { // we parse the string in case this is NOT a valid integer string return Integer.valueOf(value.toString()); } } public static Object updateProperty(PropertyResolver resolver, String name, int value) { return updateProperty(resolver.getProperties(), name, value); } public static Object updateProperty(Map props, String name, int value) { return updateProperty(props, name, Integer.valueOf(value)); } public static boolean getBooleanProperty(PropertyResolver resolver, String name, boolean defaultValue) { return toBoolean(getObject(resolver, name), defaultValue); } public static boolean getBooleanProperty(Map props, String name, boolean defaultValue) { return toBoolean(getObject(props, name), defaultValue); } /** * @param value The value to convert * @param defaultValue The default value to return if value is {@code null} or and empty string, then returns the * default value. * @return The resolved value * @see #toBoolean(Object) */ public static boolean toBoolean(Object value, boolean defaultValue) { Boolean bool = toBoolean(value); if (bool == null) { return defaultValue; } else { return bool; } } public static Boolean getBoolean(PropertyResolver resolver, String name) { Object propValue = resolvePropertyValue(resolver, name); return toBoolean(propValue); } public static Boolean getBoolean(Map props, String name) { Object propValue = resolvePropertyValue(props, name); return toBoolean(propValue); } /** *

* Attempts to convert the object into a {@link Boolean} value as follows: *

*
*
    *

    *

  • If {@code null} or an empty string then return {@code null}.
  • *

    * *

    *

  • If already a {@link Boolean} then return as-is
  • *

    * *

    *

  • If a {@link CharSequence} then invoke {@link #parseBoolean(String)}
  • *

    * *

    *

  • Otherwise, throws an {@link UnsupportedOperationException}
  • *

    *
* * @param value The value to be converted * @return The result - {@code null} if {@code null} or an empty string * @throws UnsupportedOperationException If value cannot be converted to a boolean - e.g., a number. * @see #parseBoolean(String) */ public static Boolean toBoolean(Object value) { if (value == null) { return null; } else if (value instanceof Boolean) { return (Boolean) value; } else if (value instanceof CharSequence) { return parseBoolean(value.toString()); } else { throw new UnsupportedOperationException( "Cannot convert " + value.getClass().getSimpleName() + "[" + value + "] to boolean"); } } /** * Converts a string to a {@link Boolean} value by looking for it in either the {@link #TRUE_VALUES} or * {@link #FALSE_VALUES} * * @param value The value to parse * @return The result - {@code null} if value is {@code null}/empty * @throws IllegalArgumentException If non-empty string that does not match (case insensitive) either of the * known values for boolean. */ public static Boolean parseBoolean(String value) { if (GenericUtils.isEmpty(value)) { return null; } else if (TRUE_VALUES.contains(value)) { return Boolean.TRUE; } else if (FALSE_VALUES.contains(value)) { return Boolean.FALSE; } else { throw new IllegalArgumentException("Unknown boolean value: '" + value + "'"); } } public static Object updateProperty(PropertyResolver resolver, String name, boolean value) { return updateProperty(resolver.getProperties(), name, value); } public static Object updateProperty(Map props, String name, boolean value) { return updateProperty(props, name, Boolean.valueOf(value)); } /** * @param resolver The {@link PropertyResolver} to use - ignored if {@code null} * @param name The property name * @param defaultValue The default value to return if property not set or empty * @return The set value (if not {@code null}/empty) or default one */ public static String getStringProperty( PropertyResolver resolver, String name, String defaultValue) { String value = getString(resolver, name); if (GenericUtils.isEmpty(value)) { return defaultValue; } else { return value; } } public static String getStringProperty(Map props, String name, String defaultValue) { Object value = resolvePropertyValue(props, name); if (value == null) { return defaultValue; } else { return Objects.toString(value); } } public static Charset getCharset(PropertyResolver resolver, String name, Charset defaultValue) { Object value = getObject(resolver, name); return (value == null) ? defaultValue : toCharset(value); } public static Charset getCharset(Map props, String name, Charset defaultValue) { Object value = getObject(props, name); return (value == null) ? defaultValue : toCharset(value); } public static Charset toCharset(Object value) { if (value == null) { return null; } else if (value instanceof Charset) { return (Charset) value; } else if (value instanceof CharSequence) { return Charset.forName(value.toString()); } else { throw new IllegalArgumentException("Invalid charset conversion value: " + value); } } public static String getString(PropertyResolver resolver, String name) { Object value = getObject(resolver, name); return Objects.toString(value, null); } public static String getString(Map props, String name) { Object value = getObject(props, name); return Objects.toString(value, null); } public static Object getObject(PropertyResolver resolver, String name) { return resolvePropertyValue(resolver, name); } public static Object getObject(PropertyResolver resolver, String name, Object defaultValue) { Object value = resolvePropertyValue(resolver, name); return value != null ? value : defaultValue; } // for symmetrical reasons... public static Object getObject(Map props, String name) { return resolvePropertyValue(props, name); } public static Object resolvePropertyValue(Map props, String name) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); return (props != null) ? props.get(key) : null; } /** * @param resolver The {@link PropertyResolver} instance * @param name The property name * @param value The new value - if {@code null} or an empty {@link CharSequence} the property is removed * @return The previous value - {@code null} if none */ public static Object updateProperty(PropertyResolver resolver, String name, Object value) { return updateProperty(resolver.getProperties(), name, value); } public static Object updateProperty(Map props, String name, Object value) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); if ((value == null) || ((value instanceof CharSequence) && GenericUtils.isEmpty((CharSequence) value))) { return props.remove(key); } else { return props.put(key, value); } } /** * Unwinds the resolvers hierarchy until found one with a non-{@code null} value for the requested property or * reached top. If still no value found and the key starts with "org.apache.sshd" then the system * properties are also consulted * * @param resolver The {@link PropertyResolver} to start from - ignored if {@code null} * @param name The requested property name * @return The found value or {@code null} */ public static Object resolvePropertyValue(PropertyResolver resolver, String name) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); for (PropertyResolver r = resolver; r != null; r = r.getParentPropertyResolver()) { Map props = r.getProperties(); Object value = getObject(props, key); if (value != null) { return value; } } return null; } /** * Unwinds the resolvers hierarchy until found one with a non-{@code null} value for the requested property or * reached top. * * @param resolver The {@link PropertyResolver} to start from - ignored if {@code null} * @param name The requested property name * @return The found properties {@link Map} or {@code null} */ public static Map resolvePropertiesSource(PropertyResolver resolver, String name) { String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); for (PropertyResolver r = resolver; r != null; r = r.getParentPropertyResolver()) { Map props = r.getProperties(); Object value = getObject(props, key); if (value != null) { return props; } } return null; } public static PropertyResolver toPropertyResolver(Properties props) { if (MapEntryUtils.isEmpty(props)) { return PropertyResolver.EMPTY; } Collection names = props.stringPropertyNames(); Map propsMap = new ConcurrentHashMap<>(GenericUtils.size(names)); for (String key : names) { String value = props.getProperty(key); if (value == null) { continue; } propsMap.put(key, value); } return toPropertyResolver(propsMap); } /** * Wraps a {@link Map} into a {@link PropertyResolver} so it can be used with these utilities * * @param props The properties map - may be {@code null}/empty if no properties are updated * @return The resolver wrapper */ public static PropertyResolver toPropertyResolver(Map props) { return toPropertyResolver(props, null); } public static PropertyResolver toPropertyResolver(Map props, PropertyResolver parent) { return new PropertyResolver() { @Override public PropertyResolver getParentPropertyResolver() { return parent; } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Map getProperties() { return (Map) props; } @Override public String toString() { return Objects.toString(props); } }; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy