2008-10-19 23 views
12

Como quedó claro en mi recent question, las aplicaciones Swing necesitan llamar explícitamente a System.exit() cuando se ejecutan utilizando el iniciador Sun Webstart (al menos como de Java SE 6).¿Cuál es la mejor manera de detectar si una aplicación se inicia con Webstart

Quiero restringir este truco tanto como sea posible y estoy buscando una forma confiable de detectar si la aplicación se está ejecutando en Webstart. En este momento estoy comprobando que el valor de la propiedad del sistema "webstart.version" no es nulo, pero no pude encontrar ninguna garantía en la documentación de que esta propiedad se establezca en futuras versiones/implementaciones alternativas.

¿Hay alguna manera mejor (preferiblemente los que no ceate una dependencia de la API de la WebStart?)

Respuesta

9

Cuando su código se inicia mediante javaws, se carga javaws.jar y están disponibles las clases de la API JNLP de las que no desea depender. En lugar de probar una propiedad del sistema que no está garantizado que existe, en su lugar podría ver si existe una clase API JNLP:

private boolean isRunningJavaWebStart() { 
    boolean hasJNLP = false; 
    try { 
     Class.forName("javax.jnlp.ServiceManager"); 
     hasJNLP = true; 
    } catch (ClassNotFoundException ex) { 
     hasJNLP = false; 
    } 
    return hasJNLP; 
} 

Esto también evita la necesidad de incluir javaws.jar en su ruta de clase al compilar.

Alternativamente podría pasar a compilar con javaws.jarra y la captura de NoClassDefFoundError lugar:

private boolean isRunningJavaWebStart() { 
    try { 
     ServiceManager.getServiceNames(); 
     return ds != null; 
    } catch (NoClassDefFoundError e) { 
     return false; 
    } 
} 

Usando ServiceManager.lookup (String) y UnavailableServiceException es problema porque ambos son parte de la API JNLP. El ServiceManager.getServiceNames() no está documentado para tirar. Estamos llamando específicamente a este código para buscar NoClassDefFoundError.

+2

jnlp.jar es suficiente, está disponible en el archivo zip que contiene las muestras y demostraciones de Java SE. Este JAR contiene solo las interfaces. Es mejor porque javaws.jar contiene toda la implementación, lo cual es inútil ya que el JRE ya lo proporciona, pero no está en el classpath (solo en el camino de arranque?). – gouessej

5

Uso del javax.jnlp.ServiceManager para recuperar un servicio WebStart. Si está disponible, se está ejecutando bajo Webstart.

Ver http://download.java.net/jdk7/docs/jre/api/javaws/jnlp/index.html

+0

Gracias por la sugerencia. Ya me lo figuré, pero resulta que WS no es parte de la ruta de clases JRE estándar y dado que no deseo enviar el archivo API, prefiero no usarlo (y no, la reflexión no es la respuesta que estoy buscando).) – ddimitrov

+0

O está utilizando el nuevo complemento 6u10 ... –

+2

@ddimitrov, ¿por qué quiere evitar la reflexión? Si obtiene una 'ClassNotFoundException' para' ServiceManager', sabrá que * no * se está ejecutando bajo JWS. – finnw

4

Como usted ha mencionado, comprobando la propiedad del sistema de la siguiente manera es probablemente la manera más limpia:

private boolean isRunningJavaWebStart() { 
    return System.getProperty("javawebstart.version", null) != null; 
} 

En un sistema de producción que he utilizado la técnica anterior durante años.

También puede intentar comprobar si hay propiedades que comiencen con "jnlpx". pero ninguno de ellos está realmente "garantizado" para estar allí, por lo que yo sé.

Una alternativa podría ser la de intentar crear una instancia del DownloadService nosotros sugerido por Tom:

private boolean isRunningJavaWebStart() { 
    try { 
     DownloadService ds = (DownloadService) ServiceManager.lookup("javax.jnlp.DownloadService"); 
     return ds != null; 
    } catch (UnavailableServiceException e) { 
     return false; 
    } 
} 

Por supuesto que sí tiene el inconveniente de acoplar el código para esa API.

+0

ServiceManager todavía está en el javaws.jar; ¿Sabes si hay alguna documentación oficial que indique las propiedades del sistema establecidas? – ddimitrov

+0

No pude encontrar nada en su documentación. El documento API no especifica ningún parámetro del sistema. Creo que si quieres la forma "oficial" de detectarWebStart tendrías que usar su API. –

+0

Hay implementaciones JNLP distintas de Sun's WebStart. –

3

No tengo ninguna experiencia real con Java web start, aparte de verlo hace unos años.

¿Qué le parece iniciar su aplicación con un parámetro que usted defina que el que configura cuando la aplicación se inicia a través de Java web start.

Si desea pasar argumentos a su aplicación, debe agregarlos al archivo de inicio (también conocido como descriptor JNLP) usando o elementos.

A continuación, compruebe si se han establecido estas propiedades.

De nuevo, esta es una sugerencia que no he codificado para JWS y puede que no sea tan fácil.

+0

Esa es una opción viable, pero requiere que la aplicación modifique su archivo jnlp extendiendo el hack en múltiples lugares. – ddimitrov

+1

O use una fuente principal separada. –

0

Puede verificar si el cargador de clases actual es una instancia de com.sun.jnlp.JNLPClassLoader (complemento de Java 1) o sun.plugin2.applet.JNLP2ClassLoader (complemento de Java 2). A pesar del paquete "applet", un applet que usa JNLP con el plugin Java 2 usa otro cargador de clases, sun.plugin2.applet.Applet2ClassLoader. Funciona con OpenJDK también.

Cuestiones relacionadas