Write to a local file through JNLP - java

I have a specific requirement to read a resource from jar file and then write it to local disk. But when I try to write that resource to local disk an exception:
java.io.FilePermission (write) is raised.
I have my jar signed. I have also tried the following solution but it does not work either.
AccessController.doPrivileged(new PrivilegedAction()
Nothing seems to work.
Am I missing a step after signing jar because this is the most common solution available everywhere?
How can I write to a local file without using policy files (because that can't be done on each client machine)?

You can save a file, with user interaction, from an unsigned WebStart application using javax.jnlp.FileSaveService.
Possibly a piece you are missing is marking the aplication as secure in the JNLP file. However, writing a secure application is a little tricky, and I wouldn't recommend it.

The JNLP also needs to specify:
<security>
<all-permissions/>
</security>
See the JNLP File Syntax for details.
I would generally use the FileSaveService as detailed in Tom's answer, but this sounds more like a situation where the 'file' could be a default properties file for configuring the app. The save service is not well suited to that, since the app. has no way to know where the file is stored, or how to access it later. For security reasons, the FileContents object that is provided in place of a File has no methods that return the path.
In that case, extract the details of the config. file & store them using the PersistenceService of the JNLP API. Here is a demo. of the PersistenceService. This service is also available to sand-boxed apps. (no code signing voodoo).

Related

How to sign (dynamic) JNLP files for OSX and Gatekeeper

My company produces Java Applications for Servers and delivers JNLP files to start local Applications. Since OSX 10.8.4 it is required to sign JNLP files with a Developer ID to keep Gatekeeper happy (it's actually in the release notes at the very bottom).
The question is: how to accomplish this? AFAIK you can sign Apps (we have some Java Apps signed with Developer IDs) - but JNLP - Files are just that: files.
Next: how to do this with generated JNLP files. We have to modify them as they come from a server - e.g. properties, base URL and so forth.
AFAIK Java has a certain mechanism to say JNLP files are signed via their respective JAR file (the one that holds the main class) - but: Jar files are signed with a different certificate they will not satisfy Gatekeeper as well.
I did find one reference on how to sign tools and stuff, but it does not apply the scenario of dynamic files.
What I do not want as answers: Right-Click and Open to override the Gatekeeper or change the System- or Java settings. This is not an option.
[UPDATE]
Since OSX 10.9.5 you also have to sign using OSX 10.9+ and have valid version 2 signatures. How will this be done?
I think I found a solution. The only one I can currently think up. We basically need to wrap the JNLP with a custom app launcher, sign the app, make sure we can modify the JNLP on the fly on a server and then have it run.
As you may be aware, there is an app bundler project which can wrap up any JAR files into an OSX executable. This can be signed, delivered and will not fail Gatekeeper. I made a custom fork (which is up for a pull int o the main fork) that can take an JNLP file, wrap it up and you have a custom application doing just all the stuff a JNLP should do.
A Requirement is, however, that you do have a valid "Developer ID Application" certificate
Head over to bitbucket.org and download the current version
Run the ant task and build the appbundler package.
Have a look at the documentation for an example build script that will create the app container.
The example does not include the JNLP into the application right now.
The applications signature is created in a way so that the JNLP file can be modified later.
The application is being put into a zip file. This is important for downloading an application since they are only directories
Create your server code. Load the ZIP file, put the JNLP File into the directory <yourapp>.app/Contents/Java/
Deliver the zip file.
Now, if everything went fine, the zip file should automatically be unpacked in the Download folder and you should see your application icon. If you really made no mistake, you can execute the application as if it was a normal one.
I hope this will help a lot of developers fixing the broken JNLP behavior with OSX.
[UPDATE for modifiable JNLPs]
Since OSX 10.9.5 it is required to have valid version 2 signatures on your app. This means that it the trick that was previously used by the app bundler (set a resource list file) does not work anymore. Everything and anything has to be signed now and it is virtually impossible to change the signed app afterwards.
I did however find a way: Use the app bundler. Set the JNLP to a file inside the Contents/_CodeSignature directory. Do not yet copy your modifiable JNLP in there but do this e.g. using Java later on when patching the zip (you'll need some code here anyway).
Please note: this should really only be needed if you have to put another JNLP file dynamically into the app container (thats is what the questions was about)
UPDATE (08-2017)
Oracle will be releasing Java 9 by the end of September. The appbundler does not handle the java9 vm correctly. They changed a whole lot of the API and the way that javaws works. For I need to say: stick with java8 if you want to use wrapped JNLP apps.
We've been able to determine that you can sign a jnlp file with codesign, using the "Developer ID Application" Certificate, like this:
codesign -f -s "Developer ID Application: " foo.jnlp
The result from this operation seems to pass Gatekeeper on the local machine. However, it seems like the signature gets stored as extended HFS attributes, and as a result, it is not transmitted if a user fetches the file from a HTTP transaction.
It might work if you took the .jnlp file, and packaged it in some kind of container, like a .dmg or maybe a .tar.gz, however, that's both a lot of work, and it provides a fairly challenging user experience.
From an email thread with Apple tech support, it seems the official word is to use the xip tool to work around the reliance on HFS extended attributes with codesign:
Instead of codesign, use xip (pronounced "chip")
to create a signed archive of your JNLP file. Provide your Developer
ID Installer identity as the argument to the --sign option, not your
Developer ID Application identity.
A xip archive is essentially a signed zip archive so it can be served
over the Internet in the same way as a zip archive. It will be
unarchived automatically on the client Mac.
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/xip.1.html
From my experimentation the xip tool always generates an archive with the jnlp contained in a folder when unxip'd.
Just to summarise the discussion; currently there is no existing solution on how to come around this.
This means that end users cannot launch an application via JNLP easily. Basically one needs to tell the user to Right-Click and Open to override the Gatekeeper.
The other solution would be to make an signed Mac application and have users install that via disk image.
Would it work to bundle a simple executable shell script called something like "myapp" in a signed .dmg which looks like this:
javaws http://path/to/my/app.jnlp
that way you can change the .jnlp however you like without changing your .dmg. I don't have an Apple Developer ID, so I can't try it myself right now.

Is it possible to read/write a file from an applet

I've trying to read and write a file from an applet so if I run the applet from my appletviewer it is possible for me to read/write a file but when I try to do it from my browser I get a security exception. Any idea how to do this?
Is it possible to read/write a file from an applet
Yes, but you need to sign the applet and get approval from the user.
Some useful links:
How can an Applet read files on the local file system (from coderanch.com)
Essentials, Part 1, Lesson 6: File Access and Permissions (from oracle)
Chapter 10: Signed Applets (from oracle)
A sand-boxed JWS app. can read and write to files on the local file system using the JNLP API services. Here is a demo. of the JNLP API file services. The downloadable Zip file contains the source, launch file and build script.
it's actually not that difficult. You can self sign an applet and then it will be able to read/write to/from the local file system outside the sandbox constraints. take look at the link below. it will show you how to sign your applet using the keytool and the example actually does read/write to the filesystem. no need to muck about the policy files and such.
Note that as #aioobe mentioned, the user will be prompted to accept the certificate though.

Load jar file locally

Let's say I have a jar file and I want users to load it locally from the Internet... to speed up the loading I say... how would I go about doing that?
Like when you access it from http://mydomain.com... the jar file is from my documents/game/test.jar
Look up the URLClassLoader class, I think it will do what you want.
Here is a good description:
http://java.sun.com/developer/technicalArticles/Networking/classloaders/
EDIT: Forget it, Unsigned Applets cannot create ClassLoaders.
For an Applet you will need to download everything at once.
It is exactly the purpose of JNLP files (also called "Java Web Start"). Or I have misunderstood your problem...
You can find the official documentation on Oracle website : http://download.oracle.com/javase/1.5.0/docs/guide/javaws/developersguide/syntax.html
An example famous application using this system : SweetHome3D
I'm not sure if I understand your question, but it sounds like you want Java Web Start.
http://download.oracle.com/javase/tutorial/deployment/webstart/index.html
You would create a jnlp file, and put a link to it on your website. Java will take care of downloading the file and starting it. The .jar file would be stored in a cache, and it shouldn't need to be redownloaded unless the cache is cleared or you replace your old .jar file with a new one.

How make working directory files available to WebStart application?

We have to make a Java application demo available on Internet using JWS. It goes pretty well; all that's missing is making working directory files available for the application.
We know about the getResource() way... The problem is that we have different plugins for the same application and each one require different files (and often different versions of the same files) in their working directory to work properly. So we just change the working directory when we want the application to have a different behavior.
Currently, the demo is packaged in a signed jar file and it loads correctly until it requires a file from the working directory. Obviously, the Internet users of this demo don't have the files ready. We need a way to make these files available to the WebStart application (read/write access) in its working directory.
We've thought of some things, like having the application download the files itself when it starts, or package them in the jar and extract them on startup.
Looking for advices and/or new ideas. I'll continue working on this... I'll update if I ever find something reliable.
Thank you very much!
I said I would share what I found in my research for something that would fit my needs. Here's what I have so far.
I have found that the concept of current working directory (CWD) does not really make sense in the context of a Java Web Start (JWS) application. This had for effect that I stopped trying to find the CWD of a JWS and started looking for other options.
I have found that (no, I didn't know that) you can refer (using getResource()) to a file in the root directory of a JAR file by simply adding a '/' in front of its name. ("/log4j.properties", for example.) The impact of this is that I can now take any file which is only referred to in a read-only manner in the root of that JAR file (which is really only a ZIP file). You can refer to any file in the root of the JAR file using AnyClass.class.getResourceAsStream. That rules out the problem with read-only files required to run the application, at the cost of a switch in the code telling whether the application is run from a valid CWD or from a JWS context. (You can very simply set a property in the JNLP file of the JWS application and check if that property is set or not to know where to look for the file.)
For write-only files (log files in my case), I used the property , adding a directory with the name of the application: <user.home>/.appname and added log files to it.
Read/write files (which I don't have in my case) would probably simply go at the same place than write-only files. The software could deal with uploading them somewhere if needed, once modified, I guess.
That's the way I deal with the problem for now.
Note there is a service you can explicitly ask for, to get file access to the computer (unless you go all the way and ask for full access (which requires signed jar files)).
Then you need to determine where these files need to go - basically you have no idea what is where and whether you may actually write anywhere. You can create tmp-files but those go away.
Would a file system abstraction talking to the JNLP-server do so you store the users data on the server?

problem with storing data in datastore

I am facing a problem with file upload.I have used Apache Commons
servlet file upload for uploading the file. Though the file is getting
uploaded and the data is getting stored on the local server(http://
127.0.0.1:8888/_ah/admin/datastore) but it is not going to the Google
App Engine datastore.
What I am doing is loading
the file as a stream and immediately parsing the stream and creating
datastore entities with the data. I am not actually trying to save the
file. In the local server it works. It even works when I try to access
the local server from another machine. However it does not work when I
deploy it to Appengine using the Google Pluggin for Eclipse. My parsing
code depends on resource files which are under the web-inf directory.
Is it possible these resource files are not getting uploaded and is
there a way to check what files are uploaded on Appengine?
Whatever's in your .war is going up into AppEngine. I don't see how parts of it will be selectively excluded. What's more likely is that your application is depending on stuff that is lurking SOMEwhere on your PC but not included in that .war file.
However, shouldn't your application be checking for those resources and throwing exceptions if they are not found? If it's failing silently, I'd consider that a design flaw.
Logging a lot may help you debug the problem. You can look at your program's logs via the AppEngine console. I recommend more error checking and logging.
Something else to check for is to not be running the version of your software you think you are. There's a kind of versioning mechanism that allows you to deploy different concurrent versions of your and only one will be actually accessible. One of the things you should be logging and/or making otherwise accessible is some version information (perhaps even including a build timestamp) for your app's build.
The files in the .war folder are executed in the app engine and the others are uploaded. What you need to verify is the path you have set and the path of you source java file and the file you are reading. You cannot use the local file system path in app engine. You need to include the file in your project

Categories

Resources