Github user zmacomber commented on a diff in the pull request:

    https://github.com/apache/commons-lang/pull/358#discussion_r225282462
  
    --- Diff: src/main/java/org/apache/commons/lang3/ClassUtils.java ---
    @@ -1059,6 +1066,69 @@ public static boolean isInnerClass(final Class<?> 
cls) {
             return getClass(loader, className, initialize);
         }
     
    +    /**
    +     * Returns a list of base classes/interfaces underneath the supplied 
package
    +     * This method only retrieves base classes/interfaces that have 
children that can be instantiated
    +     * via a no-args constructor
    +     * The class loader is retrieved via 
Thread.currentThread().getContextClassLoader()
    +     * This only retrieves base classes/interfaces directly underneath the 
supplied package
    +     *
    +     * @param desiredBase the desired base class/interface to retrieve
    +     * @param packageName the package name in the standard import format 
(i.e. "java.lang.String")
    +     * @param <T> The desired base class or interface type to retrieve
    +     * @return a list of base classes/interfaces that match the supplied 
type underneath the supplied package
    +     * @throws URISyntaxException if the packageName is not found in the 
class loader
    +     * @throws IOException if an I/O error occurs in getting a new 
directory stream
    +     * @throws IllegalArgumentException if the desiredBase or packageName 
are invalid
    +     */
    +    public static <T> List<T> getBaseClasses(final Class<T> desiredBase, 
final String packageName)
    +            throws URISyntaxException, IOException, 
IllegalArgumentException {
    +
    +        if (desiredBase == null) {
    +            throw new IllegalArgumentException("desiredBase must not be 
null");
    +        }
    +
    +        if (StringUtils.isBlank(packageName)) {
    +            throw new IllegalArgumentException("packageName must not be 
blank");
    +        }
    +
    +        if (packageName.contains("/")) {
    +            throw new IllegalArgumentException("packageName is not 
properly formatted (i.e. 'java.lang.String')");
    +        }
    +
    +        ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
    +        URL url = classLoader.getResource(packageName.replaceAll("[.]", 
"/"));
    +        if (url == null) {
    +            throw new URISyntaxException(packageName, "Supplied package 
not found");
    +        }
    +
    +        Path classesPath = Paths.get(url.toURI());
    +
    +        List<T> classes = new ArrayList<>();
    +
    +        try (DirectoryStream<Path> stream = 
Files.newDirectoryStream(classesPath)) {
    +            for (Path file: stream) {
    +                Path pathFileName = file.getFileName();
    +                if (( ! Files.isDirectory(file)) && (pathFileName != 
null)) {
    +                    String fullClassName = packageName + "." +
    +                                           
pathFileName.toString().replace(".class", "");
    +
    +                    // Only add classes that can be instantiated via 
newInstance()
    --- End diff --
    
    The JavaDoc explicitly states that only classes that can be instantiated 
via a default ctor can be used:
    
    "This method only retrieves base classes/interfaces that have children that 
can be instantiated via a no-args constructor"
    
    If the class can't be instantiated, an Exception is thrown and it won't be 
added to the list of returned classes:
    ```
    catch (Exception e) {
        // Class was not instantiable via newInstance()
    }
    ```


---

Reply via email to