package org.jboss.resteasy.util;
import org.jboss.resteasy.core.ExceptionAdapter;
import org.jboss.resteasy.resteasy_jaxrs.i18n.LogMessages;
import org.jboss.resteasy.resteasy_jaxrs.i18n.Messages;
import java.lang.reflect.Constructor;
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.Date;
import java.util.HashMap;
import java.util.Map;
public final class TypeConverter
{
private static final String VALUE_OF_METHOD = "valueOf";
private static final boolean java2SecurityEnabled = System.getSecurityManager() != null;
private static final Map<Class<?>, Class<?>> PRIMITIVES;
static
{
PRIMITIVES = new HashMap<Class<?>, Class<?>>();
PRIMITIVES.put(int.class, Integer.class);
PRIMITIVES.put(double.class, Double.class);
PRIMITIVES.put(float.class, Float.class);
PRIMITIVES.put(short.class, Short.class);
PRIMITIVES.put(byte.class, Byte.class);
PRIMITIVES.put(long.class, Long.class);
}
private TypeConverter()
{
}
@SuppressWarnings(value = "unchecked")
public static <T> T getType(final Class<T> targetType, final String source)
{
if (String.class.equals(targetType))
{
return targetType.cast(source);
}
if (Date.class.isAssignableFrom(targetType))
{
throw new IllegalArgumentException(Messages.MESSAGES.dateInstancesNotSupported());
}
if (Character.class.equals(targetType))
{
if (source.length() == 0) return targetType.cast(new Character('\0'));
return targetType.cast(new Character(source.charAt(0)));
}
if (char.class.equals(targetType))
{
Character c = null;
if (source.length() == 0)c = new Character('\0');
else c = new Character(source.charAt(0));
try
{
return (T)Character.class.getMethod("charValue").invoke(c);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
}
}
T result;
if (Boolean.class.equals(targetType) || boolean.class.equals(targetType))
{
Boolean booleanValue = getBooleanValue(source);
if (Boolean.class.equals(targetType))
{
return targetType.cast(booleanValue);
}
else
{
try
{
return (T)Boolean.class.getMethod("booleanValue").invoke(booleanValue);
}
catch (IllegalAccessException e)
{
throw new RuntimeException(e);
}
catch (InvocationTargetException e)
{
throw new RuntimeException(e);
}
catch (NoSuchMethodException e)
{
throw new RuntimeException(e);
}
}
}
try
{
result = getTypeViaValueOfMethod(source, targetType);
}
catch (NoSuchMethodException e)
{
LogMessages.LOGGER.noValueOfMethodAvailable(targetType.getSimpleName());
result = getTypeViaStringConstructor(source, targetType);
}
return result;
}
public static boolean isConvertable(final Class<?> targetType)
{
if (Boolean.class.equals(targetType))
{
return true;
}
if (Character.class.equals(targetType))
{
return true;
}
if (targetType.isPrimitive())
{
return true;
}
try
{
getDeclaredMethod(targetType, VALUE_OF_METHOD, String.class);
return true;
}
catch (NoSuchMethodException e)
{
try
{
getDeclaredConstructor(targetType, String.class);
return true;
}
catch (NoSuchMethodException e1)
{
return false;
}
}
}
public static Boolean getBooleanValue(final String source)
{
if ("Y".equalsIgnoreCase(source) || "T".equalsIgnoreCase(source)
|| "Yes".equalsIgnoreCase(source) || "1".equalsIgnoreCase(source))
{
return Boolean.TRUE;
}
else if ("N".equals(source) || "F".equals(source) || "No".equals(source)
|| "0".equalsIgnoreCase(source))
{
return Boolean.FALSE;
}
return Boolean.valueOf(source);
}
@SuppressWarnings("unchecked")
public static <T> T getTypeViaValueOfMethod(final String source, final Class<T> targetType)
throws NoSuchMethodException
{
Class<?> actualTarget = targetType;
if (targetType.isPrimitive())
{
actualTarget = PRIMITIVES.get(targetType);
}
T result = null;
try
{
Method valueOf = getDeclaredMethod(actualTarget, VALUE_OF_METHOD, String.class);
Object value = valueOf.invoke(null, source);
if (actualTarget.equals(targetType) && targetType.isInstance(value))
{
result = targetType.cast(value);
}
else if (!actualTarget.equals(targetType) && actualTarget.isInstance(value))
{
result = (T) value;
}
}
catch (IllegalAccessException e)
{
throw new ExceptionAdapter(e);
}
catch (InvocationTargetException e)
{
throw new ExceptionAdapter(e);
}
return result;
}
private static <T> T getTypeViaStringConstructor(String source, Class<T> targetType)
{
T result = null;
Constructor<T> c = null;
try
{
c = getDeclaredConstructor(targetType, String.class);
}
catch (NoSuchMethodException e)
{
throw new IllegalArgumentException(Messages.MESSAGES.hasNoStringConstructor(targetType.getName()), e);
}
try
{
result = c.newInstance(source);
}
catch (InstantiationException e)
{
throw new ExceptionAdapter(e);
}
catch (IllegalAccessException e)
{
throw new ExceptionAdapter(e);
}
catch (InvocationTargetException e)
{
throw new ExceptionAdapter(e);
}
return result;
}
private static Method getDeclaredMethod(Class<?> type, String name, Class<?>... parameterTypes)
throws NoSuchMethodException
{
if (java2SecurityEnabled)
{
try
{
return AccessController.doPrivileged((PrivilegedExceptionAction<Method>) () -> {
return type.getDeclaredMethod(name, parameterTypes);
});
}
catch (PrivilegedActionException pae)
{
Throwable cause = pae.getCause();
if (cause instanceof NoSuchMethodException)
throw (NoSuchMethodException) cause;
throw new RuntimeException(cause);
}
}
return type.getDeclaredMethod(name, parameterTypes);
}
private static <T> Constructor<T> getDeclaredConstructor(Class<T> type, Class<?>... parameterTypes)
throws NoSuchMethodException
{
if (java2SecurityEnabled)
{
try
{
return AccessController.doPrivileged((PrivilegedExceptionAction<Constructor<T>>) () -> {
return type.getDeclaredConstructor(parameterTypes);
});
}
catch (PrivilegedActionException pae)
{
Throwable cause = pae.getCause();
if (cause instanceof NoSuchMethodException)
throw (NoSuchMethodException) cause;
throw new RuntimeException(cause);
}
}
return type.getDeclaredConstructor(parameterTypes);
}
}