2

Please note: This question is about how to accomplish classpath scanning (via reflection) in Scala, not Java. I don't see that question anywhere on this site, and so I don't believe this is a duplicate question.


I have Scala a project directory structure that looks like this:

myapp/
  src/main/scala/
    com/
      me/
        myapp/
          messages/
            BaseMessage.scala
            FizzMessage.scala
          utils
            <omitted for brevity>
          logging
            <omitted for brevity>
          driver
            <omitted for brevity>

Notice the messages package. Currently it only has two classes defined inside of it, BaseMessage (an abstract base class) and FizzMessage (extends BaseMessage). But eventually it will contain hundreds of other classes that are all BaseMessage subclasses.

In my code I have the following:

deviceManager.registerMessage(new FizzMessage())

As I add dozens, possibly hundreds of BaseMessage subclasses to that messages package over time, I would have to add a line of code to "register" each new message type. Subsequently, if I refactor or remove messages I will have to remember to remove their respective line of registration code from above. This will be a pain to manage and I'm wondering if I could just use reflection to scan the messages package for BaseMessage impls, and then subsequently register them:

val messageImpls : Array[T > BaseMessage] = getViaReflection("com.me.myapp.messages")
messageImpls.foreach { msgImpl =>
  deviceManager.registerMessage(msgImpl)
}

Any ideas as to how I could accomplish this?

smeeb
  • 27,777
  • 57
  • 250
  • 447
  • 1
    Possible duplicate of [Can you find all classes in a package using reflection?](http://stackoverflow.com/questions/520328/can-you-find-all-classes-in-a-package-using-reflection) – Jasper-M Mar 20 '17 at 18:39
  • Thanks @Jasper-M (+1) I know how to do this in java, my question is more about whether Scala offers any syntactic sugar/APIs here. – smeeb Mar 20 '17 at 19:01
  • @smeeb does `classLoader` of Scala's [getClass](https://alvinalexander.com/scala/how-to-determine-class-of-scala-object-getclass-method/) offer enough syntactic sugar for you? – ecoe Apr 21 '21 at 02:32

1 Answers1

-1

If you're able to access the classes of interest using getResources then you can filter through those results, even recursing children directories (not shown here):

def getClasses(packageName: String) = {
    val classLoader = getClass.getClassLoader
    val path = packageName.replace('.', '/')
    val resources: util.Enumeration[URL] = classLoader.getResources(path)

    Iterator.continually((resources, resources.nextElement))
      .takeWhile(_._1.hasMoreElements)
      .map{ case (_, resource: URL) =>
        new File(resource.getFile)
          .listFiles
          .withFilter(_.getName.endsWith(".class"))
          .map{ file =>
            Class.forName(packageName + '.' + file.getName.dropRight(6))
          }
      }
  }
ecoe
  • 4,994
  • 7
  • 54
  • 72