1

クライアントマシンでローカルにファイルを開くことができ、編集後にファイルを保存できる必要があるWebアプリがあります。Webアプリは、WebDAVとFTPを介して共有されるフォルダー内のサーバー上にドキュメントを生成し、このフォルダーはクライアントマシンにマウントされます。

サーバーへの保存が許可されないため、file://タイプのURIを使用できません。

このファイルを開く処理を行うWebアプリに埋め込まれた小さなJavaアプレットで問題を解決しようとしていますが、Javaでのアクセス許可に問題があります。(Javaは私の専門分野ではありません)。とにかく、私はコードを次のように絞り込みました。

localfile.html

<html>
<body>
  <input id="input" value="Call from Javascript" type="button" onclick="callApplet('/Users/conor/1.txt')">
  <script type='text/javascript'>
  function callApplet(path) {
    applet = document.getElementById('localfile');
    applet.openFile(path);
  }
  </script>
<applet id="localfile" code="localfile.class" archive="localfile.jar"  width="150" height="50"></applet>
</body>
</html>

localfile.java

import java.applet.*;
import java.awt.*;
import java.util.*;
import java.lang.*;
import java.text.*;
import java.awt.event.*;
import java.io.*;

import java.security.*;

public class localfile extends Applet {
  public localfile() {
    Panel p = new Panel();
    p.add(new Button("Call from Java"));
    add("North",p);
  }
  public void openFile(String path) {
    System.out.println("File: " + path);
    final File ffile = new File(path);
    System.out.println("Got file.");
    if (Desktop.isDesktopSupported()) {
      System.out.println("Desktop is supported.");
      final Desktop desktop = Desktop.getDesktop();
      System.out.println("Got Desktop Handle.");
      try {
        desktop.open(ffile);
      } catch(Exception ex) {
        ex.printStackTrace();
      }
      System.out.println("File Opened.");
    }
  }

  public boolean action(Event evt, Object arg) {
    openFile("/Users/conor/1.txt");
    return true;
  }
}

コンパイルしてjarファイルを作成し、Javaソースから署名しました。

これにより、Javaボタン(テスト用)とJavascriptボタンの2つのボタンを持つページが生成されます。Javaボタンは期待どおりに機能します。ファイルなどを保存できます。ファイルパスをアプレットに渡したいので、実際に機能させたいのはJavascriptボタンです。ただし、Javascriptは次のようにスローします。

スタックトレース

java.security.AccessControlException: access denied ("java.awt.AWTPermission" "showWindowWithoutWarningBanner")
at java.security.AccessControlContext.checkPermission(AccessControlContext.java:366)
at java.security.AccessController.checkPermission(AccessController.java:560)
at java.lang.SecurityManager.checkPermission(SecurityManager.java:549)
at java.awt.Desktop.checkAWTPermission(Desktop.java:239)
at java.awt.Desktop.open(Desktop.java:267)
at localfile.openFile(localfile.java:27)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.plugin.javascript.JSInvoke.invoke(Unknown Source)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at sun.plugin.javascript.JSClassLoader.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MethodInfo.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass$MemberBundle.invoke(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke0(Unknown Source)
at sun.plugin2.liveconnect.JavaClass.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$DefaultInvocationDelegate.invoke(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo.doObjectOp(Unknown Source)
at sun.plugin2.main.client.LiveConnectSupport$PerAppletInfo$LiveConnectWorker.run(Unknown Source)
at java.lang.Thread.run(Thread.java:722)

また、次のように、desktop.open呼び出しをdoPrivilegedブロックに埋め込んでみました。

  AccessController.doPrivileged(new PrivilegedAction() {
    public Object run() {
      try {
        desktop.open(ffile);
      } catch(Exception ex) {
        ex.printStackTrace();
      }
      return null;
    }
  });

しかし、それは次のようにjavascriptとjavaボタンのエラーをスローします:

java.lang.SecurityException: class "localfile$1" does not match trust level of other classes in the same package

どんな助けでもいただければ幸いです。

4

1 に答える 1

0

うまくいったので、ここに解決策を投稿すると思いました...

doPrivileged 呼び出しを含む Java ファイルをコンパイルすると、javac コンパイラは localfile.class と localfile$1.class の 2 つのファイルを作成します。最初は localfile$1.class が何であるかわからなかったので、何らかの一時ファイルであると推測しました。ただし、これは doPrileged ブロック内の匿名クラスに対応するクラス ファイルであり、.jar ファイルに含めて適切に署名する必要がありました。

とにかく、html ファイルは以前のままで、最終的な Java ファイルは次のようになります。

localfile.java

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.security.*;

public class localfile extends Applet {

private static final long serialVersionUID = 1L;

public localfile() {
  Panel p = new Panel();
  p.add(new Button("Call from Java"));
  add("North",p);
}

public void openFile(String path) {
  System.out.println("File: " + path);
  final File ffile = new File(path);
  System.out.println("Got file.");
  if (Desktop.isDesktopSupported()) {
    System.out.println("Desktop is supported.");
    final Desktop desktop = Desktop.getDesktop();
    System.out.println("Got Desktop Handle.");
    AccessController.doPrivileged(new PrivilegedAction() {
      public Object run() {
        try {
          desktop.open(ffile);
        } catch(Exception ex) {
          ex.printStackTrace();
        }
        return null;
      }
    });
    System.out.println("File Opened.");
  }
}

public boolean action(Event evt, Object arg) {
  openFile("/Users/conor/1.txt");
  return true;
}

}

また、html ファイル内の JavaScript でアプレットを作成して DOM に挿入する必要がないこともわかりました。これはリンク先の@VGRで言及されていたと思いますが、それがなくてもうまくいきました。

みんな助けてくれてありがとう!

于 2013-01-30T11:01:14.537 に答える