views:

58

answers:

1

Hallo everybody, I got a question: I have written a Java program that implements a STAF service (just a framework for testing, http://staf.sourceforge.net/). For STAF, all my Classes have to be in an Directory STAF-INF/classes. So I packed my program to an JAR-file MyProg.jar, that looks like this:

MyProg.jar

--> STAF-INF/

-------> classes/

------------> com/

----------------->/MyClass.class

----------------->/IInterface.class

---> META-INF/

So, my JAR-Archiv got two directories, one called META-INF and called STAF-INF. In STAF-INF, there is another directory called classes, and in classes there is my package "com" that contains my class and my interface. that's the situation. this thing works very good, andthe directory structure is required by the STAF framework I use.

Now, here comes the problem: I want that other users can take my JAR-file (MyProg.jar) and include it to there own project to write classes that implements my interface IInterface.

Problem 1) When I add the MyProg.jar file to a Eclipse-Java-Project it don't find the IInterface. If even don't find any package in the JAR-file. I think that gots something to do with the directories (STAF-INF/classes)???

Problem 2) When I connect my new project in Eclipse, with my old MyProg-project, Eclipse finds the IInterface and I can implement it (this could be a workaround for problem 1, but:). Then I export my new class as a JAR-file, let's call it NewClassForMyProg.jar. But when I load the new class out of the NewClassForMyProg.jar in my MyProg-program I got an exception:

NoClassDefFoundError: com.IInterface

I think this got something to do with my directories, too. but i am not sure. I think it could be a problem with the URLClassLoader or the ClassPath, too... but i have no idea...

please help. thanx.

edit:

here's the code of the method that should load the classes:

    public static ArrayList<IInterface> getExternalWorkloads(String jarName, String packageName)
{
    jarName = "c:/STAF/services/NewClassForMyProg.jar";
    packageName = "com";

    packageName = packageName.replaceAll("\\." , "/");

    ArrayList<IInterface> myClasses = new ArrayList<IInterface>();

    JarInputStream jarFile = null;
    JarEntry jarEntry = null;

    try
    {
        jarFile = new JarInputStream(new FileInputStream (jarName));

        while(true) 
        {
            jarEntry=jarFile.getNextJarEntry();

            if(jarEntry == null)
                 break;

            if((jarEntry.getName ().startsWith (packageName)) &&
               (jarEntry.getName ().endsWith (".class"))) 
            {
                String classname = jarEntry.getName().replaceAll("/", "\\.");

                classname = classname.substring(0, classname.length() - 6);

                if(classname.contains("$") == false)
                {
                    ClassLoader.getSystemClassLoader();
                    URL url = new URL("jar:file:" + jarName + "!/");

                    URLClassLoader ucl = new URLClassLoader(new URL[] { url });

                        try
                        {
                            Class<IInterface> myLoadedClass = (Class<IInterface>) ucl.loadClass(classname);

                            IInterface myClass = (IInterface) myLoadedClass.newInstance();
                            myClasses.add(myClass);
                        }
                        catch(Exception e){}
                }
            }
        }

        jarFile.close();
   }
   catch(Exception e){}

   return myClasses;
}

Oh, and if I load with that method a class, that is inside my own JAR (MyProg.jar) it works perfect. But by a other JAR (like NewClassForMyProg.jar") I get an Error. But the method founds the classes, the problem is to make a new instance and cast it to IInterface...

A: 

problem solved! I haven't used the correct classloader.

                            ClassLoader STAFLoader = MyCurrentClass.class.getClassLoader();

                            URLClassLoader URLLoader = new URLClassLoader(jarUrl, STAFLoader);

                            Class iInterfaceClass = Class.forName(classname, true, URLLoader);

the fist line solved the problem.