/* | |
* Copyright 1999-2011 Alibaba Group. | |
* | |
* Licensed 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 com.alibaba.dubbo.common.compiler.support; | |
import java.io.PrintWriter; | |
import java.io.StringWriter; | |
import java.lang.reflect.Array; | |
import java.lang.reflect.GenericArrayType; | |
import java.lang.reflect.Method; | |
import java.lang.reflect.Modifier; | |
import java.lang.reflect.ParameterizedType; | |
import java.net.URI; | |
import java.net.URISyntaxException; | |
import java.util.Collection; | |
import java.util.HashMap; | |
import java.util.Map; | |
/** | |
* ClassUtils. (Tool, Static, ThreadSafe) | |
* | |
* @author william.liangf | |
*/ | |
public class ClassUtils { | |
public static final String CLASS_EXTENSION = ".class"; | |
public static final String JAVA_EXTENSION = ".java"; | |
public static Object newInstance(String name) { | |
try { | |
return forName(name).newInstance(); | |
} catch (InstantiationException e) { | |
throw new IllegalStateException(e.getMessage(), e); | |
} catch (IllegalAccessException e) { | |
throw new IllegalStateException(e.getMessage(), e); | |
} | |
} | |
public static Class<?> forName(String[] packages, String className) { | |
try { | |
return _forName(className); | |
} catch (ClassNotFoundException e) { | |
if (packages != null && packages.length > 0) { | |
for (String pkg : packages) { | |
try { | |
return _forName(pkg + "." + className); | |
} catch (ClassNotFoundException e2) { | |
} | |
} | |
} | |
throw new IllegalStateException(e.getMessage(), e); | |
} | |
} | |
public static Class<?> forName(String className) { | |
try { | |
return _forName(className); | |
} catch (ClassNotFoundException e) { | |
throw new IllegalStateException(e.getMessage(), e); | |
} | |
} | |
public static Class<?> _forName(String className) throws ClassNotFoundException { | |
if ("boolean".equals(className)) | |
return boolean.class; | |
if ("byte".equals(className)) | |
return byte.class; | |
if ("char".equals(className)) | |
return char.class; | |
if ("short".equals(className)) | |
return short.class; | |
if ("int".equals(className)) | |
return int.class; | |
if ("long".equals(className)) | |
return long.class; | |
if ("float".equals(className)) | |
return float.class; | |
if ("double".equals(className)) | |
return double.class; | |
if ("boolean[]".equals(className)) | |
return boolean[].class; | |
if ("byte[]".equals(className)) | |
return byte[].class; | |
if ("char[]".equals(className)) | |
return char[].class; | |
if ("short[]".equals(className)) | |
return short[].class; | |
if ("int[]".equals(className)) | |
return int[].class; | |
if ("long[]".equals(className)) | |
return long[].class; | |
if ("float[]".equals(className)) | |
return float[].class; | |
if ("double[]".equals(className)) | |
return double[].class; | |
try { | |
return arrayForName(className); | |
} catch (ClassNotFoundException e) { | |
if (className.indexOf('.') == -1) { // 尝试java.lang包 | |
try { | |
return arrayForName("java.lang." + className); | |
} catch (ClassNotFoundException e2) { | |
// 忽略尝试异常, 抛出原始异常 | |
} | |
} | |
throw e; | |
} | |
} | |
private static Class<?> arrayForName(String className) throws ClassNotFoundException { | |
return Class.forName(className.endsWith("[]") | |
? "[L" + className.substring(0, className.length() - 2) + ";" | |
: className, true, Thread.currentThread().getContextClassLoader()); | |
} | |
public static Class<?> getBoxedClass(Class<?> type) { | |
if (type == boolean.class) { | |
return Boolean.class; | |
} else if (type == char.class) { | |
return Character.class; | |
} else if (type == byte.class) { | |
return Byte.class; | |
} else if (type == short.class) { | |
return Short.class; | |
} else if (type == int.class) { | |
return Integer.class; | |
} else if (type == long.class) { | |
return Long.class; | |
} else if (type == float.class) { | |
return Float.class; | |
} else if (type == double.class) { | |
return Double.class; | |
} else { | |
return type; | |
} | |
} | |
public static Boolean boxed(boolean v) { | |
return Boolean.valueOf(v); | |
} | |
public static Character boxed(char v) { | |
return Character.valueOf(v); | |
} | |
public static Byte boxed(byte v) { | |
return Byte.valueOf(v); | |
} | |
public static Short boxed(short v) { | |
return Short.valueOf(v); | |
} | |
public static Integer boxed(int v) { | |
return Integer.valueOf(v); | |
} | |
public static Long boxed(long v) { | |
return Long.valueOf(v); | |
} | |
public static Float boxed(float v) { | |
return Float.valueOf(v); | |
} | |
public static Double boxed(double v) { | |
return Double.valueOf(v); | |
} | |
public static Object boxed(Object v) { | |
return v; | |
} | |
public static boolean unboxed(Boolean v) { | |
return v == null ? false : v.booleanValue(); | |
} | |
public static char unboxed(Character v) { | |
return v == null ? '\0' : v.charValue(); | |
} | |
public static byte unboxed(Byte v) { | |
return v == null ? 0 : v.byteValue(); | |
} | |
public static short unboxed(Short v) { | |
return v == null ? 0 : v.shortValue(); | |
} | |
public static int unboxed(Integer v) { | |
return v == null ? 0 : v.intValue(); | |
} | |
public static long unboxed(Long v) { | |
return v == null ? 0 : v.longValue(); | |
} | |
public static float unboxed(Float v) { | |
return v == null ? 0 : v.floatValue(); | |
} | |
public static double unboxed(Double v) { | |
return v == null ? 0 : v.doubleValue(); | |
} | |
public static Object unboxed(Object v) { | |
return v; | |
} | |
public static boolean isNotEmpty(Object object) { | |
return getSize(object) > 0; | |
} | |
public static int getSize(Object object) { | |
if (object == null) { | |
return 0; | |
} if (object instanceof Collection<?>) { | |
return ((Collection<?>)object).size(); | |
} else if (object instanceof Map<?, ?>) { | |
return ((Map<?, ?>)object).size(); | |
} else if (object.getClass().isArray()) { | |
return Array.getLength(object); | |
} else { | |
return -1; | |
} | |
} | |
public static URI toURI(String name) { | |
try { | |
return new URI(name); | |
} catch (URISyntaxException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
public static Class<?> getGenericClass(Class<?> cls) { | |
return getGenericClass(cls, 0); | |
} | |
public static Class<?> getGenericClass(Class<?> cls, int i) { | |
try { | |
ParameterizedType parameterizedType = ((ParameterizedType) cls.getGenericInterfaces()[0]); | |
Object genericClass = parameterizedType.getActualTypeArguments()[i]; | |
if (genericClass instanceof ParameterizedType) { // 处理多级泛型 | |
return (Class<?>) ((ParameterizedType) genericClass).getRawType(); | |
} else if (genericClass instanceof GenericArrayType) { // 处理数组泛型 | |
return (Class<?>) ((GenericArrayType) genericClass).getGenericComponentType(); | |
} else if (genericClass != null) { | |
return (Class<?>) genericClass; | |
} | |
} catch (Throwable e) { | |
} | |
if (cls.getSuperclass() != null) { | |
return getGenericClass(cls.getSuperclass(), i); | |
} else { | |
throw new IllegalArgumentException(cls.getName() + " generic type undefined!"); | |
} | |
} | |
public static boolean isBeforeJava5(String javaVersion) { | |
return (javaVersion == null || javaVersion.length() == 0 || "1.0".equals(javaVersion) | |
|| "1.1".equals(javaVersion) || "1.2".equals(javaVersion) | |
|| "1.3".equals(javaVersion) || "1.4".equals(javaVersion)); | |
} | |
public static boolean isBeforeJava6(String javaVersion) { | |
return isBeforeJava5(javaVersion) || "1.5".equals(javaVersion); | |
} | |
public static String toString(Throwable e) { | |
StringWriter w = new StringWriter(); | |
PrintWriter p = new PrintWriter(w); | |
p.print(e.getClass().getName() + ": "); | |
if (e.getMessage() != null) { | |
p.print(e.getMessage() + "\n"); | |
} | |
p.println(); | |
try { | |
e.printStackTrace(p); | |
return w.toString(); | |
} finally { | |
p.close(); | |
} | |
} | |
private static final int JIT_LIMIT = 5 * 1024; | |
public static void checkBytecode(String name, byte[] bytecode) { | |
if (bytecode.length > JIT_LIMIT) { | |
System.err.println("The template bytecode too long, may be affect the JIT compiler. template class: " + name); | |
} | |
} | |
public static String getSizeMethod(Class<?> cls) { | |
try { | |
return cls.getMethod("size", new Class<?>[0]).getName() + "()"; | |
} catch (NoSuchMethodException e) { | |
try { | |
return cls.getMethod("length", new Class<?>[0]).getName() + "()"; | |
} catch (NoSuchMethodException e2) { | |
try { | |
return cls.getMethod("getSize", new Class<?>[0]).getName() + "()"; | |
} catch (NoSuchMethodException e3) { | |
try { | |
return cls.getMethod("getLength", new Class<?>[0]).getName() + "()"; | |
} catch (NoSuchMethodException e4) { | |
return null; | |
} | |
} | |
} | |
} | |
} | |
public static String getMethodName(Method method, Class<?>[] parameterClasses, String rightCode) { | |
if (method.getParameterTypes().length > parameterClasses.length) { | |
Class<?>[] types = method.getParameterTypes(); | |
StringBuilder buf = new StringBuilder(rightCode); | |
for (int i = parameterClasses.length; i < types.length; i ++) { | |
if (buf.length() > 0) { | |
buf.append(","); | |
} | |
Class<?> type = types[i]; | |
String def; | |
if (type == boolean.class) { | |
def = "false"; | |
} else if (type == char.class) { | |
def = "\'\\0\'"; | |
} else if (type == byte.class | |
|| type == short.class | |
|| type == int.class | |
|| type == long.class | |
|| type == float.class | |
|| type == double.class) { | |
def = "0"; | |
} else { | |
def = "null"; | |
} | |
buf.append(def); | |
} | |
} | |
return method.getName() + "(" + rightCode + ")"; | |
} | |
public static Method searchMethod(Class<?> currentClass, String name, Class<?>[] parameterTypes) throws NoSuchMethodException { | |
if (currentClass == null) { | |
throw new NoSuchMethodException("class == null"); | |
} | |
try { | |
return currentClass.getMethod(name, parameterTypes); | |
} catch (NoSuchMethodException e) { | |
for (Method method : currentClass.getMethods()) { | |
if (method.getName().equals(name) | |
&& parameterTypes.length == method.getParameterTypes().length | |
&& Modifier.isPublic(method.getModifiers())) { | |
if (parameterTypes.length > 0) { | |
Class<?>[] types = method.getParameterTypes(); | |
boolean match = true; | |
for (int i = 0; i < parameterTypes.length; i ++) { | |
if (! types[i].isAssignableFrom(parameterTypes[i])) { | |
match = false; | |
break; | |
} | |
} | |
if (! match) { | |
continue; | |
} | |
} | |
return method; | |
} | |
} | |
throw e; | |
} | |
} | |
public static String getInitCode(Class<?> type) { | |
if (byte.class.equals(type) | |
|| short.class.equals(type) | |
|| int.class.equals(type) | |
|| long.class.equals(type) | |
|| float.class.equals(type) | |
|| double.class.equals(type)) { | |
return "0"; | |
} else if (char.class.equals(type)) { | |
return "'\\0'"; | |
} else if (boolean.class.equals(type)) { | |
return "false"; | |
} else { | |
return "null"; | |
} | |
} | |
public static <K, V> Map<K, V> toMap(Map.Entry<K, V>[] entries) { | |
Map<K, V> map = new HashMap<K, V>(); | |
if (entries != null && entries.length > 0) { | |
for (Map.Entry<K, V> enrty : entries) { | |
map.put(enrty.getKey(), enrty.getValue()); | |
} | |
} | |
return map; | |
} | |
private ClassUtils() {} | |
} |