| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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 org.apache.dubbo.common.compiler.support; |
| |
| import org.apache.dubbo.common.utils.StringUtils; |
| |
| import java.io.PrintWriter; |
| import java.io.StringWriter; |
| import java.lang.reflect.Array; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * ClassUtils. (Tool, Static, ThreadSafe) |
| */ |
| public class ClassUtils { |
| |
| public static final String CLASS_EXTENSION = ".class"; |
| |
| public static final String JAVA_EXTENSION = ".java"; |
| private static final int JIT_LIMIT = 5 * 1024; |
| |
| private ClassUtils() { |
| } |
| |
| public static Object newInstance(String name) { |
| try { |
| return forName(name).getDeclaredConstructor().newInstance(); |
| } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) { |
| throw new IllegalStateException(e.getMessage(), e); |
| } |
| } |
| |
| public static Class<?> forName(String[] packages, String className) { |
| try { |
| return classForName(className); |
| } catch (ClassNotFoundException e) { |
| if (packages != null && packages.length > 0) { |
| for (String pkg : packages) { |
| try { |
| return classForName(pkg + "." + className); |
| } catch (ClassNotFoundException ignore) { |
| } |
| } |
| } |
| throw new IllegalStateException(e.getMessage(), e); |
| } |
| } |
| |
| public static Class<?> forName(String className) { |
| try { |
| return classForName(className); |
| } catch (ClassNotFoundException e) { |
| throw new IllegalStateException(e.getMessage(), e); |
| } |
| } |
| |
| public static Class<?> classForName(String className) throws ClassNotFoundException { |
| switch (className) { |
| case "boolean": |
| return boolean.class; |
| case "byte": |
| return byte.class; |
| case "char": |
| return char.class; |
| case "short": |
| return short.class; |
| case "int": |
| return int.class; |
| case "long": |
| return long.class; |
| case "float": |
| return float.class; |
| case "double": |
| return double.class; |
| case "boolean[]": |
| return boolean[].class; |
| case "byte[]": |
| return byte[].class; |
| case "char[]": |
| return char[].class; |
| case "short[]": |
| return short[].class; |
| case "int[]": |
| return int[].class; |
| case "long[]": |
| return long[].class; |
| case "float[]": |
| return float[].class; |
| case "double[]": |
| return double[].class; |
| default: |
| } |
| try { |
| return arrayForName(className); |
| } catch (ClassNotFoundException e) { |
| // try to load from java.lang package |
| if (className.indexOf('.') == -1) { |
| try { |
| return arrayForName("java.lang." + className); |
| } catch (ClassNotFoundException ignore) { |
| // ignore, let the original exception be thrown |
| } |
| } |
| 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 boolean isBeforeJava5(String javaVersion) { |
| return (StringUtils.isEmpty(javaVersion) || "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(); |
| } |
| } |
| |
| 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) { |
| StringBuilder buf = new StringBuilder(rightCode); |
| if (method.getParameterTypes().length > parameterClasses.length) { |
| Class<?>[] types = method.getParameterTypes(); |
| 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() + "(" + buf + ")"; |
| } |
| |
| 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> entry : entries) { |
| map.put(entry.getKey(), entry.getValue()); |
| } |
| } |
| return map; |
| } |
| |
| /** |
| * get simple class name from qualified class name |
| */ |
| public static String getSimpleClassName(String qualifiedName) { |
| if (null == qualifiedName) { |
| return null; |
| } |
| int i = qualifiedName.lastIndexOf('.'); |
| return i < 0 ? qualifiedName : qualifiedName.substring(i + 1); |
| } |
| |
| } |