2011-01-28 11 views
7

Sto lavorando a un plug-in Eclipse che richiede classi non note al momento della compilazione. Le classi vengono inviate in rete in file jar. Mi piacerebbe caricare dinamicamente tali classi in fase di runtime.Aggiunta di jar a un plug-in Eclipse in fase di esecuzione

Ho provato l'approccio elencati qui: http://blog.imaginea.com/making-applications-work-together-in-eclipse/

Purtroppo non ha l'effetto desiderato. Mentre le classi vengono caricate, non posso usarle al di fuori della funzione in cui le ho caricate. Immagino che abbia qualcosa a che fare con l'utilizzo di caricatori di classi diverse.

Qualsiasi aiuto è apprezzato. Anche se me lo dici, non è possibile, quindi so che non devo guardare oltre.

risposta

5

Se si commette quei vasi in fasci OSGi (vale a dire, dare loro un MANIFEST.MF) allora si può installarli dinamicamente nel runtime OSGi.

Se si aggiunge un attivatore fascio per il vostro plugin, allora è possibile memorizzare l'org.osgi.framework.BundleContext e allora si può fare:

Bundle [] newBundle = new Bundle[] { bundleContext.install(location, newJarInputStream) }; 
    packageAdmin.refreshPackages(newBundle); 
    packageAdmin.resolveBundles(newBundle); 

packageAdmin è un'istanza di org.osgi.service. packageAdmin.PackageAdmin che è un servizio che è possibile acquisire con BundleContext#getService

I nuovi jar possono essere interi bundle a sé stanti oppure possono anche essere frammenti di bundle con il proprio plug-in come host. Se si tratta di frammenti del pacchetto, sarà necessario includere il gruppo (BundleContext#getBundle()) nell'array passato a refreshPackages e resolveBundles.

(caricamento classe EDIT) Class.forName dal codice del plug-in troverà solo le classi nei bundle appena installati se il plug-in ha dipendenze che saranno soddisfatte dai nuovi bundle una volta risolti.

  • Un modo per farlo sarebbe un Import-Package opzionale nel manifest del proprio plugin. In questo caso il plug-in dovrà essere incluso nell'array passato a refreshPackages.
  • Un'altra opzione consiste nell'utilizzare una dichiarazione DynamicImport-Package nel manifest del proprio plugin. Le importazioni dinamiche vengono risolte durante il caricamento della classe

Un'altra opzione è utilizzare Bundle.loadClass (anziché Class.forName) sugli oggetti bundle per i pacchetti appena installati. Questo usa il classloader del nuovo bundle in modo che il tuo stesso plugin non abbia bisogno di avere una dipendenza dai nuovi bundle.

+0

Questo suona come il modo giusto per farlo (+1) –

+0

Grazie. Sembra un buon approccio. Ho ancora qualche problema, però. Sono riuscito a caricare il pacchetto. Class.forName ("MyClass") tuttavia genera ancora un'eccezione ClassNotFound. Ho specificato il pacchetto, che contiene la classe nella dichiarazione di esportazione del manifest – Maria

+0

Ho modificato la risposta originale con ulteriori dettagli sul caricamento delle classi una volta installati i pacchetti. –

1

Recentemente ho fatto questo per un plugin per Eclipse:

Ecco il codice saliente

URL[] urls = new URL[]{ new URL("jar", "", "file:" + jarFile.getAbsolutePath() + "!/")}; 
URLClassLoader cl = URLClassLoader.newInstance(urls, this.getClass().getClassLoader()); 
Class<?> loadedClass = cl.loadClass("com.whatever.SomeClass"); 
Problemi correlati