Qual é a melhor maneira de detectar se um aplicativo é lançado por Webstart
-
03-07-2019 - |
Pergunta
Como ficou claro na minha recente questão , aplicações swing preciso chamar explicitamente System.exit () quando eles são correu usando o Sun Webstart lançador (pelo menos a partir de Java sE 6).
Eu quero restringir esse truque, tanto quanto possível e eu estou procurando uma maneira confiável para detectar se o aplicativo é executado sob Webstart. Agora eu estou verificando se o valor da propriedade do sistema "webstart.version" não é nulo, mas eu não poderia encontrar quaisquer garantias na documentação que esta propriedade deve ser definido por futuras versões / implementações alternativas.
Há alguma maneira melhor (de preferência aqueles que não ceate uma dependência na API do webstart?)
Solução
Quando seu código é lançado via javaws, javaws.jar é carregado e as classes de API JNLP que você não quer depender estão disponíveis. Em vez de testar para uma propriedade sistema que não é garantido que existe, você poderia, em vez ver se existe uma classe JNLP API:
private boolean isRunningJavaWebStart() {
boolean hasJNLP = false;
try {
Class.forName("javax.jnlp.ServiceManager");
hasJNLP = true;
} catch (ClassNotFoundException ex) {
hasJNLP = false;
}
return hasJNLP;
}
Isso também evita a necessidade de incluir javaws.jar em seu caminho de classe ao compilar.
Alternativamente, você pode mudar para compilar com javaws.jar e captura NoClassDefFoundError vez:
private boolean isRunningJavaWebStart() {
try {
ServiceManager.getServiceNames();
return ds != null;
} catch (NoClassDefFoundError e) {
return false;
}
}
Usando ServiceManager.lookup (String) e UnavailableServiceException é problema porque ambos são parte da API JNLP. Os ServiceManager.getServiceNames () não está documentada para jogar. Estamos especificamente chamando este código para verificar se há um NoClassDefFoundError.
Outras dicas
Use o javax.jnlp.ServiceManager para recuperar um serviço webstart. Se é availabe, você está executando sob Webstart.
http://download.java.net /jdk7/docs/jre/api/javaws/jnlp/index.html
Como você mencionou, verificando a propriedade Sistema conforme a seguir é provavelmente a maneira mais limpa:
private boolean isRunningJavaWebStart() {
return System.getProperty("javawebstart.version", null) != null;
}
Em um sistema de produção que tenho usado a técnica acima por anos.
Você também pode tentar verificar para ver se existem propriedades que começam com "jnlpx." mas nenhum deles é realmente "garantido" para estar lá, quer, tanto quanto eu sei.
Uma alternativa poderia ser a tentativa de instanciar o DownloadService-nos sugerido por Tom:
private boolean isRunningJavaWebStart() {
try {
DownloadService ds = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService");
return ds != null;
} catch (UnavailableServiceException e) {
return false;
}
}
É claro que tem a desvantagem de acoplar seu código para que API.
Eu não tenho nenhuma experiência real com o Java Web Start diferente de olhar para ela alguns anos atrás.
Que tal começar sua aplicação com um parâmetro que você definir do que você definiu quando o aplicativo é iniciado através de Java Web Start.
Se você quiser passar argumentos para a sua aplicação, você tem que adicioná-los ao arquivo de start-up (aka descritor JNLP), utilizando ou elementos.
Em seguida, verificar para ver se estas propriedades são definidas.
Novamente, esta é uma sugestão que eu não codificado para JWS e pode não ser tão fácil.
Você pode verificar se o carregador de classe atual é uma instância de com.sun.jnlp.JNLPClassLoader (plugin do Java 1) ou sun.plugin2.applet.JNLP2ClassLoader (plugin do Java 2). Apesar do pacote "miniaplicativo", um applet usando JNLP com o plugin do Java 2 usos outro carregador de classe, sun.plugin2.applet.Applet2ClassLoader. Ele funciona com OpenJDK também.