views:

2340

answers:

2

hi all, i bought a third-party java library which include a jar file and two dll files. i wrote my own java program which invoke the third-party jar file. now my question is how can i package all my code into a single jar file which include all my code and the third-party jar and dlls? great thanks.

ps: i know swt is such a case. the swt.jar include dlls, but i don't know how to do this and how to make it working properly.

+5  A: 

Just package it anywhere in the jar. One thing you have to keep in mind though - before you can use the DLLs you need to actually extract these from the JAR and dump these on the hard disk somewhere otherwise you won't be able to load these

So basically - I did JNI project for the client where I will use such jar packaged within the war. However - before running any native methods I would get the DLL as a resource and write it to the disc into temp directory. Then I would run regular initialization code where my DLL is set to the same location I just wrote DLL to

Oh, and just in case: there's nothing special about packaging dll or any other file into jar. It's just like packaging stuff into zip

Here's some code I just digged out

public class Foo {
private static final String LIB_BIN = "/lib-bin/";
private final static Log logger = LogFactory.getLog(ACWrapper.class);
private final static String ACWRAPPER = "acwrapper";
private final static String AAMAPI = "aamapi51";
private final static String LIBEAU = "libeay32";

static {
 logger.info("Loading DLL");
 try {
  System.loadLibrary(ACWRAPPER);
  logger.info("DLL is loaded from memory");
 } catch (UnsatisfiedLinkError e) {
  loadFromJar();
 }
}

/**
 * When packaged into JAR extracts DLLs, places these into
 */
private static void loadFromJar() {
 // we need to put both DLLs to temp dir
 String path = "AC_" + new Date().getTime();
 loadLib(path, ACWRAPPER);
 loadLib(path, AAMAPI);
 loadLib(path, LIBEAU);
}

/**
 * Puts library to temp dir and loads to memory
 */
private static void loadLib(String path, String name) {
 name = name + ".dll";
 try {
  // have to use a stream
  InputStream in = ACWrapper.class.getResourceAsStream(LIB_BIN + name);
  // always write to different location
  File fileOut = new File(System.getProperty("java.io.tmpdir") + "/" + path + LIB_BIN + name);
  logger.info("Writing dll to: " + fileOut.getAbsolutePath());
  OutputStream out = FileUtils.openOutputStream(fileOut);
  IOUtils.copy(in, out);
  in.close();
  out.close();
  System.load(fileOut.toString());
 } catch (Exception e) {
  throw new ACCoreException("Failed to load required DLL", e);
 }
}
    // blah-blah - more stuff
}
DroidIn.net
A word of caution on this approach - be sure you clean up the temp files. If you re-use the same path each time, consider what happens if multiple applications use your JAR (one will fail if the other already has a lock on the temp file). Just be careful - sometimes it's easier to deploy the JAR and DLLs separately.
Kevin Day
Code can be changed to overwrite previously installed file. In my case - this was a web app which will not be frequently recycled, bu indeed - if you just copy the code "as is" you will get new copy of DLLs each time you execute it
DroidIn.net
One thing to keep in mind: I was using JNI DLLs that were dependent on other DLLs. I included all DLLs inside a jar and used the code above to unpack. But I was getting java.lang.UnsatisfiedLinkError exceptions saying "Can't find dependent libraries". The problem is that you must call System.load() on the DLLs in order such that dependent DLLs are loaded first.
Liron Yahdav
A: 

Use http://www.jdotsoft.com/JarClassLoader.php which could load DLLs and JARs from another JAR with unlimited nesting. For example, DLL could be in JAR which is in another root JAR. All DLLs and JARs are loaded like they are in a classpath or library path.

gorokhmn