-2

I'm implementing an annotation processor that needs all classes that implement an interface.

The main issue is that these classes can be anywhere, so there isn't an easy way to get them.

I cannot edit this classes in any way.

I need to get this classes to generate a Map.

How can I achieve this?

Thanks

kylie.zoltan
  • 377
  • 3
  • 15
  • 1
    If you explain why you need to access all of those classes, we can help you in a better fashion. Also, do you create these classes or someone else uses these classes? Are you able to add some annotations to these classes? – wolfenblut Sep 27 '22 at 19:55
  • an annotation processor needs annotated types to find what it should process, once you have an element, I think you need to get to https://docs.oracle.com/javase/9/docs/api/javax/lang/model/element/TypeElement.html#getInterfaces-- to check what interfaces are implemented and filter – zapl Sep 27 '22 at 19:59
  • @wolfenblut This classes already exist but I cannot edit them in any way. – kylie.zoltan Sep 27 '22 at 20:01
  • @zapl Yes I'm able to get the classes that have an annotation but these ones don't have one, but the ones that have need this ones. – kylie.zoltan Sep 27 '22 at 20:02
  • An annotation processor can't find classes that are not annotated as far as I'm aware. The compiler during compilation provides only those classes that have an annotation you are interested in. Maybe it's the wrong tool for the job. Postprocessing compiled java bytecode (statically or from within a classloader) could work but that gets even more complicated and fragile than annotation processors. Isn't there maybe a simpler solution to the problem you are trying to solve? Maybe cheat by extending those classes and put an annotation on them. – zapl Sep 27 '22 at 20:16
  • 1
    You can’t. You’re not supposed to. Java classes are loaded dynamically, so you can’t ever know “all classes” for any qualification, except service providers. Perhaps you should describe why you believe you need this; there’s probably a better way to accomplish what you want. – VGR Sep 27 '22 at 20:22

1 Answers1

2

Depends on your definition of 'all classes that implement an interface'.

Just the ones that are being compiled right now

This is trickier than it looks like. Compilation is often incremental, meaning, even if you run a build that says 'compile everything', only those source files that actually need to be recompiled (because their source file has a more recent modification timestamp than the class files that spin off from it and it doesn't reference anything from sources that are marked for recompilation). So, 'being compiled right now' is a smaller batch of files than you think.

To do this, it's easy. First, register yourself for the annotation "*", which means, you want to trigger on every source file, annotated or not: @SupportedAnnotationTypes("*").

Next, in your process method, you can ask the RoundEnv for all classes. Go through them, check what interfaces they implement, and process everything that implements what you wanted.

Everything from my project

This is impossible. Classpath as a concept doesn't have a 'list' abstraction, therefore, you can't just 'get everything that implements X'.

What you can do, is spit out a textfile as part of your annotation processing, which lists the source file of everything that is relevant. You can then use the Filer during the final round (where process is called with a roundEnv indicating it is the final one) to read this text file (the classpath does have the concept of 'give me the resource named FOO'), then you ask the filer for each of the source (or class, whatever way you want to go) file and check if they still exist. If yes, then at least you know it hasn't changed at all. If it doesn't, then the programmer deleted it and you should act accordingly.

This is somewhat complicated and I'm not aware of any frameworks. You'll have to build it yourself.

All classes anywhere on any machine anywhere in time or space.

Yeah, well. Not possible, duh.

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72