package org.jboss.resteasy.microprofile.config;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Optional;
import javax.servlet.ServletContext;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
public class ResteasyConfig
{
private static final Method GET_CONFIG;
private static final Method GET_OPTIONAL_VALUE;
private static final Method GET_PROPERTY_NAMES;
private Object config;
public enum SOURCE
{
SYSTEM,
ENV,
SERVLET_CONTEXT
}
static {
Method getConfig;
Method getOptionalValue;
Method getPropertyNames;
try {
final ClassLoader classLoader = getClassLoader();
final Class<?> configProvider = Class.forName("org.eclipse.microprofile.config.ConfigProvider", false, classLoader);
getConfig = configProvider.getDeclaredMethod("getConfig", ClassLoader.class);
final Class<?> clazz = Class.forName("org.eclipse.microprofile.config.Config", false, classLoader);
getOptionalValue = clazz.getDeclaredMethod("getOptionalValue", String.class, Class.class);
getPropertyNames = clazz.getDeclaredMethod("getPropertyNames");
Class.forName("org.jboss.resteasy.microprofile.config.ServletConfigSourceImpl", false, classLoader);
} catch (Throwable ignore) {
getConfig = null;
getOptionalValue = null;
getPropertyNames = null;
}
GET_CONFIG = getConfig;
GET_OPTIONAL_VALUE = getOptionalValue;
GET_PROPERTY_NAMES = getPropertyNames;
}
public ResteasyConfig()
{
if (GET_CONFIG != null)
{
try
{
config = GET_CONFIG.invoke(null, getClassLoader());
}
catch (Exception e)
{
}
}
}
@SuppressWarnings("unchecked")
public String getValue(String propertyName)
{
if (config == null)
{
return null;
}
try
{
Optional<String> opt = (Optional<String>) GET_OPTIONAL_VALUE.invoke(config, propertyName, String.class);
return opt.orElse(null);
}
catch (IllegalAccessException | InvocationTargetException e) {
LogMessages.LOGGER.debugf(e, "Failed to invoke the configuration API method %s.", GET_OPTIONAL_VALUE);
return null;
}
}
public String getValue(String propertyName, SOURCE source)
{
return getValue(propertyName, source, null);
}
public String getValue(String propertyName, SOURCE source, String defaultValue)
{
if (System.getSecurityManager() == null)
{
return getValue0(propertyName, source, defaultValue);
}
else
{
String value = null;
try {
value = AccessController.doPrivileged(new PrivilegedExceptionAction<String>()
{
@Override
public String run() throws Exception
{
return getValue0(propertyName, source, defaultValue);
}
});
}
catch (PrivilegedActionException pae)
{
throw new RuntimeException(pae);
}
return value;
}
}
@SuppressWarnings("unchecked")
public String getValue0(String propertyName, SOURCE source, String defaultValue)
{
if (config == null)
{
switch (source) {
case SYSTEM:
return System.getProperty(propertyName, defaultValue);
case ENV:
String value = System.getenv(propertyName);
return value != null ? value : defaultValue;
case SERVLET_CONTEXT:
ServletContext context = ResteasyProviderFactory.getContextData(ServletContext.class);
if (context != null)
{
value = context.getInitParameter(propertyName);
return value != null ? value : defaultValue;
}
else
{
return defaultValue;
}
default:
throw new RuntimeException(Messages.MESSAGES.unknownEnumerationValue(source.toString()));
}
}
else
{
try
{
Optional<String> opt = (Optional<String>) GET_OPTIONAL_VALUE.invoke(config, propertyName, String.class);
return opt.orElse(defaultValue);
}
catch (IllegalAccessException | InvocationTargetException e) {
LogMessages.LOGGER.debugf(e, "Failed to invoke the configuration API method %s.", GET_OPTIONAL_VALUE);
return defaultValue;
}
}
}
public Iterable<String> getPropertyNames()
{
return config == null ? null : getPropertyNames0();
}
@SuppressWarnings("unchecked")
public Iterable<String> getPropertyNames0()
{
if (System.getSecurityManager() == null)
{
try
{
return (Iterable<String>) GET_PROPERTY_NAMES.invoke(config);
}
catch (IllegalAccessException | InvocationTargetException e) {
LogMessages.LOGGER.debugf(e, "Failed to invoke the configuration API method %s.", GET_PROPERTY_NAMES);
return null;
}
}
else
{
Iterable<String> value = null;
try {
value = AccessController.doPrivileged(new PrivilegedExceptionAction<Iterable<String>>()
{
@Override
public Iterable<String> run() throws Exception
{
try
{
return (Iterable<String>) GET_PROPERTY_NAMES.invoke(config);
}
catch (IllegalAccessException | InvocationTargetException e) {
LogMessages.LOGGER.debugf(e, "Failed to invoke the configuration API method %s.", GET_PROPERTY_NAMES);
return null;
}
}
});
}
catch (PrivilegedActionException pae)
{
throw new RuntimeException(pae);
}
return value;
}
}
private static ClassLoader getClassLoader()
{
if (System.getSecurityManager() == null)
{
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
return tccl != null ? tccl : ResteasyConfig.class.getClassLoader();
}
try
{
return AccessController.doPrivileged(new PrivilegedExceptionAction<ClassLoader>()
{
@Override
public ClassLoader run() throws Exception
{
final ClassLoader tccl = Thread.currentThread().getContextClassLoader();
return tccl != null ? tccl : ResteasyConfig.class.getClassLoader();
}
});
}
catch (PrivilegedActionException e)
{
throw new RuntimeException(Messages.MESSAGES.unableToFindClassloader(ResteasyConfig.class.getName()));
}
}
}