/*
 * Copyright (c) 2012, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.glassfish.jersey.internal.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

import jakarta.ws.rs.RuntimeType;

import org.glassfish.jersey.CommonProperties;
import org.glassfish.jersey.internal.LocalizationMessages;

Helper class containing convenience methods for reading org.glassfish.jersey.server.ResourceConfig and Configuration properties.
Author:Martin Matula
/** * Helper class containing convenience methods for reading * {@code org.glassfish.jersey.server.ResourceConfig} and {@link jakarta.ws.rs.core.Configuration} properties. * * @author Martin Matula */
public final class PropertiesHelper { private static final Logger LOGGER = Logger.getLogger(PropertiesHelper.class.getName()); private static final boolean METAINF_SERVICES_LOOKUP_DISABLE_DEFAULT = false;
Get system properties. This method delegates to System.getProperties() while running it in a privileged code block.
Returns:privileged action to obtain system properties.
/** * Get system properties. * * This method delegates to {@link System#getProperties()} while running it in a privileged * code block. * * @return privileged action to obtain system properties. */
public static PrivilegedAction<Properties> getSystemProperties() { return new PrivilegedAction<Properties>() { @Override public Properties run() { return System.getProperties(); } }; }
Get system property. This method delegates to System.getProperty(String) while running it in a privileged code block.
Params:
  • name – system property name.
Returns:privileged action to obtain system property value that will return null if there's no such system property.
/** * Get system property. * * This method delegates to {@link System#getProperty(String)} while running it in a privileged * code block. * * @param name system property name. * @return privileged action to obtain system property value that will return {@code null} * if there's no such system property. */
public static PrivilegedAction<String> getSystemProperty(final String name) { return new PrivilegedAction<String>() { @Override public String run() { return System.getProperty(name); } }; }
Get system property. This method delegates to System.getProperty(String) while running it in a privileged code block.
Params:
  • name – system property name.
  • def – default property value.
Returns:privileged action to obtain system property value that will return the default value if there's no such system property.
/** * Get system property. * * This method delegates to {@link System#getProperty(String)} while running it in a privileged * code block. * * @param name system property name. * @param def default property value. * @return privileged action to obtain system property value that will return the default value * if there's no such system property. */
public static PrivilegedAction<String> getSystemProperty(final String name, final String def) { return new PrivilegedAction<String>() { @Override public String run() { return System.getProperty(name, def); } }; }
Return value of a specified property. If the property is not set or the real value type is not compatible with defaultValue type, the specified defaultValue is returned. Calling this method is equivalent to calling PropertyHelper.getValue(properties, key, defaultValue, (Class<T>) defaultValue.getClass())
Params:
  • properties – Map of properties to get the property value from.
  • key – Name of the property.
  • defaultValue – Default value to be returned if the specified property is not set or cannot be read.
  • legacyMap – Legacy fallback map, where key is the actual property name, value is the old property name
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or defaultValue.
/** * Return value of a specified property. If the property is not set or the real value type is not compatible with * defaultValue type, the specified defaultValue is returned. Calling this method is equivalent to calling * {@code PropertyHelper.getValue(properties, key, defaultValue, (Class<T>) defaultValue.getClass())} * * @param properties Map of properties to get the property value from. * @param key Name of the property. * @param defaultValue Default value to be returned if the specified property is not set or cannot be read. * @param <T> Type of the property value. * @param legacyMap Legacy fallback map, where key is the actual property name, value is the old property name * @return Value of the property or defaultValue. */
public static <T> T getValue(Map<String, ?> properties, String key, T defaultValue, Map<String, String> legacyMap) { return getValue(properties, null, key, defaultValue, legacyMap); }
Return value of a specified property. If the property is not set or the real value type is not compatible with defaultValue type, the specified defaultValue is returned. Calling this method is equivalent to calling PropertyHelper.getValue(properties, runtimeType, key, defaultValue, (Class<T>) defaultValue.getClass())
Params:
  • properties – Map of properties to get the property value from.
  • runtimeType – Runtime type which is used to check whether there is a property with the same key but post-fixed by runtime type (.server or .client) which would override the key property.
  • key – Name of the property.
  • defaultValue – Default value to be returned if the specified property is not set or cannot be read.
  • legacyMap – Legacy fallback map, where key is the actual property name, value is the old property name
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or defaultValue.
/** * Return value of a specified property. If the property is not set or the real value type is not compatible with * defaultValue type, the specified defaultValue is returned. Calling this method is equivalent to calling * {@code PropertyHelper.getValue(properties, runtimeType, key, defaultValue, (Class<T>) defaultValue.getClass())} * * @param properties Map of properties to get the property value from. * @param runtimeType Runtime type which is used to check whether there is a property with the same * {@code key} but post-fixed by runtime type (<tt>.server</tt> * or {@code .client}) which would override the {@code key} property. * @param key Name of the property. * @param defaultValue Default value to be returned if the specified property is not set or cannot be read. * @param <T> Type of the property value. * @param legacyMap Legacy fallback map, where key is the actual property name, value is the old property name * @return Value of the property or defaultValue. */
@SuppressWarnings("unchecked") public static <T> T getValue(Map<String, ?> properties, RuntimeType runtimeType, String key, T defaultValue, Map<String, String> legacyMap) { return getValue(properties, runtimeType, key, defaultValue, (Class<T>) defaultValue.getClass(), legacyMap); }
Returns value of a specified property. If the property is not set or the real value type is not compatible with the specified value type, returns defaultValue.
Params:
  • properties – Map of properties to get the property value from.
  • key – Name of the property.
  • defaultValue – Default value of the property.
  • type – Type to retrieve the value as.
  • legacyMap – Legacy fallback map, where key is the actual property name, value is the old property name
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or null.
/** * Returns value of a specified property. If the property is not set or the real value type is not compatible with * the specified value type, returns defaultValue. * * @param properties Map of properties to get the property value from. * @param key Name of the property. * @param defaultValue Default value of the property. * @param type Type to retrieve the value as. * @param <T> Type of the property value. * @param legacyMap Legacy fallback map, where key is the actual property name, value is the old property name * @return Value of the property or null. */
public static <T> T getValue(Map<String, ?> properties, String key, T defaultValue, Class<T> type, Map<String, String> legacyMap) { return getValue(properties, null, key, defaultValue, type, legacyMap); }
Returns value of a specified property. If the property is not set or the real value type is not compatible with the specified value type, returns defaultValue.
Params:
  • properties – Map of properties to get the property value from.
  • runtimeType – Runtime type which is used to check whether there is a property with the same key but post-fixed by runtime type (.server or .client) which would override the key property.
  • key – Name of the property.
  • defaultValue – Default value of the property.
  • type – Type to retrieve the value as.
  • legacyMap – Legacy fallback map, where key is the actual property name, value is the old property name
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or null.
/** * Returns value of a specified property. If the property is not set or the real value type is not compatible with * the specified value type, returns defaultValue. * * @param properties Map of properties to get the property value from. * @param runtimeType Runtime type which is used to check whether there is a property with the same * {@code key} but post-fixed by runtime type (<tt>.server</tt> * or {@code .client}) which would override the {@code key} property. * @param key Name of the property. * @param defaultValue Default value of the property. * @param type Type to retrieve the value as. * @param <T> Type of the property value. * @param legacyMap Legacy fallback map, where key is the actual property name, value is the old property name * @return Value of the property or null. */
public static <T> T getValue(Map<String, ?> properties, RuntimeType runtimeType, String key, T defaultValue, Class<T> type, Map<String, String> legacyMap) { T value = getValue(properties, runtimeType, key, type, legacyMap); if (value == null) { value = defaultValue; } return value; }
Returns value of a specified property. If the property is not set or the real value type is not compatible with the specified value type, returns null.
Params:
  • properties – Map of properties to get the property value from.
  • key – Name of the property.
  • type – Type to retrieve the value as.
  • legacyMap – Legacy fallback map, where key is the actual property name, value is the old property name
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or null.
/** * Returns value of a specified property. If the property is not set or the real value type is not compatible with * the specified value type, returns null. * * @param properties Map of properties to get the property value from. * @param key Name of the property. * @param type Type to retrieve the value as. * @param <T> Type of the property value. * @param legacyMap Legacy fallback map, where key is the actual property name, value is the old property name * @return Value of the property or null. */
public static <T> T getValue(Map<String, ?> properties, String key, Class<T> type, Map<String, String> legacyMap) { return getValue(properties, null, key, type, legacyMap); }
Returns value of a specified property. If the property is not set or the real value type is not compatible with the specified value type, returns null.
Params:
  • properties – Map of properties to get the property value from.
  • runtimeType – Runtime type which is used to check whether there is a property with the same key but post-fixed by runtime type (.server or .client) which would override the key property.
  • key – Name of the property.
  • type – Type to retrieve the value as.
Type parameters:
  • <T> – Type of the property value.
Returns:Value of the property or null.
/** * Returns value of a specified property. If the property is not set or the real value type is not compatible with * the specified value type, returns null. * * @param properties Map of properties to get the property value from. * @param runtimeType Runtime type which is used to check whether there is a property with the same * {@code key} but post-fixed by runtime type (<tt>.server</tt> * or {@code .client}) which would override the {@code key} property. * @param key Name of the property. * @param type Type to retrieve the value as. * @param <T> Type of the property value. * @return Value of the property or null. */
public static <T> T getValue(Map<String, ?> properties, RuntimeType runtimeType, String key, Class<T> type, Map<String, String> legacyMap) { Object value = null; if (runtimeType != null) { String runtimeAwareKey = getPropertyNameForRuntime(key, runtimeType); if (key.equals(runtimeAwareKey)) { // legacy behaviour runtimeAwareKey = key + "." + runtimeType.name().toLowerCase(Locale.ROOT); } value = properties.get(runtimeAwareKey); } if (value == null) { value = properties.get(key); } if (value == null) { value = getLegacyFallbackValue(properties, legacyMap, key); } if (value == null) { return null; } return convertValue(value, type); }
Returns specific property value for given RuntimeType. Some properties have complementary client and server versions along with a common version (effective for both environments, if the specific one is not set). This methods returns a specific name for the environment (determined by convention), if runtime is not null, the property is a Jersey property name (starts with jersey.config) and does not contain a runtime specific part already. If those conditions are not met, original property name is returned.
Params:
  • key – property name
  • runtimeType – runtime type
Returns:runtime-specific property name, where possible, original key in other cases. original key
/** * Returns specific property value for given {@link RuntimeType}. * * Some properties have complementary client and server versions along with a common version (effective for both environments, * if the specific one is not set). This methods returns a specific name for the environment (determined by convention), * if runtime is not null, the property is a Jersey property name (starts with {@code jersey.config}) and does not contain * a runtime specific part already. If those conditions are not met, original property name is returned. * * @param key property name * @param runtimeType runtime type * @return runtime-specific property name, where possible, original key in other cases. * original key */
public static String getPropertyNameForRuntime(String key, RuntimeType runtimeType) { if (runtimeType != null && key.startsWith("jersey.config")) { RuntimeType[] types = RuntimeType.values(); for (RuntimeType type : types) { if (key.startsWith("jersey.config." + type.name().toLowerCase(Locale.ROOT))) { return key; } } return key.replace("jersey.config", "jersey.config." + runtimeType.name().toLowerCase(Locale.ROOT)); } return key; } private static Object getLegacyFallbackValue(Map<String, ?> properties, Map<String, String> legacyFallbackMap, String key) { if (legacyFallbackMap == null || !legacyFallbackMap.containsKey(key)) { return null; } String fallbackKey = legacyFallbackMap.get(key); Object value = properties.get(fallbackKey); if (value != null && LOGGER.isLoggable(Level.CONFIG)) { LOGGER.config(LocalizationMessages.PROPERTIES_HELPER_DEPRECATED_PROPERTY_NAME(fallbackKey, key)); } return value; }
Convert Object value to a value of the specified class type.
Params:
  • value – Object value to convert.
  • type – conversion type.
Type parameters:
  • <T> – converted value type.
Returns:value converted to the specified class type.
/** * Convert {@code Object} value to a value of the specified class type. * * @param value {@code Object} value to convert. * @param type conversion type. * @param <T> converted value type. * @return value converted to the specified class type. */
public static <T> T convertValue(Object value, Class<T> type) { if (!type.isInstance(value)) { // TODO: Move string value readers from server to common and utilize them here final Constructor constructor = AccessController.doPrivileged(ReflectionHelper.getStringConstructorPA(type)); if (constructor != null) { try { return type.cast(constructor.newInstance(value)); } catch (Exception e) { // calling the constructor wasn't successful - ignore and try valueOf() } } final Method valueOf = AccessController.doPrivileged(ReflectionHelper.getValueOfStringMethodPA(type)); if (valueOf != null) { try { return type.cast(valueOf.invoke(null, value)); } catch (Exception e) { // calling valueOf wasn't successful } } // at this point we don't know what to return -> return null if (LOGGER.isLoggable(Level.WARNING)) { LOGGER.warning(LocalizationMessages.PROPERTIES_HELPER_GET_VALUE_NO_TRANSFORM(String.valueOf(value), value.getClass().getName(), type.getName())); } return null; } return type.cast(value); }
Determine whether CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE does not globally disable META-INF/services lookup on client/server.
Params:
  • properties – map containing application properties. May be null
  • runtimeType – runtime (client or server) where the service finder binder is used.
Returns:true if the CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE is not se to true
/** * Determine whether {@link CommonProperties#METAINF_SERVICES_LOOKUP_DISABLE} does not globally * disable META-INF/services lookup on client/server. * * @param properties map containing application properties. May be {@code null} * @param runtimeType runtime (client or server) where the service finder binder is used. * @return {@code true} if the {@link CommonProperties#METAINF_SERVICES_LOOKUP_DISABLE} is not se to true */
public static boolean isMetaInfServicesEnabled(Map<String, Object> properties, RuntimeType runtimeType) { boolean disableMetaInfServicesLookup = METAINF_SERVICES_LOOKUP_DISABLE_DEFAULT; if (properties != null) { disableMetaInfServicesLookup = CommonProperties.getValue(properties, runtimeType, CommonProperties.METAINF_SERVICES_LOOKUP_DISABLE, METAINF_SERVICES_LOOKUP_DISABLE_DEFAULT, Boolean.class); } return !disableMetaInfServicesLookup; }
Get the value of the property with a given name converted to boolean. Returns false if the value is not convertible.
Params:
  • properties – key-value map of properties.
  • name – property name.
Returns:boolean property value or false if the property is not convertible.
/** * Get the value of the property with a given name converted to {@code boolean}. Returns {@code false} if the value is * not convertible. * * @param properties key-value map of properties. * @param name property name. * @return {@code boolean} property value or {@code false} if the property is not convertible. */
public static boolean isProperty(final Map<String, Object> properties, final String name) { return properties.containsKey(name) && isProperty(properties.get(name)); }
Get the value of the property converted to boolean. Returns false if the value is not convertible.
Params:
  • value – property value.
Returns:boolean property value or false if the property is not convertible.
/** * Get the value of the property converted to {@code boolean}. Returns {@code false} if the value is not convertible. * * @param value property value. * @return {@code boolean} property value or {@code false} if the property is not convertible. */
public static boolean isProperty(final Object value) { if (value instanceof Boolean) { return Boolean.class.cast(value); } else { return value != null && Boolean.parseBoolean(value.toString()); } }
Prevent instantiation.
/** * Prevent instantiation. */
private PropertiesHelper() { } }