access denied (java.io.FilePermission) Error - can't read

mock5c
mock5c used Ask the Experts™
on
I have a JNLP application where the user needs to upload files.  The application will compress multiple files into a single file so that the file size is reduced and there is only a single file to transfer.  This compression works fine and the file is created in the user's (if using Windows XP) Download folder: C:\Documents and Settings\user\My Documents\Downloads.

However, when I select the file for uploading upload, I will receive this error (see below).

I am running all of this on a local Windows XP computer at the moment.  How is it that I can create the file but can't read it?  What tweaks can I make to allow reading?

Thanks.
Uploading "C:\Documents and Settings\user\My Documents\Downloads\test.zip" to http://localhost:8080/TestApp/upload
Error: access denied (java.io.FilePermission "C:\Documents and Settings\user\My Documents\Downloads\test.zip" read)
java.security.AccessControlException: access denied (java.io.FilePermission "C:\Documents and Settings\user\My Documents\Downloads\test.zip" read)
	at java.security.AccessControlContext.checkPermission(Unknown Source)
	at java.security.AccessController.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkRead(Unknown Source)
	at java.io.File.isFile(Unknown Source)
	at org.apache.commons.httpclient.methods.multipart.FilePartSource.<init>(FilePartSource.java:67)
	at org.apache.commons.httpclient.methods.multipart.FilePart.<init>(FilePart.java:126)
	at org.apache.commons.httpclient.methods.MultipartPostMethod.addParameter(MultipartPostMethod.java:148)
	...

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Top Expert 2016

Commented:
Make sure the file isn't locked, either by Java or another process

Author

Commented:
I changed the code and hard-coded a file that could not be locked by Java or another process and I get the same error.
Top Expert 2016

Commented:
>>I changed the code and hard-coded a file that could not be locked by Java or another process and I get the same error.

Can you past that code?
Angular Fundamentals

Learn the fundamentals of Angular 2, a JavaScript framework for developing dynamic single page applications.

Author

Commented:
          if (checkBoxNode.isSelected()) {
              MySeries myseries = child.getSeries();
              String zipFileName = compressFiles(myseries);  // CALL compressFiles()

              String targetURL = "http://localhost:8080/TestApp/upload";
              File targetFile = new File(zipFileName);
              MultipartPostMethod filePost = new MultipartPostMethod(targetURL);

              try {
                 System.out.println("Uploading " + zipFileName + " to " + targetURL);
                 filePost.addParameter(zipFileName, targetFile);
                 HttpClient client = new HttpClient();
                 client.setConnectionTimeout(5000);
                 int status = client.executeMethod(filePost);
                 if (status == HttpStatus.SC_OK) {
                    System.out.println("Upload complete, response=" + filePost.getResponseBodyAsString());
                 }
                 else {
                    System.out.println("Upload failed, response=" + HttpStatus.getStatusText(status));
                 }
              }
              catch (Exception ex) {
                 System.out.println("Error: " + ex.getMessage());
                 ex.printStackTrace();
              }
              finally {
                 filePost.releaseConnection();
              }
           }

//-----------------------------------------------

 private String compressFiles(MySeries mySeries)
  {
    ArrayList <MyFile> myFileList = mySeries.getFileList();
    String zipFilePath = null;
    String zipFileName = null;

    if (myFileList.size() == 0)
    {
       System.out.println("There are no files in this series.");
       return zipFileName;
    }

    try
    {
      BufferedInputStream origin = null;
      zipFileName = mySeries.getSeries() + ".zip";
      FileOutputStream dest = new FileOutputStream(zipFileName);
      ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
      byte data[] = new byte[BUFFER];

      for(MyFile myFile : myFileList) {
        System.out.println("Adding: " + myFile.getFileName());
        FileInputStream fi = new FileInputStream(myFile.getFileName());

        origin = new BufferedInputStream(fi, BUFFER);

        ZipEntry entry = new ZipEntry(myFile.getFileName());
        out.putNextEntry(entry);
        int count;
        while((count = origin.read(data, 0, BUFFER)) != -1) {
           out.write(data, 0, count);
        }      
        origin.close();
      }
      out.close();
      System.out.println("Compression complete.");
      zipFilePath = "\"C:\\Documents and Settings\\user\\My Documents\\Downloads\\testuploadfile.csv\"";  // HARDCODED
      return zipFilePath;
    }
    catch (Exception ex)
    {
      System.out.println("Exception thrown zipping files.");
      eh.addFatal("Exception thrown zipping files.");
    }
    return zipFileName;
  }

If you want to have access to your local files _all_ your jars must be signed.
http://java.sun.com/developer/Books/javaprogramming/JAR/sign/signing.html

Also you can remove your app using `javaws` tool (just Start->Run type javaws -viewer) than when you install your app again you should be prompted to accept security exception.

Hope that helps.

Author

Commented:
I have verified that all jars are signed using jarsigner -verify.   As you suggested, I ran javaws and removed the app.  After installing the app again, I get a message that the application has requested  permission  to establish connections with the webserver and I am prompted if i want to allow this action.  I get this message every time I run the app, which is normal.  But there is nothing specific for security excptions.
I would suggest to try the following:
 1) Check read permission before opening the file:
if (null!=System.getSecurityManager()) {
  System.getSecurityManager().checkRead(file.getAbsolutePath());
}

Open in new window


2) Than try to copy the file to c:\test.zip and try to open it from there.

Author

Commented:
I get the same error when trying to read the file from C:\test.zip
What does your JNLP file look like?
Mick BarryJava Developer
Top Expert 2010
Commented:
your jnlp needs to specify that it needs permissions

   ...
   </information>
  <security>
      <all-permissions/>
  </security>
Can you post the stack trace with an exception from the Security manager?
Have you tried to run this app on any other computer?

Author

Commented:
In my MainClass.jnlp, I do have:

 ...
   </information>
  <security>
      <all-permissions/>
  </security>

I have other jnlp files and the are referenced by the MainClass.jnlp file with::

    <extension name="postgresql-8.4-701.jdbc4" href="postgresql-8.4-701.jdbc4.jnlp"/>
    <extension name="apache-commons" href="apache-commons.jnlp"/>

These other jnlp files do not specify <all-permissions/>.  Is this necessary?

The apache-commons.jnlp file is the most recent one I added for doing file uploading.






MainClass.jnlp
--------------

<?xml version='1.0' encoding='UTF-8' ?>
<jnlp spec='1.0+'
   codebase="http://localhost:8080/TestApp"
   href='MainClass.jnlp'>
  <information>
    <title>TestApp</title>
    <vendor>me</vendor>
  </information>

  <security>
    <all-permissions  />
  </security>

  <resources>
    <j2se version="1.2+" initial-heap-size="128m" max-heap-size="256m" />
    <jar href='MainFrame.jar' main='true'/>
    <jar href="lib/MyValidator.jar" />
    <jar href="lib/ErrorHandler.jar" />
    <extension name="commons-codec-1.3" href="commons-codec-1.3.jnlp"/>
    <extension name="postgresql-8.4-701.jdbc4" href="postgresql-8.4-701.jdbc4.jnlp"/>
    <extension name="apache-commons" href="apache-commons.jnlp"/>
  </resources>
  <application-desc main-class='TestApp.MainClass'>
    <argument>jdbc:postgresql://localhost:5432/testdb</argument>
    <argument>org.postgresql.Driver</argument>
  </application-desc>
</jnlp>

apache-commons.jnlp
-------------------
<?xml version='1.0' encoding='UTF-8' ?>
<jnlp spec='1.0+' codebase="http://localhost:8080/TestApp" href='apache-commons.jnlp'>
  <information>
    <title>apache-commons</title>
    <vendor>apache-commons</vendor>
  </information>

  <resources>
    <jar href="lib/commons-codec-1.3.jar" />
    <jar href="lib/commons-httpclient.jar" />
    <jar href="lib/commons-logging.jar" />
  </resources>

  <component-desc/>
</jnlp>

Open in new window

Mick BarryJava Developer
Top Expert 2010

Commented:
have the signed the extensions?

Author

Commented:
Yes, each jar file has been signed and verified with jarsigner -verify
The JNLP specification section 4.7 states that if an extension element points to a JNLP file with a component-desc element, then the resources in the extension JNLP file will have the permissions specified in the extension JNLP file (ie the apache-commons.jnlp file in your case).

This means, in your case, that the lib/commons-doc-1.3.jar, lib/commons-httpclient.jar, and lib/commons-logging.jar all have the permissions specified in apache-commons.jnlp.  Since the security element is not specified in the apache-commons.jnlp file, the classes in these three .jar files run in an untrusted environment which is why you're getting the AccessControlException.

Please try to add

  <security>
      <all-permissions/>
  </security>

into the extension .jnlp files and you should be okay.

Author

Commented:
btw, how would I set the download/upload directory in the JNLP app?  Currently it defaults to C:\Documents and Settings\user\My Documents\Downloads (on windows XP).  I am wondering if spaces are causing a problem here.  It is obviously not a good idea to hardcode this path as I am currently doing in the code.

I will try garypfirstech's suggestion shortly.
In order to get the download/upload directory in the JNLP app (ie to get the value of zipFilePath, I would change

 
FileOutputStream dest = new FileOutputStream(zipFileName);

Open in new window


in compressFiles to

  File zipFile = new File(zipFileName)
  FileOutputStream dest = new FileOutputStream(zipFile);

Open in new window


Then, you can change the hardcoded zipFilePath to
  zipFilePath = zipFile.getCanonicalPath();
 

Author

Commented:
Adding the <security> element did the trick.  It also corrected another problem I had been having.  Thanks!

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial