# Webstart + externe/lokale Plugins/JARS einbinden



## benhaze (19. Sep 2011)

Hallo liebe Freunde der Entwicklung!

Ich habe folgendes Problem:

Ich möchte meine Webstart-Anwendung so erweitern, das es möglich ist *lokale *JARs als Plugin einzubinden.

Das Ganze mache mit dem dem URLClassLoader.
Klappt als Standalone-App (also NICHT via Webstart) auch problemslos.

Als Webstart-App allerdings bekomme ich eine **access denied exception**, sobald das lokale JAR irgendwelche Security-Relevanten Dinge tut (z.B Systemvariablen auslesen).

Die liegt mit Sicherheit am Security-Context und der JNLP-Datei.
Die JNLP-Datzei kennt das Plugin/JAR nicht und dementsprechend hat:

```
<security>
        <all-permissions/>
    </security>
```
keine Wirkung bei dieser JAR.

Kennt jemand eine Möglichkeit, wie ich dieses lokale JAR dem SecurtiyManager-Context hinzufügen kann?

Ich dachte da an etwas wie:

```
com.sun.javaws.security.AppPolicy.getInstance().addPermissions()
oder
JNLPClassLoaderUtil.getInstance().addResource
```

Aber leider hatte ich bisher keinen Erfolg, da das Interface (für mich) nicht genügend dokumentiert ist.
Die AccessDenied exception bleibt.

In der AppPolicy.java habe ich folgendes gefunden:


```
// Get LaunchDesc for for the JARDesc.
        LaunchDesc ld = null; 
        int access = LaunchDesc.SANDBOX_SECURITY; 
    boolean trusted = false;
        // jd will not have parent if it was not in jnlp file 
        if (jd.getParent() != null) { 
            ld = jd.getParent().getParent(); 
            access = ld.getSecurityModel();         
        }
```

Es sieht so aus, wenn eine JAR nicht in der JNLP steht, bekommt diese nur SANDBOX-SECURTIY.

Meine Frage nun: Wie kann ich das ändern?


----------



## L-ectron-X (19. Sep 2011)

Signiere zusätzlich das/die Jar-Datei(en).


----------



## benhaze (19. Sep 2011)

Wenn ich die JAR-Datei *nicht* signiere, erhalte ich die Meldung:

```
Ihre Anwendung enthält unsignierten und signierten Code, trozdem ausführen? JA/NEIN
```
Wenn ich die Datei signiere, dann erscheint dieser Dialog nicht.

Der Fehler mit dem *access-denied* kommt aber trotzdem.

Das Signieren alleine bringt demzufolge nichts.

In meinem ersten Post habe ich das bereits geschrieben und Code gepostet, warum das scheinbar so ist.
Das Problem: meine JAR-Datei ist nicht Bestandteil der JNLP.
Daher nur: SANDBOX_SECURITY


----------



## TheRealSpikee (20. Sep 2011)

CROSS-POST

Webstart + externe Plugins/JARS @ tutorials.de: Tutorials, Forum & Hilfe


----------



## L-ectron-X (20. Sep 2011)

Poste mal die gesamte Fehlermeldung, die haben wir nämlich noch nicht gesehen.


----------



## benhaze (20. Sep 2011)

Folgendes habe ich getan:

*1. *Webstart-Anwendung gestartet
*2.* lokale (aber signierte!) JAR-Datei in das System geladen (via UrlClassloader)
*3.* auf das Plugin zugegriffen

Das ist die Exception die auftritt, sobald eine Methode in meinem (nachgeladenen!) JAR versucht die Umgebungsvariable auszulesen:

```
access denied (java.lang.RuntimePermission getenv.APPDATA)
    java.security.AccessControlContext.checkPermission(Unknown Source)
    java.security.AccessController.checkPermission(Unknown Source)
    java.lang.SecurityManager.checkPermission(Unknown Source)
    java.lang.System.getenv(Unknown Source)
    de.benhaze.plugin.test.createHome(GlobalSystemProperties.java:235)
```
Wie ich schon angemerkt habe, ist den AppPolicy.java Kommentaren folgendes zu entnehmen (sinngemäß):

*Wenn eine geladene JAR nicht in der JNLP deklariert wurde (unter Ressources), so wird für dieses JAR mit
SandBox-Securtity ausgeführt. *

Irgendwie deutet Vieles darauf hin, das *standardmäßig* meine Plugin-JAR:
1.in der JNLP auftauchen muss
2.irgendwie vom Server stammen muss

Das müsste allerdings auch irgendwie anders möglich sein.

Dies war mein Ansatz:

```
private void addJarToSecurityContext(URL p_url) 
    {
        if (!WebstartUtils.isWebstartApp())
            return;
        
        try
        {
            CodeSource cs = new CodeSource(p_url, (Certificate[])null);
            
            JNLPClassLoaderIf cl =  JNLPClassLoaderUtil.getInstance();
            cl.addResource(p_url, "1", null);
            
            PermissionCollection pc = new Permissions();
            Permission perm = new AllPermission();
            pc.add(perm);
            boolean ok = com.sun.javaws.security.AppPolicy.getInstance().addPermissions(pc, cs, true);
            System.out.println("adding jar to sec-context: " + ok);
        }
        catch(Exception p_ex)
        {
            ErrorViewer.showError(p_ex);
        }
    }
```
Hat allerdings nicht richtig funktioniert.
Wenn ich die JAR so dem Securtiy-Context hinzufüge, bekomme ich den Fehler (von JWS) das das JAR angeblich nicht gefunden wurde.
Dabei versucht JWS die URL mit den URLs aus der JNLP abzugleichen. (und findet die URL nicht)


----------



## L-ectron-X (20. Sep 2011)

Und was spricht dagegen, deine Jar-Datei mit in der JNLP aufzulisten?


----------



## benhaze (20. Sep 2011)

Dafür gibt es verschiedene Gründe:
- die Anwendung ist zweierlei verfügbar (Standalone + Webstart)
Ich möchte nicht unbedingt extra Code schreiben müssen, für beide Varianten (um die Plugins zu laden).
- der Client soll nicht unbedingt alle Plugins kennen (können)
- fällt mir keine passende Lösung ein, das mittels der JNLP zu lösen
(was ja nicht bedeuten soll, das es keine gibt)

Wenn es gar nicht geht (was ich mir nicht vorstellen kann), muss ich versuchen das irgendwie mit der JNLP-Datei zu machen.
Meine JNLP wird bereits mittels einer JSP generiert.
Ich muss mir das mit dem *download=lazy* mal genauer anschauen.
Möglichweise kann mir das irgendwie helfen.

-------------------------

Momentan habe ich das Problem, das es mir nicht (mehr) gelingt Webstart-Anwendung zu debuggen.
- Connection refused -
JWS startet einen neuen Prozess und leitet die JVM-Parameter nicht weiter.

Dieses Problem wurde auch hier besprochen:
(https://forums.oracle.com/forums/thread.jspa?threadID=1303538)
und
https://forums.oracle.com/forums/thread.jspa?messageID=5499355


----------



## Guest2 (20. Sep 2011)

Moin,

ins Blaue: Hast Du es schon mal mit AccessController.doPrivileged versucht?

z.B. (wie im Beispiel):

```
somemethod() {
        ...normal code here...
        String user = (String) AccessController.doPrivileged(
          new PrivilegedAction() {
            public Object run() {
                return System.getProperty("user.name");
            }
          }
        );
        ...normal code here...
  }
```

Gruß,
Fancy


----------



## benhaze (21. Sep 2011)

AccessController.doPrivileged hat nichts gebracht, da letztendlich alles im Security-Context der Webstart-anwendung läuft.

*Bisher habe ich es so gelöst:*

Beim Starten der Anwendung prüfe ich, ob diese via Webstart gestartet wurde.
Wenn dem so ist, hole ich mir die geladen JARs von der Webstart-Anwendung und
erstelle mittels ProcessBuilder einen neuen Java-Prozess der Anwendung.
Der Webstart-Prozess beendet automatisch.

- es ist keine spürbare Verzögerung zu bemerken.
- die JARs sind aufgrund des Webstart-Mechanismus immer aktuell


----------



## L-ectron-X (23. Sep 2011)

Vielleicht ist das dein Problem?
heise online - Oracle macht freie Java-Binaries sicherer ? und funktionsuntüchtig


----------

