OS-dependent library loading

Started by Spezi, January 14, 2007, 17:20:21

Previous topic - Next topic

cornholio

i sent you a mail explaining what to do...

cornholio

here is a new version of my CustomClassLoader. now it recursively adds JARs or folders
to the classpath which have been defined in manifest-files (MANIFEST.MF). hope you
understand what i'm talking about...

spezi: this should work with the test-case you sent me by email...

package foo;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.LinkedList;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.jar.Attributes.Name;

public class CustomClassLoader extends URLClassLoader {

	private static final int OS_TYPE_LINUX = 1;

	private static final int OS_TYPE_MACOSX = 2;

	private static final int OS_TYPE_WINDOWS = 3;

	private static final int OS_TYPE;

	static {

		String osName = System.getProperty("os.name");

		if (osName.startsWith("Windows")) {
			OS_TYPE = OS_TYPE_WINDOWS;
		} else if (osName.startsWith("Linux") || osName.startsWith("FreeBSD") || osName.startsWith("SunOS")) {
			OS_TYPE = OS_TYPE_LINUX;
		} else if (osName.startsWith("Mac OS X")) {
			OS_TYPE = OS_TYPE_MACOSX;
		} else {
			throw new LinkageError("Unknown platform: " + osName);
		}
	}

	public CustomClassLoader(ClassLoader parent) {
		super(buildClasspath(), null);
	}

	public static final URL[] buildClasspath() {

		LinkedList urls = new LinkedList();

		String[] tk = System.getProperty("java.class.path").split(File.pathSeparator);

		try {

			buildClasspath(urls, tk);

		} catch (IOException e) {
			throw new RuntimeException("buildClasspath() error: " + e.getMessage());
		}

		URL[] urlArray = new URL[urls.size()];
		for (int i = 0; i < urls.size(); i++)
			urlArray[i] = (URL) urls.get(i);

		return urlArray;
	}

	public static final void buildClasspath(LinkedList urls, String[] tk) throws IOException {

		for (int i = 0; i < tk.length; i++) {

			boolean isJar = (tk[i].toLowerCase().endsWith(".jar") || tk[i].toLowerCase().endsWith(".zip"));

			if (isJar) {

				File jarFile = new File(tk[i]);
				if (jarFile.exists()) {

					tk[i] = jarFile.getAbsolutePath();

					JarFile jar = new JarFile(tk[i]);
					if (jar != null) {

						Manifest jarMf = jar.getManifest();
						if (jarMf != null) {

							Attributes jarAttr = jarMf.getMainAttributes();
							if (jarAttr != null) {

								String jarCp = jarAttr.getValue(Name.CLASS_PATH);
								if (jarCp != null)
									buildClasspath(urls, jarCp.split("\\s+"));
							}
						}
					}

					urls.add(new URL("file", "localhost", tk[i]));
				}

			} else
				urls.add(new URL("file", "localhost", tk[i] + "/"));
		}
	}

	protected String findLibrary(String libName) {

		String[] libPaths = getLibraryPaths();
		String[] libNames = getLibraryNames(libName);
		for (int p = 0; p < libPaths.length; p++) {
			for (int n = 0; n < libNames.length; n++) {
				File libFile = new File(libPaths[p], libNames[n]);
				if (libFile.isFile())
					return libFile.getAbsolutePath();
			}
		}

		return super.findLibrary(libName);
	}

	public static final String[] getLibraryNames(String libName) {

		switch (OS_TYPE) {
		case OS_TYPE_LINUX:
			return new String[] { "lib" + libName + ".so" };
		case OS_TYPE_MACOSX:
			return new String[] { "lib" + libName + ".dylib", "lib" + libName + ".jnilib" };
		case OS_TYPE_WINDOWS:
			return new String[] { libName + ".dll" };
		default:
			throw new LinkageError("Unknown platform: " + System.getProperty("os.name"));
		}
	}

	public static final String[] getLibraryPaths() {

		switch (OS_TYPE) {
		case OS_TYPE_LINUX:
			return new String[] { "lib/linux" };
		case OS_TYPE_MACOSX:
			return new String[] { "lib/macosx" };
		case OS_TYPE_WINDOWS:
			return new String[] { "lib/windows" };
		default:
			throw new LinkageError("Unknown platform: " + System.getProperty("os.name"));
		}
	}

}

Spezi

OK, the test case is running fine but now I stumble on the next problem: the ResourceBundle can't be found. :-\

Exception in thread "main" java.util.MissingResourceException: Can't find bundle for base name game.lang.Language, locale de
   at java.util.ResourceBundle.throwMissingResourceException(Unknown Source)
   at java.util.ResourceBundle.getBundleImpl(Unknown Source)
   at java.util.ResourceBundle.getBundle(Unknown Source)
   at game.lang.Language.getResourceBundle(Language.java:33)

I'm sure I have to add something to the manifest but don't know what.
I feel so stupid. ;D
Ich bin, ich weiß nicht wer.
Ich komme, ich weiß nicht woher.
Ich gehe, ich weiß nicht wohin.
Mich wundert, dass ich so fröhlich bin.

cornholio

just add the ResourceBundle ( game.lang.Language_de.properties or whatever ) to your Game.jar

here is an excellent free online-book for german java-developers:
http://www.galileocomputing.de/openbook/javainsel6/


Spezi

Quote from: cornholio on February 02, 2007, 00:20:31
just add the ResourceBundle ( game.lang.Language_de.properties or whatever ) to your Game.jar

But it's already in there.
The Exception is thrown just about 12 seconds after launching the game. During this time nothing else appears and CPU or HD aren't used intensely.
And as before, everything runs fine starting from eclipse.
Ich bin, ich weiß nicht wer.
Ich komme, ich weiß nicht woher.
Ich gehe, ich weiß nicht wohin.
Mich wundert, dass ich so fröhlich bin.

Shadowritter

Hello I'm bringing back this topic cause I'm using the CustomClassLoader of Cornholio and it's working fine.

But I've tried DevIL in my project and got UnsatisfiedLinkError with DevIL fonctions (no errors when I'm writing them)

So I suppose the CustomClassLoader don't work with DevIL and I'm trying to now why or if I'm missing a little something

Any help would be appreciate.

I'm french, please excuse my english

EDIT : dammit I forgot the IL.create() fonction, problem solved sorry