DZone Forums
Go Back   DZone Forums > Community > Tools & IDEs > Eclipse
Reload this Page problem with classloader from plugin
Notices
Reply
 
LinkBack Thread Tools Display Modes
  (#1 (permalink)) Old
Member
 
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Exclamation problem with classloader from plugin - 02-08-2008, 04:39 AM

I am writing a Builder plugin. I need to be able to read a text file within the runtime project, extract a package name and class name and then create an Object for that Class, and call a method with that object. The class may be in the runtime project that is being build, or in a dependent project within the runtime workspace, or in a jar file which may be external to the workspace. eg it can be anywhere that can be see from the project being built. I have be able to use JacaCore to find and verify that the class exists and is the correct form (it has the required superclass). But have been unable to load the class file. I have been unable to find anything within the JavaModel that will allow loading and executing the class. So have tried to use Class.forName("com.example.Test") but get ClassNotFoundException unless the class is within the plugin, or in a jar that is stored within the plugin project and the jar is exported. I have tried setting the Eclipse-BuddyPolicy to various values (I think 'app' is the correct value). Can someone please point me in the right direction to solve this issue.
Thanks in advance
Nev
Reply With Quote
  (#2 (permalink)) Old
Member
 
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 05:22 AM

Class.forName will use the ClassLoader which belongs to your plugin, so this is not the way to go. Since the classloaders are managed by equinox, you should direct your search this way.

I found an eclipsezone thread, where somebody recommends using Platform.getBundle("bundle.id").loadClass("classNa me")

Good luck!
Tomas
Reply With Quote
  (#3 (permalink)) Old
Member
 
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 07:12 AM

Quote:
Originally Posted by kremso View Post
Class.forName will use the ClassLoader which belongs to your plugin, so this is not the way to go. Since the classloaders are managed by equinox, you should direct your search this way.

I found an eclipsezone thread, where somebody recommends using Platform.getBundle("bundle.id").loadClass("classNa me")

Good luck!
Tomas
Thanks for quick response but I get the same result. The Platform.getBundle("bundle.id") part return a value, but the loadClass(className) cause a ClassNotFound Exception. The class I need to load is NOT within my plugin, nor is it in another plugin. But it is a jar file visible to the runtime (not the plugin's) project.
Nev
Reply With Quote
  (#4 (permalink)) Old
Member
 
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 07:27 AM

Did you try ClassLoader.getSystemClassLoader.loadClass() ?
Reply With Quote
  (#5 (permalink)) Old
Member
 
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 02:55 PM

Quote:
Originally Posted by kremso View Post
Did you try ClassLoader.getSystemClassLoader.loadClass() ?
I have just tried this, but with the same result. It works if placed within the target project, bug fails when placed within the plugin. I need someway of getting the ClassLoader of the target project. Does the target project have a "bundle.id" if so how do you find it?
Thanks for the attempt.
Nev
Reply With Quote
  (#6 (permalink)) Old
Member
 
Posts: 8
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 07:23 PM

I am sorry, but I don't know the correct answer. You should ask on equinox mailing list, I think you could get more help there. However, the instructions on their page suggest asking on the newsgroup first.
Reply With Quote
  (#7 (permalink)) Old
Member
 
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 09:03 PM

Thanks for your help will try the equinox group.
Nev
Reply With Quote
  (#8 (permalink)) Old
Member
 
Posts: 5
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Feb 2008
Default 02-08-2008, 09:59 PM

I have found a solution. Dont know if it is the "Eclipse way" but it appears to work.
I have written my own ClassLoader, based on ideas from book "Eclipse Building Commercial Quality Plug-ins" Chap 20.9 Plug-in ClassLoaders. My loader is as follows

package mypackage.loader;

import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

public class MyClassLoader extends ClassLoader
{
private IJavaProject javaProject;

public MyClassLoader(IJavaProject project)
{
super();
if (project == null || !project.exists() || !project.isOpen())
throw new IllegalArgumentException("Invalid javaProject");
this.javaProject = project;
}

public MyClassLoader(IJavaProject project, ClassLoader classLoader)
{
super(classLoader);
if (project == null || !project.exists() || !project.isOpen())
throw new IllegalArgumentException("Invalid javaProject");
this.javaProject = project;
}

@Override
protected Class findClass(String className) throws ClassNotFoundException
{
IClassFile classFile = null;
try
{
final IPackageFragment fragment = javaProject.findType(className).getPackageFragment ();
classFile = fragment.getClassFile(className.substring(classNam e.lastIndexOf('.') + 1) + ".class");
final byte[] buff = classFile.getBytes();
if (buff == null)
throw new ClassNotFoundException(className);
return defineClass(className, buff, 0, buff.length);
}
catch (JavaModelException e)
{
throw new ClassNotFoundException(className);
}
}
}
Reply With Quote
  (#9 (permalink)) Old
Member
 
Posts: 2
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Sep 2008
Default Java Modell Exception - 09-12-2008, 09:27 AM

Hi nev.clark,

Your solution didn't work for me.
It gives me the Java Model Exception [code368] with the Explanation that the resource doesn't exist on this line:
Code:
classFile = fragment.getClassFile(className.substring(className
					.lastIndexOf('.') + 1)
					+ ".class");
The interesting is, that the project resource is not the full path of my eclipse project, but beginns with "/" and than follows immediatly the name of the project. I think it should show the full path /home/username/eclipse-workspase/Project Name/all../packages../ClassName.class But it doesn't.

Can you please write me, how do you extract the IJavaProject-object from the ISelection in order to call the loadClass()-Method from your own ClassLoader-class?


Does anyone know a solution for this problem?

Last edited by goga_ruler; 09-12-2008 at 09:47 AM.
Reply With Quote
  (#10 (permalink)) Old
Member
 
Posts: 1
Thanks: 0
Thanked 0 Times in 0 Posts
Join Date: Sep 2008
Default More simpler and easy way to load the third party classes. - 09-30-2008, 02:54 PM

Quote:
Originally Posted by goga_ruler View Post
Hi nev.clark,

Your solution didn't work for me.
It gives me the Java Model Exception [code368] with the Explanation that the resource doesn't exist on this line:
Code:
classFile = fragment.getClassFile(className.substring(className
					.lastIndexOf('.') + 1)
					+ ".class");
The interesting is, that the project resource is not the full path of my eclipse project, but beginns with "/" and than follows immediatly the name of the project. I think it should show the full path /home/username/eclipse-workspase/Project Name/all../packages../ClassName.class But it doesn't.

Can you please write me, how do you extract the IJavaProject-object from the ISelection in order to call the loadClass()-Method from your own ClassLoader-class?


Does anyone know a solution for this problem?
Bing found:

Third party libraries and classloading
Because OSGi makes use of multiple classloaders, the transparent usage of extensible / configurable third party libraries in eclipse requires the usage of an eclipse specific mechanism called "buddy loading". This mechanism allows a bundle to indicate that it needs assistance to load classes or resources when it can not find them among its prerequisites. Note that we call "extensible libraries", libraries that needs to see classes or resources provided by user code (for example log4j logger mechanism, hibernate,...).

To indicate its need for buddy loading, a bundle must modify its manifest and add the following header:

Eclipse-BuddyPolicy: <value>

<value> refers to the policy used to look for the classes. Here are the supported policies:

* registered - indicates that the buddy mechanism will consult bundles that have been registered to it. Bundle willing to be registered to a particular bundle add in their manifest: "Eclipse-RegisterBuddy: <bundleSymbolicName>";
* dependent - indicates that the classes/resources will be looked up transitively in all the dependent of the bundle;
* global - indicates that the classes/resources will be looked up in the global pool of exported package;
* app - indicates that the application classloader will be consulted;
* ext - indicates that the extensiont classloader will be consulted;
* boot - indicates that the boot classloader will be consulted.
Reply With Quote
Reply

Tags
builder, classloader, external, plugin

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Problem installing plugin over local update site zmajmatic Eclipse 0 10-19-2008 01:27 PM
Plugin SearchEngine problem oziransky Eclipse 0 09-17-2008 01:05 PM
rcp plugin dependency on non-plugin project Shefali23 Eclipse 1 07-24-2008 06:06 AM
Problem in creating plugin for RCP workdesk03 Eclipse 0 07-22-2008 04:42 AM


Copyright 1997-2009, DZone, Inc.
vBulletin Skin developed by: vBStyles.com