001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.apache.commons.proxy2; 019 020import java.lang.reflect.Method; 021import java.util.Collections; 022import java.util.HashMap; 023import java.util.Map; 024 025import org.apache.commons.lang3.ArrayUtils; 026import org.apache.commons.lang3.ClassUtils; 027 028/** 029 * Provides some helpful proxy utility methods. 030 * 031 * @since 1.0 032 */ 033public final class ProxyUtils 034{ 035 //****************************************************************************************************************** 036 // Fields 037 //****************************************************************************************************************** 038 039 public static final Object[] EMPTY_ARGUMENTS = ArrayUtils.EMPTY_OBJECT_ARRAY; 040 public static final Class<?>[] EMPTY_ARGUMENT_TYPES = ArrayUtils.EMPTY_CLASS_ARRAY; 041 private static final Map<Class<?>, Class<?>> WRAPPER_CLASS_MAP; 042 private static final Map<Class<?>, Object> NULL_VALUE_MAP; 043 044 //****************************************************************************************************************** 045 // Static Methods 046 //****************************************************************************************************************** 047 048 static 049 { 050 final Map<Class<?>, Class<?>> wrappers = new HashMap<Class<?>, Class<?>>(); 051 wrappers.put(Integer.TYPE, Integer.class); 052 wrappers.put(Character.TYPE, Character.class); 053 wrappers.put(Boolean.TYPE, Boolean.class); 054 wrappers.put(Short.TYPE, Short.class); 055 wrappers.put(Long.TYPE, Long.class); 056 wrappers.put(Float.TYPE, Float.class); 057 wrappers.put(Double.TYPE, Double.class); 058 wrappers.put(Byte.TYPE, Byte.class); 059 WRAPPER_CLASS_MAP = Collections.unmodifiableMap(wrappers); 060 061 final Map<Class<?>, Object> nullValues = new HashMap<Class<?>, Object>(); 062 nullValues.put(Integer.TYPE, Integer.valueOf(0)); 063 nullValues.put(Long.TYPE, Long.valueOf(0)); 064 nullValues.put(Short.TYPE, Short.valueOf((short) 0)); 065 nullValues.put(Byte.TYPE, Byte.valueOf((byte) 0)); 066 nullValues.put(Float.TYPE, Float.valueOf(0.0f)); 067 nullValues.put(Double.TYPE, Double.valueOf(0.0)); 068 nullValues.put(Character.TYPE, Character.valueOf((char) 0)); 069 nullValues.put(Boolean.TYPE, Boolean.FALSE); 070 NULL_VALUE_MAP = Collections.unmodifiableMap(nullValues); 071 } 072 073 /** 074 * <p> 075 * Gets an array of {@link Class} objects representing all interfaces implemented by the given class and its 076 * superclasses. 077 * </p> 078 * <p/> 079 * <p> 080 * The order is determined by looking through each interface in turn as declared in the source file and following 081 * its hierarchy up. Then each superclass is considered in the same way. Later duplicates are ignored, so the order 082 * is maintained. 083 * </p> 084 * <p/> 085 * <b>Note</b>: Implementation of this method was "borrowed" from <a href="http://commons.apache.org/lang/">Apache 086 * Commons Lang</a> to avoid a dependency. 087 * </p> 088 * 089 * @param cls 090 * the class to look up, may be <code>null</code> 091 * @return an array of {@link Class} objects representing all interfaces implemented by the given class and its 092 * superclasses or <code>null</code> if input class is null. 093 */ 094 public static Class<?>[] getAllInterfaces(Class<?> cls) 095 { 096 return cls == null ? null : ClassUtils.getAllInterfaces(cls).toArray(ArrayUtils.EMPTY_CLASS_ARRAY); 097 } 098 099 /** 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}