org.apache.jackrabbit.oak.spi.security.ConfigurationParameters Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of aem-sdk-api Show documentation
Show all versions of aem-sdk-api Show documentation
The Adobe Experience Manager SDK
/*
* 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.jackrabbit.oak.spi.security;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.jackrabbit.guava.common.collect.ImmutableMap;
import org.apache.jackrabbit.guava.common.collect.ImmutableSet;
import org.apache.jackrabbit.oak.commons.PropertiesUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* ConfigurationParameters is a convenience class that allows typed access to configuration properties. It implements
* the {@link Map} interface but is immutable.
*/
public final class ConfigurationParameters implements Map {
/**
* internal logger
*/
private static final Logger log = LoggerFactory.getLogger(ConfigurationParameters.class);
/**
* An empty configuration parameters
*/
public static final ConfigurationParameters EMPTY = new ConfigurationParameters();
/**
* internal map of the config parameters
*/
private final Map options;
/**
* creates an empty config parameters instance.
* Note: the constructor is private to avoid creation of empty maps.
*/
private ConfigurationParameters() {
this.options = Collections.emptyMap();
}
/**
* Creates an config parameter instance.
* Note: the constructor is private to avoid creation of empty maps.
* @param options the source options.
*/
private ConfigurationParameters(@NotNull Map options) {
this.options = Collections.unmodifiableMap(options);
}
/**
* Creates a new configuration parameters instance by merging all {@code params} sequentially.
* I.e. property define in subsequent arguments overwrite the ones before.
*
* @param params source parameters to merge
* @return merged configuration parameters or {@link #EMPTY} if all source params were empty.
*/
@NotNull
public static ConfigurationParameters of(@NotNull ConfigurationParameters... params) {
Map m = new HashMap<>();
for (ConfigurationParameters cp : params) {
if (cp != null) {
m.putAll(cp.options);
}
}
return m.isEmpty() ? EMPTY : new ConfigurationParameters(m);
}
/**
* Creates new a configuration parameters instance by copying the given properties.
* @param properties source properties
* @return configuration parameters or {@link #EMPTY} if the source properties were empty.
*/
@NotNull
public static ConfigurationParameters of(@NotNull Properties properties) {
if (properties.isEmpty()) {
return EMPTY;
}
Map options = new HashMap<>(properties.size());
for (Object name : properties.keySet()) {
final String key = name.toString();
options.put(key, properties.get(key));
}
return new ConfigurationParameters(options);
}
/**
* Creates new a configuration parameters instance by copying the given properties.
* @param properties source properties
* @return configuration parameters or {@link #EMPTY} if the source properties were empty.
*/
@NotNull
public static ConfigurationParameters of(@NotNull Dictionary properties) {
if (properties.isEmpty()) {
return EMPTY;
}
Map options = new HashMap<>(properties.size());
for (Enumeration keys = properties.keys(); keys.hasMoreElements();) {
String key = keys.nextElement();
options.put(key, properties.get(key));
}
return new ConfigurationParameters(options);
}
/**
* Creates new a configuration parameters instance by copying the given map.
* @param map source map
* @return configuration parameters or {@link #EMPTY} if the source map was empty.
*/
@NotNull
public static ConfigurationParameters of(@NotNull Map, ?> map) {
if (map.isEmpty()) {
return EMPTY;
}
if (map instanceof ConfigurationParameters) {
return (ConfigurationParameters) map;
}
Map options = new HashMap<>(map.size());
map.forEach((key, value) -> options.put(String.valueOf(key), value));
return new ConfigurationParameters(options);
}
/**
* Creates new a single valued configuration parameters instance from the
* given key and value.
*
* @param key The key
* @param value The value
* @return a new instance of configuration parameters.
*/
@NotNull
public static ConfigurationParameters of(@NotNull String key, @NotNull Object value) {
return new ConfigurationParameters(ImmutableMap.of(key, value));
}
/**
* Creates new a configuration parameters instance from the
* given key and value pairs.
*
* @param key1 The key of the first pair.
* @param value1 The value of the first pair
* @param key2 The key of the second pair.
* @param value2 The value of the second pair.
* @return a new instance of configuration parameters.
*/
@NotNull
public static ConfigurationParameters of(@NotNull String key1, @NotNull Object value1,
@NotNull String key2, @NotNull Object value2) {
return new ConfigurationParameters(ImmutableMap.of(key1, value1, key2, value2));
}
/**
* Returns {@code true} if this instance contains a configuration entry with
* the specified key irrespective of the defined value; {@code false} otherwise.
*
* @param key The key to be tested.
* @return {@code true} if this instance contains a configuration entry with
* the specified key irrespective of the defined value; {@code false} otherwise.
*/
public boolean contains(@NotNull String key) {
return options.containsKey(key);
}
/**
* Returns the value of the configuration entry with the given {@code key}
* applying the following rules:
*
*
* - If this instance doesn't contain a configuration entry with that
* key the specified {@code defaultValue} will be returned.
* - If {@code defaultValue} is {@code null} the original value will
* be returned.
* - If the configured value is {@code null} this method will always
* return {@code null}.
* - If neither {@code defaultValue} nor the configured value is
* {@code null} an attempt is made to convert the configured value to
* match the type of the default value.
*
*
* @param key The name of the configuration option.
* @param defaultValue The default value to return if no such entry exists
* or to use for conversion.
* @param targetClass The target class
* @return The original or converted configuration value or {@code null}.
*/
@Nullable
public T getConfigValue(@NotNull String key, @Nullable T defaultValue,
@Nullable Class targetClass) {
if (options.containsKey(key)) {
Object property = options.get(key);
return (property == null) ? null : convert(property, getTargetClass(property, defaultValue, targetClass));
} else {
return defaultValue;
}
}
/**
* Returns the value of the configuration entry with the given {@code key}
* applying the following rules:
*
*
* - If this instance doesn't contain a configuration entry with that
* key, or if the entry is {@code null}, the specified {@code defaultValue} will be returned.
* - If the configured value is not {@code null} an attempt is made to convert the configured value to
* match the type of the default value.
*
*
* @param key The name of the configuration option.
* @param defaultValue The default value to return if no such entry exists
* or to use for conversion.
* @return The original or converted configuration value or {@code defaultValue} if no entry for the given key exists.
*/
@NotNull
public T getConfigValue(@NotNull String key, @NotNull T defaultValue) {
Object property = options.get(key);
if (property == null) {
return defaultValue;
} else {
T value = convert(property, getTargetClass(property, defaultValue, null));
return (value == null) ? defaultValue : value;
}
}
//--------------------------------------------------------< private >---
@NotNull
private static Class> getTargetClass(@NotNull Object configProperty, @Nullable Object defaultValue, @Nullable Class> targetClass) {
Class> clazz = targetClass;
if (clazz == null) {
clazz = (defaultValue == null)
? configProperty.getClass()
: defaultValue.getClass();
}
return clazz;
}
@SuppressWarnings("unchecked")
@Nullable
private static T convert(@NotNull Object configProperty, @NotNull Class> clazz) {
String str = configProperty.toString();
if (clazz.isAssignableFrom(configProperty.getClass())) {
return (T) configProperty;
} else if (clazz == String.class) {
return (T) str;
} else if (clazz == Milliseconds.class) {
Milliseconds ret = Milliseconds.of(str);
return ret == null ? null : (T) ret;
} else if (clazz == Boolean.class || clazz == boolean.class) {
return (T) Boolean.valueOf(str);
} else if (clazz == String[].class){
return (T) PropertiesUtil.toStringArray(configProperty);
} else if (clazz == Set.class || Set.class.isAssignableFrom(clazz)) {
return (T) convertToSet(configProperty, clazz);
} else {
return (T) convertToNumber(str, clazz);
}
}
@NotNull
private static Object convertToNumber(@NotNull String str, @NotNull Class> clazz) {
try {
if (clazz == Integer.class || clazz == int.class) {
return Integer.valueOf(str);
} else if (clazz == Long.class || clazz == long.class) {
return Long.valueOf(str);
} else if (clazz == Float.class || clazz == float.class) {
return Float.valueOf(str);
} else if (clazz == Double.class || clazz == double.class) {
return Double.valueOf(str);
} else {
// unsupported target type
log.warn("Unsupported target type {} for value {}", clazz.getName(), str);
throw conversionFailedException(str, clazz.getName(), null);
}
} catch (NumberFormatException e) {
log.warn("Invalid value {}; cannot be parsed into {}", str, clazz.getName());
throw conversionFailedException(str, clazz.getName(), e);
}
}
@NotNull
private static Set> convertToSet(@NotNull Object configProperty, @NotNull Class> clazz) {
if (configProperty instanceof Set) {
return (Set) configProperty;
} else if (configProperty instanceof Collection>) {
return ImmutableSet.copyOf((Collection>) configProperty);
} else if (configProperty.getClass().isArray()) {
return ImmutableSet.copyOf((Object[]) configProperty);
} else {
String[] arr = PropertiesUtil.toStringArray(configProperty);
if (arr != null) {
return ImmutableSet.copyOf(arr);
} else {
String str = configProperty.toString();
log.warn("Unsupported target type {} for value {}", clazz.getName(), str);
throw conversionFailedException(str, clazz.getName(), null);
}
}
}
@NotNull
private static IllegalArgumentException conversionFailedException(@NotNull String str, @NotNull String className, @Nullable Exception e) {
return new IllegalArgumentException("Cannot convert config entry " + str + " to " + className, e);
}
//-------------------------------------------< Map interface delegation >---
/**
* {@inheritDoc}
*/
@Override
public int size() {
return options.size();
}
/**
* {@inheritDoc}
*/
@Override
public boolean isEmpty() {
return options.isEmpty();
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsKey(Object key) {
return options.containsKey(key);
}
/**
* {@inheritDoc}
*/
@Override
public boolean containsValue(Object value) {
return options.containsValue(value);
}
/**
* {@inheritDoc}
*/
@Override
public Object get(Object key) {
return options.get(key);
}
/**
* {@inheritDoc}
*/
@Override
public Object put(String key, Object value) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public Object remove(Object key) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void putAll(@NotNull Map extends String, ?> m) {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@Override
public void clear() {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
*/
@NotNull
@Override
public Set keySet() {
return options.keySet();
}
/**
* {@inheritDoc}
*/
@NotNull
@Override
public Collection
© 2015 - 2024 Weber Informatics LLC | Privacy Policy