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

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

mock5cAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

CEHJCommented:
Make sure the file isn't locked, either by Java or another process
mock5cAuthor 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.
CEHJCommented:
>>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?
Why Diversity in Tech Matters

Kesha Williams, certified professional and software developer, explores the imbalance of diversity in the world of technology -- especially when it comes to hiring women. She showcases ways she's making a difference through the Colors of STEM program.

mock5cAuthor 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;
  }

IvanLatyshCommented:
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.
mock5cAuthor 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.
IvanLatyshCommented:
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.
mock5cAuthor Commented:
I get the same error when trying to read the file from C:\test.zip
garypfirstechCommented:
What does your JNLP file look like?
Mick BarryJava DeveloperCommented:
your jnlp needs to specify that it needs permissions

   ...
   </information>
  <security>
      <all-permissions/>
  </security>
IvanLatyshCommented:
Can you post the stack trace with an exception from the Security manager?
Have you tried to run this app on any other computer?
mock5cAuthor 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 DeveloperCommented:
have the signed the extensions?
mock5cAuthor Commented:
Yes, each jar file has been signed and verified with jarsigner -verify
garypfirstechCommented:
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.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
mock5cAuthor 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.
garypfirstechCommented:
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();
 
mock5cAuthor Commented:
Adding the <security> element did the trick.  It also corrected another problem I had been having.  Thanks!
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Java

From novice to tech pro — start learning today.