From 8cfed9f5c6d958e2775ebeebf10a9dfec55e8071 Mon Sep 17 00:00:00 2001 From: Ingo Bauersachs Date: Mon, 3 Feb 2014 23:33:16 +0100 Subject: [PATCH] Webstart-launcher (with HUGE hacks) --- .gitignore | 1 + build.xml | 2 +- .../launcher/SIPCommunicatorJWS.java | 140 +++++++++ web-start/WebStartBuild.properties.sample | 9 + web-start/WebStartBuild.xml | 292 ++++++++++++++++++ web-start/ant-ext/FelixConfigSelector.java | 92 ++++++ web-start/ant-ext/GenerateFelixConfigs.java | 161 ++++++++++ web-start/ant-ext/PutJarsToJnlp.java | 76 +++++ web-start/client.jnlp_template | 102 ++++++ web-start/index.html | 21 ++ 10 files changed, 895 insertions(+), 1 deletion(-) create mode 100644 src/net/java/sip/communicator/launcher/SIPCommunicatorJWS.java create mode 100644 web-start/WebStartBuild.properties.sample create mode 100644 web-start/WebStartBuild.xml create mode 100644 web-start/ant-ext/FelixConfigSelector.java create mode 100644 web-start/ant-ext/GenerateFelixConfigs.java create mode 100644 web-start/ant-ext/PutJarsToJnlp.java create mode 100644 web-start/client.jnlp_template create mode 100644 web-start/index.html diff --git a/.gitignore b/.gitignore index e1a535379..35c645123 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ sip-communicator.utest.bin release lib/accounts.properties .DS_Store +web-start/WebStartBuild.properties diff --git a/build.xml b/build.xml index a8d0fb6db..85b9ee74f 100644 --- a/build.xml +++ b/build.xml @@ -1463,7 +1463,7 @@ javax.swing.event, javax.swing.border"/> - diff --git a/src/net/java/sip/communicator/launcher/SIPCommunicatorJWS.java b/src/net/java/sip/communicator/launcher/SIPCommunicatorJWS.java new file mode 100644 index 000000000..51c02c43d --- /dev/null +++ b/src/net/java/sip/communicator/launcher/SIPCommunicatorJWS.java @@ -0,0 +1,140 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. + * See terms of license at gnu.org. + */ +package net.java.sip.communicator.launcher; + +import java.io.*; +import java.lang.reflect.*; +import java.net.*; +import java.util.*; +import java.util.jar.*; +import java.util.logging.*; + +import net.java.sip.communicator.util.FileHandler; +import net.java.sip.communicator.util.*; + +public class SIPCommunicatorJWS +{ + public static void main(String[] args) throws Exception + { + // allow access to everything + System.setSecurityManager(null); + + // prepare the logger + // needed by the FileHandler-Logger + SIPCommunicator.setScHomeDir(System.getProperty("os.name")); + LogManager.getLogManager() + .readConfiguration( + SIPCommunicatorJWS.class + .getResourceAsStream("/logging.properties")); + + for (Handler h : LogManager.getLogManager().getLogger("").getHandlers()) + LogManager.getLogManager().getLogger("").removeHandler(h); + LogManager.getLogManager().getLogger("").addHandler(new FileHandler()); + LogManager.getLogManager().getLogger("") + .addHandler(new ConsoleHandler()); + for (Handler h : LogManager.getLogManager().getLogger("").getHandlers()) + h.setFormatter(new ScLogFormatter()); + + // be evil :-) + // find the path of the nativelibs under webstart (findLibrary is + // protected and therefore at least documented api) + Method findLibrary = + SIPCommunicatorJWS.class.getClassLoader().getClass() + .getDeclaredMethod("findLibrary", String.class); + findLibrary.setAccessible(true); + File path = + new File((String) findLibrary.invoke( + SIPCommunicatorJWS.class.getClassLoader(), "hid")) + .getParentFile(); + System.setProperty( + "java.library.path", + System.getProperty("java.library.path") + File.pathSeparator + + path.getAbsolutePath()); + + // reset sys_paths to re-read usr_paths (runtime-dependent and therefore + // very very ugly :() + Field sys_paths = ClassLoader.class.getDeclaredField("sys_paths"); + sys_paths.setAccessible(true); + sys_paths.set(null, null); + + // prepare the felix-config with the absolute paths + Properties pIn = new Properties(); + Properties pOut = new Properties(); + pIn.load(SIPCommunicatorJWS.class.getResourceAsStream(System + .getProperty("felix.config.properties"))); + + String baseServerUrl = + System.getProperty("net.java.sip.communicator.SC_JWS_BASEDIR"); + ClassLoader cl = SIPCommunicatorJWS.class.getClassLoader(); + Method getJarFile = + cl.getClass().getDeclaredMethod("getJarFile", URL.class); + getJarFile.setAccessible(true); + for (Map.Entry e : pIn.entrySet()) + { + if (((String) e.getKey()).startsWith("felix.auto.start.")) + { + String[] refs = ((String) e.getValue()).split("\\s"); + StringBuilder sb = new StringBuilder(); + for (String ref : refs) + { + JarFile localFile = + (JarFile) getJarFile.invoke(cl, new URL(baseServerUrl + + ref.replace("@URL@", ""))); + if (localFile != null) + { + String localFileName = + new File(localFile.getName()).toURI().toString(); + sb.append("reference:"); + sb.append(localFileName); + sb.append(" "); + } + else + { + throw new Exception("ref <" + ref + + "> not found in cache"); + } + } + pOut.put(e.getKey(), sb.toString()); + } + else + { + pOut.put(e.getKey(), e.getValue()); + } + } + File jwsFelixConfig = File.createTempFile("jws", ".properties"); + jwsFelixConfig.deleteOnExit(); + pOut.store(new FileOutputStream(jwsFelixConfig), + "--- autogenerated, do not edit! ---"); + System.setProperty("felix.config.properties", jwsFelixConfig.toURI() + .toString()); + + // Workaround broken desktop shortcut in ubuntu linux: + // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6957030 + try + { + if (System.getProperty("os.name").equals("Linux")) + { + File desktop = + new File(System.getProperty("user.home") + "/Desktop"); + File[] files = desktop.listFiles(); + for (File file : files) + { + if (file.getName().contains("jws_app_shortcut_")) + { + file.setExecutable(true, false); + } + } + } + } + catch (Exception e) + { + } + + // launch the original app + SIPCommunicator.main(args); + } +} diff --git a/web-start/WebStartBuild.properties.sample b/web-start/WebStartBuild.properties.sample new file mode 100644 index 000000000..f2591cc5e --- /dev/null +++ b/web-start/WebStartBuild.properties.sample @@ -0,0 +1,9 @@ +# value without trailing '/' (slash) +java.jdk.dir = c:\\java\\jdk6 + +keystore.alias = +keystore.file = +keystore.password = + +# value without trailing '/' (slash) +webstart.codebase.url = http://localhost/client diff --git a/web-start/WebStartBuild.xml b/web-start/WebStartBuild.xml new file mode 100644 index 000000000..5af278925 --- /dev/null +++ b/web-start/WebStartBuild.xml @@ -0,0 +1,292 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/web-start/ant-ext/FelixConfigSelector.java b/web-start/ant-ext/FelixConfigSelector.java new file mode 100644 index 000000000..e1ceae847 --- /dev/null +++ b/web-start/ant-ext/FelixConfigSelector.java @@ -0,0 +1,92 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +import java.io.*; +import java.util.*; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.selectors.*; + +/** + * Selector which lets those files through that are referenced in the felix + * configuration file. + */ +public class FelixConfigSelector + implements FileSelector +{ + private Set referencedBundleCache; + + private File felixConfig; + + public void setFelixConfig(File felixConifg) + { + if (!felixConifg.isFile()) + throw new BuildException("No felix configuration file provided."); + + this.felixConfig = felixConifg; + } + + @Override + public boolean isSelected(File basedir, String filename, File file) + { + cacheConfigEntries(basedir); + return referencedBundleCache.contains(file); + } + + private void cacheConfigEntries(File basedir) + { + if (referencedBundleCache != null) + return; + + // cache files referenced in felix config + referencedBundleCache = new HashSet(); + + // load felix config + Properties pIn = new Properties(); + try + { + pIn.load(new FileInputStream(felixConfig)); + } + catch (FileNotFoundException e) + { + throw new BuildException(e); + } + catch (IOException e) + { + throw new BuildException(e); + } + + for (Map.Entry e : pIn.entrySet()) + { + if (((String) e.getKey()).startsWith("felix.auto.start.")) + { + String[] refs = ((String) e.getValue()).split("\\s"); + for (String jar : refs) + { + if (jar.startsWith("reference:file:")) + { + String relPath = + jar.substring("reference:file:".length()); + String absPath = + basedir.getPath() + File.separator + relPath; + File f = new File(absPath); + if (f.isFile()) + { + referencedBundleCache.add(f); + } + else + { + System.out.println( + "WARNING: Referenced file does not exist: " + + f.getPath()); + } + } + } + } + } + + } + +} diff --git a/web-start/ant-ext/GenerateFelixConfigs.java b/web-start/ant-ext/GenerateFelixConfigs.java new file mode 100644 index 000000000..2a1db05c5 --- /dev/null +++ b/web-start/ant-ext/GenerateFelixConfigs.java @@ -0,0 +1,161 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +import org.apache.tools.ant.*; + +import java.io.*; +import java.util.*; + +public class GenerateFelixConfigs + extends Task +{ + private File baseConfig; + + private String os; + + private File libdir; + + private File bundledir; + + private File output; + + public void setFile(File f) + { + baseConfig = f; + } + + public void setOs(String os) + { + this.os = os; + } + + public void setBundledir(File bundledir) + { + this.bundledir = bundledir; + } + + public void setLibdir(File libdir) + { + this.libdir = libdir; + } + + public void setOutput(File output) + { + this.output = output; + } + + public void execute() throws BuildException + { + try + { + execute0(); + } + catch (Exception e) + { + e.printStackTrace(); + throw new BuildException(e); + } + } + + public void execute0() throws BuildException + { + Properties pIn = new Properties(); + Properties pOut = new Properties(); + try + { + pIn.load(new FileInputStream(baseConfig)); + } + catch (FileNotFoundException e) + { + throw new BuildException(e); + } + catch (IOException e) + { + throw new BuildException(e); + } + + for (Map.Entry e : pIn.entrySet()) + { + if (((String) e.getKey()).startsWith("felix.auto.start.")) + { + String[] refs = ((String) e.getValue()).split("\\s"); + StringBuilder value = new StringBuilder(); + for (String jar : refs) + { + if (jar.startsWith("reference:file:sc-bundles/")) + { + String name = + jar.substring("reference:file:sc-bundles/".length()); + if (contains( + new File(bundledir, "os-specific/" + os).list(), + name)) + { + value.append("@URL@/sc-bundles/"); + value.append("os-specific/"); + value.append(os); + value.append("/"); + value.append(name); + } + else if (contains(bundledir.list(), name)) + { + value.append("@URL@/sc-bundles/"); + value.append(name); + } + else + { + log("Bundle <" + name + "> not found in <" + + bundledir.getName() + + ">. Seems like this bundle was ignored."); + } + } + else if (jar.startsWith("reference:file:lib/bundle/")) + { + String name = + jar.substring("reference:file:lib/bundle/".length()); + if (contains(libdir.list(), name)) + { + value.append("@URL@/lib/bundle/"); + value.append(name); + } + else + { + log("Lib <" + name + "> not found in <" + libdir + + ">. Seems like this lib was ignored."); + } + } + else + { + throw new BuildException( + "unsupported reference prefix: " + jar); + } + value.append(" "); + } + pOut.put(e.getKey(), value.toString()); + } + else + { + pOut.put(e.getKey(), e.getValue()); + } + } + try + { + pOut.store(new FileOutputStream(output), + "--- autogenerated by GenerateFelixConfigs, do not edit! ---"); + } + catch (FileNotFoundException e) + { + throw new BuildException(e); + } + catch (IOException e) + { + throw new BuildException(e); + } + } + + private boolean contains(String[] files, String file) + { + return Arrays.asList(files).contains(file); + } +} diff --git a/web-start/ant-ext/PutJarsToJnlp.java b/web-start/ant-ext/PutJarsToJnlp.java new file mode 100644 index 000000000..de597608a --- /dev/null +++ b/web-start/ant-ext/PutJarsToJnlp.java @@ -0,0 +1,76 @@ +/* + * Jitsi, the OpenSource Java VoIP and Instant Messaging client. + * + * Distributable under LGPL license. See terms of license at gnu.org. + */ +import org.apache.tools.ant.*; + +import java.io.*; +import java.util.*; + +public class PutJarsToJnlp + extends Task +{ + private File bundledir; + + private File osbundles; + + public void setBundledir(File b) + { + bundledir = b; + } + + public void setOsbundles(File f) + { + osbundles = f; + } + + public void execute() throws BuildException + { + try + { + execute0(); + } + catch (Exception e) + { + e.printStackTrace(); + throw new BuildException(e); + } + } + + public void execute0() throws BuildException + { + StringBuilder common = new StringBuilder(); + for (File jar : bundledir.listFiles()) + { + if (jar.isFile()) + { + common.append("\n"); + } + } + getProject().setProperty("jnlp.jars.common", common.toString()); + + for (File dir : osbundles.listFiles()) + { + if (dir.isDirectory()) + { + StringBuilder os = new StringBuilder(); + for (File jar : dir.listFiles()) + { + if (jar.isFile()) + { + os.append("\n"); + } + } + getProject().setProperty("jnlp.jars." + dir.getName(), + os.toString()); + } + } + } +} diff --git a/web-start/client.jnlp_template b/web-start/client.jnlp_template new file mode 100644 index 000000000..58079dd5f --- /dev/null +++ b/web-start/client.jnlp_template @@ -0,0 +1,102 @@ + + + + + Jitsi + jitsi.org + Jitsi - Open Source Video Calls and Chat + + + + + + + + + + + + + + + + + + + + + @WINDOWS@ + + + + + + + + + + + + + + + + + + + + + @LINUX@ + + + + + + + + + + + + + + + + + + + + @MACOSX@ + + + + + + + + + + + + + + + + @COMMON@ + + + + + diff --git a/web-start/index.html b/web-start/index.html new file mode 100644 index 000000000..cdeadcd1a --- /dev/null +++ b/web-start/index.html @@ -0,0 +1,21 @@ + + +Launch Jitsi
+ +

+Tested Operating Systems: +

    +
  • Windows Vista, 7, 8 (32 & 64 bit)
  • +
  • Windows XP 32 bit
  • +
  • Mac OS X
  • +
  • Ubuntu Linux 32 & 64 bit
  • +
+Only Sun's/Oracle's JVM is supported and tested. Your Java Web Start cache must be enabled. +

+

+In case Jitsi starts with errors please delete the 'jitsi-jws' +folder in your home directory and try again. If this does not solve the problem contact us. +

+ + +