2016-08-12 2 views
0

Это мой первый дизайн API. У меня есть программа с папками 'plugins'. Я сделал тестовый плагин в этой папке, упакованной в JAR. В программе у меня есть класс Groovy «Конфигурация», который должен загружать плагины.Проектирование API - проблемы с загрузкой классов (Groovy)

Configuration.java:

static void processConfiguration() 
{ 
     File pluginDirectory=new File(PLUGINDIRECTORY)//it's 'plugins' 
     if(!pluginDirectory.exists()) pluginDirectory.mkdir() 
     File[] pluginfiles=pluginDirectory.listFiles() 

     for(File f:pluginfiles) 
     { 
      if(f.name.endsWith('.jar')) 
      { 
       JarFile jar=new JarFile(f) 

       for(JarEntry jarEntry:jar.entries()) 
       { 
        if(jarEntry.getName().endsWith('.class')) 
        { 
         //try loading the class 
        } 
       } 


      } 
     } 
} 

Итак, я попытался сделать это в //try loading the class блоке

Class cl=ClassLoader.getSystemClassLoader().loadClass(jarEntry.name)

Class cl=new GroovyClassLoader().loadClass(jarEntry.name)

Class cl=Configuration.classLoader.loadClass(jarEntry.name)

Class cl=Class.forName(jarEntry.getName())

также пытался с заменой - jarEntry.name.replaceAll('/','.').replace('.class',''), но я думаю, что все делается автоматически. Получение класса не найдено исключение:

Exception in Application start method 
java.lang.reflect.InvocationTargetException 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389) 
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:498) 
    at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767) 
Caused by: java.lang.RuntimeException: Exception in Application start method 
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: java.lang.ClassNotFoundException: jace/plugins/JavaPlugin.class 
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424) 
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331) 
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357) 
    at java_lang_ClassLoader$loadClass.call(Unknown Source) 
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48) 
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113) 
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) 
    at jace.Configuration.processConfiguration(Configuration.groovy:87) 
    at jace.Jace.start(Jace.java:56) 
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863) 
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326) 
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295) 
    at java.security.AccessController.doPrivileged(Native Method) 
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294) 
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) 
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) 
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139) 
+0

Вы пробовали 'Class cl = this.getClass(). ClassLoader.loadClass (name)'? – injecteer

+0

'jarEntry.name.replaceAll ('/', '.'). Replace ('. Class', '')' недопустимый синтаксис и нет, это не делается автоматически (по крайней мере, не с 'Class.forName'), как вы можете видеть в сообщении об ошибке: 'java.lang.ClassNotFoundException: jace/plugins/JavaPlugin.class'. Должно быть 'jarEntry.getName(). Replace ('/', '.'). ReplaceAll (" \\. Class $ "," ")'. Кстати: вы считали использовать «ServiceLoader»? https://docs.oracle.com/javase/tutorial/ext/basics/spi.html – fabian

ответ

1

После некоторых поисков и мастерить я, наконец, разрешили его.

Во-первых, вам необходимо создать список правильных URL-адресов;

Во-вторых, составить список классов из банки;

В-третьих, создайте экземпляр GroovyClassLoader и дайте ему все URL-адреса;

В-четвертых, загрузите классы из списка, проверьте, реализуют ли они интерфейсы плагина, а затем создайте их.

static void processConfiguration() 
{ 
    File pluginDirectory=new File(PLUGINDIRECTORY) 
    if(!pluginDirectory.exists()) pluginDirectory.mkdir() 
    File[] pluginfiles=pluginDirectory.listFiles() 
    URL[] urls=[] 
    ArrayList<String> classes=new ArrayList<>() 
    for(File f:pluginfiles) 
     { 
      if(f.name.endsWith('.jar')) 
      { 
       JarFile jar=new JarFile(f) 
       URL url=new URL('jar:file:'+PLUGINDIRECTORY+'/'+f.name+'!/') 
       urls+=url 
       jar.entries().each {if(it.name.endsWith('.class'))classes.add(it.name) } 
      } 
     } 

//  println(gcl.loadedClasses) 
     GroovyClassLoader groovyClassLoader=new GroovyClassLoader() 
     urls.each {groovyClassLoader.addURL(it)} 
//  println(classes) 
     classes.each { 
      Class cl=groovyClassLoader.loadClass(it.replaceAll('/','.').replace('.class','')) 
      Class[] interfaces=cl.getInterfaces() 
      if(interfaces.contains(Plugin.class)) 
      { 
       Object instance=cl.newInstance() 
       if(interfaces.contains(SuggestionPlugin.class)) 
       { 
        SuggestionProcessor.suggestionPlugins.add(instance as SuggestionPlugin) 
       } 
       Constructor[] constructors=cl.getConstructors() 
       println("Loaded a plugin $cl.simpleName") 
      } 
    } 
} 
Смежные вопросы