| /* |
| * 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.openejb.junit.context; |
| |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Hashtable; |
| import java.util.List; |
| |
| public final class Util { |
| private Util() { |
| } |
| |
| /** |
| * @param type |
| * @param instance |
| * @return true if the given object is of the specify type of class |
| */ |
| public static boolean isInstance(final Class type, final Object instance) { |
| if (type.isPrimitive()) { |
| // for primitives the insance can't be null |
| if (instance == null) { |
| return false; |
| } |
| |
| // verify instance is the correct wrapper type |
| if (type.equals(boolean.class)) { |
| return instance instanceof Boolean; |
| } else if (type.equals(char.class)) { |
| return instance instanceof Character; |
| } else if (type.equals(byte.class)) { |
| return instance instanceof Byte; |
| } else if (type.equals(short.class)) { |
| return instance instanceof Short; |
| } else if (type.equals(int.class)) { |
| return instance instanceof Integer; |
| } else if (type.equals(long.class)) { |
| return instance instanceof Long; |
| } else if (type.equals(float.class)) { |
| return instance instanceof Float; |
| } else if (type.equals(double.class)) { |
| return instance instanceof Double; |
| } else { |
| throw new AssertionError("Invalid primitve type: " + type); |
| } |
| } |
| |
| return instance == null || type.isInstance(instance); |
| } |
| |
| /** |
| * Parses an @Property value and adds it to the specified Hashtable |
| * |
| * @param env |
| * @param property |
| */ |
| public static void addProperty(final Hashtable env, String property) { |
| if (property == null || property.length() == 0) { |
| throw new IllegalArgumentException("No property specified."); |
| } |
| |
| if (property.charAt(0) == '=') { |
| throw new IllegalArgumentException("Invalid property has no name: " + property); |
| } |
| |
| final String name; |
| final String value; |
| |
| property = property.trim(); |
| |
| final int esp = property.indexOf('='); |
| if (esp < 0) { |
| name = property; |
| value = ""; |
| } else { |
| name = property.substring(0, esp).trim(); |
| |
| if (property.length() > esp) { |
| value = property.substring(esp + 1).trim(); |
| } else { |
| value = ""; |
| } |
| } |
| |
| env.put(name, value); |
| } |
| |
| /** |
| * Finds the setter method for a given field in the test class |
| * |
| * @param testClazz |
| * @param field |
| * @param propertyValue |
| * @return setter Method or NULL if not found |
| */ |
| public static Method findSetter(final Class<?> testClazz, final Field field, final Object propertyValue) { |
| final String propertyName = field.getName(); |
| final boolean isStatic = Modifier.isStatic(field.getModifiers()); |
| |
| final String setterName = "set" + Character.toUpperCase(propertyName.charAt(0)) + propertyName.substring(1); |
| |
| final List<Method> methods = new ArrayList<Method>(Arrays.asList(testClazz.getMethods())); |
| methods.addAll(Arrays.asList(testClazz.getDeclaredMethods())); |
| Method unpreferredValidMethod = null; |
| for (final Method clazzMethod : methods) { |
| if (clazzMethod.getName().equals(setterName)) { |
| if (clazzMethod.getParameterTypes().length == 0) { |
| continue; |
| } |
| |
| if (clazzMethod.getParameterTypes().length > 1) { |
| continue; |
| } |
| |
| if (clazzMethod.getReturnType() != Void.TYPE) { |
| continue; |
| } |
| |
| if (Modifier.isAbstract(clazzMethod.getModifiers())) { |
| continue; |
| } |
| |
| final Class methodParameterType = clazzMethod.getParameterTypes()[0]; |
| if (methodParameterType.isPrimitive() && propertyValue == null) { |
| continue; |
| } |
| |
| // Method is static, but field isn't. Can't work |
| if (!isStatic && Modifier.isStatic(clazzMethod.getModifiers())) { |
| continue; |
| } |
| |
| if (!Modifier.isPublic(clazzMethod.getModifiers())) { |
| clazzMethod.setAccessible(true); |
| } |
| |
| if (!isInstance(methodParameterType, propertyValue)) { |
| continue; |
| } |
| // not necessarily the BEST match |
| else if (methodParameterType != propertyValue.getClass()) { |
| if (unpreferredValidMethod == null) { |
| unpreferredValidMethod = clazzMethod; |
| } else { |
| unpreferredValidMethod = getMostSpecificMethod(unpreferredValidMethod, clazzMethod); |
| } |
| continue; |
| } |
| |
| return clazzMethod; |
| } |
| } |
| |
| return unpreferredValidMethod; |
| } |
| |
| /** |
| * Returns the most specific of the 2 methods. When calling this method both should |
| * already match as valid calls, so the most specific will be the one where subtype |
| * relation holds against the other. |
| * |
| * We also assume that the only difference between the method signatures is the type |
| * of it's first argument, and thus that their first arguments can't be of the |
| * same type. |
| * |
| * @param method1 |
| * @param method2 |
| * @return most specific method |
| */ |
| public static Method getMostSpecificMethod(final Method method1, final Method method2) { |
| final Class<?> class1 = method1.getParameterTypes()[0]; |
| final Class<?> class2 = method2.getParameterTypes()[0]; |
| |
| if (class1.isAssignableFrom(class2)) { |
| return method2; |
| } else { |
| return method1; |
| } |
| } |
| } |