1 /*
2 * *************************************************************************************************************************************************************
3 *
4 * TheseFoolishThings: Miscellaneous utilities
5 * http://tidalwave.it/projects/thesefoolishthings
6 *
7 * Copyright (C) 2009 - 2025 by Tidalwave s.a.s. (http://tidalwave.it)
8 *
9 * *************************************************************************************************************************************************************
10 *
11 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
13 *
14 * http://www.apache.org/licenses/LICENSE-2.0
15 *
16 * 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
17 * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18 *
19 * *************************************************************************************************************************************************************
20 *
21 * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22 * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23 *
24 * *************************************************************************************************************************************************************
25 */
26 package it.tidalwave.util.spring;
27
28 import java.lang.annotation.Annotation;
29 import jakarta.annotation.Nonnull;
30 import java.util.ArrayList;
31 import java.util.Collection;
32 import java.util.List;
33 import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
34 import org.springframework.core.type.filter.AnnotationTypeFilter;
35 import org.springframework.core.type.filter.TypeFilter;
36 import org.springframework.util.ClassUtils;
37 import it.tidalwave.role.spring.RoleSpringConfiguration;
38 import lombok.Setter;
39
40 /***************************************************************************************************************************************************************
41 *
42 * A utility for scanning classes in the classpath with some criteria.
43 *
44 * @author Fabrizio Giudici
45 *
46 **************************************************************************************************************************************************************/
47 public class ClassScanner
48 {
49 @Setter
50 private static String basePackages = System.getProperty(
51 ClassScanner.class.getCanonicalName() + ".basePackages", RoleSpringConfiguration.getBasePackages());
52
53 private final ClassPathScanningCandidateComponentProvider scanner =
54 new ClassPathScanningCandidateComponentProvider(false);
55
56 /***********************************************************************************************************************************************************
57 * Scans for classes and returns them.
58 *
59 * @return the collection of scanned classes
60 **********************************************************************************************************************************************************/
61 @Nonnull
62 public final Collection<Class<?>> findClasses()
63 {
64 final List<Class<?>> classes = new ArrayList<>();
65
66 for (final var basePackage : basePackages.split(":"))
67 {
68 for (final var candidate : scanner.findCandidateComponents(basePackage))
69 {
70 classes.add(ClassUtils.resolveClassName(candidate.getBeanClassName(),
71 ClassUtils.getDefaultClassLoader()));
72 }
73 }
74
75 return classes;
76 }
77
78 /***********************************************************************************************************************************************************
79 * Adds an "include" filter.
80 *
81 * @param filter the filter
82 * @return itself for method chaining
83 **********************************************************************************************************************************************************/
84 @Nonnull
85 public ClassScanner withIncludeFilter (@Nonnull final TypeFilter filter)
86 {
87 scanner.addIncludeFilter(filter);
88 return this;
89 }
90
91 /***********************************************************************************************************************************************************
92 * Adds a filter for an annotation.
93 *
94 * @param annotationClass the annotation class
95 * @return itself for method chaining
96 **********************************************************************************************************************************************************/
97 @Nonnull
98 public ClassScanner withAnnotationFilter (@Nonnull final Class<? extends Annotation> annotationClass)
99 {
100 return withIncludeFilter(new AnnotationTypeFilter(annotationClass));
101 }
102 }