org.jboss.jca.adapters.jdbc.util.Injection Maven / Gradle / Ivy
/*
* IronJacamar, a Java EE Connector Architecture implementation
* Copyright 2013, Red Hat Inc, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.jca.adapters.jdbc.util;
import java.io.File;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import java.util.StringTokenizer;
/**
* Injection utility which can inject values into objects. This file is a copy
* of the com.github.fungal.api.util.Injection
class.
*
* @author Jesper Pedersen
*/
public class Injection
{
/**
* Constructor
*/
public Injection()
{
}
/**
* Inject a value into an object property
* @param object The object
* @param propertyName The property name
* @param propertyValue The property value
* @exception NoSuchMethodException If the property method cannot be found
* @exception IllegalAccessException If the property method cannot be accessed
* @exception InvocationTargetException If the property method cannot be executed
*/
@SuppressWarnings("unchecked")
public void inject(Object object, String propertyName, Object propertyValue)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
inject(object, propertyName, propertyValue, null, false);
}
/**
* Inject a value into an object property
* @param object The object
* @param propertyName The property name
* @param propertyValue The property value
* @param propertyType The property type as a fully quilified class name
* @exception NoSuchMethodException If the property method cannot be found
* @exception IllegalAccessException If the property method cannot be accessed
* @exception InvocationTargetException If the property method cannot be executed
*/
@SuppressWarnings("unchecked")
public void inject(Object object, String propertyName, Object propertyValue, String propertyType)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
inject(object, propertyName, propertyValue, propertyType, false);
}
/**
* Inject a value into an object property
* @param object The object
* @param propertyName The property name
* @param propertyValue The property value
* @param propertyType The property type as a fully quilified class name
* @param includeFields Should fields be included for injection if a method can't be found
* @exception NoSuchMethodException If the property method cannot be found
* @exception IllegalAccessException If the property method cannot be accessed
* @exception InvocationTargetException If the property method cannot be executed
*/
@SuppressWarnings("unchecked")
public void inject(Object object,
String propertyName, Object propertyValue, String propertyType,
boolean includeFields)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException
{
if (object == null)
throw new IllegalArgumentException("Object is null");
if (propertyName == null || propertyName.trim().equals(""))
throw new IllegalArgumentException("PropertyName is undefined");
String methodName = "set" + propertyName.substring(0, 1).toUpperCase(Locale.US);
if (propertyName.length() > 1)
{
methodName += propertyName.substring(1);
}
Method method = findMethod(object.getClass(), methodName, propertyType);
if (method != null)
{
Class> parameterClass = method.getParameterTypes()[0];
Object parameterValue = null;
try
{
parameterValue = getValue(propertyName, parameterClass, propertyValue,
SecurityActions.getClassLoader(object.getClass()));
}
catch (Throwable t)
{
throw new InvocationTargetException(t, t.getMessage());
}
if (!parameterClass.isPrimitive() || parameterValue != null)
method.invoke(object, new Object[] {parameterValue});
}
else
{
if (!includeFields)
throw new NoSuchMethodException("Method " + methodName + " not found");
// Ok, we didn't find a method - assume field
Field field = findField(object.getClass(), propertyName, propertyType);
if (field != null)
{
Class> fieldClass = field.getType();
Object fieldValue = null;
try
{
fieldValue = getValue(propertyName, fieldClass, propertyValue,
SecurityActions.getClassLoader(object.getClass()));
}
catch (Throwable t)
{
throw new InvocationTargetException(t, t.getMessage());
}
field.set(object, fieldValue);
}
else
{
throw new NoSuchMethodException("Field " + propertyName + " not found");
}
}
}
/**
* Compare the type of a class with the actual value
* @param classType The class type
* @param propertyType The property type
* @return True if they match, or if there is a primitive mapping
*/
private boolean argumentMatches(String classType, String propertyType)
{
return (classType.equals(propertyType))
|| (classType.equals("java.lang.Byte") && propertyType.equals("byte"))
|| (classType.equals("java.lang.Short") && propertyType.equals("short"))
|| (classType.equals("java.lang.Integer") && propertyType.equals("int"))
|| (classType.equals("java.lang.Long") && propertyType.equals("long"))
|| (classType.equals("java.lang.Float") && propertyType.equals("float"))
|| (classType.equals("java.lang.Double") && propertyType.equals("double"))
|| (classType.equals("java.lang.Boolean") && propertyType.equals("boolean"))
|| (classType.equals("java.lang.Character") && propertyType.equals("char"));
}
/**
* Find a method
* @param clz The class
* @param methodName The method name
* @param propertyType The property type; can be null
* @return The method; null
if not found
*/
protected Method findMethod(Class> clz, String methodName, String propertyType)
{
while (!clz.equals(Object.class))
{
List hits = null;
Method[] methods = SecurityActions.getDeclaredMethods(clz);
for (int i = 0; i < methods.length; i++)
{
final Method method = methods[i];
if (methodName.equals(method.getName()) && method.getParameterTypes().length == 1)
{
if (propertyType == null || argumentMatches(propertyType, method.getParameterTypes()[0].getName()))
{
if (hits == null)
hits = new ArrayList(1);
SecurityActions.setAccessible(method);
hits.add(method);
}
}
}
if (hits != null)
{
if (hits.size() == 1)
{
return hits.get(0);
}
else
{
Collections.sort(hits, new MethodSorter());
if (propertyType != null)
{
for (Method m : hits)
{
if (propertyType.equals(m.getParameterTypes()[0].getName()))
return m;
}
}
return hits.get(0);
}
}
clz = clz.getSuperclass();
}
return null;
}
/**
* Find a field
* @param clz The class
* @param fieldName The field name
* @param fieldType The field type; can be null
* @return The field; null
if not found
*/
protected Field findField(Class> clz, String fieldName, String fieldType)
{
while (!clz.equals(Object.class))
{
List hits = null;
Field[] fields = SecurityActions.getDeclaredFields(clz);
for (int i = 0; i < fields.length; i++)
{
final Field field = fields[i];
if (fieldName.equals(field.getName()))
{
if (fieldType == null || argumentMatches(fieldType, field.getType().getName()))
{
if (hits == null)
hits = new ArrayList(1);
SecurityActions.setAccessible(field);
hits.add(field);
}
}
}
if (hits != null)
{
if (hits.size() == 1)
{
return hits.get(0);
}
else
{
Collections.sort(hits, new FieldSorter());
if (fieldType != null)
{
for (Field f : hits)
{
if (fieldType.equals(f.getType().getName()))
return f;
}
}
return hits.get(0);
}
}
clz = clz.getSuperclass();
}
return null;
}
/**
* Get the value
* @param name The value name
* @param clz The value class
* @param v The value
* @param cl The class loader
* @return The substituted value
* @exception Exception Thrown in case of an error
*/
protected Object getValue(String name, Class> clz, Object v, ClassLoader cl) throws Exception
{
if (v instanceof String)
{
String substituredValue = getSubstitutionValue((String)v);
if (clz.equals(String.class))
{
v = substituredValue;
}
else if (clz.equals(byte.class) || clz.equals(Byte.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Byte.valueOf(substituredValue);
}
else if (clz.equals(short.class) || clz.equals(Short.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Short.valueOf(substituredValue);
}
else if (clz.equals(int.class) || clz.equals(Integer.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Integer.valueOf(substituredValue);
}
else if (clz.equals(long.class) || clz.equals(Long.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Long.valueOf(substituredValue);
}
else if (clz.equals(float.class) || clz.equals(Float.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Float.valueOf(substituredValue);
}
else if (clz.equals(double.class) || clz.equals(Double.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Double.valueOf(substituredValue);
}
else if (clz.equals(boolean.class) || clz.equals(Boolean.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Boolean.valueOf(substituredValue);
}
else if (clz.equals(char.class) || clz.equals(Character.class))
{
if (substituredValue != null && !substituredValue.trim().equals(""))
v = Character.valueOf(substituredValue.charAt(0));
}
else if (clz.equals(InetAddress.class))
{
v = InetAddress.getByName(substituredValue);
}
else if (clz.equals(Class.class))
{
v = Class.forName(substituredValue, true, cl);
}
else if (clz.equals(Properties.class))
{
Properties prop = new Properties();
StringTokenizer st = new StringTokenizer(substituredValue, " ,");
while (st.hasMoreTokens())
{
String token = st.nextToken();
String key = "";
String value = "";
int index = token.indexOf("=");
if (index != -1)
{
key = token.substring(0, index);
if (token.length() > index + 1)
value = token.substring(index + 1);
}
else
{
key = token;
}
if (!"".equals(key))
prop.setProperty(key, value);
}
v = prop;
}
else
{
try
{
Constructor> constructor = SecurityActions.getConstructor(clz, String.class);
v = constructor.newInstance(substituredValue);
}
catch (Throwable t)
{
// Try static String valueOf method
try
{
Method valueOf = SecurityActions.getMethod(clz, "valueOf", String.class);
v = valueOf.invoke((Object)null, substituredValue);
}
catch (Throwable inner)
{
throw new IllegalArgumentException("Unknown property resolution for property " + name);
}
}
}
}
return v;
}
/**
* System property substitution
* @param input The input string
* @return The output
*/
protected String getSubstitutionValue(String input)
{
if (input == null || input.trim().equals(""))
return input;
while (input.indexOf("${") != -1)
{
int from = input.indexOf("${");
int to = input.indexOf("}");
int dv = input.indexOf(":", from + 2);
if (dv != -1)
{
if (dv > to)
dv = -1;
}
String systemProperty = "";
String defaultValue = "";
if (dv == -1)
{
String s = input.substring(from + 2, to);
if ("/".equals(s))
{
systemProperty = File.separator;
}
else if (":".equals(s))
{
systemProperty = File.pathSeparator;
}
else
{
systemProperty = SecurityActions.getSystemProperty(s);
}
}
else
{
systemProperty = SecurityActions.getSystemProperty(input.substring(from + 2, dv));
defaultValue = input.substring(dv + 1, to);
}
String prefix = "";
String postfix = "";
if (from != 0)
{
prefix = input.substring(0, from);
}
if (to + 1 < input.length() - 1)
{
postfix = input.substring(to + 1);
}
if (systemProperty != null && !systemProperty.trim().equals(""))
{
input = prefix + systemProperty + postfix;
}
else if (!defaultValue.trim().equals(""))
{
input = prefix + defaultValue + postfix;
}
else
{
input = prefix + postfix;
}
}
return input;
}
/**
* Method sorter
*/
static class MethodSorter implements Comparator, Serializable
{
private static final long serialVersionUID = 1L;
/**
* Constructor
*/
MethodSorter()
{
}
/**
* {@inheritDoc}
*/
public int compare(Method o1, Method o2)
{
int m1 = o1.getModifiers();
int m2 = o2.getModifiers();
if (Modifier.isPublic(m1))
return -1;
if (Modifier.isPublic(m2))
return 1;
if (Modifier.isProtected(m1))
return -1;
if (Modifier.isProtected(m2))
return 1;
if (Modifier.isPrivate(m1))
return -1;
if (Modifier.isPrivate(m2))
return 1;
return 0;
}
/**
* {@inheritDoc}
*/
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || !(o instanceof MethodSorter))
return false;
return true;
}
/**
* {@inheritDoc}
*/
public int hashCode()
{
return 42;
}
}
/**
* Field sorter
*/
static class FieldSorter implements Comparator, Serializable
{
private static final long serialVersionUID = 1L;
/**
* Constructor
*/
FieldSorter()
{
}
/**
* {@inheritDoc}
*/
public int compare(Field o1, Field o2)
{
int m1 = o1.getModifiers();
int m2 = o2.getModifiers();
if (Modifier.isPublic(m1))
return -1;
if (Modifier.isPublic(m2))
return 1;
if (Modifier.isProtected(m1))
return -1;
if (Modifier.isProtected(m2))
return 1;
if (Modifier.isPrivate(m1))
return -1;
if (Modifier.isPrivate(m2))
return 1;
return 0;
}
/**
* {@inheritDoc}
*/
public boolean equals(Object o)
{
if (this == o)
return true;
if (o == null || !(o instanceof FieldSorter))
return false;
return true;
}
/**
* {@inheritDoc}
*/
public int hashCode()
{
return 42;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy