| Trolltech Home | Qt-jambi-interest Home | Recent Threads | All Threads | Author | Date | |
| All threads index page 1 | |
Dear all,
After some search a found a solution to start web start apps under Mac OS
X.
First, you need to create a jar with all necessary binary. To do this i
use the attached script named "createqtjambimacjar.sh ".
Now, we can test the created jar with the qtjambi demo jar (from the
webstart app) :
$ java -cp qtjambi.jar:qtjambi-mac-1.0.0-beta2.jar:qtjambi-launcher.jar -
Dcom.trolltech.qt.verbose-loading=true -XstartOnFirstThread
com.trolltech.launcher.Launcher
This command will fail with the following message :
Loaded(libQtCore.4.dylib) using cached
Loaded(libQtGui.4.dylib) using cached
Loaded(libqtjambi.jnilib ) using cached
Loaded(libQtCore.4.dylib) using cached
Loaded(libQtGui.4.dylib) using cached
java.lang.UnsatisfiedLinkError:
/private/tmp/QtJambi_0.1.1/libcom_trolltech_qt_core.jnilib:
at java.lang.ClassLoader$NativeLibrary.load (Native Method)
at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1751)
at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1647)
at java.lang.Runtime.load0(Runtime.java:769)
at java.lang.Runtime.load(Runtime.java:757)
at com.trolltech.qt.Utilities.loadLibrary(Utilities.java:132)
at com.trolltech.qt.Utilities.loadJambiLibrary(Utilities.java:80)
at com.trolltech.qt.core.QtJambi_LibraryInitializer.<clinit>(QtJambi_LibraryInitializer.java:9)
at com.trolltech.qt.core.QAbstractFileEngineHandler.<clinit>(
QAbstractFileEngineHandler.java:12)
at com.trolltech.qt.QtJambi_LibraryInitializer.<clinit>(QtJambi_LibraryInitializer.java:26)
at com.trolltech.qt.QtJambiObject.<clinit>(QtJambiObject.java:29)
Exception in thread "main" java.lang.UnsatisfiedLinkError: __qt_initLibrary
at com.trolltech.qt.core.QtJambi_LibraryInitializer.__qt_initLibrary(Native
Method)
at com.trolltech.qt.core.QtJambi_LibraryInitializer
.<clinit>(QtJambi_LibraryInitializer.java:10)
at com.trolltech.qt.core.QAbstractFileEngineHandler.<clinit>(
QAbstractFileEngineHandler.java:12)
at com.trolltech.qt.QtJambi_LibraryInitializer
.<clinit>(QtJambi_LibraryInitializer.java:26)
at com.trolltech.qt.QtJambiObject.<clinit>(QtJambiObject.java:29)
But if in the /private/tmp/QtJambi_0.1.1 directory, we create a symlink :
$ ln -s libqtjambi.jnilib libqtjambi.1.jnilib
We can run the demo without error. com.trolltech.qt.Utilities seem to be
patched but as now i don't have the time to investigate it. :-(
If we want to start a java web start, we must run the app in another JVM
as with JSW, swing is already started. To do this, i wrote a class (
BootStrap.java attached to this mail) that call JWS internal methods to
collect all parameters of the jnlp file to create a command line to start a
new JVM. In the jnlp file the java-vm-args argument must containts at least
"-XstartOnFirstThread" to start QtJambi.
In the main file of the app to start, a function called "bootstrap()" must
be added:
private static void bootstrap() {
if (!System.getProperty("os.name").toLowerCase().startsWith("mac os x"))
return;
try {
Corsen.class.getClassLoader().loadClass("com.sun.jnlp.JNLPClassLoader
");
BootStrap.bootstrap();
} catch (ClassNotFoundException e) {
}
}
As the BootStrap class is linked to classes of the javaws.jar, we can't
call it in the bootstraped JVM (an exception will be throwed as
javaws.jaris not in the classpath), that why this function must be
defined in the main
class. Then, this method must be called at the beginning of the main method
:
public static void main(final String[] args) throws IOException {
bootstrap();
... The code of the application ...
}
Once the little bug in com.trolltech.qt.Utilities fixed, it will be
possible to run out of the box Java Web Start apps using QtJambi with this
little magic code. :-)
Laurent.
package fr.ens.transcriptome.test;
package fr.ens.transcriptome.test;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import com.sun.javaws.JnlpxArgs;
import com.sun.javaws.cache.DiskCacheEntry;
import com.sun.javaws.cache.DownloadProtocol;
import com.sun.javaws.exceptions.JNLPException;
import com.sun.javaws.jnl.ApplicationDesc;
import com.sun.javaws.jnl.JARDesc;
import com.sun.javaws.jnl.JREDesc;
import com.sun.javaws.jnl.LaunchDesc;
import com.sun.javaws.jnl.ResourcesDesc;
import com.sun.jnlp.JNLPClassLoader;
/**
* A Bootstrap class for webstart apps under Mac OS X.
* @author Laurent Jourdren
*/
public class BootStrap {
private static final String JAVA_PATH_MACOS = "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Commands/java";
private List<String> classpath = new ArrayList<String>();
private String mainClass;
private String[] args;
private Map<String, String> properties = new HashMap<String, String>();
private String vmArgs;
private long maxHeap;
private long minHeap;
private static void save(File f, String s) {
try {
Writer writer = new OutputStreamWriter(new FileOutputStream(f));
writer.write(s);
writer.close();
} catch (Exception e) {
}
}
public void collectInfos(final JNLPClassLoader cl) {
final LaunchDesc ld = cl.getLaunchDesc();
collectClasspath(ld);
collectMainClass(ld);
collectProperties(ld);
collectJVM(ld.getResources().getSelectedJRE());
}
private void collectClasspath(final LaunchDesc ld) {
final List<JARDesc> jarDescs = new ArrayList<JARDesc>();
ResourcesDesc rd = ld.getResources();
if (rd != null) {
JARDesc[] jars = rd.getEagerOrAllJarDescs(true);
for (int i = 0; i < jars.length; i++)
if (jars[i].isJavaFile() || jars[i].isNativeLib())
jarDescs.add(jars[i]);
}
for (JARDesc jd : jarDescs) {
URL location = jd.getLocation();
String version = jd.getVersion();
try {
DiskCacheEntry dce = DownloadProtocol.getResource(location, version,
DownloadProtocol.JAR_DOWNLOAD, true, null);
this.classpath.add(dce.getFile().getAbsolutePath());
} catch (JNLPException e) {
}
}
}
private void collectMainClass(final LaunchDesc ld) {
// If applet exit.
if (ld.isApplet())
System.exit(0);
ApplicationDesc ad = ld.getApplicationDescriptor();
this.mainClass = ad.getMainClass();
this.args = ad.getArguments();
}
private void collectJVM(final JREDesc jreDesc) {
this.maxHeap = JnlpxArgs.getMaxHeapSize();
this.minHeap = JnlpxArgs.getInitialHeapSize();
this.vmArgs = jreDesc.getVmArgs();
}
private void collectProperties(final LaunchDesc ld) {
ResourcesDesc rd = ld.getResources();
Properties ps = rd.getResourceProperties();
Iterator it = ps.keySet().iterator();
while (it.hasNext()) {
String key = (String) it.next();
this.properties.put(key, ps.getProperty(key));
}
}
public static void bootstrap() {
final ClassLoader cl = BootStrap.class.getClassLoader();
if (cl == null)
return;
if (cl instanceof JNLPClassLoader) {
BootStrap b = new BootStrap();
b.collectInfos((JNLPClassLoader) cl);
String cmd = b.createCommandLine();
save(new File(System.getProperty("user.home") + File.separator
+ "javacmd.txt"), cmd);
exec(cmd);
System.exit(0);
}
}
private String createCommandLine() {
StringBuffer sb = new StringBuffer();
sb.append(JAVA_PATH_MACOS);
// Set classpath
sb.append(" -cp ");
boolean first = true;
for (String path : this.classpath) {
if (first)
first = false;
else
sb.append(":");
sb.append(path);
}
// Set Java properties
for (String key : this.properties.keySet()) {
String value = this.properties.get(key);
sb.append(" -D");
sb.append(key);
sb.append("=");
sb.append(value);
}
// Set vm args
if (this.vmArgs != null) {
sb.append(" ");
sb.append(this.vmArgs);
}
// Set initial heap
if (this.minHeap != -1) {
sb.append(" -Xms");
sb.append(this.minHeap);
}
// Set max heap
if (this.maxHeap != -1) {
sb.append(" -Xmx");
sb.append(this.maxHeap);
}
// Main class
sb.append(" ");
sb.append(this.mainClass);
// Args
for (int i = 0; i < this.args.length; i++) {
sb.append(" ");
sb.append(this.args[i]);
}
return sb.toString();
}
private static void exec(final String cmd) {
Runtime rt = Runtime.getRuntime();
try {
rt.exec(cmd);
} catch (IOException e) {
}
}
//
// Constructor
//
private BootStrap() {
}
}
Attachment:
Attachment:
createqtjambimacjar.sh
Attachment:
Attachment:
createqtjambimacjar.sh
Description: Bourne shell script
Message 2 in thread
Hi all,
I'm just thinking about it: we can change the links of the libraries with
install_name_tool.
So, I've update createjambimacjar.sh and now it's works without creating
the symlink. No more need to patch com.trolltech.qt.Utilities !!!!
I've only test with the launch the qtjambi demo in command line but there
is no reason that with a Java Web Start app it fails.
Laurent.
Description: Bourne shell script
Message 3 in thread
Laurent Jourdren wrote:
>
> Hi all,
>
> I'm just thinking about it: we can change the links of the libraries
> with install_name_tool.
>
> So, I've update createjambimacjar.sh and now it's works without
> creating the symlink. No more need to patch com.trolltech.qt.Utilities !!!!
>
> I've only test with the launch the qtjambi demo in command line but
> there is no reason that with a Java Web Start app it fails.
Hi Laurent,
For the final release we use a similar approach, downloading the
packages and launch a new process with the right parameters, so we will
have webstart for all our binary platforms ;-)
-
Gunnar