1

I have a javafx window, and when I drag .class files into it I would like to "transform" them into Class<?>

I tried with Class.forname the problem is that you have to know the package, which is not my case. And I tried to read the .class file with a buffered reader to retrieve the package inside but of course it is not possible to read a .class file.

So I need to find a way to transform any .class file regardless of its location on the computer into Class<?> in my code.

@Override
    public void handle(DragEvent event) {
        Dragboard db = event.getDragboard();
        boolean success = false;
        if (db.hasFiles()) {
            for (File file : db.getFiles()) {
                String fileName = file.getName();
                // Vérifiez si le fichier a l'extension .class
                if (fileName.endsWith(".class")) {

                    //TODO
                    
                    //GlobalView.getInstance().addClassNode(new ClassNode(new Class(  the Class<?> object    )));

                }
            }
        }
        event.setDropCompleted(success);
        event.consume();
    }
  • 4
    "of course it is not possible to read a .class file" - why of course? The Java Class File Format is [well specified](https://docs.oracle.com/javase/specs/jvms/se17/html/jvms-4.html) – Johannes Kuhn Jan 03 '23 at 10:11
  • 2
    Have a look at this, maybe it helps already to at least get you started: https://stackoverflow.com/questions/6219829/method-to-dynamically-load-java-class-files – Thomas Jan 03 '23 at 10:15
  • 1
    One thing to note: If you plan on actually loading the class so that you can get an instance of `java.lang.Class`, then any other class files that the given class file depends on must also be loadable. Otherwise, you'll end up with a `ClassNotFoundException` or something similar. – Slaw Jan 03 '23 at 10:40
  • 1
    Another note: you should keep in mind that loading any user-provided code is a security risk so make sure that either the user is trusted, the application doesn't affect other systems (e.g. communicate with a server), and/or you sanitize and check the code (might be hard to do though). – Thomas Jan 03 '23 at 10:46
  • 6
    Seems like an XY problem. What do you plan to *do* with the instance of Class once you have it? i.e. what does `addClassNode` actually do? – Michael Jan 03 '23 at 10:55
  • The goal is to create a class diagram generator in javafx. When a person drags a .class file it generates a rectangle with its name, fields, methods... – Leonarddoo Campione Jan 03 '23 at 16:50
  • @LeonarddooCampione Then you shouldn't actually need to load the class. Perhaps you can provide an alternative ClassNode implementation that works with a BCEL JavaClass (as shown in my answer) instead of a java.lang.Class. The JavaClass instance has all the information about fields and methods without actually loading it. – Michael Jan 03 '23 at 17:20
  • @Michael Actually I think that's what I'm going to do. I thank you very much – Leonarddoo Campione Jan 04 '23 at 08:56

1 Answers1

5

One of your problems is that you don't know the package of the class, and you can't reasonably determine it from the filepath.

You can use Apache Commons BCEL to parse the file in order to get the package, as well as plenty of other information about it.

String path = "/path/to/com/example/MyClass.class";
// org.apache.bcel.classfile.JavaClass and org.apache.bcel.classfile.ClassParser
JavaClass clazz = new ClassParser(path).parse();
String className = clazz.getClassName(); // com.example.MyClass

From there, you can use a URLClassLoader to actually load the class by name, provided all the dependencies of that Class are loaded or loadable:

String dir = Paths.get(path).getParent().toString() + '/';
URLClassLoader loader = new URLClassLoader(
    new URL[]{ new URL("file://" + dir) },
    getClass().getClassLoader()
);
Class<?> myClass = loader.loadClass(className);

If the dependencies of the class are not loadable then you'll need to rethink your approach. It's impossible to load a class without its dependencies, and as the user is just dragging and dropping a file, that file may depend on classes that you have no reasonable way of finding.

It may well be the case that the JavaClass instance returned by BCEL already contains all the information you need, and that you don't actually need to load the class at all. You haven't been specific enough about what you're using the Class instance for, so I can't say for certain.

Michael
  • 41,989
  • 11
  • 82
  • 128