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

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

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

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.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;

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

/**
 * Property definition.
 *
 * @param   The generic property type
 * @author     Apache MINA SSHD Project
 */
public interface Property extends NamedResource {

    static Property string(String name) {
        return string(name, null);
    }

    static Property string(String name, String def) {
        return new StringProperty(name, def);
    }

    static Property bool(String name) {
        return new BooleanProperty(name);
    }

    static Property bool(String name, boolean def) {
        return new BooleanProperty(name, def);
    }

    static Property integer(String name) {
        return new IntegerProperty(name);
    }

    static Property integer(String name, int def) {
        return new IntegerProperty(name, def);
    }

    // CHECKSTYLE:OFF
    static Property long_(String name) {
        return new LongProperty(name);
    }

    static Property long_(String name, long def) {
        return new LongProperty(name, def);
    }

    static > Property enum_(String name, Class type) {
        return enum_(name, type, null);
    }

    static > Property enum_(String name, Class type, T def) {
        return new EnumProperty<>(name, type, def);
    }
    // CHECKSTYLE:ON

    static Property duration(String name) {
        return duration(name, null);
    }

    static Property duration(String name, Duration def) {
        return new DurationProperty(name, def);
    }

    static Property duration(String name, Duration def, Duration min) {
        return new DurationProperty(name, def, min);
    }

    static Property durationSec(String name) {
        return durationSec(name, null);
    }

    static Property durationSec(String name, Duration def) {
        return new DurationInSecondsProperty(name, def);
    }

    static Property durationSec(String name, Duration def, Duration min) {
        return new DurationInSecondsProperty(name, def, min);
    }

    static Property charset(String name) {
        return charset(name, null);
    }

    static Property charset(String name, Charset def) {
        return new CharsetProperty(name, def);
    }

    static Property object(String name) {
        return object(name, null);
    }

    static Property object(String name, Object def) {
        return new ObjectProperty(name, def);
    }

    static  Property validating(Property prop, Consumer validator) {
        return new Validating<>(prop, validator);
    }

    abstract class BaseProperty implements Property {
        private final String name;
        private final Class type;
        private final Optional defaultValue;

        protected BaseProperty(String name, Class type) {
            this(name, type, null);
        }

        protected BaseProperty(String name, Class type, T defaultValue) {
            this.name = ValidateUtils.checkNotNullAndNotEmpty(name, "No name provided");
            this.type = Objects.requireNonNull(type, "Type must be provided");
            this.defaultValue = Optional.ofNullable(defaultValue);
        }

        @Override
        public String getName() {
            return name;
        }

        @Override
        public Class getType() {
            return type;
        }

        @Override
        public Optional getDefault() {
            return defaultValue;
        }

        @Override
        public Optional get(PropertyResolver resolver) {
            Object propValue = PropertyResolverUtils.resolvePropertyValue(resolver, getName());
            return (propValue != null) ? Optional.of(fromStorage(propValue)) : getDefault();
        }

        @Override
        public T getOrCustomDefault(PropertyResolver resolver, T defaultValue) {
            Object propValue = PropertyResolverUtils.resolvePropertyValue(resolver, getName());
            return (propValue != null) ? fromStorage(propValue) : defaultValue;
        }

        @Override
        public void set(PropertyResolver resolver, T value) {
            PropertyResolverUtils.updateProperty(resolver, getName(), toStorage(value));
        }

        protected Object toStorage(T value) {
            return value;
        }

        protected abstract T fromStorage(Object value);

        @Override
        public String toString() {
            return "Property[" + getName() + "](" + getType().getSimpleName() + "]";
        }
    }

    class DurationProperty extends BaseProperty {

        protected final Duration min;

        public DurationProperty(String name) {
            this(name, null);
        }

        public DurationProperty(String name, Duration def) {
            super(name, Duration.class, def);
            min = null;
        }

        public DurationProperty(String name, Duration def, Duration min) {
            super(name, Duration.class, atLeast(name, def, min));
            this.min = min;
        }

        @Override
        protected Object toStorage(Duration value) {
            atLeast(getName(), value, min);
            return (value != null) ? value.toMillis() : null;
        }

        @Override
        protected Duration fromStorage(Object value) {
            Long val = PropertyResolverUtils.toLong(value);
            return (val != null) ? Duration.ofMillis(val) : null;
        }

        private static Long toMillis(Duration value) {
            return value == null ? null : value.toMillis();
        }

        protected static Duration atLeast(String name, Duration value, Duration min) {
            if (min != null) {
                ValidateUtils.checkTrue(value != null && min.compareTo(value) <= 0,
                        "Property %s must be at least %d ms; actual value: %d ms", name, toMillis(min), toMillis(value));
            }
            return value;
        }
    }

    class DurationInSecondsProperty extends DurationProperty {
        public DurationInSecondsProperty(String name) {
            this(name, null);
        }

        public DurationInSecondsProperty(String name, Duration def) {
            super(name, def);
        }

        public DurationInSecondsProperty(String name, Duration def, Duration min) {
            super(name, def, min);
        }

        @Override
        protected Object toStorage(Duration value) {
            atLeast(getName(), value, min);
            return (value != null) ? value.getSeconds() : null;
        }

        @Override
        protected Duration fromStorage(Object value) {
            Long val = PropertyResolverUtils.toLong(value);
            return val != null ? Duration.ofSeconds(val) : null;
        }
    }

    class StringProperty extends BaseProperty {
        public StringProperty(String name) {
            this(name, null);
        }

        public StringProperty(String name, String def) {
            super(name, String.class, def);
        }

        @Override
        protected String fromStorage(Object value) {
            return (value != null) ? value.toString() : null;
        }
    }

    class BooleanProperty extends BaseProperty {
        public BooleanProperty(String name) {
            this(name, null);
        }

        public BooleanProperty(String name, Boolean defaultValue) {
            super(name, Boolean.class, defaultValue);
        }

        @Override
        protected Boolean fromStorage(Object value) {
            return PropertyResolverUtils.toBoolean(value);
        }
    }

    class LongProperty extends BaseProperty {
        public LongProperty(String name) {
            this(name, null);
        }

        public LongProperty(String name, Long defaultValue) {
            super(name, Long.class, defaultValue);
        }

        @Override
        protected Long fromStorage(Object value) {
            return PropertyResolverUtils.toLong(value);
        }
    }

    class IntegerProperty extends BaseProperty {
        public IntegerProperty(String name) {
            this(name, null);
        }

        public IntegerProperty(String name, Integer defaultValue) {
            super(name, Integer.class, defaultValue);
        }

        @Override
        protected Integer fromStorage(Object value) {
            return PropertyResolverUtils.toInteger(value);
        }
    }

    class CharsetProperty extends BaseProperty {
        public CharsetProperty(String name) {
            this(name, null);
        }

        public CharsetProperty(String name, Charset defaultValue) {
            super(name, Charset.class, defaultValue);
        }

        @Override
        protected Charset fromStorage(Object value) {
            return PropertyResolverUtils.toCharset(value);
        }
    }

    class ObjectProperty extends BaseProperty {
        public ObjectProperty(String name) {
            this(name, null);
        }

        public ObjectProperty(String name, Object defaultValue) {
            super(name, Object.class, defaultValue);
        }

        @Override
        protected Object fromStorage(Object value) {
            return value;
        }
    }

    class EnumProperty> extends BaseProperty {
        protected final Collection values;

        public EnumProperty(String name, Class type) {
            this(name, type, null);
        }

        public EnumProperty(String name, Class type, T def) {
            super(name, type, def);
            values = Collections.unmodifiableSet(EnumSet.allOf(type));
        }

        @Override
        protected T fromStorage(Object value) {
            Class type = getType();
            return PropertyResolverUtils.toEnum(type, value, false, values);
        }
    }

    class Validating implements Property {
        protected final Property delegate;
        protected final Consumer validator;

        public Validating(Property delegate, Consumer validator) {
            this.delegate = delegate;
            this.validator = validator;
        }

        @Override
        public String getName() {
            return delegate.getName();
        }

        @Override
        public Class getType() {
            return delegate.getType();
        }

        @Override
        public Optional getDefault() {
            return delegate.getDefault();
        }

        @Override
        public T getRequiredDefault() {
            return delegate.getRequiredDefault();
        }

        @Override
        public Optional get(PropertyResolver resolver) {
            Optional t = delegate.get(resolver);
            t.ifPresent(validator);
            return t;
        }

        @Override
        public T getOrCustomDefault(PropertyResolver resolver, T defaultValue) {
            T value = delegate.getOrCustomDefault(resolver, defaultValue);
            validator.accept(value);
            return value;
        }

        @Override
        public void set(PropertyResolver resolver, T value) {
            validator.accept(value);
            delegate.set(resolver, value);
        }

        @Override
        public void remove(PropertyResolver resolver) {
            delegate.remove(resolver);
        }
    }

    /**
     * @return Property type - Note: for primitive types the wrapper equivalent is returned
     */
    Class getType();

    /**
     * @return The {@link Optional} pre-defined default value
     */
    Optional getDefault();

    default T getRequiredDefault() {
        return getDefault().get();
    }

    /**
     * @param  resolver The {@link PropertyResolver} to query for the property value.
     * @return          The {@link Optional} result - if resolver contains a value then the resolver's value, otherwise
     *                  the pre-defined {@link #getDefault() default}
     */
    Optional get(PropertyResolver resolver);

    /**
     * @param  resolver               The {@link PropertyResolver} to query for the property value.
     * @return                        The resolved value
     * @throws NoSuchElementException if resolver contains no value and no {@link #getDefault()} defined
     */
    default T getRequired(PropertyResolver resolver) {
        return get(resolver).get();
    }

    /**
     * @param  resolver The {@link PropertyResolver} to query for the property value.
     * @return          The resolver's value or {@code null} if no specific value found in the resolver - regardless of
     *                  whether there is a default value
     */
    default T getOrNull(PropertyResolver resolver) {
        return getOrCustomDefault(resolver, null);
    }

    /**
     * @param  resolver     The {@link PropertyResolver} to query for the property value.
     * @param  defaultValue The default value to return if no specific value found in resolver
     * @return              The resolver's value or specified default if no specific value found in the resolver -
     *                      regardless of whether there is a default value
     */
    T getOrCustomDefault(PropertyResolver resolver, T defaultValue);

    /**
     * @param resolver The {@link PropertyResolver} to update with the property value.
     * @param value    The value to set
     */
    void set(PropertyResolver resolver, T value);

    /**
     * @param resolver The {@link PropertyResolver} to remove the property from
     */
    default void remove(PropertyResolver resolver) {
        PropertyResolverUtils.updateProperty(resolver, getName(), null);
    }
}