4

I have a button in my program that, when pressed, is supposed to take you to my wiki page about the program. I used the following line to do so:

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

The problem is that, no matter what environment in which the program is run, I always get the following error:

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

does anyone know how I can fix this? Note that this only works in the one program. Any other program I make can use the same method with no problem.

Exit hook


At the start of my program, this hook is added. The program runs fine without it...

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

this hook is needed, but the browse(URI uri) method in question won't work with it. Solutions?

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
Ky -
  • 30,724
  • 51
  • 192
  • 308
  • I removed the not-relevant bits of code from the question to make it more clear. There was one unused instantiation of `SecurityManager` in your listener - get rid of it (for the sake of cleaner code) – Bozho Nov 15 '10 at 07:37

2 Answers2

7

This means you are running with a security manager:

SecurityException - if a security manager exists and it denies the AWTPermission("showWindowWithoutWarningBanner") permission, or the calling thread is not allowed to create a subprocess; and not invoked from within an applet or Java Web Started application

If this is an applet, or a Java Web Start app - sign your jar.

Update Adding a security manager to detect program exit is wrong. There are multiple ways to do this properly. In your case I guess this would be most appropriate:

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

Swing-specific solutions are:

  • if you don't have to perform extra actions, use frame.setDefaultCloseAction(Frame.EXIT_ON_CLOSE)

  • use addWindowStateListener and check for WindowEvent.WINDOW_CLOSED

That said, two notes:

  • you must not hold files open for a long time. Use try/catch/finally to open and close them whenever they are needed.

  • if you really need a security manager at some point, make sure you override the appropriate method of the SecurityManager that checks whether you can open the link. (won't tell you which one, so that you are not tempted to jump onto this solution, which is wrong)

To summarize, I'd go for setDefaultActionOnClose, and close each file right after I finish reading/writing it.

Update 2: After you linked to your original question describing what exactly are you trying to achieve, things change a bit. You are trying to prevent exit, so you do need a SecurityManager. This makes it so that you should override the checkPermission method and do nothing there (i.e. don't throw exceptions), at least when these permissions are checked (they are checked when browse is called):

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

Update 3 Here's how exactly to override the method:

@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);
}

(you can go without the outer if-s)

Update 4 The above method will work only if you have given permissions to your program. Otherwise it is a not-well documented behaviour of the JVM that overriding security managers are not allowed to be unprivileged. Take a look at this report - the comments say how to work it around.

To make your life simpler, you can simply @Override public void checkPermission(..) with an empty method body.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • I am running it as a desktop app, but as a jar or as a class file it still throws it. – Ky - Nov 10 '10 at 15:27
  • how exactly do you start your application? Because I just ran one here, and it browsed successfully. – Bozho Nov 10 '10 at 15:29
  • I have started it through an IDE, in a jar, through a shortcut to the jar, and in the command prompt. – Ky - Nov 10 '10 at 15:32
  • Try starting it from a simple class, not a jar, for a test. in my IDE it worked. – Bozho Nov 10 '10 at 15:34
  • Then your IDE is running a security manager, or your JRE is somehow guarded by one (don't know whether this is possible). The normal installation does not behave like that. – Bozho Nov 10 '10 at 15:47
  • I have the same problem on other computers – Ky - Nov 10 '10 at 20:21
  • What are your JRE, JDK and IDE versions. – Bozho Nov 10 '10 at 20:32
  • latest, 1.6.0_16 for my Desktop, Laptop, and my friend's computer. – Ky - Nov 11 '10 at 04:17
  • Tried it at home - works fine as well. I'm with 1.6.0_05 though. Try downloading this older version. – Bozho Nov 11 '10 at 05:53
  • I can't tell everyone who is running my app to DL an older version of Java. You aren't helping at all... – Ky - Nov 11 '10 at 19:19
  • @Supuhstar well, I'm sparing from my time to answer _your_ question, and you say that I'm not helping at all? I suggested downloading an older version for the sake of testing and diagnosing the problem. – Bozho Nov 11 '10 at 19:22
  • I would like to note that using this browse method on other programs I'm working on, it functions perfectly. – Ky - Nov 11 '10 at 20:04
  • then what is special about this program, compared to others? in deployment/running terms. – Bozho Nov 11 '10 at 20:32
  • its main method is now posted above, as well as the actionPerformed method of the button – Ky - Nov 11 '10 at 22:00
  • I found the problem. Still need a solution. – Ky - Nov 15 '10 at 03:40
  • Thank you! I was told that a SecurityManager was the only way to do this at http://stackoverflow.com/questions/4002976/ide-style-program-running/4003001#4003001 but I guess that's the beauty of this site, huh? – Ky - Nov 15 '10 at 14:14
  • Also, each time I close the program, an effect happens (such as fading or sliding shut), so I need the hook. Also, the file in question is the program's logging file, so I find it essential that it stay open throughout the program's run. – Ky - Nov 15 '10 at 14:16
  • also, my closeFile method requires an int representing the exit status. How do I get this? – Ky - Nov 15 '10 at 16:04
  • @Supuhstar - next time provide all the _relevant_ information from the beginning!! See what happened now - I gave you the reason why this happened, you told me that 'it does not work', then you finally showed that you indeed are using a SecurityManager, but didn't tell why you are using it. Finally you told why you are using it, and hence my answer grew so much, and so it took this long to get an answer. – Bozho Nov 15 '10 at 16:06
  • I had no idea it was the security manager. Also, the fact that the closeFile method takes an int in my example should be reason enough. If I click a button and get an error, that is what I post. I post what the the button does and what the error is. I posted all the information required to answer as you needed it. I did NOT know it was an issue with my shutdown hook. Why would I? if a BUTTON doesn't work, is the first thing that runs through your head "There's a problem with the way it shuts down"? – Ky - Nov 15 '10 at 16:45
  • @Supuhstar - my very first version of the answer indicated that a possible `SecurityManager` was the issue. But only yesterday you mentioned that you are using one. – Bozho Nov 15 '10 at 16:47
  • I had forgotten about it; the security manager is part of a separate file and was out of my mind, as it was made a long time ago and I hadn't run into any problems until now – Ky - Nov 15 '10 at 16:49
  • I still need to pass an integer representing the exit status to the closeFile method – Ky - Nov 15 '10 at 17:18
  • @Supuhstar in my last update I indicated that you keep the security manager, and just override an additional method. So the int should not be a problem, it remains the same. – Bozho Nov 15 '10 at 17:20
  • so I just throw in those 2 lines of code and it magically works? – Ky - Nov 16 '10 at 15:20
  • Well, override the method. And then optionally check the concrete permissions, or just allow all permissions. – Bozho Nov 16 '10 at 19:42
  • @Supuhstar - see updated. I thought my directions were enough, though. – Bozho Nov 18 '10 at 08:21
  • now it won't let me even show the main frame of the program. I get "Exception in thread "AWT-EventQueue-0" java.security.AccessControlException: access denied (java.lang.RuntimePermission setContextClassLoader)" – Ky - Nov 19 '10 at 06:14
0

Instead of using your own SecurityManager, install a shutdown hook instead:

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

Runtime.getRuntime().addShutdownHook(new Thread (runnable, "Close file"));
Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • The problem, now, is how do I get the "status" integer variable of exiting? – Ky - Nov 19 '10 at 15:07
  • the problem seems more complicated - in the countless comments on my answer he posted a link to his original problem, so a security manager is due. – Bozho Nov 19 '10 at 16:15