[:de]Neulich stellte sich mir die Frage, warum eigentlich nicht auch SWT Applikationen als Applet laufen können. Gut der erste Grund ist sicherlich, dass SWT nicht immer installiert ist, im Gegensatz zu Swing, was schon mit dem JRE dabei ist. Allerdings ist das so dramatisch auch wieder nicht in Zeiten schneller DSL-Leitungen, dann wird’s eben nachgeladen.
Was aber noch dazu kommt: SWT braucht native Libraries und native Libraries lassen sich nicht so einfach über den ClassLoader nachladen, wie irgendwelche Java-Klassen.
Ist das Applet allerdings signiert, dann ist auch das kein Problem und was dann mit relativ wenig Aufwand möglich ist …
Das Bespiel zeigt ein SWT Demo von IBM: den FileViewer. Die Klasse ist so gut wie nicht geändert worden, lediglich die Initialisierung der Shell muss etwas anders aussehen.
Dann habe ich noch einen kleinen Bootstrap-Loader für SWT geschrieben (bislang nur für Windows) und schon startet ein SWT Applet.
Achtung: Das Applet ist zwar nur ein Demo, aber der FileViewer ist echt: z.B. Doppelklick auf ein Word-Dokument startet Word!!
Bemerkung: das Applet ist signiert und erhält nach Bestätigung das Recht SWT zu installieren. Dazu werden zwei DLLs heruntergeladen und auf dem Java-Library-Path gespeichert. Sollte dies auf Grund unzureichender Rechte des angemeldeten Benutzers nicht funktionieren, so startet das Demo nicht korrekt und liefert stattdessen einen Fehler.
Code:
package com.rinke.solutions;
import java.applet.Applet;
import java.awt.Canvas;
import java.awt.FlowLayout;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;import javax.swing.JOptionPane;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.examples.fileviewer.FileViewer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;public class SWTApplet extends Applet {
@Override
public void init() {super.init();
try {
Runtime.getRuntime().loadLibrary(“swt-win32-3139.dll”);
} catch( Throwable e) {
System.out.println(“Load Library failed” );
String path = System.getProperty(“java.library.path”);
String[] paths = path.split(File.pathSeparator);
String targetDir = null;
for (int i = 0; i < paths.length; i++) {
String t = paths[i];
if( testWriteable(t) ) {
targetDir = t;
break;
}
}
if( targetDir != null ) {
download( “swt-win32-3139.dll”, targetDir );
download( “swt-awt-win32-3139.dll”, targetDir );
} else {
JOptionPane.showMessageDialog(this,“Could not download swt dlls, java.library.path not writeable”,
“Error Downloading DLLs”, JOptionPane.ERROR_MESSAGE);
}
}resize(640, 400);
final Canvas c = new Canvas();
setLayout(new FlowLayout());
c.setSize(640, 400);
add(c);new Thread( new Runnable() {
public void run() {
createSWT(c);
}}).start();
}private boolean testWriteable(String dir) {
try {
FileOutputStream fos = new FileOutputStream( dir + File.pathSeparator + “test” );
fos.write(1);
fos.close();
File f = new File( dir + File.pathSeparator + “test” );
f.delete();
return true;
} catch( Exception e){}
return false;
}private void download(String filename, String targetDir) {
try {
URL url = new URL( getCodeBase() + filename );
InputStream is = url.openStream();
File of = new File(targetDir + “/” + filename);
FileOutputStream o = new FileOutputStream( of );
System.out.println(“downloading from ” + url + “to ” + of.getAbsolutePath());
byte[] buffer = new byte[10000];
while( true ) {
int c = is.read(buffer);
if( c == –1 ) break;
o.write(buffer,0,c);
}
o.close();
is.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
Shell shell;
Display display;
protected void createSWT(Canvas c) {
display = new Display();
shell = SWT_AWT.new_Shell(display, c);shell.setLayout(new FillLayout());
FileViewer app = new FileViewer();
app.open(display,shell);
// Size AWT Panel so that it is big enough to hold the SWT widgets
Point size = shell.computeSize (SWT.DEFAULT, SWT.DEFAULT);
c.setSize(size.x + 2, size.y + 200);validate();
// shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();
}}
[:en]
Recently I asked myself, why swt applications couldn’t run as applet actually? Okay one certain reason is swt is not part of the jre as swing is. However this should not be to dramatic in times of highspeed internet connections, we can download and install it on the fly.
But in addition: SWT needs native libraries and native libraries could not easily loaded by an url classloader like some simple java class files.
But if the applet is signet, then even this isn’t really a problem, and then with little effort you can see …
The example demonstrates a swt demo by IBM: the FileViewer. The class isn’t virtually changed, solely the initialiasation of the shell looks somewaht different.
Further on I added a simple boot loader for swt applets (until now its windows only) und yet a SWT Applet starts.
Warning: This applet indeed is just a demo, but the FileViewer is real: for instance a double click on a word document starts word!!
Note: the applet is signet and gets the permission to install swt after confirmation. To achieve this the applet will dowload two DLLs and store them to the java library path. If this isn’t possible due insufficient rights of the user logged in, the demo wont start and you will get an error message.
Code:
package com.rinke.solutions;
import java.applet.Applet;
import java.awt.Canvas;
import java.awt.FlowLayout;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;import javax.swing.JOptionPane;
import org.eclipse.swt.SWT;
import org.eclipse.swt.awt.SWT_AWT;
import org.eclipse.swt.examples.fileviewer.FileViewer;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;public class SWTApplet extends Applet {
@Override
public void init() {super.init();
try {
Runtime.getRuntime().loadLibrary("swt-win32-3139.dll");
} catch( Throwable e) {
System.out.println("Load Library failed" );
String path = System.getProperty("java.library.path");
String[] paths = path.split(File.pathSeparator);
String targetDir = null;
for (int i = 0; i < paths.length; i++) {
String t = paths[i];
if( testWriteable(t) ) {
targetDir = t;
break;
}
}
if( targetDir != null ) {
download( "swt-win32-3139.dll", targetDir );
download( "swt-awt-win32-3139.dll", targetDir );
} else {
JOptionPane.showMessageDialog(this,"Could not download swt dlls, java.library.path not writeable",
"Error Downloading DLLs", JOptionPane.ERROR_MESSAGE);
}
}resize(640, 400);
final Canvas c = new Canvas();
setLayout(new FlowLayout());
c.setSize(640, 400);
add(c);new Thread( new Runnable() {
public void run() {
createSWT(c);
}}).start();
}
private boolean testWriteable(String dir) {
try {
FileOutputStream fos = new FileOutputStream( dir + File.pathSeparator + "test" );
fos.write(1);
fos.close();
File f = new File( dir + File.pathSeparator + "test" );
f.delete();
return true;
} catch( Exception e){}
return false;
}private void download(String filename, String targetDir) {
try {
URL url = new URL( getCodeBase() + filename );
InputStream is = url.openStream();
File of = new File(targetDir + "/" + filename);
FileOutputStream o = new FileOutputStream( of );
System.out.println("downloading from " + url + "to " + of.getAbsolutePath());
byte[] buffer = new byte[10000];
while( true ) {
int c = is.read(buffer);
if( c == -1 ) break;
o.write(buffer,0,c);
}
o.close();
is.close();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}}
Shell shell;
Display display;
protected void createSWT(Canvas c) {
display = new Display();
shell = SWT_AWT.new_Shell(display, c);shell.setLayout(new FillLayout());
FileViewer app = new FileViewer();
app.open(display,shell);
// Size AWT Panel so that it is big enough to hold the SWT widgets
Point size = shell.computeSize (SWT.DEFAULT, SWT.DEFAULT);
c.setSize(size.x + 2, size.y + 200);validate();
// shell.open();
while (!shell.isDisposed())
if (!display.readAndDispatch())
display.sleep();}
}
20 Antworten auf SWT Applikation als Applet