diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java index 0ab48a6c4fc..ffbc31241a1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Version.java @@ -18,7 +18,7 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.StringUtils; import java.io.IOException; @@ -240,7 +240,7 @@ public static void checkDuplicate(String path, boolean failOnError) { * search resources in caller's classloader */ private static Set getResources(String path) throws IOException { - Enumeration urls = ClassHelper.getCallerClassLoader(Version.class).getResources(path); + Enumeration urls = ClassUtils.getCallerClassLoader(Version.class).getResources(path); Set files = new HashSet(); while (urls.hasMoreElements()) { URL url = urls.nextElement(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java index 40ae8856cfe..fdcabb8c0f5 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java @@ -16,10 +16,6 @@ */ package org.apache.dubbo.common.bytecode; -import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.ClassHelper; -import org.apache.dubbo.common.utils.ReflectUtils; - import javassist.CannotCompileException; import javassist.ClassPool; import javassist.CtClass; @@ -30,6 +26,9 @@ import javassist.CtNewMethod; import javassist.LoaderClassPath; import javassist.NotFoundException; +import org.apache.dubbo.common.utils.ArrayUtils; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import java.lang.reflect.Constructor; @@ -285,7 +284,7 @@ public ClassPool getClassPool() { } public Class toClass() { - return toClass(ClassHelper.getClassLoader(ClassGenerator.class), + return toClass(ClassUtils.getClassLoader(ClassGenerator.class), getClass().getProtectionDomain()); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java index df95dabf445..f7a84236384 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.common.bytecode; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ReflectUtils; import java.lang.reflect.Method; @@ -69,7 +69,7 @@ public static Mixin mixin(Class[] ics, Class dc, ClassLoader cl) { * @return Mixin instance. */ public static Mixin mixin(Class[] ics, Class[] dcs) { - return mixin(ics, dcs, ClassHelper.getCallerClassLoader(Mixin.class)); + return mixin(ics, dcs, ClassUtils.getCallerClassLoader(Mixin.class)); } /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java index e72faae2cb1..8381bd20ca0 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java @@ -17,7 +17,7 @@ package org.apache.dubbo.common.bytecode; import org.apache.dubbo.common.Constants; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ReflectUtils; import java.lang.ref.Reference; @@ -62,7 +62,7 @@ protected Proxy() { * @return Proxy instance. */ public static Proxy getProxy(Class... ics) { - return getProxy(ClassHelper.getClassLoader(Proxy.class), ics); + return getProxy(ClassUtils.getClassLoader(Proxy.class), ics); } /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java index 6d3f42bd8fe..7f83f97efd1 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.common.bytecode; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ReflectUtils; import java.lang.reflect.Field; @@ -127,7 +127,7 @@ private static Wrapper makeWrapper(Class c) { } String name = c.getName(); - ClassLoader cl = ClassHelper.getClassLoader(c); + ClassLoader cl = ClassUtils.getClassLoader(c); StringBuilder c1 = new StringBuilder("public void setPropertyValue(Object o, String n, Object v){ "); StringBuilder c2 = new StringBuilder("public Object getPropertyValue(Object o, String n){ "); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java index 7323641284d..f0794302849 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AbstractCompiler.java @@ -17,7 +17,6 @@ package org.apache.dubbo.common.compiler.support; import org.apache.dubbo.common.compiler.Compiler; -import org.apache.dubbo.common.utils.ClassHelper; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -50,7 +49,7 @@ public Class compile(String code, ClassLoader classLoader) { } String className = pkg != null && pkg.length() > 0 ? pkg + "." + cls : cls; try { - return Class.forName(className, true, ClassHelper.getCallerClassLoader(getClass())); + return Class.forName(className, true, org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass())); } catch (ClassNotFoundException e) { if (!code.endsWith("}")) { throw new IllegalStateException("The java code not endsWith \"}\", code: \n" + code + "\n"); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java index 11f76b1e6bd..3a058849d8f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JavassistCompiler.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.common.compiler.support; -import org.apache.dubbo.common.utils.ClassHelper; import javassist.CtClass; @@ -49,25 +48,25 @@ public Class doCompile(String name, String source) throws Throwable { while (matcher.find()) { builder.addImports(matcher.group(1).trim()); } - + // process extended super class matcher = EXTENDS_PATTERN.matcher(source); if (matcher.find()) { builder.setSuperClassName(matcher.group(1).trim()); } - + // process implemented interfaces matcher = IMPLEMENTS_PATTERN.matcher(source); if (matcher.find()) { String[] ifaces = matcher.group(1).trim().split("\\,"); Arrays.stream(ifaces).forEach(i -> builder.addInterface(i.trim())); } - + // process constructors, fields, methods String body = source.substring(source.indexOf('{') + 1, source.length() - 1); String[] methods = METHODS_PATTERN.split(body); String className = ClassUtils.getSimpleClassName(name); - Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method-> { + Arrays.stream(methods).map(String::trim).filter(m -> !m.isEmpty()).forEach(method -> { if (method.startsWith(className)) { builder.addConstructor("public " + method); } else if (FIELD_PATTERN.matcher(method).matches()) { @@ -76,9 +75,9 @@ public Class doCompile(String name, String source) throws Throwable { builder.addMethod("public " + method); } }); - + // compile - ClassLoader classLoader = ClassHelper.getCallerClassLoader(getClass()); + ClassLoader classLoader = org.apache.dubbo.common.utils.ClassUtils.getCallerClassLoader(getClass()); CtClass cls = builder.build(classLoader); return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java index 9c2800cc217..78619eeb7a7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.common.compiler.support; -import org.apache.dubbo.common.utils.ClassHelper; import javax.tools.DiagnosticCollector; import javax.tools.FileObject; @@ -261,7 +260,7 @@ protected Class findClass(final String qualifiedClassName) throws ClassNotFou return defineClass(qualifiedClassName, bytes, 0, bytes.length); } try { - return ClassHelper.forNameWithCallerClassLoader(qualifiedClassName, getClass()); + return org.apache.dubbo.common.utils.ClassUtils.forNameWithCallerClassLoader(qualifiedClassName, getClass()); } catch (ClassNotFoundException nf) { return super.findClass(qualifiedClassName); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 3f2709e8621..9d0b46c4469 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -22,13 +22,14 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.ConcurrentHashSet; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.Holder; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; -import org.apache.dubbo.common.utils.CollectionUtils; + import java.io.BufferedReader; import java.io.InputStreamReader; import java.lang.reflect.Method; @@ -142,7 +143,7 @@ public static void resetExtensionLoader(Class type) { } private static ClassLoader findClassLoader() { - return ClassHelper.getClassLoader(ExtensionLoader.class); + return ClassUtils.getClassLoader(ExtensionLoader.class); } public String getExtensionName(T extensionInstance) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java index 3abeb660a64..d695b46d169 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java @@ -18,7 +18,7 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import java.util.Collections; import java.util.HashSet; @@ -415,7 +415,7 @@ public long pendingTimeouts() { } private static void reportTooManyInstances() { - String resourceType = ClassHelper.simpleClassName(HashedWheelTimer.class); + String resourceType = ClassUtils.simpleClassName(HashedWheelTimer.class); logger.error("You are creating too many " + resourceType + " instances. " + resourceType + " is a shared resource that must be reused across the JVM," + "so that only a few instances are created."); @@ -657,7 +657,7 @@ public void expire() { public String toString() { final long currentTime = System.nanoTime(); long remaining = deadline - currentTime + timer.startTime; - String simpleClassName = ClassHelper.simpleClassName(this.getClass()); + String simpleClassName = ClassUtils.simpleClassName(this.getClass()); StringBuilder buf = new StringBuilder(192) .append(simpleClassName) diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassHelper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassHelper.java index d249645c2bf..fe3a21586f9 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassHelper.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassHelper.java @@ -17,68 +17,19 @@ package org.apache.dubbo.common.utils; -import java.lang.reflect.Array; import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; +/** + * @see org.apache.dubbo.common.utils.ClassUtils + * @deprecated Replace to ClassUtils + */ public class ClassHelper { - - /** - * Suffix for array class names: "[]" - */ - public static final String ARRAY_SUFFIX = "[]"; - /** - * Prefix for internal array class names: "[L" - */ - private static final String INTERNAL_ARRAY_PREFIX = "[L"; - /** - * Map with primitive type name as key and corresponding primitive type as - * value, for example: "int" -> "int.class". - */ - private static final Map> primitiveTypeNameMap = new HashMap>(16); - /** - * Map with primitive wrapper type as key and corresponding primitive type - * as value, for example: Integer.class -> int.class. - */ - private static final Map, Class> primitiveWrapperTypeMap = new HashMap, Class>(8); - - private static final char PACKAGE_SEPARATOR_CHAR = '.'; - - static { - primitiveWrapperTypeMap.put(Boolean.class, boolean.class); - primitiveWrapperTypeMap.put(Byte.class, byte.class); - primitiveWrapperTypeMap.put(Character.class, char.class); - primitiveWrapperTypeMap.put(Double.class, double.class); - primitiveWrapperTypeMap.put(Float.class, float.class); - primitiveWrapperTypeMap.put(Integer.class, int.class); - primitiveWrapperTypeMap.put(Long.class, long.class); - primitiveWrapperTypeMap.put(Short.class, short.class); - - Set> primitiveTypeNames = new HashSet>(16); - primitiveTypeNames.addAll(primitiveWrapperTypeMap.values()); - primitiveTypeNames.addAll(Arrays - .asList(new Class[]{boolean[].class, byte[].class, char[].class, double[].class, - float[].class, int[].class, long[].class, short[].class})); - for (Iterator> it = primitiveTypeNames.iterator(); it.hasNext(); ) { - Class primitiveClass = (Class) it.next(); - primitiveTypeNameMap.put(primitiveClass.getName(), primitiveClass); - } - } - - public static Class forNameWithThreadContextClassLoader(String name) - throws ClassNotFoundException { - return forName(name, Thread.currentThread().getContextClassLoader()); + public static Class forNameWithThreadContextClassLoader(String name) throws ClassNotFoundException { + return ClassUtils.forName(name, Thread.currentThread().getContextClassLoader()); } - public static Class forNameWithCallerClassLoader(String name, Class caller) - throws ClassNotFoundException { - return forName(name, caller.getClassLoader()); + public static Class forNameWithCallerClassLoader(String name, Class caller) throws ClassNotFoundException { + return ClassUtils.forName(name, caller.getClassLoader()); } public static ClassLoader getCallerClassLoader(Class caller) { @@ -92,26 +43,7 @@ public static ClassLoader getCallerClassLoader(Class caller) { * @return class loader */ public static ClassLoader getClassLoader(Class clazz) { - ClassLoader cl = null; - try { - cl = Thread.currentThread().getContextClassLoader(); - } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back to system class loader... - } - if (cl == null) { - // No thread context class loader -> use class loader of this class. - cl = clazz.getClassLoader(); - if (cl == null) { - // getClassLoader() returning null indicates the bootstrap ClassLoader - try { - cl = ClassLoader.getSystemClassLoader(); - } catch (Throwable ex) { - // Cannot access system ClassLoader - oh well, maybe the caller can live with null... - } - } - } - - return cl; + return ClassUtils.getClassLoader(clazz); } /** @@ -155,38 +87,7 @@ public static Class forName(String name) throws ClassNotFoundException { */ public static Class forName(String name, ClassLoader classLoader) throws ClassNotFoundException, LinkageError { - - Class clazz = resolvePrimitiveClassName(name); - if (clazz != null) { - return clazz; - } - - // "java.lang.String[]" style arrays - if (name.endsWith(ARRAY_SUFFIX)) { - String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); - Class elementClass = forName(elementClassName, classLoader); - return Array.newInstance(elementClass, 0).getClass(); - } - - // "[Ljava.lang.String;" style arrays - int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX); - if (internalArrayMarker != -1 && name.endsWith(";")) { - String elementClassName = null; - if (internalArrayMarker == 0) { - elementClassName = name - .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); - } else if (name.startsWith("[")) { - elementClassName = name.substring(1); - } - Class elementClass = forName(elementClassName, classLoader); - return Array.newInstance(elementClass, 0).getClass(); - } - - ClassLoader classLoaderToUse = classLoader; - if (classLoaderToUse == null) { - classLoaderToUse = getClassLoader(); - } - return classLoaderToUse.loadClass(name); + return ClassUtils.forName(name, classLoader); } /** @@ -202,94 +103,40 @@ public static Class forName(String name, ClassLoader classLoader) * denote a primitive class or primitive array class */ public static Class resolvePrimitiveClassName(String name) { - Class result = null; - // Most class names will be quite long, considering that they - // SHOULD sit in a package, so a length check is worthwhile. - if (name != null && name.length() <= 8) { - // Could be a primitive - likely. - result = (Class) primitiveTypeNameMap.get(name); - } - return result; + return ClassUtils.resolvePrimitiveClassName(name); } public static String toShortString(Object obj) { - if (obj == null) { - return "null"; - } - return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); + return ClassUtils.toShortString(obj); } public static String simpleClassName(Class clazz) { - if (clazz == null) { - throw new NullPointerException("clazz"); - } - String className = clazz.getName(); - final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); - if (lastDotIdx > -1) { - return className.substring(lastDotIdx + 1); - } - return className; + return ClassUtils.simpleClassName(clazz); } + /** + * @see org.apache.dubbo.common.utils.MethodUtils#isSetter(Method) + * @deprecated Replace to MethodUtils#isSetter(Method) + */ public static boolean isSetter(Method method) { - return method.getName().startsWith("set") - && !"set".equals(method.getName()) - && Modifier.isPublic(method.getModifiers()) - && method.getParameterCount() == 1 - && isPrimitive(method.getParameterTypes()[0]); + return MethodUtils.isSetter(method); } + /** + * @see org.apache.dubbo.common.utils.MethodUtils#isGetter(Method) (Method) + * @deprecated Replace to MethodUtils#isGetter(Method) + */ public static boolean isGetter(Method method) { - String name = method.getName(); - return (name.startsWith("get") || name.startsWith("is")) - && !"get".equals(name) && !"is".equals(name) - && !"getClass".equals(name) && !"getObject".equals(name) - && Modifier.isPublic(method.getModifiers()) - && method.getParameterTypes().length == 0 - && isPrimitive(method.getReturnType()); + return MethodUtils.isGetter(method); } public static boolean isPrimitive(Class type) { - return type.isPrimitive() - || type == String.class - || type == Character.class - || type == Boolean.class - || type == Byte.class - || type == Short.class - || type == Integer.class - || type == Long.class - || type == Float.class - || type == Double.class - || type == Object.class; + return ClassUtils.isPrimitive(type); } public static Object convertPrimitive(Class type, String value) { - if (value == null) { - return null; - } else if (type == char.class || type == Character.class) { - return value.length() > 0 ? value.charAt(0) : '\0'; - } else if (type == boolean.class || type == Boolean.class) { - return Boolean.valueOf(value); - } - try { - if (type == byte.class || type == Byte.class) { - return Byte.valueOf(value); - } else if (type == short.class || type == Short.class) { - return Short.valueOf(value); - } else if (type == int.class || type == Integer.class) { - return Integer.valueOf(value); - } else if (type == long.class || type == Long.class) { - return Long.valueOf(value); - } else if (type == float.class || type == Float.class) { - return Float.valueOf(value); - } else if (type == double.class || type == Double.class) { - return Double.valueOf(value); - } - } catch (NumberFormatException e) { - return null; - } - return value; + return ClassUtils.convertPrimitive(type,value); } @@ -301,10 +148,6 @@ public static Object convertPrimitive(Class type, String value) { * @return */ public static boolean isTypeMatch(Class type, String value) { - if ((type == boolean.class || type == Boolean.class) - && !("true".equals(value) || "false".equals(value))) { - return false; - } - return true; + return ClassUtils.isTypeMatch(type,value); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java new file mode 100644 index 00000000000..51e4ee516b0 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java @@ -0,0 +1,288 @@ +/* + * 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.utils; + + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class ClassUtils { + /** + * Suffix for array class names: "[]" + */ + public static final String ARRAY_SUFFIX = "[]"; + /** + * Prefix for internal array class names: "[L" + */ + private static final String INTERNAL_ARRAY_PREFIX = "[L"; + /** + * Map with primitive type name as key and corresponding primitive type as + * value, for example: "int" -> "int.class". + */ + private static final Map> primitiveTypeNameMap = new HashMap>(16); + /** + * Map with primitive wrapper type as key and corresponding primitive type + * as value, for example: Integer.class -> int.class. + */ + private static final Map, Class> primitiveWrapperTypeMap = new HashMap, Class>(8); + + private static final char PACKAGE_SEPARATOR_CHAR = '.'; + + static { + primitiveWrapperTypeMap.put(Boolean.class, boolean.class); + primitiveWrapperTypeMap.put(Byte.class, byte.class); + primitiveWrapperTypeMap.put(Character.class, char.class); + primitiveWrapperTypeMap.put(Double.class, double.class); + primitiveWrapperTypeMap.put(Float.class, float.class); + primitiveWrapperTypeMap.put(Integer.class, int.class); + primitiveWrapperTypeMap.put(Long.class, long.class); + primitiveWrapperTypeMap.put(Short.class, short.class); + + Set> primitiveTypeNames = new HashSet<>(16); + primitiveTypeNames.addAll(primitiveWrapperTypeMap.values()); + primitiveTypeNames.addAll(Arrays + .asList(boolean[].class, byte[].class, char[].class, double[].class, + float[].class, int[].class, long[].class, short[].class)); + for (Class primitiveTypeName : primitiveTypeNames) { + primitiveTypeNameMap.put(primitiveTypeName.getName(), primitiveTypeName); + } + } + + public static Class forNameWithThreadContextClassLoader(String name) + throws ClassNotFoundException { + return forName(name, Thread.currentThread().getContextClassLoader()); + } + + public static Class forNameWithCallerClassLoader(String name, Class caller) + throws ClassNotFoundException { + return forName(name, caller.getClassLoader()); + } + + public static ClassLoader getCallerClassLoader(Class caller) { + return caller.getClassLoader(); + } + + /** + * get class loader + * + * @param clazz + * @return class loader + */ + public static ClassLoader getClassLoader(Class clazz) { + ClassLoader cl = null; + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (Throwable ex) { + // Cannot access thread context ClassLoader - falling back to system class loader... + } + if (cl == null) { + // No thread context class loader -> use class loader of this class. + cl = clazz.getClassLoader(); + if (cl == null) { + // getClassLoader() returning null indicates the bootstrap ClassLoader + try { + cl = ClassLoader.getSystemClassLoader(); + } catch (Throwable ex) { + // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + } + } + } + + return cl; + } + + /** + * Return the default ClassLoader to use: typically the thread context + * ClassLoader, if available; the ClassLoader that loaded the ClassUtils + * class will be used as fallback. + *

+ * Call this method if you intend to use the thread context ClassLoader in a + * scenario where you absolutely need a non-null ClassLoader reference: for + * example, for class path resource loading (but not necessarily for + * Class.forName, which accepts a null ClassLoader + * reference as well). + * + * @return the default ClassLoader (never null) + * @see java.lang.Thread#getContextClassLoader() + */ + public static ClassLoader getClassLoader() { + return getClassLoader(ClassUtils.class); + } + + /** + * Same as Class.forName(), except that it works for primitive + * types. + */ + public static Class forName(String name) throws ClassNotFoundException { + return forName(name, getClassLoader()); + } + + /** + * Replacement for Class.forName() that also returns Class + * instances for primitives (like "int") and array class names (like + * "String[]"). + * + * @param name the name of the Class + * @param classLoader the class loader to use (may be null, + * which indicates the default class loader) + * @return Class instance for the supplied name + * @throws ClassNotFoundException if the class was not found + * @throws LinkageError if the class file could not be loaded + * @see Class#forName(String, boolean, ClassLoader) + */ + public static Class forName(String name, ClassLoader classLoader) + throws ClassNotFoundException, LinkageError { + + Class clazz = resolvePrimitiveClassName(name); + if (clazz != null) { + return clazz; + } + + // "java.lang.String[]" style arrays + if (name.endsWith(ARRAY_SUFFIX)) { + String elementClassName = name.substring(0, name.length() - ARRAY_SUFFIX.length()); + Class elementClass = forName(elementClassName, classLoader); + return Array.newInstance(elementClass, 0).getClass(); + } + + // "[Ljava.lang.String;" style arrays + int internalArrayMarker = name.indexOf(INTERNAL_ARRAY_PREFIX); + if (internalArrayMarker != -1 && name.endsWith(";")) { + String elementClassName = null; + if (internalArrayMarker == 0) { + elementClassName = name + .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); + } else if (name.startsWith("[")) { + elementClassName = name.substring(1); + } + Class elementClass = forName(elementClassName, classLoader); + return Array.newInstance(elementClass, 0).getClass(); + } + + ClassLoader classLoaderToUse = classLoader; + if (classLoaderToUse == null) { + classLoaderToUse = getClassLoader(); + } + return classLoaderToUse.loadClass(name); + } + + /** + * Resolve the given class name as primitive class, if appropriate, + * according to the JVM's naming rules for primitive classes. + *

+ * Also supports the JVM's internal class names for primitive arrays. Does + * not support the "[]" suffix notation for primitive arrays; this is + * only supported by {@link #forName}. + * + * @param name the name of the potentially primitive class + * @return the primitive class, or null if the name does not + * denote a primitive class or primitive array class + */ + public static Class resolvePrimitiveClassName(String name) { + Class result = null; + // Most class names will be quite long, considering that they + // SHOULD sit in a package, so a length check is worthwhile. + if (name != null && name.length() <= 8) { + // Could be a primitive - likely. + result = (Class) primitiveTypeNameMap.get(name); + } + return result; + } + + public static String toShortString(Object obj) { + if (obj == null) { + return "null"; + } + return obj.getClass().getSimpleName() + "@" + System.identityHashCode(obj); + + } + + public static String simpleClassName(Class clazz) { + if (clazz == null) { + throw new NullPointerException("clazz"); + } + String className = clazz.getName(); + final int lastDotIdx = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR); + if (lastDotIdx > -1) { + return className.substring(lastDotIdx + 1); + } + return className; + } + + + public static boolean isPrimitive(Class type) { + return type.isPrimitive() + || type == String.class + || type == Character.class + || type == Boolean.class + || type == Byte.class + || type == Short.class + || type == Integer.class + || type == Long.class + || type == Float.class + || type == Double.class + || type == Object.class; + } + + public static Object convertPrimitive(Class type, String value) { + if (value == null) { + return null; + } else if (type == char.class || type == Character.class) { + return value.length() > 0 ? value.charAt(0) : '\0'; + } else if (type == boolean.class || type == Boolean.class) { + return Boolean.valueOf(value); + } + try { + if (type == byte.class || type == Byte.class) { + return Byte.valueOf(value); + } else if (type == short.class || type == Short.class) { + return Short.valueOf(value); + } else if (type == int.class || type == Integer.class) { + return Integer.valueOf(value); + } else if (type == long.class || type == Long.class) { + return Long.valueOf(value); + } else if (type == float.class || type == Float.class) { + return Float.valueOf(value); + } else if (type == double.class || type == Double.class) { + return Double.valueOf(value); + } + } catch (NumberFormatException e) { + return null; + } + return value; + } + + + /** + * We only check boolean value at this moment. + * + * @param type + * @param value + * @return + */ + public static boolean isTypeMatch(Class type, String value) { + if ((type == boolean.class || type == Boolean.class) + && !("true".equals(value) || "false".equals(value))) { + return false; + } + return true; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java index 0c68512c20e..1f26bf035a7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java @@ -235,7 +235,7 @@ public static Properties loadProperties(String fileName, boolean allowMultiFile, List list = new ArrayList(); try { - Enumeration urls = ClassHelper.getClassLoader().getResources(fileName); + Enumeration urls = ClassUtils.getClassLoader().getResources(fileName); list = new ArrayList(); while (urls.hasMoreElements()) { list.add(urls.nextElement()); @@ -261,7 +261,7 @@ public static Properties loadProperties(String fileName, boolean allowMultiFile, // fall back to use method getResourceAsStream try { - properties.load(ClassHelper.getClassLoader().getResourceAsStream(fileName)); + properties.load(ClassUtils.getClassLoader().getResourceAsStream(fileName)); } catch (Throwable e) { logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java new file mode 100644 index 00000000000..00ea97a663a --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java @@ -0,0 +1,41 @@ +/* + * 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.utils; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +public class MethodUtils { + + public static boolean isSetter(Method method) { + return method.getName().startsWith("set") + && !"set".equals(method.getName()) + && Modifier.isPublic(method.getModifiers()) + && method.getParameterCount() == 1 + && ClassUtils.isPrimitive(method.getParameterTypes()[0]); + } + + public static boolean isGetter(Method method) { + String name = method.getName(); + return (name.startsWith("get") || name.startsWith("is")) + && !"get".equals(name) && !"is".equals(name) + && !"getClass".equals(name) && !"getObject".equals(name) + && Modifier.isPublic(method.getModifiers()) + && method.getParameterTypes().length == 0 + && ClassUtils.isPrimitive(method.getReturnType()); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java index 18998dc6239..37aa5ddaa68 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java @@ -380,7 +380,7 @@ private static Object realize0(Object pojo, Class type, Type genericType, fin Object className = ((Map) pojo).get("class"); if (className instanceof String) { try { - type = ClassHelper.forName((String) className); + type = ClassUtils.forName((String) className); } catch (ClassNotFoundException e) { // ignore } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java index 20e091acc45..ccec6875ca8 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java @@ -665,7 +665,7 @@ public static Class forName(ClassLoader cl, String name) { * @return Class instance. */ public static Class name2class(String name) throws ClassNotFoundException { - return name2class(ClassHelper.getClassLoader(), name); + return name2class(ClassUtils.getClassLoader(), name); } /** @@ -734,7 +734,7 @@ private static Class name2class(ClassLoader cl, String name) throws ClassNotF } if (cl == null) { - cl = ClassHelper.getClassLoader(); + cl = ClassUtils.getClassLoader(); } Class clazz = NAME_CLASS_CACHE.get(name); if (clazz == null) { @@ -754,7 +754,7 @@ private static Class name2class(ClassLoader cl, String name) throws ClassNotF * @throws ClassNotFoundException */ public static Class desc2class(String desc) throws ClassNotFoundException { - return desc2class(ClassHelper.getClassLoader(), desc); + return desc2class(ClassUtils.getClassLoader(), desc); } /** @@ -798,7 +798,7 @@ private static Class desc2class(ClassLoader cl, String desc) throws ClassNotF } if (cl == null) { - cl = ClassHelper.getClassLoader(); + cl = ClassUtils.getClassLoader(); } Class clazz = DESC_CLASS_CACHE.get(desc); if (clazz == null) { @@ -816,7 +816,7 @@ private static Class desc2class(ClassLoader cl, String desc) throws ClassNotF * @throws ClassNotFoundException */ public static Class[] desc2classArray(String desc) throws ClassNotFoundException { - Class[] ret = desc2classArray(ClassHelper.getClassLoader(), desc); + Class[] ret = desc2classArray(ClassUtils.getClassLoader(), desc); return ret; } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassHelperTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassHelperTest.java deleted file mode 100644 index 470e58709a1..00000000000 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassHelperTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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.utils; - -import org.junit.jupiter.api.Test; -import org.mockito.Mockito; - -import static org.apache.dubbo.common.utils.ClassHelper.forName; -import static org.apache.dubbo.common.utils.ClassHelper.getCallerClassLoader; -import static org.apache.dubbo.common.utils.ClassHelper.getClassLoader; -import static org.apache.dubbo.common.utils.ClassHelper.resolvePrimitiveClassName; -import static org.apache.dubbo.common.utils.ClassHelper.toShortString; -import static org.apache.dubbo.common.utils.ClassHelper.convertPrimitive; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.is; -import static org.hamcrest.Matchers.sameInstance; -import static org.hamcrest.Matchers.startsWith; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.verify; - -public class ClassHelperTest { - @Test - public void testForNameWithThreadContextClassLoader() throws Exception { - ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); - try { - ClassLoader classLoader = Mockito.mock(ClassLoader.class); - Thread.currentThread().setContextClassLoader(classLoader); - ClassHelper.forNameWithThreadContextClassLoader("a.b.c.D"); - verify(classLoader).loadClass("a.b.c.D"); - } finally { - Thread.currentThread().setContextClassLoader(oldClassLoader); - } - } - - @Test - public void tetForNameWithCallerClassLoader() throws Exception { - Class c = ClassHelper.forNameWithCallerClassLoader(ClassHelper.class.getName(), ClassHelperTest.class); - assertThat(c == ClassHelper.class, is(true)); - } - - @Test - public void testGetCallerClassLoader() throws Exception { - assertThat(getCallerClassLoader(ClassHelperTest.class), sameInstance(ClassHelperTest.class.getClassLoader())); - } - - @Test - public void testGetClassLoader1() throws Exception { - ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); - try { - assertThat(getClassLoader(ClassHelperTest.class), sameInstance(oldClassLoader)); - Thread.currentThread().setContextClassLoader(null); - assertThat(getClassLoader(ClassHelperTest.class), sameInstance(ClassHelperTest.class.getClassLoader())); - } finally { - Thread.currentThread().setContextClassLoader(oldClassLoader); - } - } - - @Test - public void testGetClassLoader2() throws Exception { - assertThat(getClassLoader(), sameInstance(ClassHelper.class.getClassLoader())); - } - - @Test - public void testForName1() throws Exception { - assertThat(forName(ClassHelperTest.class.getName()) == ClassHelperTest.class, is(true)); - } - - @Test - public void testForName2() throws Exception { - assertThat(forName("byte") == byte.class, is(true)); - assertThat(forName("java.lang.String[]") == String[].class, is(true)); - assertThat(forName("[Ljava.lang.String;") == String[].class, is(true)); - } - - @Test - public void testForName3() throws Exception { - ClassLoader classLoader = Mockito.mock(ClassLoader.class); - forName("a.b.c.D", classLoader); - verify(classLoader).loadClass("a.b.c.D"); - } - - @Test - public void testResolvePrimitiveClassName() throws Exception { - assertThat(resolvePrimitiveClassName("boolean") == boolean.class, is(true)); - assertThat(resolvePrimitiveClassName("byte") == byte.class, is(true)); - assertThat(resolvePrimitiveClassName("char") == char.class, is(true)); - assertThat(resolvePrimitiveClassName("double") == double.class, is(true)); - assertThat(resolvePrimitiveClassName("float") == float.class, is(true)); - assertThat(resolvePrimitiveClassName("int") == int.class, is(true)); - assertThat(resolvePrimitiveClassName("long") == long.class, is(true)); - assertThat(resolvePrimitiveClassName("short") == short.class, is(true)); - assertThat(resolvePrimitiveClassName("[Z") == boolean[].class, is(true)); - assertThat(resolvePrimitiveClassName("[B") == byte[].class, is(true)); - assertThat(resolvePrimitiveClassName("[C") == char[].class, is(true)); - assertThat(resolvePrimitiveClassName("[D") == double[].class, is(true)); - assertThat(resolvePrimitiveClassName("[F") == float[].class, is(true)); - assertThat(resolvePrimitiveClassName("[I") == int[].class, is(true)); - assertThat(resolvePrimitiveClassName("[J") == long[].class, is(true)); - assertThat(resolvePrimitiveClassName("[S") == short[].class, is(true)); - } - - @Test - public void testToShortString() throws Exception { - assertThat(toShortString(null), equalTo("null")); - assertThat(toShortString(new ClassHelperTest()), startsWith("ClassHelperTest@")); - } - - @Test - public void testConvertPrimitive() throws Exception { - - assertThat(convertPrimitive(char.class, ""), equalTo('\0')); - assertThat(convertPrimitive(char.class, null), equalTo(null)); - assertThat(convertPrimitive(char.class, "6"), equalTo('6')); - - assertThat(convertPrimitive(boolean.class, ""), equalTo(Boolean.FALSE)); - assertThat(convertPrimitive(boolean.class, null), equalTo(null)); - assertThat(convertPrimitive(boolean.class, "true"), equalTo(Boolean.TRUE)); - - - assertThat(convertPrimitive(byte.class, ""), equalTo(null)); - assertThat(convertPrimitive(byte.class, null), equalTo(null)); - assertThat(convertPrimitive(byte.class, "127"), equalTo(Byte.MAX_VALUE)); - - - assertThat(convertPrimitive(short.class, ""), equalTo(null)); - assertThat(convertPrimitive(short.class, null), equalTo(null)); - assertThat(convertPrimitive(short.class, "32767"), equalTo(Short.MAX_VALUE)); - - assertThat(convertPrimitive(int.class, ""), equalTo(null)); - assertThat(convertPrimitive(int.class, null), equalTo(null)); - assertThat(convertPrimitive(int.class, "6"), equalTo(6)); - - assertThat(convertPrimitive(long.class, ""), equalTo(null)); - assertThat(convertPrimitive(long.class, null), equalTo(null)); - assertThat(convertPrimitive(long.class, "6"), equalTo(new Long(6))); - - assertThat(convertPrimitive(float.class, ""), equalTo(null)); - assertThat(convertPrimitive(float.class, null), equalTo(null)); - assertThat(convertPrimitive(float.class, "1.1"), equalTo(new Float(1.1))); - - assertThat(convertPrimitive(double.class, ""), equalTo(null)); - assertThat(convertPrimitive(double.class, null), equalTo(null)); - assertThat(convertPrimitive(double.class, "10.1"), equalTo(new Double(10.1))); - } - -} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassUtilsTest.java new file mode 100644 index 00000000000..211e6f4d09c --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ClassUtilsTest.java @@ -0,0 +1,155 @@ +/* + * 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.utils; + +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.sameInstance; +import static org.hamcrest.Matchers.startsWith; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.mockito.Mockito.verify; + +public class ClassUtilsTest { + @Test + public void testForNameWithThreadContextClassLoader() throws Exception { + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + ClassLoader classLoader = Mockito.mock(ClassLoader.class); + Thread.currentThread().setContextClassLoader(classLoader); + ClassUtils.forNameWithThreadContextClassLoader("a.b.c.D"); + verify(classLoader).loadClass("a.b.c.D"); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + + @Test + public void tetForNameWithCallerClassLoader() throws Exception { + Class c = ClassUtils.forNameWithCallerClassLoader(ClassUtils.class.getName(), ClassUtilsTest.class); + assertThat(c == ClassUtils.class, is(true)); + } + + @Test + public void testGetCallerClassLoader() throws Exception { + assertThat(ClassUtils.getCallerClassLoader(ClassUtilsTest.class), sameInstance(ClassUtilsTest.class.getClassLoader())); + } + + @Test + public void testGetClassLoader1() throws Exception { + ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader(); + try { + assertThat(ClassUtils.getClassLoader(ClassUtilsTest.class), sameInstance(oldClassLoader)); + Thread.currentThread().setContextClassLoader(null); + assertThat(ClassUtils.getClassLoader(ClassUtilsTest.class), sameInstance(ClassUtilsTest.class.getClassLoader())); + } finally { + Thread.currentThread().setContextClassLoader(oldClassLoader); + } + } + + @Test + public void testGetClassLoader2() throws Exception { + assertThat(ClassUtils.getClassLoader(), sameInstance(ClassUtils.class.getClassLoader())); + } + + @Test + public void testForName1() throws Exception { + assertThat(ClassUtils.forName(ClassUtilsTest.class.getName()) == ClassUtilsTest.class, is(true)); + } + + @Test + public void testForName2() throws Exception { + assertThat(ClassUtils.forName("byte") == byte.class, is(true)); + assertThat(ClassUtils.forName("java.lang.String[]") == String[].class, is(true)); + assertThat(ClassUtils.forName("[Ljava.lang.String;") == String[].class, is(true)); + } + + @Test + public void testForName3() throws Exception { + ClassLoader classLoader = Mockito.mock(ClassLoader.class); + ClassUtils.forName("a.b.c.D", classLoader); + verify(classLoader).loadClass("a.b.c.D"); + } + + @Test + public void testResolvePrimitiveClassName() throws Exception { + assertThat(ClassUtils.resolvePrimitiveClassName("boolean") == boolean.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("byte") == byte.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("char") == char.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("double") == double.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("float") == float.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("int") == int.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("long") == long.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("short") == short.class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[Z") == boolean[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[B") == byte[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[C") == char[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[D") == double[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[F") == float[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[I") == int[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[J") == long[].class, is(true)); + assertThat(ClassUtils.resolvePrimitiveClassName("[S") == short[].class, is(true)); + } + + @Test + public void testToShortString() throws Exception { + assertThat(ClassUtils.toShortString(null), equalTo("null")); + assertThat(ClassUtils.toShortString(new ClassUtilsTest()), startsWith("ClassUtilsTest@")); + } + + @Test + public void testConvertPrimitive() throws Exception { + + assertThat(ClassUtils.convertPrimitive(char.class, ""), equalTo('\0')); + assertThat(ClassUtils.convertPrimitive(char.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(char.class, "6"), equalTo('6')); + + assertThat(ClassUtils.convertPrimitive(boolean.class, ""), equalTo(Boolean.FALSE)); + assertThat(ClassUtils.convertPrimitive(boolean.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(boolean.class, "true"), equalTo(Boolean.TRUE)); + + + assertThat(ClassUtils.convertPrimitive(byte.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(byte.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(byte.class, "127"), equalTo(Byte.MAX_VALUE)); + + + assertThat(ClassUtils.convertPrimitive(short.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(short.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(short.class, "32767"), equalTo(Short.MAX_VALUE)); + + assertThat(ClassUtils.convertPrimitive(int.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(int.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(int.class, "6"), equalTo(6)); + + assertThat(ClassUtils.convertPrimitive(long.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(long.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(long.class, "6"), equalTo(new Long(6))); + + assertThat(ClassUtils.convertPrimitive(float.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(float.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(float.class, "1.1"), equalTo(new Float(1.1))); + + assertThat(ClassUtils.convertPrimitive(double.class, ""), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(double.class, null), equalTo(null)); + assertThat(ClassUtils.convertPrimitive(double.class, "10.1"), equalTo(new Double(10.1))); + } + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java new file mode 100644 index 00000000000..cc15d111690 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java @@ -0,0 +1,62 @@ +/* + * 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.utils; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.lang.reflect.Method; + +public class MethodUtilsTest { + + @Test + public void testGetMethod() { + Method getMethod = null; + for (Method method : MethodTestClazz.class.getMethods()) { + if (MethodUtils.isGetter(method)) { + getMethod = method; + } + } + Assertions.assertNotNull(getMethod); + Assertions.assertTrue(getMethod.getName().equals("getValue")); + } + + @Test + public void testSetMethod() { + Method setMethod = null; + for (Method method : MethodTestClazz.class.getMethods()) { + if (MethodUtils.isSetter(method)) { + setMethod = method; + } + } + Assertions.assertNotNull(setMethod); + Assertions.assertTrue(setMethod.getName().equals("setValue")); + } + + public class MethodTestClazz { + private String value; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + } + +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java index 61d05c56702..30b3f50daf5 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java @@ -24,8 +24,9 @@ import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.common.utils.MethodUtils; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.support.Parameter; @@ -156,7 +157,7 @@ protected static void appendParameters(Map parameters, Object co for (Method method : methods) { try { String name = method.getName(); - if (ClassHelper.isGetter(method)) { + if (MethodUtils.isGetter(method)) { Parameter parameter = method.getAnnotation(Parameter.class); if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) { continue; @@ -224,7 +225,7 @@ protected static void appendAttributes(Map parameters, Object co continue; } String name = method.getName(); - if (ClassHelper.isGetter(method)) { + if (MethodUtils.isGetter(method)) { String key; if (parameter.key().length() > 0) { key = parameter.key(); @@ -555,12 +556,12 @@ public void refresh() { // loop methods, get override value and set the new value back to method Method[] methods = getClass().getMethods(); for (Method method : methods) { - if (ClassHelper.isSetter(method)) { + if (MethodUtils.isSetter(method)) { try { String value = StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method))); // isTypeMatch() is called to avoid duplicate and incorrect update, for example, we have two 'setGeneric' methods in ReferenceConfig. - if (StringUtils.isNotEmpty(value) && ClassHelper.isTypeMatch(method.getParameterTypes()[0], value)) { - method.invoke(this, ClassHelper.convertPrimitive(method.getParameterTypes()[0], value)); + if (StringUtils.isNotEmpty(value) && ClassUtils.isTypeMatch(method.getParameterTypes()[0], value)) { + method.invoke(this, ClassUtils.convertPrimitive(method.getParameterTypes()[0], value)); } } catch (NoSuchMethodException e) { logger.info("Failed to override the property " + method.getName() + " in " + @@ -583,7 +584,7 @@ public String toString() { Method[] methods = getClass().getMethods(); for (Method method : methods) { try { - if (ClassHelper.isGetter(method)) { + if (MethodUtils.isGetter(method)) { String name = method.getName(); String key = calculateAttributeFromGetter(name); Object value = method.invoke(this); @@ -632,7 +633,7 @@ private boolean isMetaMethod(Method method) { if (method.getParameterTypes().length != 0) { return false; } - if (!ClassHelper.isPrimitive(method.getReturnType())) { + if (!ClassUtils.isPrimitive(method.getReturnType())) { return false; } return true; @@ -646,7 +647,7 @@ public boolean equals(Object obj) { Method[] methods = this.getClass().getMethods(); for (Method method1 : methods) { - if (ClassHelper.isGetter(method1) && ClassHelper.isPrimitive(method1.getReturnType())) { + if (MethodUtils.isGetter(method1) && ClassUtils.isPrimitive(method1.getReturnType())) { Parameter parameter = method1.getAnnotation(Parameter.class); if (parameter != null && parameter.excluded()) { continue; diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java index fe0f43a1865..e1df3193c13 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java @@ -21,7 +21,7 @@ import org.apache.dubbo.common.Version; import org.apache.dubbo.common.bytecode.Wrapper; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.NetUtils; @@ -108,7 +108,7 @@ public class ReferenceConfig extends AbstractReferenceConfig { * The interface class of the reference service */ private Class interfaceClass; - + /** * client type */ @@ -328,6 +328,7 @@ private ConsumerModel buildConsumerModel(String serviceKey, Map } return new ConsumerModel(serviceKey, serviceInterface, ref, methods, attributes); } + @SuppressWarnings({"unchecked", "rawtypes", "deprecation"}) private T createProxy(Map map) { if (shouldJvmRefer(map)) { @@ -439,7 +440,7 @@ protected boolean shouldJvmRefer(Map map) { protected boolean shouldCheck() { Boolean shouldCheck = isCheck(); - if (shouldCheck == null && getConsumer()!= null) { + if (shouldCheck == null && getConsumer() != null) { shouldCheck = getConsumer().isCheck(); } if (shouldCheck == null) { @@ -515,7 +516,7 @@ public Class getInterfaceClass() { } try { if (interfaceName != null && interfaceName.length() > 0) { - this.interfaceClass = Class.forName(interfaceName, true, ClassHelper.getClassLoader()); + this.interfaceClass = Class.forName(interfaceName, true, ClassUtils.getClassLoader()); } } catch (ClassNotFoundException t) { throw new IllegalStateException(t.getMessage(), t); diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java index 602b5d4f467..2fbb85a8db5 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java @@ -23,7 +23,7 @@ import org.apache.dubbo.common.bytecode.Wrapper; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.NamedThreadFactory; @@ -301,7 +301,7 @@ public void checkAndUpdateSubConfigs() { } Class localClass; try { - localClass = ClassHelper.forNameWithThreadContextClassLoader(local); + localClass = ClassUtils.forNameWithThreadContextClassLoader(local); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } @@ -315,7 +315,7 @@ public void checkAndUpdateSubConfigs() { } Class stubClass; try { - stubClass = ClassHelper.forNameWithThreadContextClassLoader(stub); + stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub); } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } diff --git a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java index 58058f4f64f..ceef6ccf774 100644 --- a/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java +++ b/dubbo-rpc/dubbo-rpc-thrift/src/main/java/org/apache/dubbo/rpc/protocol/thrift/ThriftCodec.java @@ -18,7 +18,7 @@ import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.extension.ExtensionLoader; -import org.apache.dubbo.common.utils.ClassHelper; +import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.remoting.Channel; import org.apache.dubbo.remoting.Codec2; import org.apache.dubbo.remoting.buffer.ChannelBuffer; @@ -199,7 +199,7 @@ private Object decode(TProtocol protocol) if (clazz == null) { try { - clazz = ClassHelper.forNameWithThreadContextClassLoader(argsClassName); + clazz = ClassUtils.forNameWithThreadContextClassLoader(argsClassName); cachedClass.putIfAbsent(argsClassName, clazz); @@ -313,7 +313,7 @@ private Object decode(TProtocol protocol) try { - clazz = ClassHelper.forNameWithThreadContextClassLoader(resultClassName); + clazz = ClassUtils.forNameWithThreadContextClassLoader(resultClassName); cachedClass.putIfAbsent(resultClassName, clazz); @@ -429,7 +429,7 @@ private void encodeRequest(Channel channel, ChannelBuffer buffer, Request reques try { - clazz = ClassHelper.forNameWithThreadContextClassLoader(methodArgs); + clazz = ClassUtils.forNameWithThreadContextClassLoader(methodArgs); cachedClass.putIfAbsent(methodArgs, clazz); @@ -555,7 +555,7 @@ private void encodeResponse(Channel channel, ChannelBuffer buffer, Response resp if (clazz == null) { try { - clazz = ClassHelper.forNameWithThreadContextClassLoader(resultClassName); + clazz = ClassUtils.forNameWithThreadContextClassLoader(resultClassName); cachedClass.putIfAbsent(resultClassName, clazz); } catch (ClassNotFoundException e) { throw new RpcException(RpcException.SERIALIZATION_EXCEPTION, e.getMessage(), e); diff --git a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java index 2ed71f814ec..e8817746a64 100644 --- a/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java +++ b/dubbo-serialization/dubbo-serialization-jdk/src/main/java/org/apache/dubbo/common/serialize/java/CompactedObjectInputStream.java @@ -16,7 +16,8 @@ */ package org.apache.dubbo.common.serialize.java; -import org.apache.dubbo.common.utils.ClassHelper; + +import org.apache.dubbo.common.utils.ClassUtils; import java.io.EOFException; import java.io.IOException; @@ -37,7 +38,7 @@ public CompactedObjectInputStream(InputStream in) throws IOException { public CompactedObjectInputStream(InputStream in, ClassLoader cl) throws IOException { super(in); - mClassLoader = cl == null ? ClassHelper.getClassLoader() : cl; + mClassLoader = cl == null ? ClassUtils.getClassLoader() : cl; } @Override