Skip to content

Instantly share code, notes, and snippets.

@Talon876
Created June 14, 2012 07:11
Show Gist options
  • Save Talon876/2928605 to your computer and use it in GitHub Desktop.
Save Talon876/2928605 to your computer and use it in GitHub Desktop.
Extract /natives from root of jar to ~/.<appname>/natives/<version>
What needs to be done:
In NativeExtractor.java, rename the package to the package you're using.
Remove the logger if you do not have log4j setup.
In App.java, rename the package to the package you're using.
In the getAppname() and getVersion() methods replace the <groupId> and <artifactId> of what's in your pom file. If you aren't using maven, just hardcode the appname and version with return "appname"; and return "version";
You will also need the commons-io from apache. You can find the jar online and put it in your classpath or add this to your <dependencies> in maven.
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
I wrote this in a hurry, I may have left something out. You can see the full pom.xml and project here: https://github.com/Talon876/Falldown
IMPORTANT! For this to work, you must have all of your native files (*.dll, *.jnilib, *.so) at the root of the jar in a folder called 'natives'. Also note that the method to extract them is not recursive, so you must have them all be in '/natives' and not '/natives/windows' or etc.
The main method in App.java is not meant to be ran. It's an example that I pulled out of one of my other projects.
The <version> in the path is so that when you upgrade your application version, you can force new native files without ruining the old versions native files. Of course, if you don't change the native version when you change the application version, this creates unnecessary duplicates.
package org.sample.package;
import java.io.IOException;
import java.util.Properties;
import org.apache.log4j.Logger; //remove if you don't have the logger
import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.SlickException;
public class App {
private static final Logger log = Logger.getLogger(App.class); //remove if you don't have the logger
public static void main(String[] args) {
String nativeDir = NativeExtractor.extractNatives();
log.info("Set org.lwjgl.librarypath to " + nativeDir); //remove if you don't have the logger
System.setProperty("org.lwjgl.librarypath", nativeDir);
try {
AppGameContainer app = new AppGameContainer(new Somegame(getAppname() + " - " + getVersion()));
app.setDisplayMode(2560, 1600, true);
app.start();
} catch (SlickException e) {
log.error(e); //remove if you don't have the logger
}
}
public static String getVersion() {
String version = "";
final Properties pom = new Properties();
try {
pom.load(App.class.getResourceAsStream("/META-INF/maven/<groupId>/<artifactId>/pom.properties"));
version = pom.getProperty("version");
} catch (IOException e) {
log.error(e); //remove if you don't have the logger
}
return version;
}
public static String getAppname() {
String appname = "";
final Properties pom = new Properties();
try {
pom.load(App.class.getResourceAsStream("/META-INF/maven/<groupId>/<artifactId>/pom.properties"));
appname = pom.getProperty("artifactId");
} catch (IOException e) {
appname = "DEV";
log.error(e); //remove if you don't have the logger
}
return appname;
}
}
package org.sample.package;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger; //remove if you don't have the logger
public class NativeExtractor {
private static final Logger log = Logger.getLogger(NativeExtractor.class); //remove if you don't have the logger
public static String extractNatives() {
String nativeDirPath = System.getProperty("user.home") + "/." + App.getAppname().toLowerCase() + "/natives/"
+ App.getVersion() + "/";
File nativeDir = new File(nativeDirPath);
nativeDir.mkdirs();
String pathToJar = NativeExtractor.class.getProtectionDomain().getCodeSource().getLocation().getPath();
try {
String decodedPathToJar = URLDecoder.decode(pathToJar, "UTF-8");
log.info("Loading jar at " + decodedPathToJar); //remove if you don't have the logger
JarFile self = new JarFile(decodedPathToJar);
for (Enumeration<JarEntry> list = self.entries(); list.hasMoreElements();) {
ZipEntry entry = list.nextElement();
if (entry.getName().startsWith("natives/")) {
try {
String[] tokens = entry.getName().split("/");
String fileName = tokens[tokens.length - 1];
extractFromJar("/natives/" + fileName, nativeDirPath + fileName);
} catch (IOException e) {
e.printStackTrace();
log.error(e); //remove if you don't have the logger
}
}
}
} catch (Exception e) {
log.error(e); //remove if you don't have the logger
}
return nativeDirPath;
}
private static void extractFromJar(String jarPath, String fsPath) throws IOException {
try {
InputStream in = NativeExtractor.class.getResourceAsStream(jarPath);
File fileOut = new File(fsPath);
if (!fileOut.exists()) { //only copy if the file doesn't already exist.
log.info("Moving " + jarPath + " from jar to " + fsPath); //remove if you don't have the logger
OutputStream out = FileUtils.openOutputStream(fileOut);
IOUtils.copy(in, out);
in.close();
out.close();
}
} catch (Exception e) {
log.error(e); //remove if you don't have the logger
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment