View Javadoc
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 }