From 9d6b88165f30fcbaf1874485112d9ed5d7c78226 Mon Sep 17 00:00:00 2001 From: tkellner Date: Mon, 1 Aug 2011 08:23:21 +0000 Subject: Autostart feature added (Linux, Windows) git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@948 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../java/at/gv/egiz/bku/webstart/Configurator.java | 5 +- .../java/at/gv/egiz/bku/webstart/Launcher.java | 543 +++++++++++---------- .../bku/webstart/autostart/AbstractAutostart.java | 38 ++ .../gv/egiz/bku/webstart/autostart/Autostart.java | 68 +++ .../bku/webstart/autostart/AutostartInterface.java | 30 ++ .../bku/webstart/autostart/AutostartLinux.java | 135 +++++ .../bku/webstart/autostart/AutostartWindows.java | 207 ++++++++ .../egiz/bku/webstart/autostart/WinRegistry.java | 386 +++++++++++++++ .../bku/webstart/gui/BKUControllerInterface.java | 13 + .../at/gv/egiz/bku/webstart/gui/MOCCAIcon.java | 121 +++-- 10 files changed, 1241 insertions(+), 305 deletions(-) create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AbstractAutostart.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/Autostart.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartInterface.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartLinux.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartWindows.java create mode 100644 BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/WinRegistry.java (limited to 'BKUWebStart/src/main/java/at/gv/egiz/bku/webstart') diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java index 7bb80860..c3f2a699 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java @@ -68,8 +68,9 @@ public class Configurator { * allowed: MAJOR[.MINOR[.X[-SNAPSHOT]]] */ public static final String MIN_CONFIG_VERSION = "1.3.4-SNAPSHOT"; - public static final String CONFIG_DIR = ".mocca/conf/"; - public static final String CERTS_DIR = ".mocca/certs/"; + public static final String BKU_USER_DIR = ".mocca/"; + public static final String CONFIG_DIR = BKU_USER_DIR + "conf/"; + public static final String CERTS_DIR = BKU_USER_DIR + "certs/"; public static final String VERSION_FILE = ".version"; public static final String UNKOWN_VERSION = "unknown"; public static final String CONF_TEMPLATE_FILE = "conf-tmp.zip"; diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java index 547b46b6..3fa7f805 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java @@ -22,266 +22,283 @@ */ -package at.gv.egiz.bku.webstart; - -import at.gv.egiz.bku.webstart.gui.StatusNotifier; -import at.gv.egiz.bku.webstart.gui.BKUControllerInterface; -import at.gv.egiz.bku.webstart.gui.MOCCAIcon; -import iaik.asn1.CodingException; -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Locale; - -import javax.jnlp.UnavailableServiceException; - -//import com.sun.javaws.security.JavaWebStartSecurity; -import java.awt.Desktop; -import java.awt.SplashScreen; -import java.net.BindException; -import java.net.MalformedURLException; -import java.net.URL; -import java.security.GeneralSecurityException; -import java.util.jar.Attributes; -import java.util.jar.Manifest; -import javax.jnlp.BasicService; -import javax.jnlp.ServiceManager; -import org.mortbay.util.MultiException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Launcher implements BKUControllerInterface { - - public static final String WEBAPP_RESOURCE = "BKULocal.war"; - public static final String CERTIFICATES_RESOURCE = "BKUCertificates.jar"; - public static final String WEBAPP_FILE = "BKULocal.war"; - /** no leading slash for messages, but for image */ - public static final String MESSAGES_RESOURCE = "at/gv/egiz/bku/webstart/messages"; - public static final String TRAYICON_RESOURCE = "/at/gv/egiz/bku/webstart/chip"; - private static Logger log = LoggerFactory.getLogger(Launcher.class); - /** local bku uri */ - public static final URL HTTP_SECURITY_LAYER_URL; - public static final URL HTTPS_SECURITY_LAYER_URL; - public static final URL INSTALL_CERT_URL; - public static final URL PIN_MANAGEMENT_URL; - public static final URL HELP_URL; - - static { - URL http = null; - URL https = null; - URL pin = null; - URL cert = null; - URL help = null; - try { - http = new URL("http://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3495).intValue() + '/'); - https = new URL("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue() + '/'); - pin = new URL(http, "/PINManagement"); - cert = new URL(http, "/ca.crt"); - help = new URL(http, "/help/"); - } catch (MalformedURLException ex) { - log.error("Failed to create URL.", ex); - } finally { - HTTP_SECURITY_LAYER_URL = http; - HTTPS_SECURITY_LAYER_URL = https; - PIN_MANAGEMENT_URL = pin; - INSTALL_CERT_URL = cert; - HELP_URL = help; - } - } - public static final String version; - - static { - String tmp = Configurator.UNKOWN_VERSION; - try { - String bkuWebStartJar = Launcher.class.getProtectionDomain().getCodeSource().getLocation().toString(); - URL manifestURL = new URL("jar:" + bkuWebStartJar + "!/META-INF/MANIFEST.MF"); - if (log.isTraceEnabled()) { - log.trace("read version information from " + manifestURL); - } - Manifest manifest = new Manifest(manifestURL.openStream()); - Attributes atts = manifest.getMainAttributes(); - if (atts != null) { - tmp = atts.getValue("Implementation-Build"); - } - } catch (IOException ex) { - log.error("failed to read version", ex); - } finally { - version = tmp; - log.info("BKU Web Start " + version); - } - } - private Configurator config; - private Container server; - private BasicService basicService; - private StatusNotifier status; - - public Launcher() { - log.info("Initializing Launcher"); - - // SocketPerm * required (DataURL), FilePermission * write (JFileChooser) required, - // jetty does not allow fine-grained permission config (codeBase?) - // ie. we don't need a security manager - log.trace("disabling (JNLP) security manager"); - System.setSecurityManager(null); - - status = new MOCCAIcon(this); - } - - public void launch() throws Exception { - initStart(); - try { - initConfig(); - } catch (Exception ex) { - log.error("Failed to initialize configuration", ex); - status.error(StatusNotifier.ERROR_CONFIG); - throw ex; - } - try { - startServer(); - initFinished(); - } catch (BindException ex) { - log.error("Failed to launch server, " + ex.getMessage(), ex); - status.error(StatusNotifier.ERROR_BIND); - throw ex; - } catch (MultiException ex) { - log.error("Failed to launch server, " + ex.getMessage(), ex); - if (ex.getThrowable(0) instanceof BindException) { - status.error(StatusNotifier.ERROR_BIND); - } else { - status.error(StatusNotifier.ERROR_START); - } - throw ex; - } catch (Exception ex) { - ex.printStackTrace(); - log.error("Failed to launch server, " + ex.getMessage(), ex); - status.error(StatusNotifier.ERROR_START); - throw ex; - } - } - - private void browse(URL url) throws IOException, URISyntaxException { - // don't use basicService.showDocument(), which causes a java ssl warning dialog - if (Desktop.isDesktopSupported()) { - Desktop desktop = Desktop.getDesktop(); - if (desktop.isSupported(Desktop.Action.BROWSE)) { - desktop.browse(url.toURI()); - return; - } - } - throw new IOException("current platform does not support Java Desktop API"); - } - - private void initStart() { - try { - status.info(StatusNotifier.MESSAGE_START); - basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService"); - if (basicService.isOffline()) { - log.info("launching MOCCA Web Start offline"); - } else { - log.info("launching MOCCA Web Start online"); - } - } catch (UnavailableServiceException ex) { - log.info("Failed to obtain JNLP service: " + ex.getMessage()); - } - } - - private void initConfig() throws IOException, CodingException, GeneralSecurityException { - config = new Configurator(); - config.ensureConfiguration(); - config.ensureCertificates(); - } - - private void startServer() throws Exception { - log.info("init servlet container and MOCCA webapp"); - server = new Container(); - server.init(); - server.start(); - } - - private void initFinished() { - try { - status.info(StatusNotifier.MESSAGE_FINISHED); - // standalone (non-webstart) version has splashscreen - if (SplashScreen.getSplashScreen() != null) { - try { - SplashScreen.getSplashScreen().close(); - } catch (IllegalStateException ex) { - log.warn("Failed to close splash screen: " + ex.getMessage()); - } - } - if (config.isCertRenewed()) { - try { - if ("".equals(status.getLocale().getLanguage())) { - browse(HTTP_SECURITY_LAYER_URL); - } else { - browse(new URL(HTTP_SECURITY_LAYER_URL, status.getLocale().getLanguage())); - } - } catch (Exception ex) { - log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL, ex); - } - } - log.info("BKU successfully started"); - server.join(); - } catch (InterruptedException e) { - log.warn("failed to join server: " + e.getMessage(), e); - } - } - - @Override - public void shutDown() { - log.info("Shutting down server"); - status.info(StatusNotifier.MESSAGE_SHUTDOWN); - if ((server != null) && (server.isRunning())) { - try { - if (server.isRunning()) { - server.stop(); - } - } catch (Exception e) { - log.debug(e.toString()); - } finally { - if (server.isRunning()) { - server.destroy(); - } - } - } - System.exit(0); - } - - public static void main(String[] args) throws InterruptedException, IOException { - try { - Launcher launcher = new Launcher(); - launcher.launch(); - } catch (Exception ex) { - ex.printStackTrace(); - log.debug("Caught exception " + ex.getMessage(), ex); - log.info("waiting to shutdown..."); - Thread.sleep(5000); - log.info("exit"); - System.exit(-1000); - } - } - - @Override - public void showHelp(Locale locale) { - try { - if ("".equals(locale.getLanguage())) { - browse(HELP_URL); - } else { - browse(new URL(HELP_URL, locale.getLanguage())); - } - } catch (Exception ex) { - log.error("Failed to open " + HELP_URL, ex); - status.error(StatusNotifier.ERROR_OPEN_URL, HELP_URL); - } - - } - - @Override - public void pinManagement(Locale locale) { - new Thread(new PINManagementInvoker(status)).start(); - } - - @Override - public String getVersion() { - return version; - } -} +package at.gv.egiz.bku.webstart; + +import at.gv.egiz.bku.webstart.autostart.Autostart; +import at.gv.egiz.bku.webstart.gui.StatusNotifier; +import at.gv.egiz.bku.webstart.gui.BKUControllerInterface; +import at.gv.egiz.bku.webstart.gui.MOCCAIcon; +import iaik.asn1.CodingException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Locale; + +import javax.jnlp.UnavailableServiceException; + +//import com.sun.javaws.security.JavaWebStartSecurity; +import java.awt.Desktop; +import java.awt.SplashScreen; +import java.net.BindException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import javax.jnlp.BasicService; +import javax.jnlp.ServiceManager; +import org.mortbay.util.MultiException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Launcher implements BKUControllerInterface { + + public static final String WEBAPP_RESOURCE = "BKULocal.war"; + public static final String CERTIFICATES_RESOURCE = "BKUCertificates.jar"; + public static final String WEBAPP_FILE = "BKULocal.war"; + /** no leading slash for messages, but for image */ + public static final String MESSAGES_RESOURCE = "at/gv/egiz/bku/webstart/messages"; + public static final String TRAYICON_RESOURCE = "/at/gv/egiz/bku/webstart/chip"; + private static final String WEBSTART_FILENAME = "mocca.jnlp"; + private static Logger log = LoggerFactory.getLogger(Launcher.class); + /** local bku uri */ + public static final URL HTTP_SECURITY_LAYER_URL; + public static final URL HTTPS_SECURITY_LAYER_URL; + public static final URL INSTALL_CERT_URL; + public static final URL PIN_MANAGEMENT_URL; + public static final URL HELP_URL; + + static { + URL http = null; + URL https = null; + URL pin = null; + URL cert = null; + URL help = null; + try { + http = new URL("http://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3495).intValue() + '/'); + https = new URL("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue() + '/'); + pin = new URL(http, "/PINManagement"); + cert = new URL(http, "/ca.crt"); + help = new URL(http, "/help/"); + } catch (MalformedURLException ex) { + log.error("Failed to create URL.", ex); + } finally { + HTTP_SECURITY_LAYER_URL = http; + HTTPS_SECURITY_LAYER_URL = https; + PIN_MANAGEMENT_URL = pin; + INSTALL_CERT_URL = cert; + HELP_URL = help; + } + } + public static final String version; + + static { + String tmp = Configurator.UNKOWN_VERSION; + try { + String bkuWebStartJar = Launcher.class.getProtectionDomain().getCodeSource().getLocation().toString(); + URL manifestURL = new URL("jar:" + bkuWebStartJar + "!/META-INF/MANIFEST.MF"); + if (log.isTraceEnabled()) { + log.trace("read version information from " + manifestURL); + } + Manifest manifest = new Manifest(manifestURL.openStream()); + Attributes atts = manifest.getMainAttributes(); + if (atts != null) { + tmp = atts.getValue("Implementation-Build"); + } + } catch (IOException ex) { + log.error("failed to read version", ex); + } finally { + version = tmp; + log.info("BKU Web Start " + version); + } + } + private Configurator config; + private Container server; + private BasicService basicService; + private StatusNotifier status; + private Autostart autostart; + + private static URL codeBase; + + public Launcher() { + log.info("Initializing Launcher"); + + // SocketPerm * required (DataURL), FilePermission * write (JFileChooser) required, + // jetty does not allow fine-grained permission config (codeBase?) + // ie. we don't need a security manager + log.trace("disabling (JNLP) security manager"); + System.setSecurityManager(null); + + autostart = new Autostart(); + status = new MOCCAIcon(this); + } + + public void launch() throws Exception { + initStart(); + try { + initConfig(); + } catch (Exception ex) { + log.error("Failed to initialize configuration", ex); + status.error(StatusNotifier.ERROR_CONFIG); + throw ex; + } + try { + startServer(); + initFinished(); + } catch (BindException ex) { + log.error("Failed to launch server, " + ex.getMessage(), ex); + status.error(StatusNotifier.ERROR_BIND); + throw ex; + } catch (MultiException ex) { + log.error("Failed to launch server, " + ex.getMessage(), ex); + if (ex.getThrowable(0) instanceof BindException) { + status.error(StatusNotifier.ERROR_BIND); + } else { + status.error(StatusNotifier.ERROR_START); + } + throw ex; + } catch (Exception ex) { + ex.printStackTrace(); + log.error("Failed to launch server, " + ex.getMessage(), ex); + status.error(StatusNotifier.ERROR_START); + throw ex; + } + } + + private void browse(URL url) throws IOException, URISyntaxException { + // don't use basicService.showDocument(), which causes a java ssl warning dialog + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + if (desktop.isSupported(Desktop.Action.BROWSE)) { + desktop.browse(url.toURI()); + return; + } + } + throw new IOException("current platform does not support Java Desktop API"); + } + + private void initStart() { + try { + status.info(StatusNotifier.MESSAGE_START); + basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService"); + codeBase = basicService.getCodeBase(); + autostart.setWebstartName(codeBase + WEBSTART_FILENAME); + if (basicService.isOffline()) { + log.info("launching MOCCA Web Start offline"); + } else { + log.info("launching MOCCA Web Start online"); + } + } catch (UnavailableServiceException ex) { + log.info("Failed to obtain JNLP service: " + ex.getMessage()); + } + } + + private void initConfig() throws IOException, CodingException, GeneralSecurityException { + config = new Configurator(); + config.ensureConfiguration(); + config.ensureCertificates(); + } + + private void startServer() throws Exception { + log.info("init servlet container and MOCCA webapp"); + server = new Container(); + server.init(); + server.start(); + } + + private void initFinished() { + try { + status.info(StatusNotifier.MESSAGE_FINISHED); + // standalone (non-webstart) version has splashscreen + if (SplashScreen.getSplashScreen() != null) { + try { + SplashScreen.getSplashScreen().close(); + } catch (IllegalStateException ex) { + log.warn("Failed to close splash screen: " + ex.getMessage()); + } + } + if (config.isCertRenewed()) { + try { + if ("".equals(status.getLocale().getLanguage())) { + browse(HTTP_SECURITY_LAYER_URL); + } else { + browse(new URL(HTTP_SECURITY_LAYER_URL, status.getLocale().getLanguage())); + } + } catch (Exception ex) { + log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL, ex); + } + } + log.info("BKU successfully started"); + server.join(); + } catch (InterruptedException e) { + log.warn("failed to join server: " + e.getMessage(), e); + } + } + + @Override + public void shutDown() { + log.info("Shutting down server"); + status.info(StatusNotifier.MESSAGE_SHUTDOWN); + if ((server != null) && (server.isRunning())) { + try { + if (server.isRunning()) { + server.stop(); + } + } catch (Exception e) { + log.debug(e.toString()); + } finally { + if (server.isRunning()) { + server.destroy(); + } + } + } + System.exit(0); + } + + public static void main(String[] args) throws InterruptedException, IOException { + try { + Launcher launcher = new Launcher(); + launcher.launch(); + } catch (Exception ex) { + ex.printStackTrace(); + log.debug("Caught exception " + ex.getMessage(), ex); + log.info("waiting to shutdown..."); + Thread.sleep(5000); + log.info("exit"); + System.exit(-1000); + } + } + + @Override + public void showHelp(Locale locale) { + try { + if ("".equals(locale.getLanguage())) { + browse(HELP_URL); + } else { + browse(new URL(HELP_URL, locale.getLanguage())); + } + } catch (Exception ex) { + log.error("Failed to open " + HELP_URL, ex); + status.error(StatusNotifier.ERROR_OPEN_URL, HELP_URL); + } + + } + + @Override + public void pinManagement(Locale locale) { + new Thread(new PINManagementInvoker(status)).start(); + } + + @Override + public String getVersion() { + return version; + } + + @Override + public boolean isAutostartEnabled() { + return autostart.isEnabled(); + } + @Override + public boolean setAutostart(boolean doAutostart) { + return autostart.set(doAutostart); + } +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AbstractAutostart.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AbstractAutostart.java new file mode 100644 index 00000000..5e7966b8 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AbstractAutostart.java @@ -0,0 +1,38 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +public abstract class AbstractAutostart implements AutostartInterface { + protected static final String AUTOSTART_FILENAME_PREFIX = "MOCCA"; + + String _os = System.getProperty("os.name"); + String _userHome = System.getProperty("user.home") + System.getProperty("file.separator"); + String _webstartName = null; + + @Override + public void setWebstartName(String webstartName) { + _webstartName = webstartName; + } + +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/Autostart.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/Autostart.java new file mode 100644 index 00000000..a3291d05 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/Autostart.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +public class Autostart { + private static AutostartInterface _autostart = null; + + private String _webstartName = null; + + private AutostartInterface getAutostart() + { + if (_autostart == null) + { + String os = System.getProperty("os.name"); + if (os.equalsIgnoreCase("linux")) + _autostart = new AutostartLinux(); + else if (os.toLowerCase().contains("windows")) + _autostart = new AutostartWindows(); + if (_webstartName != null) + _autostart.setWebstartName(_webstartName); + } + + return _autostart; + } + + public boolean isEnabled() { + if (getAutostart() == null) + return false; + + return getAutostart().isEnabled(); + } + + public boolean set(boolean enable) { + if (getAutostart() == null) + return false; + + return getAutostart().set(enable); + } + + public void setWebstartName(String webstartName) { + if (_autostart == null) + _webstartName = webstartName; + else + _autostart.setWebstartName(webstartName); + } + +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartInterface.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartInterface.java new file mode 100644 index 00000000..f085fc94 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartInterface.java @@ -0,0 +1,30 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +public interface AutostartInterface { + public boolean isEnabled(); + public boolean set(boolean enable); + public void setWebstartName(String webstartName); +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartLinux.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartLinux.java new file mode 100644 index 00000000..4fc91a30 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartLinux.java @@ -0,0 +1,135 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AutostartLinux extends AbstractAutostart { + private static Logger log = LoggerFactory.getLogger(AutostartLinux.class); + + private Map getAutostartFiles() + { + Map autostartFiles = new HashMap(); + String autostartFileName, autostartFileContent; + String autostartCommand = "javaws -Xnosplash " + _webstartName; + + // KDE Autostart + File f = new File(_userHome + ".kde/Autostart"); + if ((f.exists()) && (f.isDirectory())) { + autostartFileName = _userHome + ".kde/Autostart/" + + AUTOSTART_FILENAME_PREFIX + ".sh"; + autostartFileContent = "#!/bin/sh\n" + autostartCommand + "\n"; + autostartFiles.put(autostartFileName, autostartFileContent); + } + + // Gnome Autostart + f = new File(_userHome + ".config/autostart"); + if ((f.exists()) && (f.isDirectory())) { + autostartFileName = _userHome + ".config/autostart/" + + AUTOSTART_FILENAME_PREFIX + ".desktop"; + autostartFileContent = + "[Desktop Entry]\n" + + "Name=" + AUTOSTART_FILENAME_PREFIX + "\n" + + "Type=Application\n" + + "Exec=" + autostartCommand + "\n" + + "Terminal=false\n" + + "Hidden=false\n"; + autostartFiles.put(autostartFileName, autostartFileContent); + } + return autostartFiles; + } + + @Override + public boolean isEnabled() { + Map autostartFiles = getAutostartFiles(); + + if (autostartFiles.isEmpty()) + return false; + + for (Map.Entry file : autostartFiles.entrySet()) { + String autostartFileName = file.getKey(); + try { + File f = new File(autostartFileName); + if (f.exists()) + return true; + } catch (Exception e) { + // ignore + } + } + return false; + } + + @Override + public boolean set(boolean enable) { + Map autostartFiles = getAutostartFiles(); + + if (autostartFiles.isEmpty()) + return false; + + boolean ret = false; + for (Map.Entry file : autostartFiles.entrySet()) { + String autostartFileName = file.getKey(); + String autostartFileContent = file.getValue(); + File f = new File(autostartFileName); + + if (enable) + { + log.debug("Enabling AutoStart (" + autostartFileName + ")"); + try { + FileWriter fw = new FileWriter(f, false); + BufferedWriter bw = new BufferedWriter(fw); + bw.write(autostartFileContent); + bw.flush(); + bw.close(); + fw.close(); + if (autostartFileName.contains(".kde")) + f.setExecutable(true, false); + f.setReadable(true, false); + ret = true; + } catch (Exception e) { + log.error("Failed to add autostart file", e); + } + } + else + { + log.debug("Disabling AutoStart (" + autostartFileName + ")"); + try { + f.delete(); + } catch (Exception e) { + log.error("Failed to remove autostart file", e); + } + } + } + + return ret; + } + +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartWindows.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartWindows.java new file mode 100644 index 00000000..50c38d97 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/AutostartWindows.java @@ -0,0 +1,207 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.channels.FileChannel; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class AutostartWindows extends AbstractAutostart { + private static Logger log = LoggerFactory.getLogger(AutostartWindows.class); + private static final String DESKTOP_SHORTCUT_NAME = "MOCCA Start.lnk"; + + private String _linkname = null; + + public AutostartWindows() { + try { + // BKA Workaround: If shortcut exists on desktop, use it for autostart + _linkname = WinRegistry.readString( + WinRegistry.HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + "Desktop") + + "\\" + DESKTOP_SHORTCUT_NAME; + File f = new File(_linkname); + if (f.exists()) + return; + _linkname = WinRegistry.readString( + WinRegistry.HKEY_LOCAL_MACHINE, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + "Common Desktop") + + "\\" + DESKTOP_SHORTCUT_NAME; + f = new File(_linkname); + if (f.exists()) + return; + _linkname = null; + } catch (Exception e) { + log.debug("Registry reading failed", e); + } + } + + private static boolean copyFile(File srcF, File dstF) { + boolean ret = false; + try { + if (!dstF.exists()) + dstF.createNewFile(); + FileChannel src = null; + FileChannel dst = null; + try { + src = new FileInputStream(srcF).getChannel(); + dst = new FileOutputStream(dstF).getChannel(); + if (dst.transferFrom(src, 0, src.size()) < src.size()) { + dst.close(); + dst = null; + dstF.delete(); + log.error("Failed to copy autostart shortcut"); + } else + ret = true; + } catch (FileNotFoundException e) { + log.error("Failed to copy autostart shortcut", e); + } finally { + if (src != null) + src.close(); + if (dst != null) + dst.close(); + } + } catch (IOException e) { + log.error("Failed to copy autostart shortcut", e); + } + return ret; + } + + private static boolean createFile(File f, String content) { + try { + FileWriter fw = new FileWriter(f, false); + BufferedWriter bw = new BufferedWriter(fw); + bw.write(content); + bw.flush(); + bw.close(); + fw.close(); + f.setExecutable(true); + return true; + } catch (Exception e) { + log.error("Failed to add autostart file", e); + } + return false; + } + + private String getAutostartFileName() { + String fileName = AUTOSTART_FILENAME_PREFIX + + (_linkname != null ? ".lnk" : ".bat"); + String autostartFileName = null; + try { + autostartFileName = WinRegistry + .readString( + WinRegistry.HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + "Startup"); + if (autostartFileName == null) + throw new Exception("Null returned"); + autostartFileName += "\\" + fileName; + } catch (Exception e) { + log.debug("Registry reading failed - trying fallback", e); + + String autostartFolderPaths[] = { + _userHome + "Startmenü\\Programme\\Autostart", // German + // Windows + // default + // autostart + // path + _userHome + "Startmenu\\Programs\\Startup" // English + // Windows + // default + // autostart + // path + }; + + for (String path : autostartFolderPaths) { + File f = new File(path); + if (f.exists()) { + autostartFileName = _userHome + path + "\\" + fileName; + break; + } + } + } + return autostartFileName; + } + + @Override + public boolean isEnabled() { + String autostartFileName = getAutostartFileName(); + + if (autostartFileName == null) + return false; + + try { + File f = new File(autostartFileName); + if (f.exists()) + return true; + } catch (Exception e) { + // ignore + } + return false; + } + + @Override + public boolean set(boolean enable) { + String autostartFileName = getAutostartFileName(); + + if (autostartFileName == null) + return false; + + String javaws_loc = System.getProperty("java.home") + + "\\bin\\javaws.exe"; + File f = new File(javaws_loc); + if (!f.exists()) + javaws_loc = "javaws.exe"; + String autostartFileContent = "@\"" + javaws_loc + "\" -Xnosplash " + + _webstartName + "\r\n"; + + f = new File(autostartFileName); + + if (enable) { + log.debug("Enabling AutoStart (" + autostartFileName + ")"); + if (_linkname != null) + return copyFile(new File(_linkname), f); + else + return createFile(f, autostartFileContent); + } else { + log.debug("Disabling AutoStart (" + autostartFileName + ")"); + try { + f.delete(); + } catch (Exception e) { + log.error("Failed to remove autostart file", e); + } + return false; + } + } + +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/WinRegistry.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/WinRegistry.java new file mode 100644 index 00000000..8a79d227 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/autostart/WinRegistry.java @@ -0,0 +1,386 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + +package at.gv.egiz.bku.webstart.autostart; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.Map; +import java.util.ArrayList; +import java.util.List; +import java.util.prefs.Preferences; + +public class WinRegistry { + public static final int HKEY_CURRENT_USER = 0x80000001; + public static final int HKEY_LOCAL_MACHINE = 0x80000002; + public static final int REG_SUCCESS = 0; + public static final int REG_NOTFOUND = 2; + public static final int REG_ACCESSDENIED = 5; + +// private static final int KEY_ALL_ACCESS = 0xf003f; + private static final int KEY_READ = 0x20019; + private static Preferences userRoot = Preferences.userRoot(); + private static Preferences systemRoot = Preferences.systemRoot(); + private static Class userClass = userRoot.getClass(); + private static Method regOpenKey = null; + private static Method regCloseKey = null; + private static Method regQueryValueEx = null; + private static Method regEnumValue = null; + private static Method regQueryInfoKey = null; + private static Method regEnumKeyEx = null; +// private static Method regCreateKeyEx = null; +// private static Method regSetValueEx = null; +// private static Method regDeleteKey = null; +// private static Method regDeleteValue = null; + + static { + try { + regOpenKey = userClass.getDeclaredMethod("WindowsRegOpenKey", + new Class[] { int.class, byte[].class, int.class }); + regOpenKey.setAccessible(true); + regCloseKey = userClass.getDeclaredMethod("WindowsRegCloseKey", + new Class[] { int.class }); + regCloseKey.setAccessible(true); + regQueryValueEx = userClass.getDeclaredMethod( + "WindowsRegQueryValueEx", new Class[] { int.class, + byte[].class }); + regQueryValueEx.setAccessible(true); + regEnumValue = userClass.getDeclaredMethod("WindowsRegEnumValue", + new Class[] { int.class, int.class, int.class }); + regEnumValue.setAccessible(true); + regQueryInfoKey = userClass.getDeclaredMethod( + "WindowsRegQueryInfoKey1", new Class[] { int.class }); + regQueryInfoKey.setAccessible(true); + regEnumKeyEx = userClass.getDeclaredMethod("WindowsRegEnumKeyEx", + new Class[] { int.class, int.class, int.class }); + regEnumKeyEx.setAccessible(true); +// regCreateKeyEx = userClass.getDeclaredMethod( +// "WindowsRegCreateKeyEx", new Class[] { int.class, +// byte[].class }); +// regCreateKeyEx.setAccessible(true); +// regSetValueEx = userClass.getDeclaredMethod("WindowsRegSetValueEx", +// new Class[] { int.class, byte[].class, byte[].class }); +// regSetValueEx.setAccessible(true); +// regDeleteValue = userClass.getDeclaredMethod( +// "WindowsRegDeleteValue", new Class[] { int.class, +// byte[].class }); +// regDeleteValue.setAccessible(true); +// regDeleteKey = userClass.getDeclaredMethod("WindowsRegDeleteKey", +// new Class[] { int.class, byte[].class }); +// regDeleteKey.setAccessible(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private WinRegistry() { + } + + /** + * Read a value from key and value name + * + * @param hkey + * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE + * @param key + * @param valueName + * @return the value + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static String readString(int hkey, String key, String valueName) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + if (hkey == HKEY_LOCAL_MACHINE) { + return readString(systemRoot, hkey, key, valueName); + } else if (hkey == HKEY_CURRENT_USER) { + return readString(userRoot, hkey, key, valueName); + } else { + throw new IllegalArgumentException("hkey=" + hkey); + } + } + + /** + * Read value(s) and value name(s) form given key + * + * @param hkey + * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE + * @param key + * @return the value name(s) plus the value(s) + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static Map readStringValues(int hkey, String key) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + if (hkey == HKEY_LOCAL_MACHINE) { + return readStringValues(systemRoot, hkey, key); + } else if (hkey == HKEY_CURRENT_USER) { + return readStringValues(userRoot, hkey, key); + } else { + throw new IllegalArgumentException("hkey=" + hkey); + } + } + + /** + * Read the value name(s) from a given key + * + * @param hkey + * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE + * @param key + * @return the value name(s) + * @throws IllegalArgumentException + * @throws IllegalAccessException + * @throws InvocationTargetException + */ + public static List readStringSubKeys(int hkey, String key) + throws IllegalArgumentException, IllegalAccessException, + InvocationTargetException { + if (hkey == HKEY_LOCAL_MACHINE) { + return readStringSubKeys(systemRoot, hkey, key); + } else if (hkey == HKEY_CURRENT_USER) { + return readStringSubKeys(userRoot, hkey, key); + } else { + throw new IllegalArgumentException("hkey=" + hkey); + } + } + +// /** +// * Create a key +// * +// * @param hkey +// * HKEY_CURRENT_USER/HKEY_LOCAL_MACHINE +// * @param key +// * @throws IllegalArgumentException +// * @throws IllegalAccessException +// * @throws InvocationTargetException +// */ +// public static void createKey(int hkey, String key) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// int[] ret; +// if (hkey == HKEY_LOCAL_MACHINE) { +// ret = createKey(systemRoot, hkey, key); +// regCloseKey +// .invoke(systemRoot, new Object[] { new Integer(ret[0]) }); +// } else if (hkey == HKEY_CURRENT_USER) { +// ret = createKey(userRoot, hkey, key); +// regCloseKey.invoke(userRoot, new Object[] { new Integer(ret[0]) }); +// } else { +// throw new IllegalArgumentException("hkey=" + hkey); +// } +// if (ret[1] != REG_SUCCESS) { +// throw new IllegalArgumentException("rc=" + ret[1] + " key=" + key); +// } +// } + +// /** +// * Write a value in a given key/value name +// * +// * @param hkey +// * @param key +// * @param valueName +// * @param value +// * @throws IllegalArgumentException +// * @throws IllegalAccessException +// * @throws InvocationTargetException +// */ +// public static void writeStringValue(int hkey, String key, String valueName, +// String value) throws IllegalArgumentException, +// IllegalAccessException, InvocationTargetException { +// if (hkey == HKEY_LOCAL_MACHINE) { +// writeStringValue(systemRoot, hkey, key, valueName, value); +// } else if (hkey == HKEY_CURRENT_USER) { +// writeStringValue(userRoot, hkey, key, valueName, value); +// } else { +// throw new IllegalArgumentException("hkey=" + hkey); +// } +// } + +// /** +// * Delete a given key +// * +// * @param hkey +// * @param key +// * @throws IllegalArgumentException +// * @throws IllegalAccessException +// * @throws InvocationTargetException +// */ +// public static void deleteKey(int hkey, String key) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// int rc = -1; +// if (hkey == HKEY_LOCAL_MACHINE) { +// rc = deleteKey(systemRoot, hkey, key); +// } else if (hkey == HKEY_CURRENT_USER) { +// rc = deleteKey(userRoot, hkey, key); +// } +// if (rc != REG_SUCCESS) { +// throw new IllegalArgumentException("rc=" + rc + " key=" + key); +// } +// } + +// /** +// * delete a value from a given key/value name +// * +// * @param hkey +// * @param key +// * @param value +// * @throws IllegalArgumentException +// * @throws IllegalAccessException +// * @throws InvocationTargetException +// */ +// public static void deleteValue(int hkey, String key, String value) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// int rc = -1; +// if (hkey == HKEY_LOCAL_MACHINE) { +// rc = deleteValue(systemRoot, hkey, key, value); +// } else if (hkey == HKEY_CURRENT_USER) { +// rc = deleteValue(userRoot, hkey, key, value); +// } +// if (rc != REG_SUCCESS) { +// throw new IllegalArgumentException("rc=" + rc + " key=" + key +// + " value=" + value); +// } +// } + + // ===================== + +// private static int deleteValue(Preferences root, int hkey, String key, +// String value) throws IllegalArgumentException, +// IllegalAccessException, InvocationTargetException { +// int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { +// new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) }); +// if (handles[1] != REG_SUCCESS) { +// return handles[1]; // can be REG_NOTFOUND, REG_ACCESSDENIED +// } +// int rc = ((Integer) regDeleteValue.invoke(root, new Object[] { +// new Integer(handles[0]), toCstr(value) })).intValue(); +// regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) }); +// return rc; +// } + +// private static int deleteKey(Preferences root, int hkey, String key) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// int rc = ((Integer) regDeleteKey.invoke(root, new Object[] { +// new Integer(hkey), toCstr(key) })).intValue(); +// return rc; // can REG_NOTFOUND, REG_ACCESSDENIED, REG_SUCCESS +// } + + private static String readString(Preferences root, int hkey, String key, + String value) throws IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { + new Integer(hkey), toCstr(key), new Integer(KEY_READ) }); + if (handles[1] != REG_SUCCESS) { + return null; + } + byte[] valb = (byte[]) regQueryValueEx.invoke(root, new Object[] { + new Integer(handles[0]), toCstr(value) }); + regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) }); + return (valb != null ? new String(valb).trim() : null); + } + + private static Map readStringValues(Preferences root, + int hkey, String key) throws IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + HashMap results = new HashMap(); + int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { + new Integer(hkey), toCstr(key), new Integer(KEY_READ) }); + if (handles[1] != REG_SUCCESS) { + return null; + } + int[] info = (int[]) regQueryInfoKey.invoke(root, + new Object[] { new Integer(handles[0]) }); + + int count = info[2]; // count + int maxlen = info[3]; // value length max + for (int index = 0; index < count; index++) { + byte[] name = (byte[]) regEnumValue.invoke(root, new Object[] { + new Integer(handles[0]), new Integer(index), + new Integer(maxlen + 1) }); + String value = readString(hkey, key, new String(name)); + results.put(new String(name).trim(), value); + } + regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) }); + return results; + } + + private static List readStringSubKeys(Preferences root, int hkey, + String key) throws IllegalArgumentException, + IllegalAccessException, InvocationTargetException { + List results = new ArrayList(); + int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { + new Integer(hkey), toCstr(key), new Integer(KEY_READ) }); + if (handles[1] != REG_SUCCESS) { + return null; + } + int[] info = (int[]) regQueryInfoKey.invoke(root, + new Object[] { new Integer(handles[0]) }); + + int count = info[2]; // count + int maxlen = info[3]; // value length max + for (int index = 0; index < count; index++) { + byte[] name = (byte[]) regEnumKeyEx.invoke(root, new Object[] { + new Integer(handles[0]), new Integer(index), + new Integer(maxlen + 1) }); + results.add(new String(name).trim()); + } + regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) }); + return results; + } + +// private static int[] createKey(Preferences root, int hkey, String key) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// return (int[]) regCreateKeyEx.invoke(root, new Object[] { +// new Integer(hkey), toCstr(key) }); +// } + +// private static void writeStringValue(Preferences root, int hkey, +// String key, String valueName, String value) +// throws IllegalArgumentException, IllegalAccessException, +// InvocationTargetException { +// int[] handles = (int[]) regOpenKey.invoke(root, new Object[] { +// new Integer(hkey), toCstr(key), new Integer(KEY_ALL_ACCESS) }); +// +// regSetValueEx.invoke(root, new Object[] { new Integer(handles[0]), +// toCstr(valueName), toCstr(value) }); +// regCloseKey.invoke(root, new Object[] { new Integer(handles[0]) }); +// } + + // utility + private static byte[] toCstr(String str) { + byte[] result = new byte[str.length() + 1]; + + for (int i = 0; i < str.length(); i++) { + result[i] = (byte) str.charAt(i); + } + result[str.length()] = 0; + return result; + } +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java index 16067614..91ce0e77 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java @@ -36,4 +36,17 @@ public interface BKUControllerInterface { public void pinManagement(Locale locale); + + /** + * Check if MOCCA Autostart is enabled + * @return autostart state + */ + boolean isAutostartEnabled(); + + /** + * Set MOCCA Autostart + * @param doAutostart whether to enable or disable autostart + * @return new autostart state + */ + public boolean setAutostart(boolean doAutostart); } diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/MOCCAIcon.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/MOCCAIcon.java index afc14889..d6dc6d5b 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/MOCCAIcon.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/MOCCAIcon.java @@ -21,17 +21,20 @@ * that you distribute must include a readable copy of the "NOTICE" text file. */ - package at.gv.egiz.bku.webstart.gui; import java.awt.AWTException; +import java.awt.CheckboxMenuItem; import java.awt.Image; +import java.awt.Menu; import java.awt.MenuItem; import java.awt.PopupMenu; import java.awt.SystemTray; import java.awt.TrayIcon; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; import java.awt.event.WindowAdapter; import java.io.IOException; import java.text.MessageFormat; @@ -43,21 +46,24 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * - * @author clemens + * @author clemenso + * @author tkellner */ -public class MOCCAIcon implements StatusNotifier, ActionListener { +public class MOCCAIcon implements StatusNotifier, ActionListener, ItemListener { public static final String LABEL_SHUTDOWN = "tray.label.shutdown"; public static final String LABEL_PIN = "tray.label.pin"; public static final String LABEL_HELP = "tray.label.help"; public static final String LABEL_ABOUT = "tray.label.about"; + public static final String LABEL_SETTINGS = "tray.label.settings"; + public static final String LABEL_AUTOSTART = "tray.label.autostart"; public static final String TOOLTIP_DEFAULT = "tray.tooltip.default"; + /** action commands for tray menu */ - public static final String SHUTDOWN_COMMAND = "shutdown"; - public static final String PIN_COMMAND = "pin"; - public static final String ABOUT_COMMAND = "about"; - public static final String HELP_COMMAND = "help"; + private static enum COMMANDS { + SHUTDOWN_COMMAND, PIN_COMMAND, ABOUT_COMMAND, HELP_COMMAND, AUTOSTART_COMMAND + }; + private static final Logger log = LoggerFactory.getLogger(MOCCAIcon.class); protected BKUControllerInterface controller; protected TrayIcon trayIcon; @@ -67,7 +73,8 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { public MOCCAIcon(BKUControllerInterface controller) { this.controller = controller; - messages = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault()); + messages = ResourceBundle.getBundle(MESSAGES_RESOURCE, + Locale.getDefault()); this.trayIcon = initTrayIcon(); } @@ -88,33 +95,49 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { } else { iconResource = TRAYICON_RESOURCE + "48.png"; } - Image image = ImageIO.read(getClass().getResourceAsStream(iconResource)); + Image image = ImageIO.read(getClass().getResourceAsStream( + iconResource)); PopupMenu menu = new PopupMenu(); MenuItem helpItem = new MenuItem(messages.getString(LABEL_HELP)); helpItem.addActionListener(this); - helpItem.setActionCommand(HELP_COMMAND); + helpItem.setActionCommand(COMMANDS.HELP_COMMAND.name()); menu.add(helpItem); MenuItem pinItem = new MenuItem(messages.getString(LABEL_PIN)); pinItem.addActionListener(this); - pinItem.setActionCommand(PIN_COMMAND); + pinItem.setActionCommand(COMMANDS.PIN_COMMAND.name()); menu.add(pinItem); - MenuItem shutdownItem = new MenuItem(messages.getString(LABEL_SHUTDOWN)); - shutdownItem.addActionListener(this); - shutdownItem.setActionCommand(SHUTDOWN_COMMAND); - menu.add(shutdownItem); + MenuItem aboutItem = new MenuItem( + messages.getString(LABEL_ABOUT)); + aboutItem.setActionCommand(COMMANDS.ABOUT_COMMAND.name()); + aboutItem.addActionListener(this); + menu.add(aboutItem); menu.addSeparator(); - MenuItem aboutItem = new MenuItem(messages.getString(LABEL_ABOUT)); - aboutItem.setActionCommand(ABOUT_COMMAND); - aboutItem.addActionListener(this); - menu.add(aboutItem); + Menu settingsMenu = new Menu(messages.getString(LABEL_SETTINGS)); + menu.add(settingsMenu); + + CheckboxMenuItem autostartItem = new CheckboxMenuItem( + messages.getString(LABEL_AUTOSTART)); + autostartItem.addItemListener(this); + autostartItem.setActionCommand(COMMANDS.AUTOSTART_COMMAND.name()); + autostartItem.setState(controller.isAutostartEnabled()); + settingsMenu.add(autostartItem); - TrayIcon ti = new TrayIcon(image, messages.getString(TOOLTIP_DEFAULT), menu); + menu.addSeparator(); + + MenuItem shutdownItem = new MenuItem( + messages.getString(LABEL_SHUTDOWN)); + shutdownItem.addActionListener(this); + shutdownItem.setActionCommand(COMMANDS.SHUTDOWN_COMMAND.name()); + menu.add(shutdownItem); + + TrayIcon ti = new TrayIcon(image, + messages.getString(TOOLTIP_DEFAULT), menu); ti.setImageAutoSize(true); ti.addActionListener(this); tray.add(ti); @@ -133,10 +156,8 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { @Override public void error(String msgKey) { if (trayIcon != null) { - trayIcon.displayMessage( - messages.getString(CAPTION_ERROR), - messages.getString(msgKey), - TrayIcon.MessageType.ERROR); + trayIcon.displayMessage(messages.getString(CAPTION_ERROR), + messages.getString(msgKey), TrayIcon.MessageType.ERROR); } else { log.error(messages.getString(msgKey)); } @@ -145,22 +166,20 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { @Override public void error(String msgPatternKey, Object... argument) { if (trayIcon != null) { - trayIcon.displayMessage( - messages.getString(CAPTION_ERROR), - MessageFormat.format(messages.getString(msgPatternKey), argument), - TrayIcon.MessageType.ERROR); + trayIcon.displayMessage(messages.getString(CAPTION_ERROR), + MessageFormat.format(messages.getString(msgPatternKey), + argument), TrayIcon.MessageType.ERROR); } else { - log.error(MessageFormat.format(messages.getString(msgPatternKey), argument)); + log.error(MessageFormat.format(messages.getString(msgPatternKey), + argument)); } } @Override public void info(String msgKey) { if (trayIcon != null) { - trayIcon.displayMessage( - messages.getString(CAPTION_DEFAULT), - messages.getString(msgKey), - TrayIcon.MessageType.INFO); + trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT), + messages.getString(msgKey), TrayIcon.MessageType.INFO); } else { log.info(messages.getString(msgKey)); } @@ -173,18 +192,23 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { /** * Listen for TrayMenu actions (display error messages on trayIcon) + * * @param e */ @Override public void actionPerformed(ActionEvent e) { - if (SHUTDOWN_COMMAND.equals(e.getActionCommand())) { + switch (COMMANDS.valueOf(e.getActionCommand())) { + case SHUTDOWN_COMMAND: log.debug("shutdown requested via tray menu"); controller.shutDown(); - } else if (ABOUT_COMMAND.equals(e.getActionCommand())) { + break; + + case ABOUT_COMMAND: log.debug("about dialog requested via tray menu"); if (aboutDialog == null) { - aboutDialog = new AboutDialog(new JFrame(), true, controller.getVersion()); + aboutDialog = new AboutDialog(new JFrame(), true, + controller.getVersion()); aboutDialog.addWindowListener(new WindowAdapter() { @Override @@ -195,17 +219,34 @@ public class MOCCAIcon implements StatusNotifier, ActionListener { } aboutDialog.setLocationByPlatform(true); aboutDialog.setVisible(true); + break; - } else if (PIN_COMMAND.equals(e.getActionCommand())) { + case PIN_COMMAND: log.debug("pin management dialog requested via tray menu"); controller.pinManagement(messages.getLocale()); + break; - } else if (HELP_COMMAND.equals(e.getActionCommand())) { + case HELP_COMMAND: log.debug("help page requested via tray menu"); controller.showHelp(messages.getLocale()); + break; - } else { + default: log.error("unknown tray menu command: " + e.getActionCommand()); } } + + @Override + public void itemStateChanged(ItemEvent e) { + log.debug("autostart toggle requested via tray menu"); + CheckboxMenuItem item = (CheckboxMenuItem) e.getItemSelectable(); + switch (COMMANDS.valueOf(item.getActionCommand())) { + case AUTOSTART_COMMAND: + item.setState((controller.setAutostart(item.getState()))); + break; + + default: + log.error("unknown tray menu command: " + item.getActionCommand()); + } + } } -- cgit v1.2.3