diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/ManifestArtifactResourceResolver.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/ManifestArtifactResourceResolver.java index 97f79ff08..3521245dc 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/ManifestArtifactResourceResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/ManifestArtifactResourceResolver.java @@ -207,7 +207,9 @@ Artifact resolveArtifactMetaInfoInManifest(Manifest manifest, URL resourceURL) { } String version = resolveVersion(mainAttributes); Artifact artifact = create(artifactId, version, resourceURL); - logger.trace("The artifactId was resolved from the resource URL['{}']: {}", artifactId, artifact); + if (logger.isTraceEnabled()) { + logger.trace("The artifactId was resolved from the resource URL['{}']: {}", artifactId, artifact); + } return artifact; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/classloading/StreamArtifactResourceResolver.java b/microsphere-java-core/src/main/java/io/microsphere/classloading/StreamArtifactResourceResolver.java index 58ed3de1a..0b4312624 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/classloading/StreamArtifactResourceResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/classloading/StreamArtifactResourceResolver.java @@ -113,7 +113,9 @@ public final Artifact resolve(URL resourceURL) { Artifact artifact = null; try { if (archiveFile == null) { - logger.trace("The resourceURL['{}'] can't be resolved to be an archive file", resourceURL); + if (logger.isTraceEnabled()) { + logger.trace("The resourceURL['{}'] can't be resolved to be an archive file", resourceURL); + } artifactMetadataData = readArtifactMetadataDataFromResource(resourceURL, classLoader); } else { artifactMetadataData = readArtifactMetadataDataFromArchiveFile(archiveFile); @@ -149,7 +151,9 @@ protected InputStream readArtifactMetadataDataFromFile(File archiveFile) throws JarFile jarFile = new JarFile(archiveFile); JarEntry jarEntry = findArtifactMetadataEntry(jarFile); if (jarEntry == null) { - logger.trace("The artifact metadata entry can't be resolved from the JarFile[path: '{}']", archiveFile); + if (logger.isTraceEnabled()) { + logger.trace("The artifact metadata entry can't be resolved from the JarFile[path: '{}']", archiveFile); + } return null; } return jarFile.getInputStream(jarEntry); @@ -159,7 +163,9 @@ protected InputStream readArtifactMetadataDataFromFile(File archiveFile) throws protected InputStream readArtifactMetadataDataFromDirectory(File directory) throws IOException { File artifactMetadataFile = findArtifactMetadata(directory); if (artifactMetadataFile == null) { - logger.trace("The artifact metadata file can't be found in the directory[path: '{}']", directory); + if (logger.isTraceEnabled()) { + logger.trace("The artifact metadata file can't be found in the directory[path: '{}']", directory); + } return null; } return new FileInputStream(artifactMetadataFile); diff --git a/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java b/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java index 88a357691..5bc2a60fc 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/collection/ListUtils.java @@ -668,6 +668,10 @@ public static void forEach(List values, Consumer consumer) { forEach(values, (i, e) -> consumer.accept(e)); } + public static boolean addIfAbsent(List values, T newValue) { + return values.contains(newValue) ? false : values.add(newValue); + } + private ListUtils() { } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/concurrent/ExecutorUtils.java b/microsphere-java-core/src/main/java/io/microsphere/concurrent/ExecutorUtils.java index 930ce67d8..b49c49e93 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/concurrent/ExecutorUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/concurrent/ExecutorUtils.java @@ -135,7 +135,9 @@ public static boolean shutdown(ExecutorService executorService) { if (!executorService.isShutdown()) { executorService.shutdown(); } - logger.trace("The ExecutorService({}) has been shutdown", executorService); + if (logger.isTraceEnabled()) { + logger.trace("The ExecutorService({}) has been shutdown", executorService); + } return true; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java b/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java index c5bd0b47e..424454bff 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/IOUtils.java @@ -367,7 +367,9 @@ public static int copy(InputStream in, OutputStream out) throws IOException { byteCount += bytesRead; } out.flush(); - logger.trace("Copied {} bytes[buffer size : {}] from InputStream[{}] to OutputStream[{}]", byteCount, BUFFER_SIZE, in, out); + if (logger.isTraceEnabled()) { + logger.trace("Copied {} bytes[buffer size : {}] from InputStream[{}] to OutputStream[{}]", byteCount, BUFFER_SIZE, in, out); + } return byteCount; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/StandardFileWatchService.java b/microsphere-java-core/src/main/java/io/microsphere/io/StandardFileWatchService.java index ba892d397..80b334813 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/StandardFileWatchService.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/StandardFileWatchService.java @@ -245,7 +245,9 @@ private void dispatchFileChangedEvent(Path filePath, WatchEvent.Kind watchEventK Kind kind = toKind(watchEventKind); FileChangedEvent fileChangedEvent = new FileChangedEvent(file, kind); eventDispatcher.dispatch(fileChangedEvent); - logger.trace("The {} was dispatched", fileChangedEvent); + if (logger.isTraceEnabled()) { + logger.trace("The {} was dispatched", fileChangedEvent); + } } private void registerDirectoriesToWatchService(WatchService watchService) throws Exception { @@ -254,8 +256,10 @@ private void registerDirectoriesToWatchService(WatchService watchService) throws FileChangedMetadata metadata = entry.getValue(); WatchEvent.Kind[] kinds = metadata.watchEventKinds; directoryPath.register(watchService, kinds); - logger.trace("The directory[path : '{}' , event kinds : {}] registers the WatchService : {}", - directoryPath, arrayToString(kinds), watchService); + if (logger.isTraceEnabled()) { + logger.trace("The directory[path : '{}' , event kinds : {}] registers the WatchService : {}", + directoryPath, arrayToString(kinds), watchService); + } } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java index 6356cc99a..48adfa663 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java +++ b/microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleFileScanner.java @@ -100,7 +100,7 @@ public Set scan(File rootDirectory, boolean recursive, IOFileFilter ioFile filesSet.add(subFile); } if (recursive && subFile.isDirectory()) { - filesSet.addAll(this.scan(subFile, recursive, ioFileFilter)); + filesSet.addAll(scan(subFile, recursive, ioFileFilter)); } } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/net/StandardURLStreamHandlerFactory.java b/microsphere-java-core/src/main/java/io/microsphere/net/StandardURLStreamHandlerFactory.java index 9a23d0c79..71c6161b7 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/net/StandardURLStreamHandlerFactory.java +++ b/microsphere-java-core/src/main/java/io/microsphere/net/StandardURLStreamHandlerFactory.java @@ -86,7 +86,9 @@ URLStreamHandler createURLStreamHandler(Field defaultFactoryField, String protoc URLStreamHandler createURLStreamHandlerFromDefaultFactory(Field defaultFactoryField, String protocol) { if (defaultFactoryField == null) { - logger.trace("The 'defaultFactory' field can't be found in the class URL."); + if (logger.isTraceEnabled()) { + logger.trace("The 'defaultFactory' field can't be found in the class URL."); + } return null; } URLStreamHandlerFactory factory = getStaticFieldValue(defaultFactoryField); diff --git a/microsphere-java-core/src/main/java/io/microsphere/net/URLUtils.java b/microsphere-java-core/src/main/java/io/microsphere/net/URLUtils.java index 8f23b03f0..e8387f49d 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/net/URLUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/net/URLUtils.java @@ -1184,7 +1184,9 @@ public static String resolveProtocol(String url) { } for (int i = 0; i <= indexOfColon; i++) { if (isWhitespace(url.charAt(i))) { - logger.trace("The protocol content should not contain the whitespace[url : '{}' , index : {}]", url, i); + if (logger.isTraceEnabled()) { + logger.trace("The protocol content should not contain the whitespace[url : '{}' , index : {}]", url, i); + } return null; } } diff --git a/microsphere-java-core/src/main/java/io/microsphere/process/ClassicProcessIdResolver.java b/microsphere-java-core/src/main/java/io/microsphere/process/ClassicProcessIdResolver.java index 10ff9f6ac..496914eab 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/process/ClassicProcessIdResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/process/ClassicProcessIdResolver.java @@ -82,7 +82,9 @@ public boolean supports() { @Override public Long current() { Long processId = valueOf(processIdValue); - logger.trace("The PID was resolved from the method 'java.lang.management.RuntimeMXBean#getName()' = {} : {}", runtimeName, processId); + if (logger.isTraceEnabled()) { + logger.trace("The PID was resolved from the method 'java.lang.management.RuntimeMXBean#getName()' = {} : {}", runtimeName, processId); + } return processId; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/process/ModernProcessIdResolver.java b/microsphere-java-core/src/main/java/io/microsphere/process/ModernProcessIdResolver.java index c1c606418..65dd726d3 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/process/ModernProcessIdResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/process/ModernProcessIdResolver.java @@ -64,7 +64,9 @@ public boolean supports() { public Long current() { Object processHandle = invokeStaticMethod(PROCESS_HANDLE_CLASS, "current"); Long pid = invokeMethod(processHandle, PROCESS_HANDLE_CLASS, "pid"); - logger.trace("The PID was resolved from the method 'java.lang.ProcessHandle#pid()' : {}", pid); + if (logger.isTraceEnabled()) { + logger.trace("The PID was resolved from the method 'java.lang.ProcessHandle#pid()' : {}", pid); + } return pid; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/process/ProcessExecutor.java b/microsphere-java-core/src/main/java/io/microsphere/process/ProcessExecutor.java index 043b5d155..a21a695d2 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/process/ProcessExecutor.java +++ b/microsphere-java-core/src/main/java/io/microsphere/process/ProcessExecutor.java @@ -175,7 +175,9 @@ public void execute(OutputStream outputStream, long timeout, TimeUnit timeUnit) } } finally { processManager.removeUnfinishedProcess(process, options); - logger.trace("The command['{}'] is executed with exit value : {}", commandLine, exitValue); + if (logger.isTraceEnabled()) { + logger.trace("The command['{}'] is executed with exit value : {}", commandLine, exitValue); + } } return targetOutputStream.toByteArray(); }); diff --git a/microsphere-java-core/src/main/java/io/microsphere/process/VirtualMachineProcessIdResolver.java b/microsphere-java-core/src/main/java/io/microsphere/process/VirtualMachineProcessIdResolver.java index a2e48bbba..de4c5bead 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/process/VirtualMachineProcessIdResolver.java +++ b/microsphere-java-core/src/main/java/io/microsphere/process/VirtualMachineProcessIdResolver.java @@ -90,7 +90,9 @@ public Long current() { RuntimeMXBean runtimeMXBean = getRuntimeMXBean(); Object jvm = getFieldValue(runtimeMXBean, JVM_FIELD); Integer processId = invokeMethod(jvm, GET_PROCESS_ID_METHOD_NAME); - logger.trace("The PID was resolved from the native method 'sun.management.VMManagementImpl#getProcessId()' : {}", processId); + if (logger.isTraceEnabled()) { + logger.trace("The PID was resolved from the native method 'sun.management.VMManagementImpl#getProcessId()' : {}", processId); + } return valueOf(processId.longValue()); } diff --git a/microsphere-java-core/src/main/java/io/microsphere/reflect/FieldUtils.java b/microsphere-java-core/src/main/java/io/microsphere/reflect/FieldUtils.java index fe139f1d3..da327d5b2 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/reflect/FieldUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/reflect/FieldUtils.java @@ -115,7 +115,9 @@ public static Field findField(Class klass, String fieldName) { // ignore, try the super class field = findField(klass.getSuperclass(), fieldName); } - logger.trace("To find the field[name :'{}'] from the class : '{}'", fieldName, klass); + if (logger.isTraceEnabled()) { + logger.trace("To find the field[name :'{}'] from the class : '{}'", fieldName, klass); + } return field; } @@ -507,8 +509,6 @@ public static V getFieldValue(Object instance, String fieldName, Class fi * @param instance The object instance from which to retrieve the field value * @param field The {@link Field} object representing the field to retrieve * @return The value of the field if found and accessible; otherwise, {@code null} - * @throws IllegalStateException if this Field object is enforcing Java language access control and the underlying - * field is inaccessible * @throws IllegalArgumentException if the specified object is not an instance of the class or interface declaring * the underlying field (or a subclass or implementor thereof) */ @@ -523,10 +523,9 @@ public static V getFieldValue(Object instance, Field field) throws IllegalSt try { accessible = trySetAccessible(field); fieldValue = (V) field.get(instance); - } catch (IllegalAccessException e) { - handleIllegalAccessException(e, instance, field, accessible); - } catch (IllegalArgumentException e) { - handleIllegalArgumentException(e, instance, field); + } catch (IllegalAccessException | IllegalArgumentException e) { + handleFieldException(e, instance, field); + throw new IllegalArgumentException(e); } return fieldValue; @@ -610,7 +609,6 @@ public static V setFieldValue(Object instance, String fieldName, V value) th * @param field The {@link Field} object representing the field to modify * @param value The new value to assign to the field * @return The previous value of the field before modification, or {@code null} if the field was not found or inaccessible - * @throws IllegalStateException If this Field object is enforcing Java language access control and the underlying field is inaccessible * @throws IllegalArgumentException If the specified object is not an instance of the class or interface declaring the underlying field */ @Nullable @@ -620,17 +618,15 @@ public static V setFieldValue(Object instance, Field field, V value) throws } V previousValue = null; - boolean accessible = false; try { - accessible = trySetAccessible(field); + trySetAccessible(field); previousValue = (V) field.get(instance); if (!Objects.equals(previousValue, value)) { field.set(instance, value); } - } catch (IllegalAccessException e) { - handleIllegalAccessException(e, instance, field, accessible); - } catch (IllegalArgumentException e) { - handleIllegalArgumentException(e, instance, field); + } catch (IllegalAccessException | IllegalArgumentException e) { + handleFieldException(e, instance, field); + throw new IllegalArgumentException(e); } return previousValue; @@ -679,18 +675,11 @@ public static void assertFieldMatchType(Object instance, String fieldName, Class } } - static void handleIllegalAccessException(IllegalAccessException e, Object instance, Field field, boolean accessible) { - String errorMessage = format("The instance [object : {} , class : {} ] can't access the field[name : '{}' , type : {} , accessible : {}]", - instance, getTypeName(instance.getClass()), field.getName(), getTypeName(field.getType()), accessible); - logger.trace(errorMessage); - throw new IllegalStateException(errorMessage, e); - } - - static void handleIllegalArgumentException(IllegalArgumentException e, Object instance, Field field) { - String errorMessage = format("The instance[object : {} , class : {}] can't match the field[name : '{}' , type : {}]", - instance, getTypeName(instance.getClass()), field.getName(), getTypeName(field.getType())); - logger.trace(errorMessage); - throw new IllegalArgumentException(errorMessage, e); + static void handleFieldException(Exception e, Object instance, Field field) { + if (logger.isTraceEnabled()) { + logger.trace("The instance[object : {} , class : {}] can't match the field[name : '{}' , type : {}]", + instance, getTypeName(instance.getClass()), field.getName(), getTypeName(field.getType()), e); + } } private FieldUtils() { diff --git a/microsphere-java-core/src/main/java/io/microsphere/reflect/ReflectionUtils.java b/microsphere-java-core/src/main/java/io/microsphere/reflect/ReflectionUtils.java index f5bf4c3ca..2f5e5aaf9 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/reflect/ReflectionUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/reflect/ReflectionUtils.java @@ -7,6 +7,7 @@ import io.microsphere.logging.Logger; import io.microsphere.util.Utils; +import java.lang.invoke.MethodHandle; import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.Field; @@ -14,18 +15,24 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; import static io.microsphere.collection.MapUtils.newLinkedHashMap; +import static io.microsphere.invoke.MethodHandlesLookupUtils.findPublicStatic; import static io.microsphere.logging.LoggerFactory.getLogger; import static io.microsphere.reflect.FieldUtils.getFieldValue; import static io.microsphere.reflect.MemberUtils.isStatic; +import static io.microsphere.reflect.MethodUtils.findMethod; +import static io.microsphere.reflect.MethodUtils.invokeMethod; +import static io.microsphere.reflect.MethodUtils.invokeStaticMethod; import static io.microsphere.reflect.TypeUtils.getTypeName; import static io.microsphere.util.ClassLoaderUtils.resolveClass; import static io.microsphere.util.ClassUtils.getType; import static io.microsphere.util.ClassUtils.isPrimitive; import static io.microsphere.util.ClassUtils.isSimpleType; -import static java.lang.Class.forName; -import static java.lang.Thread.currentThread; +import static io.microsphere.util.StackTraceUtils.getCallerClassNameInStackTrace; import static java.lang.reflect.Array.get; import static java.lang.reflect.Array.getLength; import static java.util.Collections.emptyMap; @@ -59,30 +66,85 @@ public abstract class ReflectionUtils implements Utils { */ public static final String SUN_REFLECT_REFLECTION_CLASS_NAME = "sun.reflect.Reflection"; + /** + * The {@link Class} of sun.reflect.Reflection + */ + @Nullable + public static final Class SUN_REFLECT_REFLECTION_CLASS = resolveClass(SUN_REFLECT_REFLECTION_CLASS_NAME); + /** * sun.reflect.Reflection method name */ private static final String getCallerClassMethodName = "getCallerClass"; /** - * sun.reflect.Reflection invocation frame + * The {@link MethodHandle} of Reflection#getCallerClass(int) */ - private static final int sunReflectReflectionInvocationFrame; + @Nullable + private static final MethodHandle getCallerClassMethodHandle = findPublicStatic(SUN_REFLECT_REFLECTION_CLASS, getCallerClassMethodName, int.class); /** - * {@link StackTraceElement} invocation frame + * sun.reflect.Reflection invocation frame offset */ - private static final int stackTraceElementInvocationFrame; + private static final int sunReflectReflectionInvocationFrameOffset; /** * Is Supported sun.reflect.Reflection ? */ - private static final boolean supportedSunReflectReflection; + private static final boolean supportedSunReflectReflection = getCallerClassMethodHandle != null; + + /** + * The class name of {@linkplain java.lang.StackWalker} that was introduced in JDK 9. + */ + public static final String STACK_WALKER_CLASS_NAME = "java.lang.StackWalker"; + + /** + * The class name of {@linkplain java.lang.StackWalker.StackFrame} that was introduced in JDK 9. + */ + public static final String STACK_WALKER_STACK_FRAME_CLASS_NAME = "java.lang.StackWalker$StackFrame"; + + /** + * The {@link Class} of {@linkplain java.lang.StackWalker} that was introduced in JDK 9. + * (optional) + */ + @Nullable + public static final Class STACK_WALKER_CLASS = resolveClass(STACK_WALKER_CLASS_NAME); + + /** + * The {@link Class} of {@linkplain java.lang.StackWalker.StackFrame} that was introduced in JDK 9. + * (optional) + */ + @Nullable + public static final Class STACK_WALKER_STACK_FRAME_CLASS = resolveClass(STACK_WALKER_STACK_FRAME_CLASS_NAME); + + /** + * The {@link Method method} name of {@linkplain java.lang.StackWalker#getInstance()} + */ + static final String GET_INSTANCE_METHOD_NAME = "getInstance"; /** - * sun.reflect.Reflection#getCallerClass(int) method + * The {@link Method method} name of {{@linkplain java.lang.StackWalker#walk(java.util.function.Function)} */ - private static final Method getCallerClassMethod; + static final String WALK_METHOD_NAME = "walk"; + + /** + * The {@link Method method} name of {@linkplain java.lang.StackWalker.StackFrame#getClassName()} + */ + static final String GET_CLASS_NAME_METHOD_NAME = "getClassName"; + + static final Method WALK_METHOD = findMethod(STACK_WALKER_CLASS, WALK_METHOD_NAME, Function.class); + + static final Method GET_CLASS_NAME_METHOD = findMethod(STACK_WALKER_STACK_FRAME_CLASS, GET_CLASS_NAME_METHOD_NAME); + + @Nullable + private static Object stackWalkerInstance; + + /** + * {@linkplain java.lang.StackWalker} invocation frame offset. + */ + private static final int stackWalkerInvocationFrameOffset; + + private static final Function, Object> getClassNamesFunction = ReflectionUtils::getCallerClassNamesInStackWalker; /** * The class name of {@linkplain java.lang.reflect.InaccessibleObjectException} since JDK 9 @@ -96,55 +158,39 @@ public abstract class ReflectionUtils implements Utils { @Nullable public static final Class INACCESSIBLE_OBJECT_EXCEPTION_CLASS = (Class) resolveClass(INACCESSIBLE_OBJECT_EXCEPTION_CLASS_NAME); - // Initialize sun.reflect.Reflection + // Initialize java.lang.StackWalker static { - Method method = null; - boolean supported = false; int invocationFrame = 0; - try { - // Use sun.reflect.Reflection to calculate frame - Class type = forName(SUN_REFLECT_REFLECTION_CLASS_NAME); - method = type.getMethod(getCallerClassMethodName, int.class); - method.setAccessible(true); - // Adapt SUN JDK ,The value of invocation frame in JDK 6/7/8 may be different - for (int i = 0; i < 9; i++) { - Class callerClass = (Class) method.invoke(null, i); - if (TYPE.equals(callerClass)) { - invocationFrame = i; + if (STACK_WALKER_CLASS != null) { + stackWalkerInstance = invokeStaticMethod(STACK_WALKER_CLASS, GET_INSTANCE_METHOD_NAME); + List stackFrameClassNames = getCallerClassNamesInStackWalker(); + for (String stackFrameClassName : stackFrameClassNames) { + if (TYPE.getName().equals(stackFrameClassName)) { break; } - } - supported = true; - } catch (Throwable e) { - if (logger.isTraceEnabled()) { - logger.trace("The class '{}' or its' method '{}({})' can't be initialized.", SUN_REFLECT_REFLECTION_CLASS_NAME, getCallerClassMethodName, int.class, e); + invocationFrame++; } } - // set method info - getCallerClassMethod = method; - supportedSunReflectReflection = supported; - // getCallerClass() -> getCallerClass(int) - // Plugs 1 , because Invocation getCallerClass() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClass(int) method was considered as increment invocation frame - sunReflectReflectionInvocationFrame = invocationFrame + 2; + stackWalkerInvocationFrameOffset = invocationFrame; } - // Initialize StackTraceElement + // Initialize sun.reflect.Reflection static { int invocationFrame = 0; - // Use java.lang.StackTraceElement to calculate frame - StackTraceElement[] stackTraceElements = currentThread().getStackTrace(); - for (StackTraceElement stackTraceElement : stackTraceElements) { - String className = stackTraceElement.getClassName(); - if (TYPE.getName().equals(className)) { - break; + if (supportedSunReflectReflection) { + // Adapt SUN JDK ,The value of invocation frame in JDK 7/8 may be different + for (int i = 0; i < 9; i++) { + Class callerClass = getCallerClassInSunReflectReflection(i); + if (TYPE.equals(callerClass)) { + invocationFrame = i; + break; + } } - invocationFrame++; } - // getCallerClass() -> getCallerClass(int) - // Plugs 1 , because Invocation getCallerClass() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClass(int) method was considered as increment invocation frame - stackTraceElementInvocationFrame = invocationFrame + 2; + + // Plus 1 , because Invocation getCallerClass()/getCallerClassName() method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassInSunReflectReflection(int) method was considered as increment invocation frame + sunReflectReflectionInvocationFrameOffset = invocationFrame + 2; } /** @@ -199,66 +245,47 @@ public static boolean isSupportedSunReflectReflection() { @Nonnull public static String getCallerClassName() { if (supportedSunReflectReflection) { - Class callerClass = getCallerClassInSunJVM(sunReflectReflectionInvocationFrame); - if (callerClass != null) return callerClass.getName(); + return getCallerClassInSunReflectReflection(sunReflectReflectionInvocationFrameOffset).getName(); } - return getCallerClassNameInGeneralJVM(stackTraceElementInvocationFrame); + return getCallerClassName(stackWalkerInstance, 1); } - /** - * General implementation, get the calling class name - * - * @return call class name - * @see #getCallerClassNameInGeneralJVM(int) - */ - static String getCallerClassNameInGeneralJVM() { - return getCallerClassNameInGeneralJVM(stackTraceElementInvocationFrame); - } + @Nullable + static String getCallerClassName(Object stackWalkerInstance, int frameOffSet) { + if (stackWalkerInstance == null) { + // Plus 1 , because Invocation getCallerClassName() method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassName(Object stackWalkerInstance, int frameOffSet) method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassNameInStackTrace(int) method was considered as increment invocation frame + return getCallerClassNameInStackTrace(3 + frameOffSet); + } - /** - * General implementation, get the calling class name by specifying the calling level value - * - * @param invocationFrame invocation frame - * @return specified invocation frame class - */ - static String getCallerClassNameInGeneralJVM(int invocationFrame) throws IndexOutOfBoundsException { - StackTraceElement[] elements = currentThread().getStackTrace(); - if (invocationFrame < elements.length) { - StackTraceElement targetStackTraceElement = elements[invocationFrame]; - return targetStackTraceElement.getClassName(); + // Plus 1 , because Invocation getCallerClassName() method was considered as increment invocation frame + // Plus 1, because Invocation getCallerClassName(Object,int) method was considered as increment invocation frame + List callerClassNames = getCallerClassNamesInStackWalker(stackWalkerInstance); + int frame = stackWalkerInvocationFrameOffset + 2 + frameOffSet; + if (frame < callerClassNames.size()) { + return callerClassNames.get(frame); } return null; } - static Class getCallerClassInSunJVM(int realFramesToSkip) throws UnsupportedOperationException { - if (!supportedSunReflectReflection) { - throw new UnsupportedOperationException("Requires SUN's JVM!"); - } - Class callerClass = null; - if (getCallerClassMethod != null) { - try { - callerClass = (Class) getCallerClassMethod.invoke(null, realFramesToSkip); - } catch (Exception ignored) { - } - } - return callerClass; + @Nonnull + static List getCallerClassNamesInStackWalker(@Nonnull Object stackWalkerInstance) { + return invokeMethod(stackWalkerInstance, WALK_METHOD, getClassNamesFunction); } - /** - * Get caller class in General JVM - * - * @param invocationFrame invocation frame - * @return caller class - * @see #getCallerClassNameInGeneralJVM(int) - */ - static Class getCallerClassInGeneralJVM(int invocationFrame) { - String className = getCallerClassNameInGeneralJVM(invocationFrame + 1); - Class targetClass = null; - try { - targetClass = className == null ? null : forName(className); - } catch (Throwable ignored) { - } - return targetClass; + static List getCallerClassNamesInStackWalker() { + return invokeMethod(stackWalkerInstance, WALK_METHOD, getClassNamesFunction); + } + + private static List getCallerClassNamesInStackWalker(Stream stackFrames) { + return stackFrames.limit(9) + .map(ReflectionUtils::getClassName) + .collect(Collectors.toList()); + } + + private static String getClassName(Object stackFrame) { + return invokeMethod(stackFrame, GET_CLASS_NAME_METHOD); } /** @@ -284,80 +311,44 @@ static Class getCallerClassInGeneralJVM(int invocationFrame) { */ @Nonnull public static Class getCallerClass() throws IllegalStateException { - if (supportedSunReflectReflection) { - Class callerClass = getCallerClassInSunJVM(sunReflectReflectionInvocationFrame); - if (callerClass != null) { - return callerClass; - } + Class callerClass = getCallerClassInSunReflectReflection(sunReflectReflectionInvocationFrameOffset); + if (callerClass != null) { + return callerClass; } - return getCallerClassInGeneralJVM(stackTraceElementInvocationFrame); + String className = getCallerClassName(stackWalkerInstance, 1); + return resolveClass(className); } - /** - * Get caller class In SUN HotSpot JVM - * - * @return Caller Class - * @throws UnsupportedOperationException If JRE is not a SUN HotSpot JVM - * @see #getCallerClassInSunJVM(int) - */ - static Class getCallerClassInSunJVM() throws UnsupportedOperationException { - return getCallerClassInSunJVM(sunReflectReflectionInvocationFrame); + @Nullable + static Class getCallerClassInSunReflectReflection(int realFramesToSkip) { + try { + return (Class) getCallerClassMethodHandle.invokeExact(realFramesToSkip); + } catch (Throwable ignored) { + } + return null; } /** - * Get caller class name In SUN HotSpot JVM + * Get caller class In SUN HotSpot JVM * * @return Caller Class - * @throws UnsupportedOperationException If JRE is not a SUN HotSpot JVM - * @see #getCallerClassInSunJVM(int) + * @see #getCallerClassInSunReflectReflection(int) */ - static String getCallerClassNameInSunJVM() throws UnsupportedOperationException { - Class callerClass = getCallerClassInSunJVM(sunReflectReflectionInvocationFrame); - return callerClass.getName(); - } - - /** - * Retrieves the class of the caller at the specified invocation frame. - * - *

This method attempts to use the internal Sun JDK class - * {@code sun.reflect.Reflection} for high-performance caller class detection if - * available and supported. If not supported (e.g., non-Sun/HotSpot JVM), it falls back to using - * the {@link StackTraceElement} approach.

- * - *

Example Usage

- *
{@code
-     * public class Example {
-     *     public void exampleMethod() {
-     *         Class callerClass = ReflectionUtils.getCallerClass(2);
-     *         System.out.println("Caller class: " + callerClass.getName());
-     *     }
-     * }
-     * }
- * - * @param invocationFrame The depth in the call stack to retrieve the caller class from. - * A value of 0 typically represents the immediate caller, but this may vary - * depending on the JVM implementation and call context. - * @return The class of the caller at the specified invocation frame. - * @throws IllegalStateException if an error occurs while determining the caller class. - */ - public static Class getCallerClass(int invocationFrame) { - if (supportedSunReflectReflection) { - Class callerClass = getCallerClassInSunJVM(invocationFrame + 1); - if (callerClass != null) { - return callerClass; - } - } - return getCallerClassInGeneralJVM(invocationFrame + 1); + @Nullable + static Class getCallerClassInSunReflectReflection() { + return getCallerClassInSunReflectReflection(sunReflectReflectionInvocationFrameOffset); } /** - * Get caller class in General JVM + * Get caller class name In SUN HotSpot JVM * * @return Caller Class - * @see #getCallerClassInGeneralJVM(int) + * @see #getCallerClassInSunReflectReflection(int) */ - static Class getCallerClassInGeneralJVM() { - return getCallerClassInGeneralJVM(stackTraceElementInvocationFrame); + @Nullable + static String getCallerClassNameInSunReflectReflection() { + Class callerClass = getCallerClassInSunReflectReflection(sunReflectReflectionInvocationFrameOffset); + return callerClass == null ? null : callerClass.getName(); } /** diff --git a/microsphere-java-core/src/main/java/io/microsphere/security/SecurityUtils.java b/microsphere-java-core/src/main/java/io/microsphere/security/SecurityUtils.java new file mode 100644 index 000000000..ff80ca478 --- /dev/null +++ b/microsphere-java-core/src/main/java/io/microsphere/security/SecurityUtils.java @@ -0,0 +1,77 @@ +/* + * 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 io.microsphere.security; + +import io.microsphere.annotation.ConfigurationProperty; +import io.microsphere.annotation.Nonnull; +import io.microsphere.annotation.Nullable; +import io.microsphere.util.Utils; + +import java.io.File; + +import static io.microsphere.annotation.ConfigurationProperty.SYSTEM_PROPERTIES_SOURCE; +import static java.lang.System.getProperty; +import static java.lang.System.setProperty; + +/** + * The utilities class for Java Security + * + * @author Mercy + * @see SecurityManager + * @see SecurityException + * @since 1.0.0 + */ +public abstract class SecurityUtils implements Utils { + + /** + * The System Property name of Java Security Policy File. + */ + @ConfigurationProperty(source = SYSTEM_PROPERTIES_SOURCE) + public static final String JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME = "java.security.policy"; + + /** + * Set the Java Security Policy File + * + * @param javaSecurityPolicyFilePath the absolute path of Java Security Policy File + */ + public static void setJavaSecurityPolicyFile(@Nonnull String javaSecurityPolicyFilePath) { + setProperty(JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME, javaSecurityPolicyFilePath); + } + + /** + * Set the Java Security Policy File + * + * @param javaSecurityPolicyFile the Java Security Policy File + */ + public static void setJavaSecurityPolicyFile(@Nonnull File javaSecurityPolicyFile) { + setJavaSecurityPolicyFile(javaSecurityPolicyFile.getAbsolutePath()); + } + + /** + * Get the Java Security Policy File + * + * @return the Java Security Policy File + */ + @Nullable + public static String getJavaSecurityPolicyFile() { + return getProperty(JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME); + } + + private SecurityUtils() { + } +} \ No newline at end of file diff --git a/microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java b/microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java index 4bb15f331..a1293c6f4 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java @@ -47,12 +47,12 @@ import static io.microsphere.reflect.FieldUtils.getFieldValue; import static io.microsphere.reflect.MethodUtils.findMethod; import static io.microsphere.reflect.MethodUtils.invokeMethod; -import static io.microsphere.reflect.ReflectionUtils.getCallerClass; import static io.microsphere.util.ArrayUtils.asArray; import static io.microsphere.util.Assert.assertNoNullElements; import static io.microsphere.util.Assert.assertNotNull; import static io.microsphere.util.ClassLoaderUtils.ResourceType.values; import static io.microsphere.util.ClassUtils.resolvePrimitiveClassForName; +import static io.microsphere.util.StackTraceUtils.getCallerClassInStatckTrace; import static io.microsphere.util.StringUtils.contains; import static io.microsphere.util.StringUtils.endsWith; import static io.microsphere.util.StringUtils.isBlank; @@ -257,7 +257,7 @@ public static ClassLoader getClassLoader(@Nullable Class loadedClass) { ClassLoader classLoader = null; try { if (loadedClass == null) { - classLoader = getCallerClassLoader(4); + classLoader = getCallerClassLoader(5); } else { classLoader = loadedClass.getClassLoader(); } @@ -288,7 +288,7 @@ public static ClassLoader getClassLoader(@Nullable Class loadedClass) { */ @Nullable public static ClassLoader getCallerClassLoader() { - return getCallerClassLoader(4); + return getCallerClassLoader(5); } /** @@ -1757,7 +1757,7 @@ public static URLClassLoader resolveURLClassLoader(@Nullable ClassLoader classLo */ static ClassLoader getCallerClassLoader(int invocationFrame) { ClassLoader classLoader = null; - Class callerClass = getCallerClass(invocationFrame); + Class callerClass = getCallerClassInStatckTrace(invocationFrame); if (callerClass != null) { classLoader = callerClass.getClassLoader(); } diff --git a/microsphere-java-core/src/main/java/io/microsphere/util/ClassUtils.java b/microsphere-java-core/src/main/java/io/microsphere/util/ClassUtils.java index 53a1430bf..c9166b8fa 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/util/ClassUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/util/ClassUtils.java @@ -1119,7 +1119,9 @@ public static Set findClassNamesInClassPath(@Nullable File classPath, bo classNames = findClassNamesInJarFile(classPath, recursive); } - logger.trace("To find the class names in the class path['{}' , recursive : {}] : {}", classPath, recursive, classNames); + if (logger.isTraceEnabled()) { + logger.trace("To find the class names in the class path['{}' , recursive : {}] : {}", classPath, recursive, classNames); + } return classNames; } @@ -1218,8 +1220,10 @@ public static Set findClassNamesInJarFile(@Nullable File jarFile, boolea } } catch (Exception e) { classNames = emptySet(); - logger.trace("The class names can't be resolved by SimpleJarEntryScanner#scan(jarFile = {} ," + - " recursive = {} , jarEntryFilter = ClassFileJarEntryFilter)", jarFile, recursive, e); + if (logger.isTraceEnabled()) { + logger.trace("The class names can't be resolved by SimpleJarEntryScanner#scan(jarFile = {} ," + + " recursive = {} , jarEntryFilter = ClassFileJarEntryFilter)", jarFile, recursive, e); + } } return classNames; } diff --git a/microsphere-java-core/src/main/java/io/microsphere/util/StackTraceUtils.java b/microsphere-java-core/src/main/java/io/microsphere/util/StackTraceUtils.java index f120b9d96..4ad4b6f97 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/util/StackTraceUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/util/StackTraceUtils.java @@ -17,22 +17,8 @@ package io.microsphere.util; import io.microsphere.annotation.Nonnull; -import io.microsphere.annotation.Nullable; -import io.microsphere.logging.Logger; -import java.lang.reflect.Method; -import java.util.List; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import static io.microsphere.logging.LoggerFactory.getLogger; -import static io.microsphere.reflect.MethodUtils.findMethod; -import static io.microsphere.reflect.MethodUtils.invokeMethod; -import static io.microsphere.reflect.MethodUtils.invokeStaticMethod; import static io.microsphere.util.ClassLoaderUtils.resolveClass; -import static io.microsphere.util.VersionUtils.CURRENT_JAVA_VERSION; -import static io.microsphere.util.VersionUtils.JAVA_VERSION_9; import static java.lang.Thread.currentThread; /** @@ -46,120 +32,78 @@ public abstract class StackTraceUtils implements Utils { private static final Class TYPE = StackTraceUtils.class; - private static final Logger logger = getLogger(TYPE); - - private static final boolean IS_JDK_9_OR_LATER = CURRENT_JAVA_VERSION.ge(JAVA_VERSION_9); - - /** - * The class name of {@linkplain java.lang.StackWalker} that was introduced in JDK 9. - */ - public static final String STACK_WALKER_CLASS_NAME = "java.lang.StackWalker"; - - /** - * The class name of {@linkplain java.lang.StackWalker.Option} that was introduced in JDK 9. - */ - public static final String STACK_WALKER_OPTION_CLASS_NAME = "java.lang.StackWalker$Option"; - - /** - * The class name of {@linkplain java.lang.StackWalker.StackFrame} that was introduced in JDK 9. - */ - public static final String STACK_WALKER_STACK_FRAME_CLASS_NAME = "java.lang.StackWalker$StackFrame"; - - /** - * The {@link Class} of {@linkplain java.lang.StackWalker} that was introduced in JDK 9. - * (optional) - */ - public static final @Nullable Class STACK_WALKER_CLASS = resolveClass(STACK_WALKER_CLASS_NAME); - /** - * The {@link Class} of {@linkplain java.lang.StackWalker.Option} that was introduced in JDK 9. - * (optional) + * {@link StackTraceElement} invocation frame offset */ - public static final @Nullable Class STACK_WALKER_OPTION_CLASS = resolveClass(STACK_WALKER_OPTION_CLASS_NAME); + private static final int invocationFrameOffset; - /** - * The {@link Class} of {@linkplain java.lang.StackWalker.StackFrame} that was introduced in JDK 9. - * (optional) - */ - public static final @Nullable Class STACK_WALKER_STACK_FRAME_CLASS = resolveClass(STACK_WALKER_STACK_FRAME_CLASS_NAME); - - /** - * The name of {@linkplain java.lang.StackWalker.Option#RETAIN_CLASS_REFERENCE} - */ - static final String RETAIN_CLASS_REFERENCE_OPTION_NAME = "RETAIN_CLASS_REFERENCE"; - - /** - * The name of {@linkplain java.lang.StackWalker.Option#SHOW_REFLECT_FRAMES} - */ - static final String SHOW_REFLECT_FRAMES_OPTION_NAME = "SHOW_REFLECT_FRAMES"; - - /** - * The name of {@linkplain java.lang.StackWalker.Option#SHOW_HIDDEN_FRAMES} - */ - static final String SHOW_HIDDEN_FRAMES_OPTION_NAME = "SHOW_HIDDEN_FRAMES"; - - /** - * The {@link Method method} name of {@linkplain java.lang.StackWalker#getInstance()} - */ - static final String GET_INSTANCE_METHOD_NAME = "getInstance"; + // Initialize java.lang.StackTraceElement + static { + int offset = 0; + // Use java.lang.StackTraceElement to calculate frame + StackTraceElement[] stackTraceElements = getStackTrace(); + for (; ; offset++) { + StackTraceElement stackTraceElement = stackTraceElements[offset]; + String className = stackTraceElement.getClassName(); + if (TYPE.getName().equals(className)) { + break; + } + } + invocationFrameOffset = offset; + } /** - * The {@link Method method} name of {{@linkplain java.lang.StackWalker#walk(java.util.function.Function)} - */ - static final String WALK_METHOD_NAME = "walk"; + * Get caller class from {@link Thread#getStackTrace() stack traces} + * + * @return Caller Class + * @see #getCallerClassInStatckTrace(int) + */ + public static Class getCallerClassInStatckTrace() { + // Plus 1 , because Invocation getStackTrace() method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassNameInStackTrace(int) method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassInStatckTrace(int) method was considered as increment invocation frame + return getCallerClassInStatckTrace(invocationFrameOffset + 3); + } /** - * The {@link Method method} name of {@linkplain java.lang.StackWalker.StackFrame#getClassName()} + * General implementation, get the calling class name + * + * @return call class name + * @see #getCallerClassNameInStackTrace(int) */ - static final String GET_CLASS_NAME_METHOD_NAME = "getClassName"; - - static final Method WALK_METHOD = findMethod(STACK_WALKER_CLASS, WALK_METHOD_NAME, Function.class); - - static final Method GET_CLASS_NAME_METHOD = findMethod(STACK_WALKER_STACK_FRAME_CLASS, GET_CLASS_NAME_METHOD_NAME); - - private static @Nullable Object stackWalkerInstance; - - private static final Function, Object> getClassNamesFunction = StackTraceUtils::getCallerClassNames; + public static String getCallerClassNameInStackTrace() { + // Plus 1 , because Invocation getStackTrace() method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassNameInStackTrace() method was considered as increment invocation frame + // Plus 1 , because Invocation getCallerClassNameInStackTrace(int) method was considered as increment invocation frame + return getCallerClassNameInStackTrace(invocationFrameOffset + 3); + } /** - * {@link StackTraceElement} invocation frame. + * Get caller class in General JVM + * + * @param invocationFrame invocation frame + * @return caller class + * @see #getCallerClassNameInStackTrace(int) */ - private static final int stackTraceElementInvocationFrame; + public static Class getCallerClassInStatckTrace(int invocationFrame) { + // Plus 1 , because Invocation getCallerClassNameInStackTrace(int) method was considered as increment invocation frame + String className = getCallerClassNameInStackTrace(invocationFrame + 1); + return className == null ? null : resolveClass(className); + } /** - * {@linkplain java.lang.StackWalker} invocation frame. + * General implementation, get the calling class name by specifying the calling level value + * + * @param invocationFrame invocation frame + * @return specified invocation frame class */ - private static final int stackWalkerInvocationFrame; - - // Initialize java.lang.StackWalker - static { - int invocationFrame = 0; - if (IS_JDK_9_OR_LATER) { - stackWalkerInstance = invokeStaticMethod(STACK_WALKER_CLASS, GET_INSTANCE_METHOD_NAME); - List stackFrameClassNames = getCallerClassNames(); - for (String stackFrameClassName : stackFrameClassNames) { - if (TYPE.getName().equals(stackFrameClassName)) { - break; - } - invocationFrame++; - } - } - stackWalkerInvocationFrame = invocationFrame + 2; - } - - // Initialize java.lang.StackTraceElement - static { - int invocationFrame = 0; - // Use java.lang.StackTraceElement to calculate frame - StackTraceElement[] stackTraceElements = getStackTrace(); - for (StackTraceElement stackTraceElement : stackTraceElements) { - String className = stackTraceElement.getClassName(); - if (TYPE.getName().equals(className)) { - break; - } - invocationFrame++; + public static String getCallerClassNameInStackTrace(int invocationFrame) throws IndexOutOfBoundsException { + StackTraceElement[] elements = getStackTrace(); + if (invocationFrame < elements.length) { + StackTraceElement targetStackTraceElement = elements[invocationFrame]; + return targetStackTraceElement.getClassName(); } - stackTraceElementInvocationFrame = invocationFrame; + return null; } /** @@ -188,83 +132,6 @@ public static StackTraceElement[] getStackTrace() { return currentThread().getStackTrace(); } - /** - * Retrieves the fully qualified name of the class that called this method. - * - *

This method utilizes either {@link java.lang.StackWalker} (available in JDK 9+) or falls back to - * using {@link StackTraceElement} to determine the caller's class name. It ensures compatibility across different JVM versions.

- * - *

Example Usage

- *
{@code
-     * String callerClassName = StackTraceUtils.getCallerClassName();
-     * System.out.println("Caller class: " + callerClassName);
-     * }
- * - * @return the fully qualified name of the calling class - * @throws IndexOutOfBoundsException if the stack trace does not have enough frames to determine the caller - */ - public static String getCallerClassName() { - return getCallerClassName(stackWalkerInstance, 1); - } - - static String getCallerClassName(Object stackWalkerInstance, int frameOffSet) { - if (stackWalkerInstance == null) { - // Plugs 1 , because Invocation getStackTrace() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClassName() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClassNameInGeneralJVM(int) method was considered as increment invocation frame - return getCallerClassNameInGeneralJVM(stackTraceElementInvocationFrame + 3 + frameOffSet); - } - List callerClassNames = getCallerClassNames(stackWalkerInstance); - String className = callerClassNames.get(stackWalkerInvocationFrame + frameOffSet); - return className; - } - - static List getCallerClassNames(Object stackWalkerInstance) { - return invokeMethod(stackWalkerInstance, WALK_METHOD, getClassNamesFunction); - } - - static List getCallerClassNames() { - return invokeMethod(stackWalkerInstance, WALK_METHOD, getClassNamesFunction); - } - - private static List getCallerClassNames(Stream stackFrames) { - return stackFrames.limit(5) - .map(StackTraceUtils::getClassName) - .collect(Collectors.toList()); - } - - private static String getClassName(Object stackFrame) { - return invokeMethod(stackFrame, GET_CLASS_NAME_METHOD); - } - - /** - * General implementation, get the calling class name - * - * @return call class name - * @see #getCallerClassNameInGeneralJVM(int) - */ - static String getCallerClassNameInGeneralJVM() { - // Plugs 1 , because Invocation getStackTrace() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClassNameInGeneralJVM() method was considered as increment invocation frame - // Plugs 1 , because Invocation getCallerClassNameInGeneralJVM(int) method was considered as increment invocation frame - return getCallerClassNameInGeneralJVM(stackTraceElementInvocationFrame + 3); - } - - /** - * General implementation, get the calling class name by specifying the calling level value - * - * @param invocationFrame invocation frame - * @return specified invocation frame class - */ - static String getCallerClassNameInGeneralJVM(int invocationFrame) throws IndexOutOfBoundsException { - StackTraceElement[] elements = getStackTrace(); - if (invocationFrame < elements.length) { - StackTraceElement targetStackTraceElement = elements[invocationFrame]; - return targetStackTraceElement.getClassName(); - } - return null; - } - private StackTraceUtils() { } -} +} \ No newline at end of file diff --git a/microsphere-java-core/src/main/java/io/microsphere/util/TypeFinder.java b/microsphere-java-core/src/main/java/io/microsphere/util/TypeFinder.java index 66c21dcf2..438f8ae20 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/util/TypeFinder.java +++ b/microsphere-java-core/src/main/java/io/microsphere/util/TypeFinder.java @@ -24,6 +24,7 @@ import java.util.function.Function; import java.util.function.Predicate; +import static io.microsphere.collection.ListUtils.addIfAbsent; import static io.microsphere.collection.ListUtils.newArrayList; import static io.microsphere.collection.ListUtils.newLinkedList; import static io.microsphere.lang.function.Predicates.EMPTY_PREDICATE_ARRAY; @@ -34,6 +35,7 @@ import static io.microsphere.util.ArrayUtils.EMPTY_TYPE_ARRAY; import static io.microsphere.util.ArrayUtils.contains; import static io.microsphere.util.ArrayUtils.isNotEmpty; +import static io.microsphere.util.ArrayUtils.length; import static io.microsphere.util.Assert.assertNoNullElements; import static io.microsphere.util.Assert.assertNotEmpty; import static io.microsphere.util.Assert.assertNotNull; @@ -169,7 +171,7 @@ protected List getSuperTypes(T type, boolean includeSuperclass, boolean inclu } T[] interfaceTypes = includedGenericInterfaces ? getInterfaces(type) : (T[]) EMPTY_TYPE_ARRAY; - int interfaceTypesLength = interfaceTypes.length; + int interfaceTypesLength = length(interfaceTypes); int size = interfaceTypesLength + (hasSuperclass ? 1 : 0); @@ -180,16 +182,12 @@ protected List getSuperTypes(T type, boolean includeSuperclass, boolean inclu List types = newArrayList(size); if (hasSuperclass) { - if (!types.contains(superclass)) { - types.add(superclass); - } + types.add(superclass); } for (int i = 0; i < interfaceTypesLength; i++) { T interfaceType = interfaceTypes[i]; - if (!types.contains(interfaceType)) { - types.add(interfaceType); - } + addIfAbsent(types, interfaceType); } return types; } @@ -225,9 +223,8 @@ protected void addSuperTypes(List allTypes, T type, boolean includeHierarchic for (int i = 0; i < superTypesSize; i++) { T superType = superTypes.get(i); - if (!allTypes.contains(superType)) { - allTypes.add(superType); - } + addIfAbsent(allTypes, superType); + if (includeHierarchicalTypes) { addSuperTypes(allTypes, superType, true, includeSuperclass, includeInterfaces); } @@ -273,5 +270,4 @@ public static TypeFinder genericTypeFinder(Type type, boolean includeSelf, return new TypeFinder(type, genericTypeGetSuperClassFunction, genericTypeGetInterfacesFunction, includeSelf, includeHierarchicalTypes, includeSuperclass, includeInterfaces); } - -} +} \ No newline at end of file diff --git a/microsphere-java-core/src/main/java/io/microsphere/util/jar/JarUtils.java b/microsphere-java-core/src/main/java/io/microsphere/util/jar/JarUtils.java index 0fd1a9d73..de940e334 100644 --- a/microsphere-java-core/src/main/java/io/microsphere/util/jar/JarUtils.java +++ b/microsphere-java-core/src/main/java/io/microsphere/util/jar/JarUtils.java @@ -89,7 +89,9 @@ public static JarFile toJarFile(URL jarURL) throws IllegalArgumentException { try { jarFile = new JarFile(jarAbsolutePath); } catch (IOException e) { - logger.trace("The JarFile can't be open from the url : {}", jarURL, e); + if (logger.isTraceEnabled()) { + logger.trace("The JarFile can't be open from the url : {}", jarURL, e); + } } return jarFile; } diff --git a/microsphere-java-core/src/test/java/io/microsphere/AbstractTestCase.java b/microsphere-java-core/src/test/java/io/microsphere/AbstractTestCase.java index a4ab1c011..f8ea785fa 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/AbstractTestCase.java +++ b/microsphere-java-core/src/test/java/io/microsphere/AbstractTestCase.java @@ -50,7 +50,7 @@ * @since 1.0.0 */ @Disabled -public abstract class AbstractTestCase extends Loggable { +public abstract class AbstractTestCase implements Loggable { public static final String TEST_ELEMENT = "test"; diff --git a/microsphere-java-core/src/test/java/io/microsphere/Loggable.java b/microsphere-java-core/src/test/java/io/microsphere/Loggable.java index 13aa8c44b..03d5641ac 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/Loggable.java +++ b/microsphere-java-core/src/test/java/io/microsphere/Loggable.java @@ -29,23 +29,24 @@ * @see Logger * @since 1.0.0 */ -public abstract class Loggable { +public interface Loggable { - protected final Logger logger = getLogger(getClass()); - - protected void log(Object object) { + default void log(Object object) { + Logger logger = getLogger(getClass()); if (logger.isTraceEnabled()) { logger.trace(valueOf(object)); } } - protected void log(String object, Object... args) { + default void log(String object, Object... args) { + Logger logger = getLogger(getClass()); if (logger.isTraceEnabled()) { logger.trace(object, args); } } - protected void log(String message, Throwable t) { + default void log(String message, Throwable t) { + Logger logger = getLogger(getClass()); if (logger.isTraceEnabled()) { logger.trace(message, t); } diff --git a/microsphere-java-core/src/test/java/io/microsphere/LoggingTest.java b/microsphere-java-core/src/test/java/io/microsphere/LoggingTest.java new file mode 100644 index 000000000..578b52537 --- /dev/null +++ b/microsphere-java-core/src/test/java/io/microsphere/LoggingTest.java @@ -0,0 +1,69 @@ +/* + * 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 io.microsphere; + +import ch.qos.logback.classic.Level; +import ch.qos.logback.classic.Logger; +import ch.qos.logback.classic.LoggerContext; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; + +import static ch.qos.logback.classic.Level.valueOf; +import static org.slf4j.LoggerFactory.getILoggerFactory; + +/** + * The abstract class for loggging with repeated levels + * + * @author Mercy + * @see LoggerContext + * @since 1.0.0 + */ +@ParameterizedClass +@ValueSource(strings = {"INFO", "TRACE"}) +@Disabled +public abstract class LoggingTest { + + private static final LoggerContext loggerContext = (LoggerContext) getILoggerFactory(); + + @Parameter + private String logLevel; + + private Level orginalLevel; + + @BeforeEach + final void setLoggingLevel() { + Logger logger = getTargetLogger(); + this.orginalLevel = logger.getLevel(); + Level level = valueOf(logLevel); + logger.setLevel(level); + } + + @AfterEach + final void resetLoggingLevel() { + Logger logger = getTargetLogger(); + logger.setLevel(this.orginalLevel); + } + + protected Logger getTargetLogger() { + return loggerContext.getLogger(getClass().getPackage().getName()); + } +} diff --git a/microsphere-java-core/src/test/java/io/microsphere/classloading/AbstractArtifactResourceResolverTest.java b/microsphere-java-core/src/test/java/io/microsphere/classloading/AbstractArtifactResourceResolverTest.java index 581f5b1ec..319600b0b 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/classloading/AbstractArtifactResourceResolverTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/classloading/AbstractArtifactResourceResolverTest.java @@ -16,6 +16,7 @@ */ package io.microsphere.classloading; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,7 +36,7 @@ * @see AbstractArtifactResourceResolver * @since 1.0.0 */ -abstract class AbstractArtifactResourceResolverTest { +abstract class AbstractArtifactResourceResolverTest extends LoggingTest { static final Class TEST_ANNOTATION_CLASS = Nonnull.class; diff --git a/microsphere-java-core/src/test/java/io/microsphere/classloading/ArtifactDetectorTest.java b/microsphere-java-core/src/test/java/io/microsphere/classloading/ArtifactDetectorTest.java index 47161aa8c..efb90f837 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/classloading/ArtifactDetectorTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/classloading/ArtifactDetectorTest.java @@ -17,6 +17,7 @@ package io.microsphere.classloading; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.Test; import java.util.List; @@ -33,7 +34,7 @@ * @see ArtifactDetector * @since 1.0.0 */ -class ArtifactDetectorTest { +class ArtifactDetectorTest extends LoggingTest { @Test void testDetect() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/collection/CollectionUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/collection/CollectionUtilsTest.java index 7a2aef4f5..cfe3a7a38 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/collection/CollectionUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/collection/CollectionUtilsTest.java @@ -74,7 +74,7 @@ * @author Mercy * @since 1.0.0 */ -class CollectionUtilsTest extends Loggable { +class CollectionUtilsTest implements Loggable { @Test void testIsEmpty() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/collection/ListUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/collection/ListUtilsTest.java index 2efe188d9..a51411614 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/collection/ListUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/collection/ListUtilsTest.java @@ -30,6 +30,7 @@ import static io.microsphere.AbstractTestCase.TEST_NULL_ITERABLE; import static io.microsphere.AbstractTestCase.TEST_NULL_ITERATOR; import static io.microsphere.AbstractTestCase.TEST_NULL_LIST; +import static io.microsphere.collection.ListUtils.addIfAbsent; import static io.microsphere.collection.ListUtils.first; import static io.microsphere.collection.ListUtils.forEach; import static io.microsphere.collection.ListUtils.isList; @@ -61,7 +62,7 @@ * @see ListUtils * @since 1.0.0 */ -class ListUtilsTest extends Loggable { +class ListUtilsTest implements Loggable { private static final List TEST_LIST = asList("A", "B", "C"); @@ -204,4 +205,12 @@ void testForEach() { assertEquals(iterator2.next(), value); }); } + + @Test + void testAddIfAbsent() { + List values = newArrayList(); + assertTrue(addIfAbsent(values, "A")); + assertFalse(addIfAbsent(values, "A")); + assertTrue(addIfAbsent(values, "B")); + } } \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/collection/ReadOnlyIteratorTest.java b/microsphere-java-core/src/test/java/io/microsphere/collection/ReadOnlyIteratorTest.java index 260a1c33a..0867b97a8 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/collection/ReadOnlyIteratorTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/collection/ReadOnlyIteratorTest.java @@ -34,7 +34,7 @@ * @see ReadOnlyIterator * @since 1.0.0 */ -public abstract class ReadOnlyIteratorTest extends Loggable { +public abstract class ReadOnlyIteratorTest implements Loggable { Iterator instance = createIterator(); diff --git a/microsphere-java-core/src/test/java/io/microsphere/concurrent/DelegatingScheduledExecutorServiceTest.java b/microsphere-java-core/src/test/java/io/microsphere/concurrent/DelegatingScheduledExecutorServiceTest.java index 87d369b78..212252e6b 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/concurrent/DelegatingScheduledExecutorServiceTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/concurrent/DelegatingScheduledExecutorServiceTest.java @@ -23,7 +23,7 @@ * @see DelegatingScheduledExecutorService * @since 1.0.0 */ -class DelegatingScheduledExecutorServiceTest extends Loggable { +class DelegatingScheduledExecutorServiceTest implements Loggable { private ScheduledExecutorService delegate = newSingleThreadScheduledExecutor(); diff --git a/microsphere-java-core/src/test/java/io/microsphere/concurrent/ExecutorUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/concurrent/ExecutorUtilsTest.java index 4babd9e25..106cbeee7 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/concurrent/ExecutorUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/concurrent/ExecutorUtilsTest.java @@ -1,6 +1,7 @@ package io.microsphere.concurrent; import io.microsphere.Loggable; +import io.microsphere.LoggingTest; import io.microsphere.util.ShutdownHookUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -28,7 +29,7 @@ * @see ExecutorUtils * @since 1.0.0 */ -class ExecutorUtilsTest extends Loggable { +class ExecutorUtilsTest extends LoggingTest implements Loggable { private ExecutorService executorService; diff --git a/microsphere-java-core/src/test/java/io/microsphere/convert/BaseConverterTest.java b/microsphere-java-core/src/test/java/io/microsphere/convert/BaseConverterTest.java index 08b5e08d9..481858868 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/convert/BaseConverterTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/convert/BaseConverterTest.java @@ -36,7 +36,7 @@ * @see AbstractConverter * @since 1.0.0 */ -abstract class BaseConverterTest extends Loggable { +abstract class BaseConverterTest implements Loggable { protected AbstractConverter converter; diff --git a/microsphere-java-core/src/test/java/io/microsphere/event/AbstractEventListener.java b/microsphere-java-core/src/test/java/io/microsphere/event/AbstractEventListener.java index 68de276a3..36e9c4074 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/event/AbstractEventListener.java +++ b/microsphere-java-core/src/test/java/io/microsphere/event/AbstractEventListener.java @@ -20,7 +20,7 @@ import java.util.concurrent.atomic.AtomicInteger; -public abstract class AbstractEventListener extends Loggable implements EventListener { +public abstract class AbstractEventListener implements Loggable, EventListener { private final AtomicInteger eventOccurs = new AtomicInteger(0); diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/FileUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/FileUtilsTest.java index 0649d43bb..39c774ee4 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/FileUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/FileUtilsTest.java @@ -60,7 +60,7 @@ * @see FileUtils * @since 1.0.0 */ -class FileUtilsTest extends Loggable { +class FileUtilsTest implements Loggable { private final URL classFileResource = getClassResource(TEST_CLASS_LOADER, FileUtilsTest.class); diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/FileWatchServiceTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/FileWatchServiceTest.java index ca8ece861..6d392e557 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/FileWatchServiceTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/FileWatchServiceTest.java @@ -17,7 +17,7 @@ * @see FileWatchService * @since 1.0.0 */ -class FileWatchServiceTest extends Loggable { +class FileWatchServiceTest implements Loggable { private FileWatchService service = (file, listener, kinds) -> { log("Watching : {} , listener : {} , kinds : {}", file, listener, kinds); diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/IOUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/IOUtilsTest.java index 0f5994c10..63ade98f1 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/IOUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/IOUtilsTest.java @@ -1,5 +1,6 @@ package io.microsphere.io; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -31,7 +32,7 @@ * @see IOUtils * @since 1.0.0 */ -class IOUtilsTest { +class IOUtilsTest extends LoggingTest { private static final String TEST_VALUE = "Hello"; diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/StandardFileWatchServiceTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/StandardFileWatchServiceTest.java index 020c92afa..721d0c541 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/StandardFileWatchServiceTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/StandardFileWatchServiceTest.java @@ -17,6 +17,7 @@ package io.microsphere.io; import io.microsphere.Loggable; +import io.microsphere.LoggingTest; import io.microsphere.io.event.DefaultFileChangedListener; import io.microsphere.io.event.FileChangedEvent; import io.microsphere.io.event.FileChangedEvent.Kind; @@ -74,7 +75,7 @@ * @author Mercy * @since 1.0.0 */ -class StandardFileWatchServiceTest extends Loggable { +class StandardFileWatchServiceTest extends LoggingTest implements Loggable { private File testDir; diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/event/FileChangedListenerTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/event/FileChangedListenerTest.java index 7bfbfd32a..c65fa3add 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/event/FileChangedListenerTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/event/FileChangedListenerTest.java @@ -28,7 +28,7 @@ * @see FileChangedListener * @since */ -class FileChangedListenerTest extends Loggable { +class FileChangedListenerTest implements Loggable { private FileChangedListener listener; diff --git a/microsphere-java-core/src/test/java/io/microsphere/io/scanner/SimpleFileScannerTest.java b/microsphere-java-core/src/test/java/io/microsphere/io/scanner/SimpleFileScannerTest.java index e8209df7e..9c84641a2 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/io/scanner/SimpleFileScannerTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/io/scanner/SimpleFileScannerTest.java @@ -8,12 +8,16 @@ import org.junit.jupiter.api.Test; import java.io.File; +import java.io.IOException; import java.util.Set; +import static io.microsphere.AbstractTestCase.createRandomTempDirectory; +import static io.microsphere.AbstractTestCase.createRandomTempFile; import static io.microsphere.io.scanner.SimpleFileScanner.INSTANCE; import static io.microsphere.util.SystemUtils.JAVA_HOME; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * {@link SimpleFileScanner} {@link Test} @@ -48,4 +52,20 @@ void testScanOnBinDirectory() { Set directories = simpleFileScanner.scan(JAVA_HOME_DIR, true, new NameFileFilter("bin")); assertEquals(1, directories.size()); } + + @Test + void testScanOnEmptyDirectory() { + File tempDir = createRandomTempDirectory(); + Set directories = simpleFileScanner.scan(tempDir, true); + assertEquals(1, directories.size()); + assertTrue(directories.contains(tempDir)); + } + + @Test + void testScanOnFile() throws IOException { + File file = createRandomTempFile(); + Set files = simpleFileScanner.scan(file, true); + assertEquals(1, files.size()); + assertTrue(files.contains(file)); + } } \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/json/JSONArrayTest.java b/microsphere-java-core/src/test/java/io/microsphere/json/JSONArrayTest.java index 8b5a6ab8f..4947aa4b4 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/json/JSONArrayTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/json/JSONArrayTest.java @@ -30,6 +30,7 @@ import static io.microsphere.util.ArrayUtils.ofArray; import static java.lang.Boolean.TRUE; import static java.lang.Double.NaN; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -117,6 +118,12 @@ void testConstructorWithArrayOnNotArray() { assertThrows(JSONException.class, () -> new JSONArray(new Object())); } + @Test + void testConstructorWithJSONTokener() { + assertDoesNotThrow(() -> new JSONArray(new JSONTokener("[1,2,3]"))); + assertThrows(JSONException.class, () -> new JSONArray(new JSONTokener("{}"))); + } + @Test void testLength() { assertEquals(0, jsonArray.length()); diff --git a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableActionTest.java b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableActionTest.java index 297b6ee34..5dbe3452f 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableActionTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableActionTest.java @@ -27,7 +27,7 @@ * * @since 1.0.0 */ -class ThrowableActionTest extends Loggable { +class ThrowableActionTest implements Loggable { private final ThrowableAction action = () -> { log("ThrowableAction#execute()"); diff --git a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableBiConsumerTest.java b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableBiConsumerTest.java index 58ab7a4cf..13463dca8 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableBiConsumerTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableBiConsumerTest.java @@ -27,7 +27,7 @@ * @see ThrowableBiConsumer * @since 1.0.0 */ -class ThrowableBiConsumerTest extends Loggable { +class ThrowableBiConsumerTest implements Loggable { @Test void testAccept() throws Throwable { diff --git a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableConsumerTest.java b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableConsumerTest.java index ed91c7f90..dcae2fee8 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableConsumerTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/lang/function/ThrowableConsumerTest.java @@ -61,6 +61,12 @@ void testExecute3() { }); } + @Test + void testExecute3OnHandleException() { + execute("For testing", throwableConsumer, (t, e) -> { + }); + } + @Test void testExecute3OnException() { assertThrows(RuntimeException.class, () -> execute("For testing", m -> { @@ -69,4 +75,4 @@ void testExecute3OnException() { throw new RuntimeException(t, e); })); } -} +} \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/metadata/ClassPathResourceConfigurationPropertyLoaderTest.java b/microsphere-java-core/src/test/java/io/microsphere/metadata/ClassPathResourceConfigurationPropertyLoaderTest.java index 2850b6724..a1e54172a 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/metadata/ClassPathResourceConfigurationPropertyLoaderTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/metadata/ClassPathResourceConfigurationPropertyLoaderTest.java @@ -18,6 +18,7 @@ package io.microsphere.metadata; +import io.microsphere.LoggingTest; import io.microsphere.beans.ConfigurationProperty; import org.junit.jupiter.api.Test; @@ -35,7 +36,7 @@ * @see ClassPathResourceConfigurationPropertyLoader * @since 1.0.0 */ -class ClassPathResourceConfigurationPropertyLoaderTest { +class ClassPathResourceConfigurationPropertyLoaderTest extends LoggingTest { @Test void testLoadWithSingleResource() throws Throwable { diff --git a/microsphere-java-core/src/test/java/io/microsphere/net/StandardURLStreamHandlerFactoryTest.java b/microsphere-java-core/src/test/java/io/microsphere/net/StandardURLStreamHandlerFactoryTest.java index 527850016..a75c25ff3 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/net/StandardURLStreamHandlerFactoryTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/net/StandardURLStreamHandlerFactoryTest.java @@ -18,6 +18,7 @@ package io.microsphere.net; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -30,7 +31,7 @@ * @see StandardURLStreamHandlerFactory * @since 1.0.0 */ -class StandardURLStreamHandlerFactoryTest { +class StandardURLStreamHandlerFactoryTest extends LoggingTest { private StandardURLStreamHandlerFactory factory; diff --git a/microsphere-java-core/src/test/java/io/microsphere/net/URLUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/net/URLUtilsTest.java index 923ddd112..7b5738ac4 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/net/URLUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/net/URLUtilsTest.java @@ -3,6 +3,7 @@ */ package io.microsphere.net; +import io.microsphere.LoggingTest; import io.microsphere.net.console.Handler; import io.microsphere.util.StringUtils; import org.junit.jupiter.api.AfterEach; @@ -101,7 +102,7 @@ * @see URLUtilsTest * @since 1.0.0 */ -class URLUtilsTest { +class URLUtilsTest extends LoggingTest { private static final String TEST_PATH = "/abc/def"; diff --git a/microsphere-java-core/src/test/java/io/microsphere/performance/AbstractPerformanceTest.java b/microsphere-java-core/src/test/java/io/microsphere/performance/AbstractPerformanceTest.java index 8a6dfdb49..0ff95947b 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/performance/AbstractPerformanceTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/performance/AbstractPerformanceTest.java @@ -11,7 +11,7 @@ * @since 1.0.0 */ @Disabled -public abstract class AbstractPerformanceTest extends Loggable { +public abstract class AbstractPerformanceTest implements Loggable { protected void execute(PerformanceAction action) { long startTime = System.nanoTime(); diff --git a/microsphere-java-core/src/test/java/io/microsphere/process/ClassicProcessIdResolverTest.java b/microsphere-java-core/src/test/java/io/microsphere/process/ClassicProcessIdResolverTest.java index 30cb457e4..4d4acb7a2 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/process/ClassicProcessIdResolverTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/process/ClassicProcessIdResolverTest.java @@ -1,5 +1,6 @@ package io.microsphere.process; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -14,7 +15,7 @@ * @see ClassicProcessIdResolver * @since 1.0.0 */ -class ClassicProcessIdResolverTest { +class ClassicProcessIdResolverTest extends LoggingTest { private ClassicProcessIdResolver resolver; diff --git a/microsphere-java-core/src/test/java/io/microsphere/process/ModernProcessIdResolverTest.java b/microsphere-java-core/src/test/java/io/microsphere/process/ModernProcessIdResolverTest.java index f98cb7a7b..8a82333e0 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/process/ModernProcessIdResolverTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/process/ModernProcessIdResolverTest.java @@ -1,5 +1,6 @@ package io.microsphere.process; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -17,7 +18,7 @@ * @see ModernProcessIdResolver * @since 1.0.0 */ -class ModernProcessIdResolverTest { +class ModernProcessIdResolverTest extends LoggingTest { private ModernProcessIdResolver resolver; diff --git a/microsphere-java-core/src/test/java/io/microsphere/process/ProcessExecutorTest.java b/microsphere-java-core/src/test/java/io/microsphere/process/ProcessExecutorTest.java index e296b1025..1c9f0ecbb 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/process/ProcessExecutorTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/process/ProcessExecutorTest.java @@ -1,6 +1,7 @@ package io.microsphere.process; import io.microsphere.Loggable; +import io.microsphere.LoggingTest; import io.microsphere.io.FastByteArrayOutputStream; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; @@ -20,7 +21,7 @@ * @see ProcessExecutorTest * @since 1.0.0 */ -class ProcessExecutorTest extends Loggable { +class ProcessExecutorTest extends LoggingTest implements Loggable { private FastByteArrayOutputStream outputStream; diff --git a/microsphere-java-core/src/test/java/io/microsphere/process/ProcessManagerTest.java b/microsphere-java-core/src/test/java/io/microsphere/process/ProcessManagerTest.java index 47e666867..7ad4cfbb1 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/process/ProcessManagerTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/process/ProcessManagerTest.java @@ -23,7 +23,7 @@ * @see ProcessManager * @since 1.0.0 */ -class ProcessManagerTest extends Loggable { +class ProcessManagerTest implements Loggable { @BeforeEach void setUp() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/process/VirtualMachineProcessIdResolverTest.java b/microsphere-java-core/src/test/java/io/microsphere/process/VirtualMachineProcessIdResolverTest.java index f727f8a1c..c80f8828e 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/process/VirtualMachineProcessIdResolverTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/process/VirtualMachineProcessIdResolverTest.java @@ -1,5 +1,6 @@ package io.microsphere.process; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -14,7 +15,7 @@ * @see VirtualMachineProcessIdResolver * @since 1.0.0 */ -class VirtualMachineProcessIdResolverTest { +class VirtualMachineProcessIdResolverTest extends LoggingTest { private VirtualMachineProcessIdResolver resolver; diff --git a/microsphere-java-core/src/test/java/io/microsphere/reflect/AbstractReflectiveDefinitionTest.java b/microsphere-java-core/src/test/java/io/microsphere/reflect/AbstractReflectiveDefinitionTest.java index 56c1d0f64..f1c3724fc 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/reflect/AbstractReflectiveDefinitionTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/reflect/AbstractReflectiveDefinitionTest.java @@ -30,7 +30,7 @@ * @see ReflectiveDefinition * @since 1.0.0 */ -public abstract class AbstractReflectiveDefinitionTest extends Loggable { +public abstract class AbstractReflectiveDefinitionTest implements Loggable { private final List[] headConstructorArgumentsArray = ofArray( ofList(SINCE, getClassName()), diff --git a/microsphere-java-core/src/test/java/io/microsphere/reflect/FieldUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/reflect/FieldUtilsTest.java index 27be787b9..4dbc8c77a 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/reflect/FieldUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/reflect/FieldUtilsTest.java @@ -16,6 +16,7 @@ */ package io.microsphere.reflect; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -29,12 +30,13 @@ import static io.microsphere.reflect.FieldUtils.getDeclaredField; import static io.microsphere.reflect.FieldUtils.getFieldValue; import static io.microsphere.reflect.FieldUtils.getStaticFieldValue; -import static io.microsphere.reflect.FieldUtils.handleIllegalAccessException; +import static io.microsphere.reflect.FieldUtils.handleFieldException; import static io.microsphere.reflect.FieldUtils.setFieldValue; import static io.microsphere.reflect.FieldUtils.setStaticFieldValue; import static io.microsphere.util.VersionUtils.CURRENT_JAVA_VERSION; import static io.microsphere.util.VersionUtils.JAVA_VERSION_8; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; @@ -48,7 +50,7 @@ * @author Mercy * @since 1.0.0 */ -class FieldUtilsTest { +class FieldUtilsTest extends LoggingTest { private static String value = "1"; @@ -262,9 +264,9 @@ void testAssertFieldMatchTypeOnIllegalArgumentException() { } @Test - void testHandleIllegalAccessException() { + void testHandleFieldException() { Field field = findField(ReflectionTest.class, "staticField"); - assertThrows(IllegalStateException.class, () -> handleIllegalAccessException(new IllegalAccessException(), test, field, field.isAccessible())); + assertDoesNotThrow(() -> handleFieldException(new IllegalAccessException(), test, field)); } private void assertFindField(Object object, String fieldName) { diff --git a/microsphere-java-core/src/test/java/io/microsphere/reflect/ModifierTest.java b/microsphere-java-core/src/test/java/io/microsphere/reflect/ModifierTest.java index ecaa38576..c7bee110d 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/reflect/ModifierTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/reflect/ModifierTest.java @@ -16,9 +16,9 @@ */ package io.microsphere.reflect; -import io.microsphere.Loggable; import org.junit.jupiter.api.Test; +import java.lang.reflect.Proxy; import java.util.AbstractList; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedSynchronizer; @@ -99,7 +99,7 @@ void testIsPrivate() throws NoSuchFieldException { @Test void testIsProtected() throws NoSuchFieldException { - assertTrue(isProtected(Loggable.class.getDeclaredField("logger").getModifiers())); + assertTrue(isProtected(Proxy.class.getDeclaredField("h").getModifiers())); assertFalse(isProtected(String.class.getModifiers())); } diff --git a/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsBenchmark.java b/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsBenchmark.java index fc2ec7771..bc861f313 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsBenchmark.java +++ b/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsBenchmark.java @@ -25,6 +25,9 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import static io.microsphere.reflect.ReflectionUtils.getCallerClassInSunReflectReflection; +import static io.microsphere.reflect.ReflectionUtils.getCallerClassNamesInStackWalker; +import static io.microsphere.util.StackTraceUtils.getCallerClassNameInStackTrace; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.openjdk.jmh.annotations.Mode.AverageTime; @@ -44,13 +47,23 @@ @State(Scope.Thread) public class ReflectionUtilsBenchmark { +// @Benchmark +// public void getCallerClassDirectly() { +// sun.reflect.Reflection.getCallerClass(1); +// } + + @Benchmark + public void getCallerClassOnMethodHanle() { + getCallerClassInSunReflectReflection(); + } + @Benchmark - public void getCallerClassNameInSunJVM() { - ReflectionUtils.getCallerClassNameInSunJVM(); + public void getCallerClassNameInStackWalker() { + getCallerClassNamesInStackWalker(); } @Benchmark - public void getCallerClassNameInGeneralJVM() { - ReflectionUtils.getCallerClassNameInGeneralJVM(); + public void getCallerClassNameOnStackTrace() { + getCallerClassNameInStackTrace(); } } diff --git a/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsTest.java index 3b3d1f8dd..8060c6a43 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/reflect/ReflectionUtilsTest.java @@ -11,21 +11,25 @@ import static io.microsphere.reflect.ReflectionUtils.INACCESSIBLE_OBJECT_EXCEPTION_CLASS; import static io.microsphere.reflect.ReflectionUtils.INACCESSIBLE_OBJECT_EXCEPTION_CLASS_NAME; import static io.microsphere.reflect.ReflectionUtils.getCallerClass; -import static io.microsphere.reflect.ReflectionUtils.getCallerClassInGeneralJVM; -import static io.microsphere.reflect.ReflectionUtils.getCallerClassInSunJVM; +import static io.microsphere.reflect.ReflectionUtils.getCallerClassInSunReflectReflection; import static io.microsphere.reflect.ReflectionUtils.getCallerClassName; -import static io.microsphere.reflect.ReflectionUtils.getCallerClassNameInGeneralJVM; -import static io.microsphere.reflect.ReflectionUtils.getCallerClassNameInSunJVM; +import static io.microsphere.reflect.ReflectionUtils.getCallerClassNameInSunReflectReflection; +import static io.microsphere.reflect.ReflectionUtils.getCallerClassNamesInStackWalker; import static io.microsphere.reflect.ReflectionUtils.isInaccessibleObjectException; import static io.microsphere.reflect.ReflectionUtils.isSupportedSunReflectReflection; import static io.microsphere.reflect.ReflectionUtils.readFieldsAsMap; import static io.microsphere.reflect.ReflectionUtils.toList; import static io.microsphere.reflect.ReflectionUtils.toObject; import static io.microsphere.util.ArrayUtils.ofArray; +import static io.microsphere.util.StackTraceUtils.getCallerClassInStatckTrace; +import static io.microsphere.util.StackTraceUtils.getCallerClassNameInStackTrace; +import static io.microsphere.util.VersionUtils.JAVA_VERSION_9; +import static io.microsphere.util.VersionUtils.testCurrentJavaVersion; import static java.util.Arrays.asList; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; /** @@ -37,39 +41,55 @@ */ class ReflectionUtilsTest { + private static final Class CALLER_CLASS = ReflectionUtilsTest.class; + + private static final String CALLER_CLASS_NAME = CALLER_CLASS.getName(); + @Test void testGetCallerClassX() { - Class expectedClass = ReflectionUtilsTest.class; - Class callerClass = getCallerClass(); - assertEquals(expectedClass, callerClass); + assertEquals(CALLER_CLASS, callerClass); + Class callerClassInSunReflectReflection = getCallerClassInSunReflectReflection(); if (isSupportedSunReflectReflection()) { - Class callerClassInSunJVM = getCallerClassInSunJVM(); - assertEquals(callerClassInSunJVM, callerClass); + assertEquals(CALLER_CLASS, callerClassInSunReflectReflection); + } else { + assertNull(callerClassInSunReflectReflection); } - Class callerClassInGeneralJVM = getCallerClassInGeneralJVM(); - assertEquals(callerClassInGeneralJVM, callerClass); - + Class callerClassInStatckTrace = getCallerClassInStatckTrace(); + assertEquals(callerClassInStatckTrace, callerClass); } @Test void testGetCallerClassName() { - String expectedClassName = ReflectionUtilsTest.class.getName(); - String callerClassName = getCallerClassName(); - assertEquals(expectedClassName, callerClassName); + assertEquals(CALLER_CLASS_NAME, callerClassName); if (isSupportedSunReflectReflection()) { - String callerClassNameInSunJVM = getCallerClassNameInSunJVM(); + String callerClassNameInSunJVM = getCallerClassNameInSunReflectReflection(); assertEquals(callerClassNameInSunJVM, callerClassName); } - String callerClassNameInGeneralJVM = getCallerClassNameInGeneralJVM(); + String callerClassNameInGeneralJVM = getCallerClassNameInStackTrace(); assertEquals(callerClassNameInGeneralJVM, callerClassName); } + @Test + void testGetCallerClassNameOnStackWalkerSupportedForTesting() { + assertEquals(getCallerClassNameInStackTrace(), getCallerClassName(null, 1)); + assertEquals(CALLER_CLASS_NAME, getCallerClassName()); + } + + @Test + void testGetCallerClassNamesInStackWalker() { + if (testCurrentJavaVersion("<", JAVA_VERSION_9)) { + assertThrows(NullPointerException.class, () -> getCallerClassNamesInStackWalker()); + } else { + assertTrue(getCallerClassNamesInStackWalker().contains(CALLER_CLASS_NAME)); + } + } + @Test void testToList() { int[] intArray = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9}; diff --git a/microsphere-java-core/src/test/java/io/microsphere/security/SecurityUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/security/SecurityUtilsTest.java new file mode 100644 index 000000000..3ac8ddb6e --- /dev/null +++ b/microsphere-java-core/src/test/java/io/microsphere/security/SecurityUtilsTest.java @@ -0,0 +1,73 @@ +/* + * 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 io.microsphere.security; + + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.net.URL; + +import static io.microsphere.security.SecurityUtils.JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME; +import static io.microsphere.security.SecurityUtils.getJavaSecurityPolicyFile; +import static io.microsphere.security.SecurityUtils.setJavaSecurityPolicyFile; +import static io.microsphere.util.ClassLoaderUtils.ResourceType.CLASS; +import static io.microsphere.util.ClassLoaderUtils.getResource; +import static io.microsphere.util.StringUtils.substringBefore; +import static java.lang.System.clearProperty; +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * {@link SecurityUtils} + * + * @author Mercy + * @see SecurityUtils + * @since 1.0.0 + */ +class SecurityUtilsTest { + + private static final String MODULE_BASE_PROPERTY_NAME = "module.base"; + + private static final URL policyResource = getResource("META-INF/class-load-test.policy"); + + private static final File policyFile = new File(policyResource.getFile()); + + static { + URL classResource = getResource(SecurityUtilsTest.class.getClassLoader(), CLASS, SecurityUtilsTest.class.getName() + ".class"); + String moduleBasePath = substringBefore(classResource.getFile(), "target/"); + System.setProperty(MODULE_BASE_PROPERTY_NAME, moduleBasePath); + } + + @AfterEach + void tearDown() { + clearProperty(JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME); + clearProperty(MODULE_BASE_PROPERTY_NAME); + } + + @Test + void testtConstants() { + assertEquals("java.security.policy", JAVA_SECURITY_POLICY_FILE_PROPERTY_NAME); + } + + @Test + void testJavaSecurityPolicyFile() { + setJavaSecurityPolicyFile(policyFile); + assertEquals(policyFile.getAbsolutePath(), getJavaSecurityPolicyFile()); + } +} \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ArrayUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/ArrayUtilsTest.java index 580aca9ed..202159e11 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ArrayUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ArrayUtilsTest.java @@ -89,7 +89,7 @@ * @author Mercy * @since 1.0.0 */ -class ArrayUtilsTest extends Loggable { +class ArrayUtilsTest implements Loggable { @Test void testConstants() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ClassPathUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/ClassPathUtilsTest.java index 66e449a72..bcbc1b748 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ClassPathUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ClassPathUtilsTest.java @@ -30,7 +30,7 @@ * @see ClassPathUtilsTest * @since 1.0.0 */ -class ClassPathUtilsTest extends Loggable { +class ClassPathUtilsTest implements Loggable { @Test void testGetBootstrapClassPaths() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ClassUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/ClassUtilsTest.java index 185715140..0c7623b60 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ClassUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ClassUtilsTest.java @@ -3,6 +3,7 @@ */ package io.microsphere.util; +import io.microsphere.LoggingTest; import io.microsphere.lang.ClassDataRepository; import io.microsphere.test.A; import org.junit.jupiter.api.Test; @@ -110,7 +111,7 @@ * @see ClassUtilsTest * @since 1.0.0 */ -class ClassUtilsTest { +class ClassUtilsTest extends LoggingTest { @Test void testConstants() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallback.java b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallback.java index f8305e561..9087a3cab 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallback.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallback.java @@ -27,7 +27,7 @@ * @see ShutdownHookUtils * @since 1.0.0 */ -class ShutdownHookCallback extends Loggable implements Runnable, Prioritized { +class ShutdownHookCallback implements Loggable, Runnable, Prioritized { private final int priority; diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallbacksThreadTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallbacksThreadTest.java index 26dfe3b1e..36a25dd7b 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallbacksThreadTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookCallbacksThreadTest.java @@ -1,5 +1,6 @@ package io.microsphere.util; +import io.microsphere.LoggingTest; import org.junit.jupiter.api.Test; import static io.microsphere.util.ShutdownHookCallbacksThread.INSTANCE; @@ -12,7 +13,7 @@ * @see ShutdownHookCallbacksThread * @since 1.0.0 */ -class ShutdownHookCallbacksThreadTest { +class ShutdownHookCallbacksThreadTest extends LoggingTest { @Test void testRun() { @@ -25,6 +26,5 @@ void testRun() { } thread.run(); - } } \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookUtilsTest.java index 89799e3cb..0009475d6 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/ShutdownHookUtilsTest.java @@ -42,7 +42,7 @@ * @author Mercy * @since 1.0.0 */ -class ShutdownHookUtilsTest extends Loggable { +class ShutdownHookUtilsTest implements Loggable { @BeforeEach void setUp() { diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceElementUtilsBenchmark.java b/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceElementUtilsBenchmark.java deleted file mode 100644 index 306ec684c..000000000 --- a/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceElementUtilsBenchmark.java +++ /dev/null @@ -1,58 +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 io.microsphere.util; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import static io.microsphere.util.StackTraceUtils.getCallerClassName; -import static io.microsphere.util.StackTraceUtils.getCallerClassNameInGeneralJVM; -import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.openjdk.jmh.annotations.Mode.AverageTime; - -/** - * {@link StackTraceUtils} Benchmark - * - * @author Mercy - * @see StackTraceUtils - * @since 1.0.0 - */ -@Warmup(iterations = 5, time = 1, timeUnit = SECONDS) -@Measurement(iterations = 20, time = 1, timeUnit = SECONDS) -@Fork(1) -@BenchmarkMode(AverageTime) -@OutputTimeUnit(NANOSECONDS) -@State(Scope.Thread) -public class StackTraceElementUtilsBenchmark { - - @Benchmark - public void testGetCallerClassNameInGeneralJVM() { - getCallerClassNameInGeneralJVM(); - } - - @Benchmark - public void testGetCallerClassName() { - getCallerClassName(); - } -} diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceUtilsTest.java index d774da899..12fb90663 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/StackTraceUtilsTest.java @@ -2,16 +2,12 @@ import org.junit.jupiter.api.Test; -import static io.microsphere.util.StackTraceUtils.getCallerClassName; -import static io.microsphere.util.StackTraceUtils.getCallerClassNameInGeneralJVM; -import static io.microsphere.util.StackTraceUtils.getCallerClassNames; -import static io.microsphere.util.VersionUtils.JAVA_VERSION_9; -import static io.microsphere.util.VersionUtils.testCurrentJavaVersion; -import static java.lang.Integer.MAX_VALUE; +import static io.microsphere.util.StackTraceUtils.getCallerClassInStatckTrace; +import static io.microsphere.util.StackTraceUtils.getCallerClassNameInStackTrace; +import static io.microsphere.util.StackTraceUtils.getStackTrace; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; /** * {@link StackTraceUtils} Test @@ -22,37 +18,29 @@ */ class StackTraceUtilsTest { - private static final String CALLER_CLASS_NAME = StackTraceUtilsTest.class.getName(); + private static final Class CALLER_CLASS = StackTraceUtilsTest.class; - @Test - void testGetCallerClassName() { - assertEquals(CALLER_CLASS_NAME, getCallerClassName()); - } + private static final String CALLER_CLASS_NAME = CALLER_CLASS.getName(); @Test - void testGetCallerClassNameOnStackWalkerSupportedForTesting() { - assertEquals(getCallerClassNameInGeneralJVM(), getCallerClassName(null, 0)); - assertEquals(CALLER_CLASS_NAME, getCallerClassName()); + void testGetCallerClassInStatckTrace() { + Class callerClassInStatckTrace = getCallerClassInStatckTrace(); + assertEquals(CALLER_CLASS, callerClassInStatckTrace); } @Test - void testGetCallerClassNames() { - if (testCurrentJavaVersion("<", JAVA_VERSION_9)) { - assertThrows(NullPointerException.class, () -> getCallerClassNames()); - } else { - assertTrue(getCallerClassNames().contains(CALLER_CLASS_NAME)); - } + void testGetCallerClassNameInStackTrace() { + String callerClassName = getCallerClassNameInStackTrace(); + assertEquals(CALLER_CLASS_NAME, callerClassName); } @Test - void testGetCallerClassNameInGeneralJVM() { - String callerClassName = getCallerClassNameInGeneralJVM(); - assertEquals(CALLER_CLASS_NAME, callerClassName); + void testGetCallerClassInStatckTraceWithFrame() { + assertNull(getCallerClassInStatckTrace(99999)); } @Test - void testGetCallerClassNameInGeneralJVMOnOverStack() { - assertNull(getCallerClassNameInGeneralJVM(MAX_VALUE)); + void testGetStackTrace() { + assertNotNull(getStackTrace()); } - } \ No newline at end of file diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/StopWatchTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/StopWatchTest.java index e811476f0..55bdb6782 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/StopWatchTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/StopWatchTest.java @@ -40,7 +40,7 @@ * @author Mercy * @since 1.0.0 */ -class StopWatchTest extends Loggable { +class StopWatchTest implements Loggable { private static final String testName = "test"; diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/TypeFinderTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/TypeFinderTest.java index fa0ed880d..5f461ce59 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/TypeFinderTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/TypeFinderTest.java @@ -8,6 +8,7 @@ import io.microsphere.util.TypeFinder.Include; import org.junit.jupiter.api.Test; +import java.io.Serializable; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.TypeVariable; @@ -15,16 +16,24 @@ import java.util.function.BiFunction; import static io.microsphere.AbstractTestCase.assertValues; +import static io.microsphere.collection.ListUtils.newArrayList; +import static io.microsphere.collection.Lists.ofList; import static io.microsphere.reflect.TypeUtils.NON_OBJECT_TYPE_FILTER; +import static io.microsphere.util.ArrayUtils.ofArray; import static io.microsphere.util.TypeFinder.Include.HIERARCHICAL; import static io.microsphere.util.TypeFinder.Include.INTERFACES; import static io.microsphere.util.TypeFinder.Include.SUPER_CLASS; import static io.microsphere.util.TypeFinder.Include.values; import static io.microsphere.util.TypeFinder.classFinder; +import static io.microsphere.util.TypeFinder.classGetSuperClassFunction; import static io.microsphere.util.TypeFinder.genericTypeFinder; +import static io.microsphere.util.TypeFinder.genericTypeGetInterfacesFunction; +import static io.microsphere.util.TypeFinder.genericTypeGetSuperClassFunction; import static java.util.Collections.emptyList; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -33,7 +42,6 @@ * {@link TypeFinder} Test * * @author Mercy - * @see io.microsphere.util.ClassFinder * @since 1.0.0 */ class TypeFinderTest { @@ -187,6 +195,51 @@ void testFindAllGenericClasses() { assertGenericInterfaces(types); } + @Test + void testGetSuperTypes() { + TypeFinder> typeFinder = new TypeFinder(String.class, classGetSuperClassFunction, + t -> ofArray(Serializable.class, Serializable.class, Comparable.class), true, true, true, true); + List> superTypes = typeFinder.getSuperTypes(String.class, true, true); + assertEquals(ofList(Object.class, Serializable.class, Comparable.class), superTypes); + } + + @Test + void testGetSuperTypesWithNullType() { + TypeFinder typeFinder = genericTypeFinder(StringIntegerToBooleanClass.class, values()); + List superTypes = typeFinder.getSuperTypes(null, true, true); + assertSame(emptyList(), superTypes); + + superTypes = typeFinder.getSuperTypes(null, false, true); + assertSame(emptyList(), superTypes); + + superTypes = typeFinder.getSuperTypes(null, false, false); + assertSame(emptyList(), superTypes); + + superTypes = typeFinder.getSuperTypes(null, true, false); + assertSame(emptyList(), superTypes); + } + + @Test + void testGenericTypeGetSuperClassFunctionWithNull() { + assertNull(genericTypeGetSuperClassFunction.apply(null)); + } + + @Test + void testGenericTypeGetInterfacesFunction() { + assertNull(genericTypeGetInterfacesFunction.apply(null)); + } + + @Test + void testAddSuperTypes() { + TypeFinder typeFinder = genericTypeFinder(String.class, values()); + List types = newArrayList(); + typeFinder.addSuperTypes(types, String.class, false, false, false); + assertTrue(types.isEmpty()); + + typeFinder.addSuperTypes(types, String.class, false, true, true); + assertFalse(types.isEmpty()); + } + private void assertGenericInterfaces(List types) { assertEquals(StringIntegerToBoolean.class, types.get(types.size() - 5)); assertStringIntegerF1(types.get(types.size() - 4)); diff --git a/microsphere-java-core/src/test/java/io/microsphere/util/jar/JarUtilsTest.java b/microsphere-java-core/src/test/java/io/microsphere/util/jar/JarUtilsTest.java index 4964e755a..11c03dea8 100644 --- a/microsphere-java-core/src/test/java/io/microsphere/util/jar/JarUtilsTest.java +++ b/microsphere-java-core/src/test/java/io/microsphere/util/jar/JarUtilsTest.java @@ -3,6 +3,7 @@ */ package io.microsphere.util.jar; +import io.microsphere.LoggingTest; import io.microsphere.filter.JarEntryFilter; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -50,7 +51,7 @@ * @see JarUtilsTest * @since 1.0.0 */ -class JarUtilsTest { +class JarUtilsTest extends LoggingTest { private File targetDirectory; diff --git a/microsphere-java-core/src/test/resources/META-INF/class-load-test.policy b/microsphere-java-core/src/test/resources/META-INF/class-load-test.policy new file mode 100644 index 000000000..4511f0aa5 --- /dev/null +++ b/microsphere-java-core/src/test/resources/META-INF/class-load-test.policy @@ -0,0 +1,4 @@ + +grant { + permission java.security.AllPermission; +}; \ No newline at end of file