|
33 | 33 | import java.nio.file.Path; |
34 | 34 | import java.nio.file.Paths; |
35 | 35 | import java.util.ArrayList; |
36 | | -import java.util.Arrays; |
37 | 36 | import java.util.HashSet; |
38 | 37 | import java.util.List; |
39 | | -import java.util.Objects; |
40 | 38 | import java.util.Set; |
| 39 | +import java.util.regex.Pattern; |
41 | 40 | import java.util.stream.Stream; |
42 | 41 |
|
43 | 42 | import org.apache.commons.lang3.ObjectUtils; |
@@ -208,10 +207,7 @@ void allSerializableClassesShouldHaveSerialVersionOrSuppressWarnings() throws Ex |
208 | 207 | boolean hasSerialVersion = Stream.of(clazz.getDeclaredFields()) |
209 | 208 | .map(Field::getName) |
210 | 209 | .anyMatch((n) -> n.equals("serialVersionUID")); |
211 | | - SuppressWarnings suppressWarnings = clazz.getAnnotation(SuppressWarnings.class); |
212 | | - boolean hasSerialIgnore = Objects.nonNull(suppressWarnings) |
213 | | - && Arrays.asList(suppressWarnings.value()).contains("serial"); |
214 | | - if (!hasSerialVersion && !hasSerialIgnore) { |
| 210 | + if (!hasSerialVersion && !hasSuppressSerialInSource(clazz)) { |
215 | 211 | classes.add(clazz); |
216 | 212 | continue; |
217 | 213 | } |
@@ -250,6 +246,58 @@ static Stream<Class<?>> getClassesToSerialize() throws Exception { |
250 | 246 | return classes.stream(); |
251 | 247 | } |
252 | 248 |
|
| 249 | + private static boolean hasSuppressSerialInSource(Class<?> clazz) { |
| 250 | + try { |
| 251 | + Class<?> fileClass = clazz; |
| 252 | + while (fileClass.getEnclosingClass() != null) { |
| 253 | + fileClass = fileClass.getEnclosingClass(); |
| 254 | + } |
| 255 | + var codeSource = fileClass.getProtectionDomain().getCodeSource(); |
| 256 | + if (codeSource == null) { |
| 257 | + return false; |
| 258 | + } |
| 259 | + Path sourceFile = findSourceFile(Path.of(codeSource.getLocation().toURI()), fileClass); |
| 260 | + if (sourceFile == null) { |
| 261 | + return false; |
| 262 | + } |
| 263 | + return hasSuppressSerialAnnotation(Files.readAllLines(sourceFile), clazz.getSimpleName()); |
| 264 | + } |
| 265 | + catch (Exception ex) { |
| 266 | + return false; |
| 267 | + } |
| 268 | + } |
| 269 | + |
| 270 | + private static Path findSourceFile(Path start, Class<?> clazz) { |
| 271 | + String relativePath = clazz.getName().replace('.', '/') + ".java"; |
| 272 | + Path dir = start; |
| 273 | + for (int i = 0; i < 10 && dir != null; i++) { |
| 274 | + for (String sourceRoot : List.of("src/main/java", "src/test/java")) { |
| 275 | + Path candidate = dir.resolve(sourceRoot).resolve(relativePath); |
| 276 | + if (Files.exists(candidate)) { |
| 277 | + return candidate; |
| 278 | + } |
| 279 | + } |
| 280 | + dir = dir.getParent(); |
| 281 | + } |
| 282 | + return null; |
| 283 | + } |
| 284 | + |
| 285 | + private static boolean hasSuppressSerialAnnotation(List<String> lines, String simpleClassName) { |
| 286 | + Pattern classDeclaration = Pattern |
| 287 | + .compile("\\b(?:class|interface|enum|record)\\s+" + Pattern.quote(simpleClassName) + "\\b"); |
| 288 | + for (int i = 0; i < lines.size(); i++) { |
| 289 | + if (classDeclaration.matcher(lines.get(i)).find()) { |
| 290 | + for (int j = Math.max(0, i - 5); j < i; j++) { |
| 291 | + String line = lines.get(j); |
| 292 | + if (line.contains("@SuppressWarnings") && line.contains("\"serial\"")) { |
| 293 | + return true; |
| 294 | + } |
| 295 | + } |
| 296 | + } |
| 297 | + } |
| 298 | + return false; |
| 299 | + } |
| 300 | + |
253 | 301 | private static String getCurrentVersion() { |
254 | 302 | String version = System.getProperty("springSecurityVersion"); |
255 | 303 | String[] parts = version.split("\\."); |
|
0 commit comments