Skip to content

Commit 4bde0c8

Browse files
ClassFinder Fixes
Fixed IdeClassFinder trying to iterate over null files Fixed JarClassFinder's recursive search
1 parent 7f99420 commit 4bde0c8

File tree

5 files changed

+116
-27
lines changed

5 files changed

+116
-27
lines changed

pom.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
<groupId>top.wavelength</groupId>
3131
<artifactId>Java-BetterReflection</artifactId>
32-
<version>1.3.1</version>
32+
<version>1.3.2</version>
3333

3434
<properties>
3535
<maven.compiler.source>1.8</maven.compiler.source>
@@ -62,7 +62,6 @@
6262
<extensions>true</extensions>
6363
<configuration>
6464
<publishingServerId>central-wl</publishingServerId>
65-
<tokenAuth>true</tokenAuth>
6665
</configuration>
6766
</plugin>
6867
<plugin>

src/main/java/top/wavelength/betterreflection/BetterReflection.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ public class BetterReflection {
3737
PRIMITIVES.put(Boolean.class, new BetterReflectionClass<>(Boolean.class));
3838
PRIMITIVES.put(Long.class, new BetterReflectionClass<>(Long.class));
3939
PRIMITIVES.put(Void.class, new BetterReflectionClass<>(Void.class));
40+
PRIMITIVES.put(Character.class, new BetterReflectionClass<>(Character.class));
41+
PRIMITIVES.put(String.class, new BetterReflectionClass<>(String.class));
4042

4143
PRIMITIVES.put(short.class, new BetterReflectionClass<>(short.class));
4244
PRIMITIVES.put(byte.class, new BetterReflectionClass<>(byte.class));
@@ -46,6 +48,7 @@ public class BetterReflection {
4648
PRIMITIVES.put(boolean.class, new BetterReflectionClass<>(boolean.class));
4749
PRIMITIVES.put(long.class, new BetterReflectionClass<>(long.class));
4850
PRIMITIVES.put(void.class, new BetterReflectionClass<>(void.class));
51+
PRIMITIVES.put(char.class, new BetterReflectionClass<>(char.class));
4952
}
5053

5154
/**
@@ -95,6 +98,20 @@ public static Map<Class<?>, BetterReflectionClass<?>> getPrimitives() {
9598
return PRIMITIVES;
9699
}
97100

101+
/**
102+
* @param name The primitive name
103+
* @return a BetterReflectionClass matching the given primitive name
104+
* @since 1.3.2
105+
*/
106+
public static BetterReflectionClass<?> getPrimitive(String name) {
107+
for (Class<?> clasz : PRIMITIVES.keySet()) {
108+
BetterReflectionClass<?> betterReflectionClass = PRIMITIVES.get(clasz);
109+
if (betterReflectionClass.getSimpleName().equals(name))
110+
return betterReflectionClass;
111+
}
112+
return null;
113+
}
114+
98115
public static Object getFieldValue(BetterReflectionClass<?> betterReflectionClass, Object instance, String fieldName) throws IllegalAccessException {
99116
return betterReflectionClass.getDeclaredField(fieldName).get(instance);
100117
}
@@ -166,7 +183,7 @@ else if (version[i] < latestVersion[i])
166183
* @since 0.4
167184
*/
168185
public static String getVersion() {
169-
return "1.3.1";
186+
return "1.3.2";
170187
}
171188

172189
/**

src/main/java/top/wavelength/betterreflection/BetterReflectionUtils.java

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,13 +219,27 @@ public static List<File> getDirectoriesFromPackageName(String packageName) throw
219219
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
220220
assert classLoader != null;
221221

222-
String path = packageName.replace('.', '/');
222+
String path = packageName.replace('.', File.separatorChar);
223223

224-
Enumeration<URL> resources = classLoader.getResources(path);
225224
List<File> directories = new ArrayList<>();
225+
Enumeration<URL> resources = classLoader.getResources(path);
226226
while (resources.hasMoreElements()) {
227227
URL resource = resources.nextElement();
228-
directories.add(new File(resource.toURI()));
228+
if ("file".equals(resource.getProtocol())) {
229+
// Handle filesystem directories
230+
try {
231+
File dir = new File(resource.toURI());
232+
if (dir.isDirectory()) {
233+
directories.add(dir);
234+
}
235+
} catch (Exception e) {
236+
throw new IOException("Failed to process filesystem resource: " + resource, e);
237+
}
238+
} else if ("jar".equals(resource.getProtocol())) {
239+
// Handle JAR entries (optional: add JAR file to list)
240+
String jarPath = resource.getPath().split("!")[0].replace("file:", "");
241+
directories.add(new File(jarPath)); // Add JAR file itself
242+
}
229243
}
230244

231245
return directories;
@@ -246,7 +260,7 @@ public static List<File> getDirectoriesFromPackageName(String packageName) throw
246260
* @deprecated This method is deprecated in favour of ClassFinder
247261
*/
248262
@Deprecated
249-
public static List<BetterReflectionClass<Object>> getClassesInPackage(String packageName) throws IOException, URISyntaxException, CannotReadJarException, ClassNotFoundException {
263+
public static List<BetterReflectionClass<Object>> getClassesInPackage(String packageName) throws IOException, URISyntaxException, CannotReadJarException {
250264
return ClassFinderFactory.create(packageName, CLASS).findClasses();
251265
}
252266

@@ -267,7 +281,7 @@ public static List<BetterReflectionClass<Object>> getClassesInPackage(String pac
267281
* Jar and the Jar file cannot be found or it
268282
* cannot be read.
269283
*/
270-
public static List<BetterReflectionClass<?>> getClassesFromNameBeginning(String packageName, String beginning) throws IOException, URISyntaxException, CannotReadJarException, ClassNotFoundException {
284+
public static List<BetterReflectionClass<?>> getClassesFromNameBeginning(String packageName, String beginning) throws IOException, URISyntaxException, CannotReadJarException {
271285
List<BetterReflectionClass<?>> classes = new ArrayList<>();
272286
for (BetterReflectionClass<?> clasz : getClassesInPackage(packageName))
273287
if (clasz.getSimpleName().startsWith(beginning))
@@ -347,6 +361,33 @@ public static void setFinal(Field field, boolean setFinal) throws Exception {
347361
}
348362
}
349363

364+
/**
365+
* Dynamically discerns the separator used in a given path.
366+
*
367+
* @param path The path to analyze.
368+
* @return The detected separator as a String (either "/" or "\").
369+
* @throws IllegalArgumentException if the path is null, empty, or contains no valid separators.
370+
* @since 1.3.2
371+
*/
372+
public static String discernSeparator(String path) {
373+
if (path == null || path.isEmpty())
374+
throw new IllegalArgumentException("Path cannot be null or empty.");
375+
376+
// Count occurrences of '/' and '\'
377+
long forwardSlashCount = path.chars().filter(ch -> ch == '/').count();
378+
long backslashCount = path.chars().filter(ch -> ch == '\\').count();
379+
380+
// Determine the separator based on the counts
381+
if (forwardSlashCount > 0 && backslashCount == 0)
382+
return "/";
383+
else if (backslashCount > 0 && forwardSlashCount == 0)
384+
return "\\";
385+
else if (forwardSlashCount > 0)
386+
return "/";
387+
else
388+
throw new IllegalArgumentException("Path contains no valid separators.");
389+
}
390+
350391
/**
351392
* @param method the method to dump
352393
* @param includeModifiers whether the method's modifiers should be dumped

src/main/java/top/wavelength/betterreflection/lookup/IdeClassFinder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ public List<BetterReflectionClass<T>> scanDirectory(List<File> directories, Stri
6161

6262
for (File directory : directories) {
6363
File[] files = directory.listFiles();
64-
assert files != null;
64+
if (files == null)
65+
continue;
6566
for (File file : files) {
6667
if (file.isDirectory() && isRecursive())
6768
classes.addAll(scanDirectory(Collections.singletonList(file), base + file.getName()));

src/main/java/top/wavelength/betterreflection/lookup/JarClassFinder.java

Lines changed: 49 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package top.wavelength.betterreflection.lookup;
22

33
import top.wavelength.betterreflection.BetterReflectionClass;
4+
import top.wavelength.betterreflection.BetterReflectionUtils;
45
import top.wavelength.betterreflection.exceptions.CannotReadJarException;
56

67
import java.io.File;
78
import java.io.IOException;
8-
import java.util.ArrayList;
9-
import java.util.Enumeration;
10-
import java.util.List;
11-
import java.util.Objects;
9+
import java.io.PrintWriter;
10+
import java.io.StringWriter;
11+
import java.util.*;
1212
import java.util.jar.JarEntry;
1313
import java.util.jar.JarFile;
1414

@@ -43,11 +43,13 @@ public JarClassFinder(String packageName) {
4343
@Override
4444
public List<BetterReflectionClass<T>> findClasses() throws IOException {
4545
List<BetterReflectionClass<T>> classes = new ArrayList<>();
46-
String basePackage = this.basePackage == null ? "" : this.basePackage.replace('.', '/');
46+
String basePackage = this.basePackage == null ? "" : this.basePackage;
4747
File jarFile = getJarFile();
4848
if (jarFile == null || !jarFile.exists() || !jarFile.canRead())
4949
throw new CannotReadJarException(jarFile == null ? "[NO NAME]" : jarFile.getName());
5050

51+
Map<JarEntry, Exception> problematicEntries = new HashMap<>();
52+
5153
try (JarFile jar = new JarFile(jarFile)) {
5254
Enumeration<JarEntry> entries = jar.entries();
5355
while (entries.hasMoreElements()) {
@@ -57,27 +59,56 @@ public List<BetterReflectionClass<T>> findClasses() throws IOException {
5759
String name = entry.getName();
5860
if (!name.endsWith(".class"))
5961
continue;
62+
try {
63+
String separator = BetterReflectionUtils.discernSeparator(entry.getName());
64+
String packageName = entry.getName().contains(separator) ?
65+
entry.getName().substring(0, name.lastIndexOf(separator)).replace(separator, ".")
66+
: "";
67+
String className = entry.getName().substring(packageName.length() + 1, entry.getName().lastIndexOf('.'));
68+
String fullName = packageName + '.' + className;
6069

61-
String packageName = entry.getName().substring(0, name.lastIndexOf('/')).replace('/', '.');
62-
String className = entry.getName().substring(packageName.length() + 1, entry.getName().lastIndexOf('.'));
63-
String fullName = packageName + '.' + className;
70+
if (isRecursive()) {
71+
if (!packageName.startsWith(basePackage))
72+
continue;
73+
} else if (!packageName.equals(basePackage))
74+
continue;
6475

65-
if ((isRecursive() && !packageName.startsWith(basePackage))
66-
|| (!isRecursive() && !packageName.equalsIgnoreCase(basePackage)))
67-
continue;
76+
BetterReflectionClass<?> clasz;
77+
try {
78+
clasz = new BetterReflectionClass<>(Class.forName(fullName, true, getClassLoader()));
79+
} catch (ClassNotFoundException | NoClassDefFoundError e) {
80+
continue;
81+
}
6882

69-
BetterReflectionClass<?> clasz;
70-
try {
71-
clasz = new BetterReflectionClass<>(Class.forName(fullName, true, getClassLoader()));
72-
} catch (ClassNotFoundException | NoClassDefFoundError e) {
73-
continue;
83+
if (getType() == null || getType().isAssignableFrom(Objects.requireNonNull(clasz)))
84+
classes.add((BetterReflectionClass<T>) clasz);
85+
} catch (Exception e) {
86+
e.printStackTrace();
87+
problematicEntries.put(entry, e);
7488
}
89+
}
90+
}
7591

76-
if (getType() == null || getType().isAssignableFrom(Objects.requireNonNull(clasz)))
77-
classes.add((BetterReflectionClass<T>) clasz);
92+
if (!problematicEntries.isEmpty()) {
93+
StringBuilder errors = new StringBuilder("There has been an issue trying to load some entries:");
94+
for (JarEntry jarEntry : problematicEntries.keySet()) {
95+
StringWriter stringWriter = new StringWriter();
96+
PrintWriter printWriter = new PrintWriter(stringWriter);
97+
problematicEntries.get(jarEntry).printStackTrace(printWriter);
98+
String stackTrace = stringWriter.toString(); // stack trace as a string
99+
printWriter.close();
100+
stringWriter.close();
101+
102+
errors.append('\n')
103+
.append(jarEntry.getName())
104+
.append('\n')
105+
.append(stackTrace)
106+
.append("------------------");
78107
}
108+
throw new IllegalStateException(errors.toString());
79109
}
80110

81111
return classes;
82112
}
113+
83114
}

0 commit comments

Comments
 (0)