1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.commons.proxy2; 19 20 import java.lang.reflect.Method; 21 import java.util.Collections; 22 import java.util.HashMap; 23 import java.util.Map; 24 25 import org.apache.commons.lang3.ArrayUtils; 26 import org.apache.commons.lang3.ClassUtils; 27 28 /** 29 * Provides some helpful proxy utility methods. 30 * 31 * @since 1.0 32 */ 33 public final class ProxyUtils 34 { 35 //****************************************************************************************************************** 36 // Fields 37 //****************************************************************************************************************** 38 39 public static final Object[] EMPTY_ARGUMENTS = ArrayUtils.EMPTY_OBJECT_ARRAY; 40 public static final Class<?>[] EMPTY_ARGUMENT_TYPES = ArrayUtils.EMPTY_CLASS_ARRAY; 41 private static final Map<Class<?>, Class<?>> WRAPPER_CLASS_MAP; 42 private static final Map<Class<?>, Object> NULL_VALUE_MAP; 43 44 //****************************************************************************************************************** 45 // Static Methods 46 //****************************************************************************************************************** 47 48 static 49 { 50 final Map<Class<?>, Class<?>> wrappers = new HashMap<Class<?>, Class<?>>(); 51 wrappers.put(Integer.TYPE, Integer.class); 52 wrappers.put(Character.TYPE, Character.class); 53 wrappers.put(Boolean.TYPE, Boolean.class); 54 wrappers.put(Short.TYPE, Short.class); 55 wrappers.put(Long.TYPE, Long.class); 56 wrappers.put(Float.TYPE, Float.class); 57 wrappers.put(Double.TYPE, Double.class); 58 wrappers.put(Byte.TYPE, Byte.class); 59 WRAPPER_CLASS_MAP = Collections.unmodifiableMap(wrappers); 60 61 final Map<Class<?>, Object> nullValues = new HashMap<Class<?>, Object>(); 62 nullValues.put(Integer.TYPE, Integer.valueOf(0)); 63 nullValues.put(Long.TYPE, Long.valueOf(0)); 64 nullValues.put(Short.TYPE, Short.valueOf((short) 0)); 65 nullValues.put(Byte.TYPE, Byte.valueOf((byte) 0)); 66 nullValues.put(Float.TYPE, Float.valueOf(0.0f)); 67 nullValues.put(Double.TYPE, Double.valueOf(0.0)); 68 nullValues.put(Character.TYPE, Character.valueOf((char) 0)); 69 nullValues.put(Boolean.TYPE, Boolean.FALSE); 70 NULL_VALUE_MAP = Collections.unmodifiableMap(nullValues); 71 } 72 73 /** 74 * <p> 75 * Gets an array of {@link Class} objects representing all interfaces implemented by the given class and its 76 * superclasses. 77 * </p> 78 * <p/> 79 * <p> 80 * The order is determined by looking through each interface in turn as declared in the source file and following 81 * its hierarchy up. Then each superclass is considered in the same way. Later duplicates are ignored, so the order 82 * is maintained. 83 * </p> 84 * <p/> 85 * <b>Note</b>: Implementation of this method was "borrowed" from <a href="http://commons.apache.org/lang/">Apache 86 * Commons Lang</a> to avoid a dependency. 87 * </p> 88 * 89 * @param cls 90 * the class to look up, may be <code>null</code> 91 * @return an array of {@link Class} objects representing all interfaces implemented by the given class and its 92 * superclasses or <code>null</code> if input class is null. 93 */ 94 public static Class<?>[] getAllInterfaces(Class<?> cls) 95 { 96 return cls == null ? null : ClassUtils.getAllInterfaces(cls).toArray(ArrayUtils.EMPTY_CLASS_ARRAY); 97 } 98 99 /** 100 * Returns the class name as you would expect to see it in Java code. 101 * <p/> 102 * <b>Examples:</b> 103 * <ul> 104 * <li>getJavaClassName( Object[].class ) == "Object[]"</li> 105 * <li>getJavaClassName( Object[][].class ) == "Object[][]"</li> 106 * <li>getJavaClassName( Integer.TYPE ) == "int"</li> 107 * </p> 108 * 109 * @param clazz 110 * the class 111 * @return the class' name as you would expect to see it in Java code 112 */ 113 public static String getJavaClassName(Class<?> clazz) 114 { 115 if (clazz.isArray()) 116 { 117 return getJavaClassName(clazz.getComponentType()) + "[]"; 118 } 119 return clazz.getName(); 120 } 121 122 /** 123 * Returns the wrapper class for the given primitive type. 124 * 125 * @param primitiveType 126 * the primitive type 127 * @return the wrapper class 128 */ 129 public static Class<?> getWrapperClass(Class<?> primitiveType) 130 { 131 return WRAPPER_CLASS_MAP.get(primitiveType); 132 } 133 134 /** 135 * Returns the proper "null value" as specified by the Java language. 136 * 137 * @param type 138 * the type 139 * @return the null value 140 */ 141 public static <T> T nullValue(Class<T> type) 142 { 143 @SuppressWarnings("unchecked") // map only contains matching type/value entries 144 final T result = (T) NULL_VALUE_MAP.get(type); 145 return result; 146 } 147 148 /** 149 * Learn whether the specified method is/overrides {@link Object#equals(Object)}. 150 * 151 * @param method 152 * to compare 153 * @return <code>true</code> for a method with signature <code>equals(Object)</code> 154 */ 155 public static boolean isEqualsMethod(Method method) 156 { 157 return "equals".equals(method.getName()) && method.getParameterTypes().length == 1 158 && Object.class.equals(method.getParameterTypes()[0]); 159 } 160 161 /** 162 * Learn whether the specified method is/overrides {@link Object#hashCode()}. 163 * 164 * @param method 165 * to compare 166 * @return true for a method with signature <code>hashCode()</code> 167 */ 168 public static boolean isHashCode(Method method) 169 { 170 return "hashCode".equals(method.getName()) && method.getParameterTypes().length == 0; 171 } 172 173 /** 174 * Get a {@link ProxyFactory} that delegates to discoverable {@link ProxyFactory} service providers. 175 * 176 * @return {@link ProxyFactory} 177 */ 178 public static ProxyFactory proxyFactory() 179 { 180 return DefaultProxyFactory.INSTANCE; 181 } 182 183 private ProxyUtils() 184 { 185 // Hiding constructor in utility class! 186 } 187 }