Fix Plugin dynamic injection

This commit is contained in:
SiboVG 2024-02-27 02:53:28 +01:00
parent 84a897525f
commit 46849e14e1
10 changed files with 18 additions and 87 deletions

View File

@ -56,8 +56,8 @@ subprojects {
}
}
// Common dependencies
dependencies {
// Common dependencies
testImplementation group: 'org.hamcrest', name: 'hamcrest', version: '2.2'
testImplementation group: 'org.hamcrest', name: 'hamcrest-core', version: '2.2'
testImplementation group: 'org.hamcrest', name: 'hamcrest-library', version: '2.2'

View File

@ -33,7 +33,6 @@ checkstyle {
extraJavaModuleInfo {
failOnMissingModuleInfo.set(false)
module('obj-0.4.0.jar', 'de.javagl.obj', '0.4.0')
module('annotation-detector-3.0.5.jar', 'eu.infomas.annotation.detector', '3.0.5')
}
dependencies {
@ -44,7 +43,6 @@ dependencies {
implementation group: 'org.apache.commons', name: 'commons-lang3', version: '3.8.1' // 3.12.0
implementation group: 'com.google.inject', name: 'guice', version: '7.0.0'
implementation group: 'com.opencsv', name: 'opencsv', version: '5.7.1'
implementation group: 'eu.infomas', name: 'annotation-detector', version: '3.0.5'
implementation group: 'org.graalvm.sdk', name: 'graal-sdk', version: '23.0.3'
implementation group: 'org.graalvm.js', name: 'js-scriptengine', version: '23.0.3'
implementation group: 'org.graalvm.js', name: 'js', version: '23.0.3'
@ -53,6 +51,7 @@ dependencies {
implementation group: 'com.ibm.icu', name: 'icu4j', version: '71.1' // 72.1
implementation group: 'com.sun.istack', name: 'istack-commons-tools', version: '4.1.1' // TODO: Should be gotten rid of?
implementation group: 'com.sun.istack', name: 'istack-commons-runtime', version: '4.1.1' // TODO: Should be gotten rid of?
implementation group: 'io.github.classgraph', name: 'classgraph', version: '4.8.165'
implementation 'de.javagl:obj:0.4.0'

View File

@ -1,5 +1,6 @@
package info.openrocket.core.plugin;
import java.lang.annotation.Annotation;
import java.util.List;
/**
@ -11,6 +12,6 @@ public interface AnnotationFinder {
* Return a list of all types (classes and interfaces) that are annotated
* with the provided annotation.
*/
public List<Class<?>> findAnnotatedTypes(Class<?> annotation);
public List<Class<?>> findAnnotatedTypes(Class<? extends Annotation> annotation);
}

View File

@ -1,19 +1,11 @@
package info.openrocket.core.plugin;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import info.openrocket.core.util.BugException;
import info.openrocket.core.util.JarUtil;
import eu.infomas.annotation.AnnotationDetector;
import eu.infomas.annotation.AnnotationDetector.TypeReporter;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ScanResult;
/**
* An AnnotationFinder that uses annotation-detector library to scan
@ -22,69 +14,11 @@ import eu.infomas.annotation.AnnotationDetector.TypeReporter;
public class AnnotationFinderImpl implements AnnotationFinder {
@Override
public List<Class<?>> findAnnotatedTypes(Class<?> annotation) {
final List<Class<?>> classes = new ArrayList<Class<?>>();
TypeReporter reporter = new ListReporter(classes);
final AnnotationDetector cf = new AnnotationDetector(reporter);
try {
ClassLoader loader = this.getClass().getClassLoader();
if (loader instanceof URLClassLoader) {
/*
* In case of URLClassLoader (which may be our own instantiation)
* use the URLs from there, as java.class.path may not be up-to-date.
*/
URLClassLoader urlClassLoader = (URLClassLoader) loader;
URL[] urls = urlClassLoader.getURLs();
List<File> files = new ArrayList<File>();
for (URL url : urls) {
if (url.getProtocol().equals("file")) {
files.add(JarUtil.urlToFile(url));
}
}
cf.detect(files.toArray(new File[0]));
} else {
/*
* If not using a URLClassLoader, just do the default.
*/
cf.detect();
}
} catch (IOException e) {
throw new BugException("Unable to search class path", e);
public List<Class<?>> findAnnotatedTypes(Class<? extends Annotation> annotation) {
List<Class<?>> classes;
try (ScanResult scanResult = new ClassGraph().enableAllInfo().scan()) {
classes = new ArrayList<>(scanResult.getClassesWithAnnotation(annotation.getName()).loadClasses());
}
return classes;
}
private static class ListReporter implements TypeReporter {
private final List<Class<?>> classes;
private final Set<String> names = new HashSet<String>();
public ListReporter(List<Class<?>> classes) {
this.classes = classes;
}
@SuppressWarnings("unchecked")
@Override
public Class<? extends Annotation>[] annotations() {
return new Class[] { Plugin.class };
}
@Override
public void reportTypeAnnotation(Class<? extends Annotation> annotation, String className) {
if (names.add(className)) {
try {
classes.add(this.getClass().getClassLoader().loadClass(className));
} catch (ClassNotFoundException e) {
// Ignore
}
}
}
}
}

View File

@ -17,15 +17,14 @@ import com.google.inject.multibindings.Multibinder;
*/
public class PluginModule extends AbstractModule {
private final Map<Class<?>, Multibinder<?>> binders = new HashMap<Class<?>, Multibinder<?>>();
private final Map<Class<?>, Multibinder<?>> binders = new HashMap<>();
private final AnnotationFinder finder = new AnnotationFinderImpl();
@SuppressWarnings("unchecked")
@Override
protected void configure() {
List<Class<?>> classes = finder.findAnnotatedTypes(Plugin.class);
List<Class<?>> interfaces = new ArrayList<Class<?>>();
List<Class<?>> interfaces = new ArrayList<>();
List<Class<?>> unusedInterfaces;
// Find plugin interfaces
@ -34,7 +33,7 @@ public class PluginModule extends AbstractModule {
interfaces.add(c);
}
}
unusedInterfaces = new ArrayList<Class<?>>(interfaces);
unusedInterfaces = new ArrayList<>(interfaces);
// Find plugin implementations
for (Class<?> c : classes) {

View File

@ -20,7 +20,7 @@ open module openrocket.core {
requires jakarta.inject;
requires java.prefs;
requires java.xml.bind;
requires transitive eu.infomas.annotation.detector;
requires io.github.classgraph;
requires java.json;
requires org.slf4j;
requires com.opencsv;

View File

@ -6,8 +6,10 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import java.util.prefs.BackingStoreException;
import com.google.inject.multibindings.Multibinder;
import info.openrocket.core.formatting.RocketDescriptor;
import info.openrocket.core.formatting.RocketDescriptorImpl;
import info.openrocket.core.formatting.RocketSubstitutor;
import info.openrocket.core.l10n.DebugTranslator;
import info.openrocket.core.l10n.ResourceBundleTranslator;
import info.openrocket.core.l10n.Translator;

View File

@ -63,14 +63,12 @@ extraJavaModuleInfo {
exportAllPackages()
}
module('annotation-detector-3.0.5.jar', 'eu.infomas.annotation.detector', '3.0.5')
module('obj-0.4.0.jar', 'de.javagl.obj', '0.4.0')
}
dependencies {
implementation project(':core')
implementation group: 'eu.infomas', name: 'annotation-detector', version: '3.0.5'
implementation 'de.javagl:obj:0.4.0'
implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.12'

View File

@ -80,7 +80,8 @@ public class AboutDialog extends JDialog {
"Darklaf (dark theme)" + href("https://github.com/weisJ/darklaf", true, true) + "<br>" +
"jSystemThemeDetector" + href("https://github.com/Dansoftowner/jSystemThemeDetector", true, true) + "<br>" +
"Obj" + href("https://github.com/javagl/Obj", true, true) + "<br>" +
"<br>" +
"ClassGraph" + href("https://github.com/classgraph/classgraph", true, true) + "<br>" +
"<br>" +
"<b>OpenRocket gratefully acknowledges our use of the following databases:</b><br>" +
"<br>" +
"Rocket Motor Data" + href("https://www.thrustcurve.org", true, true) + "<br>" +

View File

@ -53,9 +53,6 @@ public class GuiModule extends AbstractModule {
bind(Translator.class).toProvider(TranslatorProvider.class).in(Scopes.SINGLETON);
bind(RocketDescriptor.class).to(RocketDescriptorImpl.class).in(Scopes.SINGLETON);
bind(WatchService.class).to(WatchServiceImpl.class).in(Scopes.SINGLETON);
// Setup for Set<RocketSubstitutor>
Multibinder.newSetBinder(binder(), RocketSubstitutor.class);
BlockingComponentPresetDatabaseProvider componentDatabaseProvider = new BlockingComponentPresetDatabaseProvider(presetLoader);
bind(ComponentPresetDao.class).toProvider(componentDatabaseProvider).in(Scopes.SINGLETON);