Skip to content

Commit e5c235b

Browse files
authored
Merge pull request #19 from microsphere-projects/feature-compatible-with-jdk21
Feature compatible with jdk21
2 parents 8c4c4ed + 8a8d57b commit e5c235b

14 files changed

Lines changed: 385 additions & 270 deletions

File tree

.github/workflows/maven.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
runs-on: ubuntu-latest
2020
strategy:
2121
matrix:
22-
java: [ '8', '11' ]
22+
java: [ '8', '11' , '17' , '21' ]
2323
steps:
2424
- uses: actions/checkout@v4
2525
- name: Java ${{ matrix.Java }}

microsphere-annotation-processor/src/test/java/io/microsphere/annotation/processor/util/MethodUtilsTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ public void testDeclaredMethods() {
6666
assertEquals(12, methods.size());
6767

6868
methods = getAllDeclaredMethods(type);
69-
assertEquals(34, methods.size());
69+
assertTrue(methods.size() >= 33);
7070

7171
assertTrue(getAllDeclaredMethods((TypeElement) null).isEmpty());
7272
assertTrue(getAllDeclaredMethods((TypeMirror) null).isEmpty());

microsphere-java-core/pom.xml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@
110110
<artifactId>javax.annotation-api</artifactId>
111111
</dependency>
112112
</dependencies>
113+
<build>
114+
<plugins>
115+
<plugin>
116+
<groupId>org.apache.maven.plugins</groupId>
117+
<artifactId>maven-surefire-plugin</artifactId>
118+
<configuration>
119+
<argLine>
120+
--illegal-access=permit
121+
--add-opens java.base/java.lang.invoke=ALL-UNNAMED
122+
</argLine>
123+
</configuration>
124+
</plugin>
125+
</plugins>
126+
</build>
113127
</profile>
114128
</profiles>
115129

microsphere-java-core/src/main/java/io/microsphere/io/scanner/SimpleClassScanner.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@
55

66
import io.microsphere.filter.FilterUtils;
77
import io.microsphere.filter.PackageNameClassNameFilter;
8+
import io.microsphere.lang.ClassDataRepository;
89
import io.microsphere.util.ClassLoaderUtils;
9-
import io.microsphere.util.ClassUtils;
1010

1111
import java.io.File;
1212
import java.io.IOException;
@@ -21,7 +21,9 @@
2121

2222
import static io.microsphere.lang.function.Streams.filterAll;
2323
import static io.microsphere.net.URLUtils.resolveArchiveFile;
24+
import static io.microsphere.util.ClassLoaderUtils.ResourceType.PACKAGE;
2425
import static io.microsphere.util.ClassLoaderUtils.findLoadedClass;
26+
import static io.microsphere.util.ClassLoaderUtils.getResources;
2527
import static io.microsphere.util.ClassLoaderUtils.loadClass;
2628
import static io.microsphere.util.ClassUtils.findClassNamesInClassPath;
2729
import static io.microsphere.util.StringUtils.substringBefore;
@@ -90,19 +92,20 @@ public Set<Class<?>> scan(ClassLoader classLoader, String packageName, boolean r
9092
public Set<Class<?>> scan(ClassLoader classLoader, String packageName, final boolean recursive, boolean requiredLoad) throws IllegalArgumentException, IllegalStateException {
9193
Set<Class<?>> classesSet = new LinkedHashSet();
9294

93-
final String packageResourceName = ClassLoaderUtils.ResourceType.PACKAGE.resolve(packageName);
95+
final String packageResourceName = PACKAGE.resolve(packageName);
9496

9597
try {
9698
Set<String> classNames = new LinkedHashSet();
9799
// Find in class loader
98-
Set<URL> resourceURLs = ClassLoaderUtils.getResources(classLoader, ClassLoaderUtils.ResourceType.PACKAGE, packageName);
100+
Set<URL> resourceURLs = getResources(classLoader, PACKAGE, packageName);
99101

100102
if (resourceURLs.isEmpty()) {
101103
//Find in class path
102-
List<String> classNamesInPackage = new ArrayList<>(ClassUtils.getClassNamesInPackage(packageName));
104+
ClassDataRepository repository = ClassDataRepository.INSTANCE;
105+
List<String> classNamesInPackage = new ArrayList<>(repository.getClassNamesInPackage(packageName));
103106

104107
if (!classNamesInPackage.isEmpty()) {
105-
String classPath = ClassUtils.findClassPath(classNamesInPackage.get(0));
108+
String classPath = repository.findClassPath(classNamesInPackage.get(0));
106109
URL resourceURL = new File(classPath).toURI().toURL();
107110
resourceURLs = new HashSet();
108111
resourceURLs.add(resourceURL);
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package io.microsphere.lang;
18+
19+
import io.microsphere.collection.CollectionUtils;
20+
import io.microsphere.util.ClassPathUtils;
21+
22+
import javax.annotation.Nonnull;
23+
import javax.annotation.Nullable;
24+
import java.io.File;
25+
import java.net.MalformedURLException;
26+
import java.net.URL;
27+
import java.security.CodeSource;
28+
import java.security.ProtectionDomain;
29+
import java.util.LinkedHashMap;
30+
import java.util.LinkedHashSet;
31+
import java.util.Map;
32+
import java.util.Set;
33+
import java.util.jar.JarFile;
34+
35+
import static io.microsphere.util.ClassPathUtils.getBootstrapClassPaths;
36+
import static io.microsphere.util.ClassPathUtils.getClassPaths;
37+
import static io.microsphere.util.ClassUtils.findClassNamesInClassPath;
38+
import static io.microsphere.util.ClassUtils.resolvePackageName;
39+
import static io.microsphere.util.StringUtils.isNotBlank;
40+
import static java.util.Collections.emptySet;
41+
import static java.util.Collections.unmodifiableMap;
42+
import static java.util.Collections.unmodifiableSet;
43+
44+
/**
45+
* The Class Data Repository
46+
*
47+
* @author <a href="mailto:mercyblitz@gmail.com">Mercy<a/>
48+
* @see ClassPathUtils
49+
* @since 1.0.0
50+
*/
51+
public class ClassDataRepository {
52+
53+
/**
54+
* Singleton instance of {@link ClassDataRepository}
55+
*/
56+
public static final ClassDataRepository INSTANCE = new ClassDataRepository();
57+
58+
private final Map<String, Set<String>> classPathToClassNamesMap = initClassPathToClassNamesMap();
59+
60+
private final Map<String, String> classNameToClassPathsMap = initClassNameToClassPathsMap();
61+
62+
private final Map<String, Set<String>> packageNameToClassNamesMap = initPackageNameToClassNamesMap();
63+
64+
private ClassDataRepository() {
65+
}
66+
67+
/**
68+
* Get all package names in {@link ClassPathUtils#getClassPaths() class paths}
69+
*
70+
* @return all package names in class paths
71+
*/
72+
@Nonnull
73+
public Set<String> getAllPackageNamesInClassPaths() {
74+
return packageNameToClassNamesMap.keySet();
75+
}
76+
77+
/**
78+
* Find class path under specified class name
79+
*
80+
* @param type class
81+
* @return class path
82+
*/
83+
@Nullable
84+
public String findClassPath(Class<?> type) {
85+
return findClassPath(type.getName());
86+
}
87+
88+
/**
89+
* Find class path under specified class name
90+
*
91+
* @param className class name
92+
* @return class path
93+
*/
94+
@Nullable
95+
public String findClassPath(String className) {
96+
return classNameToClassPathsMap.get(className);
97+
}
98+
99+
/**
100+
* Gets class name {@link Set} under specified class path
101+
*
102+
* @param classPath class path
103+
* @param recursive is recursive on sub directories
104+
* @return non-null {@link Set}
105+
*/
106+
@Nonnull
107+
public Set<String> getClassNamesInClassPath(String classPath, boolean recursive) {
108+
Set<String> classNames = classPathToClassNamesMap.get(classPath);
109+
if (CollectionUtils.isEmpty(classNames)) {
110+
classNames = findClassNamesInClassPath(classPath, recursive);
111+
}
112+
return classNames;
113+
}
114+
115+
/**
116+
* Gets class name {@link Set} under specified package
117+
*
118+
* @param onePackage one package
119+
* @return non-null {@link Set}
120+
*/
121+
@Nonnull
122+
public Set<String> getClassNamesInPackage(Package onePackage) {
123+
return getClassNamesInPackage(onePackage.getName());
124+
}
125+
126+
/**
127+
* Gets class name {@link Set} under specified package name
128+
*
129+
* @param packageName package name
130+
* @return non-null {@link Set}
131+
*/
132+
@Nonnull
133+
public Set<String> getClassNamesInPackage(String packageName) {
134+
Set<String> classNames = packageNameToClassNamesMap.get(packageName);
135+
return classNames == null ? emptySet() : classNames;
136+
}
137+
138+
/**
139+
* The map of all class names in {@link ClassPathUtils#getClassPaths() class path} , the class path for one {@link
140+
* JarFile} or classes directory as key , the class names set as value
141+
*
142+
* @return Read-only
143+
*/
144+
@Nonnull
145+
public Map<String, Set<String>> getClassPathToClassNamesMap() {
146+
return classPathToClassNamesMap;
147+
}
148+
149+
/**
150+
* The set of all class names in {@link ClassPathUtils#getClassPaths() class path}
151+
*
152+
* @return Read-only
153+
*/
154+
@Nonnull
155+
public Set<String> getAllClassNamesInClassPaths() {
156+
Set<String> allClassNames = new LinkedHashSet();
157+
for (Set<String> classNames : classPathToClassNamesMap.values()) {
158+
allClassNames.addAll(classNames);
159+
}
160+
return unmodifiableSet(allClassNames);
161+
}
162+
163+
/**
164+
* Get {@link Class}'s code source location URL
165+
*
166+
* @param type
167+
* @return If , return <code>null</code>.
168+
* @throws NullPointerException If <code>type</code> is <code>null</code> , {@link NullPointerException} will be thrown.
169+
*/
170+
public URL getCodeSourceLocation(Class<?> type) throws NullPointerException {
171+
172+
URL codeSourceLocation = null;
173+
ClassLoader classLoader = type.getClassLoader();
174+
175+
if (classLoader == null) { // Bootstrap ClassLoader or type is primitive or void
176+
String path = findClassPath(type);
177+
if (isNotBlank(path)) {
178+
try {
179+
codeSourceLocation = new File(path).toURI().toURL();
180+
} catch (MalformedURLException ignored) {
181+
codeSourceLocation = null;
182+
}
183+
}
184+
} else {
185+
ProtectionDomain protectionDomain = type.getProtectionDomain();
186+
CodeSource codeSource = protectionDomain == null ? null : protectionDomain.getCodeSource();
187+
codeSourceLocation = codeSource == null ? null : codeSource.getLocation();
188+
}
189+
return codeSourceLocation;
190+
}
191+
192+
private Map<String, Set<String>> initClassPathToClassNamesMap() {
193+
Map<String, Set<String>> classPathToClassNamesMap = new LinkedHashMap<>();
194+
Set<String> classPaths = new LinkedHashSet<>();
195+
classPaths.addAll(getBootstrapClassPaths());
196+
classPaths.addAll(getClassPaths());
197+
for (String classPath : classPaths) {
198+
Set<String> classNames = findClassNamesInClassPath(classPath, true);
199+
classPathToClassNamesMap.put(classPath, classNames);
200+
}
201+
return unmodifiableMap(classPathToClassNamesMap);
202+
}
203+
204+
private Map<String, String> initClassNameToClassPathsMap() {
205+
Map<String, String> classNameToClassPathsMap = new LinkedHashMap<>();
206+
207+
for (Map.Entry<String, Set<String>> entry : classPathToClassNamesMap.entrySet()) {
208+
String classPath = entry.getKey();
209+
Set<String> classNames = entry.getValue();
210+
for (String className : classNames) {
211+
classNameToClassPathsMap.put(className, classPath);
212+
}
213+
}
214+
215+
return unmodifiableMap(classNameToClassPathsMap);
216+
}
217+
218+
private Map<String, Set<String>> initPackageNameToClassNamesMap() {
219+
Map<String, Set<String>> packageNameToClassNamesMap = new LinkedHashMap();
220+
for (Map.Entry<String, String> entry : classNameToClassPathsMap.entrySet()) {
221+
String className = entry.getKey();
222+
String packageName = resolvePackageName(className);
223+
Set<String> classNamesInPackage = packageNameToClassNamesMap.get(packageName);
224+
if (classNamesInPackage == null) {
225+
classNamesInPackage = new LinkedHashSet();
226+
packageNameToClassNamesMap.put(packageName, classNamesInPackage);
227+
}
228+
classNamesInPackage.add(className);
229+
}
230+
231+
return unmodifiableMap(packageNameToClassNamesMap);
232+
}
233+
}

microsphere-java-core/src/main/java/io/microsphere/reflect/ExecutableUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
import java.lang.reflect.Method;
3131

3232
import static io.microsphere.logging.LoggerFactory.getLogger;
33-
import static io.microsphere.reflect.AccessibleObjectUtils.trySetAccessible;
33+
import static io.microsphere.reflect.AccessibleObjectUtils.setAccessible;
3434
import static io.microsphere.text.FormatUtils.format;
3535

3636
/**
@@ -133,7 +133,7 @@ public static <E extends Executable & Member, R> R execute(E executableMember, T
133133
boolean accessible = false;
134134
RuntimeException failure = null;
135135
try {
136-
accessible = trySetAccessible(executableMember);
136+
accessible = setAccessible(executableMember);
137137
result = callback.apply(executableMember);
138138
} catch (IllegalAccessException e) {
139139
String errorMessage = format("The executable member['{}'] can't be accessed[accessible : {}]", executableMember, accessible);

microsphere-java-core/src/main/java/io/microsphere/reflect/MethodUtils.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
import javax.lang.model.element.ExecutableElement;
2525
import javax.lang.model.element.TypeElement;
2626
import javax.lang.model.util.Elements;
27-
import java.lang.annotation.Annotation;
2827
import java.lang.reflect.InvocationTargetException;
2928
import java.lang.reflect.Method;
3029
import java.lang.reflect.Modifier;
@@ -53,7 +52,6 @@
5352
import static io.microsphere.util.AnnotationUtils.CALLER_SENSITIVE_ANNOTATION_CLASS;
5453
import static io.microsphere.util.AnnotationUtils.isAnnotationPresent;
5554
import static io.microsphere.util.ArrayUtils.EMPTY_CLASS_ARRAY;
56-
import static io.microsphere.util.ClassLoaderUtils.resolveClass;
5755
import static io.microsphere.util.ClassUtils.getAllInheritedTypes;
5856
import static io.microsphere.util.ClassUtils.getTypeName;
5957
import static io.microsphere.util.ClassUtils.getTypes;

microsphere-java-core/src/main/java/io/microsphere/reflect/ReflectionUtils.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
import java.lang.reflect.Constructor;
1212
import java.lang.reflect.Field;
1313
import java.lang.reflect.Method;
14-
import java.lang.reflect.Modifier;
1514
import java.lang.reflect.ParameterizedType;
1615
import java.lang.reflect.Type;
1716
import java.util.ArrayList;

microsphere-java-core/src/main/java/io/microsphere/util/ClassLoaderUtils.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package io.microsphere.util;
55

66
import io.microsphere.classloading.URLClassPathHandle;
7+
import io.microsphere.lang.ClassDataRepository;
78
import io.microsphere.logging.Logger;
89
import io.microsphere.net.URLUtils;
910
import io.microsphere.reflect.ReflectionUtils;
@@ -42,7 +43,6 @@
4243
import static io.microsphere.reflect.FieldUtils.getFieldValue;
4344
import static io.microsphere.reflect.MethodUtils.findMethod;
4445
import static io.microsphere.reflect.MethodUtils.invokeMethod;
45-
import static io.microsphere.util.ClassUtils.getClassNamesInClassPath;
4646
import static io.microsphere.util.ServiceLoaderUtils.loadServicesList;
4747
import static io.microsphere.util.StringUtils.EMPTY;
4848
import static io.microsphere.util.StringUtils.contains;
@@ -529,7 +529,7 @@ public static Set<Class<?>> getLoadedClasses(ClassLoader classLoader) throws Uns
529529
* @throws UnsupportedOperationException If JVM does not support
530530
*/
531531
public static Set<Class<?>> findLoadedClassesInClassPath(ClassLoader classLoader) throws UnsupportedOperationException {
532-
Set<String> classNames = ClassUtils.getAllClassNamesInClassPaths();
532+
Set<String> classNames = ClassDataRepository.INSTANCE.getAllClassNamesInClassPaths();
533533
return findLoadedClasses(classLoader, classNames);
534534
}
535535

@@ -560,7 +560,7 @@ public static Set<Class<?>> findLoadedClassesInClassPaths(ClassLoader classLoade
560560
* @see #findLoadedClass(ClassLoader, String)
561561
*/
562562
public static Set<Class<?>> findLoadedClassesInClassPath(ClassLoader classLoader, String classPath) throws UnsupportedOperationException {
563-
Set<String> classNames = getClassNamesInClassPath(classPath, true);
563+
Set<String> classNames = ClassDataRepository.INSTANCE.getClassNamesInClassPath(classPath, true);
564564
return findLoadedClasses(classLoader, classNames);
565565
}
566566

0 commit comments

Comments
 (0)