Проблема с java.awt.Desktop - PullRequest
       0

Проблема с java.awt.Desktop

4 голосов
/ 10 ноября 2010

В моей программе есть кнопка, которая при нажатии должна перейти на мою вики-страницу о программе. Для этого я использовал следующую строку:

java.awt.Desktop.getDesktop().browse(new java.net.URI("http://supuh.wikia.com/wiki/BHT"));

Проблема в том, что независимо от того, в какой среде запущена программа, я всегда получаю следующую ошибку:

java.security.AccessControlException: access denied (java.awt.AWTPermission showWindowWithoutWarningBanner)

Кто-нибудь знает, как я могу это исправить? Обратите внимание, что это работает только в одной программе. Любая другая программа, которую я создаю, может без проблем использовать тот же метод.

Крючок выхода


В начале моей программы этот хук добавлен. Программа прекрасно работает без нее ...

System.setSecurityManager(new SecurityManager()
{
  @Override
  public void checkExit(int status)
  {
    closeFile(status);
  }
});

этот хук необходим, но рассматриваемый метод browse(URI uri) не будет работать с ним. Решения?

Ответы [ 2 ]

7 голосов
/ 10 ноября 2010

Это означает, что вы работаете с менеджером безопасности:

SecurityException - если менеджер безопасности существует и он запрещает разрешение AWTPermission ("showWindowWithoutWarningBanner"), или вызывающему потоку не разрешено создавать подпроцесс; и не вызывается из апплета или приложения Java Web Started

Если это апплет или приложение Java Web Start - подпишите свой jar.

Обновление Добавление диспетчера безопасности для обнаружения выхода из программы неправильно . Есть несколько способов сделать это правильно. В вашем случае, я думаю, это было бы наиболее подходящим:

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
      @Override
      public void run() {
         closeFile();
      }
));

Свинг-решениями являются:

  • , если вам не нужно выполнять дополнительные действия, используйте frame.setDefaultCloseAction(Frame.EXIT_ON_CLOSE)

  • используйте addWindowStateListener и проверьте на WindowEvent.WINDOW_CLOSED

Тем не менее, две заметки:

  • Вы не должны держать файлы открытыми в течение длительного времени. Используйте try/catch/finally, чтобы открывать и закрывать их всякий раз, когда они необходимы.

  • если вам действительно нужен менеджер безопасности в какой-то момент, убедитесь, что вы переопределили соответствующий метод SecurityManager, который проверяет, можете ли вы открыть ссылку. (не скажу, какой именно, чтобы вы не испытывали искушения перейти на это решение, что неправильно)

Подводя итог, я бы взял setDefaultActionOnClose и закрыл каждый файл сразу после того, как я закончу читать / записывать его.

Обновление 2: После того, как вы связались со своим первоначальным вопросом, описывающим, чего именно вы пытаетесь достичь, все немного меняется. Вы пытаетесь предотвратить выход, поэтому вам нужно SecurityManager. Это позволяет вам переопределить метод checkPermission и ничего не делать там (т. Е. Не выдавать исключения), по крайней мере, когда проверяются эти разрешения (они проверяются при вызове browse):

  • new AWTPermission("showWindowWithoutWarningBanner")
  • new FilePermission("<<ALL FILES>>", SecurityConstants.FILE_EXECUTE_ACTION)

Обновление 3 Вот как именно переопределить метод:

@Override
public void checkPermission(Permission permission) {
   if (permission instanceof AWTPermission) {
       if (permission.getName().equals("showWindowWithoutWarningBanner")) {
           return;
       }
   }

   if (permission instanceof FilePermission) {
       if (permission.getActions().equalsIgnoreCase("execute")) {
          return;
       }
   }

   java.security.AccessController.checkPermission(permission);
}

(вы можете обойтись без внешнего if-s)

Обновление 4 Описанный выше метод будет работать только в том случае, если вы дали разрешения для своей программы. В противном случае поведение JVM не очень хорошо задокументировано, так как переопределенные менеджеры безопасности не могут быть непривилегированными. Взгляните на этот отчет - в комментариях говорится, как его обойти.

Чтобы сделать вашу жизнь проще, вы можете просто @Override public void checkPermission(..) с пустым телом метода.

0 голосов
/ 19 ноября 2010

Вместо использования своего собственного SecurityManager, установите вместо этого отключающий хук:

Runnable runnable = new Runnable() {
    closeFile(status);
}

Runtime.getRuntime().addShutdownHook(new Thread (runnable, "Close file"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...