Skip to main content

about cross-platform jdic release

4 replies [Last post]
armin_chen
Offline
Joined: 2004-09-29
Points: 0

Currently, JDIC release contains platform-depentent jdic.jar file and several native binary files for specified platform.
The directory structure is like this:
jdic-0.8.6-bin-platform
|
|-jdic.jar
|
|-demo, javadoc...
|
|-native files...

We notice that there are demands for a cross-platform release that contains all needed files.

We are now planing to release a cross-platform version for JDIC 0.8.7(should be available in 2 weeks). This release will contain only one unified jdic.jar file for all supported platforms. Given that native files for different paltform may have the same filename such as libjdic.so, so we have to put them in separated directories for each platform.

The directory structure will be like this:
jdic-0.8.7-bin-cross-platform
|
|-jdic.jar
|
|-demo, javadoc...
|
|-linux
| |--native files...
|
|-solaris_sparc
| |--native files...
|
|-solaris_x86
| |--native files...
|
|-windows
| |--native files...

Currently, jdic code assume that the native binary files and jdic.jar are located at the same directory, so it automatically set the environment variables for native libraries and executable files by adding the directory path to PATH or LD_LIBRARY_PATH. If the binary files and jdic.jar do not locate at a same directory, JDIC code will fail to find the binary file. So, it's programmer's responsibility to add the correct path to PATH or LD_LIBRARY_PATH in their application code.

Also, JDIC will continue to offer old style of release that contains platform-depentent jdic.jar file and several native binary files for specified platform.

I post these words for commends. Any suggestion will be appreciated.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Gary Orser

Setting LD_LIBRARY_PATH and PATH is bogus.
(very user unfriendly)

If possible, we should have the code check multiple locations.

Cheers, Gary
------------------------------------------------------
Gary Orser , (406) 994-6451, orser@cns.montana.edu
Montana State University
Center for Computational Biology
1 Lewis Hall, Bozeman MT, 59717

On Fri, 12 Nov 2004 jdic@javadesktop.org wrote:

> Currently, JDIC release contains platform-depentent jdic.jar file and several native binary files for specified platform.
> The directory structure is like this:
> jdic-0.8.6-bin-platform
> |
> |-jdic.jar
> |
> |-demo, javadoc...
> |
> |-native files...
>
> We notice that there are demands for a cross-platform release that contains all needed files.
>
> We are now planing to release a cross-platform version for JDIC 0.8.7(should be available in 2 weeks). This release will contain only one unified jdic.jar file for all supported platforms. Given that native files for different paltform may have the same filename such as libjdic.so, so we have to put them in separated directories for each platform.
>
> The directory structure will be like this:
> jdic-0.8.7-bin-cross-platform
> |
> |-jdic.jar
> |
> |-demo, javadoc...
> |
> |-linux
> | |--native files...
> |
> |-solaris_sparc
> | |--native files...
> |
> |-solaris_x86
> | |--native files...
> |
> |-windows
> | |--native files...
>
> Currently, jdic code assume that the native binary files and jdic.jar are located at the same directory, so it automatically set the environment variables for native libraries and executable files by adding the directory path to PATH or LD_LIBRARY_PATH. If the binary files and jdic.jar do not locate at a same directory, JDIC code will fail to find the binary file. So, it's programmer's responsibility to add the correct path to PATH or LD_LIBRARY_PATH in their application code.
>
> Also, JDIC will continue to offer old style of release that contains platform-depentent jdic.jar file and several native binary files for specified platform.
>
> I post these words for commends. Any suggestion will be appreciated.
> ---
> [Message sent by forum member 'armin_chen' (Armin Chen)]
>
> http://www.javadesktop.org/forums/thread.jspa?messageID=37882&#37882
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: jdic-unsubscribe@jdic.dev.java.net
> For additional commands, e-mail: jdic-help@jdic.dev.java.net
>

---------------------------------------------------------------------
To unsubscribe, e-mail: jdic-unsubscribe@jdic.dev.java.net
For additional commands, e-mail: jdic-help@jdic.dev.java.net

chas
Offline
Joined: 2004-06-23
Points: 0

See http://www.javadesktop.org/forums/thread.jspa?threadID=2753&tstart=100 and http://www.javadesktop.org/forums/thread.jspa?threadID=5155&tstart=60 for prior discusions on this topic. I also started issue (https://jdic.dev.java.net/issues/show_bug.cgi?id=114) which contains an installer for jdic.

What I'd like to see in the single distribution zip is:

jdic-0.8.7-bin
|
|-readme.html
|-jdic.jar
|-jdic-installer.jar
|
|-demo, javadoc...
|
|-linux
| |-jdic-platform.jar
| |-x86
| | |--native files...
|
|-solaris
| |-jdic-platform.jar
| |-x86
| | |--native files...
| |-sparc
| | |--native files...
|
|-windows
| |-x86
| | |--native files...

The jdic-installer.jar will install the required jars and shared libraries into a JRE. The jdic-installer.jar also contains a WebInstaller class to support webstart installs.

I'd also like to see the distributions available from https://jdic.dev.java.net/ as webstart downloads.

armin_chen
Offline
Joined: 2004-09-29
Points: 0

Hi Chas,

Thank you for your suggestions!

Your solution sounds good. It install the needed jar files and binary files to JRE, so there will be no problem with environment setting. But this solution force user to install the application first. And, it also force programmer to offer installation for their applications.

However, there are many applications that do not need to install, they just run by "java -jar myapp.jar". Then, how to deal with this situation?

Anyway, i will think about your suggestion, and talk about it with some other contributors.

Anyone who has more idea, please post your comments.

Thanks.
-Armin

chas
Offline
Joined: 2004-06-23
Points: 0

Applications that do not want to install jdic will need to include a custom classloader. The application jar must include the jdic.jar and all jdic-platform.jar contents. Additionally, the application jar must contain all the shared libraries. The custom classloader will copy the proper shared library out of the application jar into a temporary file for the jvm to use.

In effect, the custom classloader provides a temporary runtime installation of the shared libraries.

The custom classloader could look something like the following:

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;

import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;

import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedExceptionAction;

/** Demonstration Main for packaging multiple platform native libraries into distribution jar.

  • Application is packaged as jar
  • Application depends on native libraries
  • No installation into jre
  • No environment variables for PATH or LD_LIBRARY_PATH

This is not a full solution. If the shared libraries are dependent upon additional shared libraries,
the dependent shared libraries may not found by the operating system load routines.
*/

public class Main {

// this constructor is run in new ClassLoader
public Main(String[] args) {
// replace with application startup code
new ApplicationMain(args);
}

/**
* Return the canonical name of the platform. This value is derived from the System property os.name.
* @return The platform string.
*/
private static String getPlatform() {
// See list of os names at: http://lopica.sourceforge.net/os.html
// or at: http://www.tolstoy.com/samizdat/sysprops.html
String osName= System.getProperty("os.name");
if(osName.startsWith("Windows")) {
return "windows";
}
return canonical(osName);
}

/**
* Strip whitespace and replace file seperators
* @param value The value to be canonicalized.
* @return The value with all white space characters stripped,
* '/' and '\' replaced with '_',
* and all uppercase characters replaced with lower case equivalents.
*/
private static String canonical(String value) {
StringBuffer sb= new StringBuffer(value.length());
for(int i= 0; i char c= value.charAt(i);

// cannot abide argument separator
if(Character.isWhitespace(c)) {
// delete any space
}
// cannot abide file separator
else if(c=='/' || c=='\\') {
sb.append('_');
}
else {
sb.append(Character.toLowerCase(c));
}
}
return sb.toString();
}

/**
* Return the name of the architecture. This value is determined by the System property os.arch.
* @return The architecture string.
*/
private static String getArchitecture() {
return canonical(System.getProperty("os.arch"));
}

private static void copyStream(InputStream is, OutputStream os) throws IOException {
byte[] buffer= new byte[8192];
for( ; ; ) {
int nread= is.read(buffer);
if(nread<=0)
break;
os.write(buffer, 0, nread);
}
}

public static void main(String[] args) throws Exception {
// the jar Main is found within
final URL jarLocation = Main.class.getProtectionDomain().getCodeSource().getLocation();
final File jar= new File(URLDecoder.decode(jarLocation.getPath(), "UTF-8"));

//
// load Main in new ClassLoader
// the point of this ClassLoader is to intercept the findLibrary method
//
Class mainClass= new URLClassLoader(new URL[]{jarLocation}, Main.class.getClassLoader().getParent()) {

private AccessControlContext acc = AccessController.getContext();

/**
* Copy platform dependent shared library from the jar into a temporary file.
* return the temporary file name for the java vm to load the library.
*/
private String findLibrary(String sysName, String nameInJar) {
URL url= getResource(nameInJar);
if (url == null)
return null;

try {
InputStream is= url.openStream();
try {
int dotIdx= sysName.indexOf('.');
File outFile= File.createTempFile(sysName.substring(0, dotIdx), sysName.substring(dotIdx));
OutputStream os= new FileOutputStream(outFile);
try {
copyStream(is, os);
return outFile.getAbsolutePath();
}
finally {
os.close();
outFile.deleteOnExit();
}
}
finally {
is.close();
}
}
catch(IOException ignore) {
return null;
}
}

/**
* All calls to System.loadLibrary made by classes loaded by this classloader
* will get routed to this method.
*/
protected String findLibrary(String libname) {
final String sysName= System.mapLibraryName(libname);
final String nameInJar= getPlatform()+"/"+getArchitecture()+"/"+sysName;

return (String)AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return findLibrary(sysName, nameInJar);
}
}, acc);
}

/**
* find the class bytecode in the jar and create the class
*/
private Class findClass(String path, String name) throws ClassNotFoundException {
URL url= getResource(path);
if (url == null || !url.getProtocol().equals("file"))
throw new ClassNotFoundException(name);

try {
File file= new File(URLDecoder.decode(url.getPath(), "UTF-8"));
byte[] bc= new byte[(int)file.length()];
RandomAccessFile rf= new RandomAccessFile(file, "r");
try {
rf.read(bc);
}
finally {
rf.close();
}
return defineClass(name, bc, 0, bc.length);
}
catch(IOException io) {
throw new ClassNotFoundException(name, io);
}
}

/**
* calls to ClassLoader.loadClass made by classes loaded by this classloader
* will get routed to this method.
*/
protected Class findClass(final String name) throws ClassNotFoundException {
final String path = name.replace('.', '/').concat(".class");

try {
return (Class) AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws ClassNotFoundException {
return findClass(path, name);
}
}, acc);
} catch (java.security.PrivilegedActionException pae) {
throw (ClassNotFoundException) pae.getException();
}
}

}.loadClass("Main");

// create Main in new ClassLoader
mainClass.getConstructor(new Class[] {String[].class}).newInstance(new Object[]{args});
}

}