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 }