Oh, applets.... *sigh* Why, why, why....
Yes, you're right. It hadn't occurred to me that reading/writing
the VM's system properties should require elevated
privileges—still doesn't make a whole lot of sense to me, given
that reading them is fairly harmless, and you can set them
directly in the in HTML of the page with
`-D<arg>=<value>` arguments, anyway!—but you are
correct.
And [the security restrictions] would mean the props extension would be useless in applets anyway.
Useless: No
Kind of inconvenient to leverage: Yes
But when I want to query my database I get a runtime error: extension
exception: No active database connection available error while observer running SQL:EXEC_QUERY
[...] offhand, it sounds like it could be another applet security restriction problem.
From the tests that I've done on my machine, that seems to be the
case. It's curious to me that the exception doesn't display like
other security access violations, but it failed for me just like
how Maëlle described when the '.jar's weren't signed, and worked
fine for me when they were signed, so...
causality.
Alright, so... looks like you need some signed '.jar's, Maëlle.
This will require some more effort, but I've tested it out and
verified that both the Props and SQL extensions seem to work
without security access violations when the '.jar's are signed.
To get started, you'll first need a key with which to sign the
'.jar's. To create one, run `keytool -genkey -alias <your
desired keyname; for the remainder on this monologue, this will be
"coolkey">` from the command line and fill out the resulting
questionnaire—a bit obnoxious, I know. If your shell complains
that 'keytool' is not found, ensure that the 'bin' folder of your
JDK is on your path. (Some additional info on 'keytool'
here.)
Alright, we now have a key for signing '.jar's. Now, we actually
have to sign them. (P.S. This part sucks....) Except that I
created a script that makes it bearable! See, the 'jarsigner'
utility is a real piece of crap, and it only works on one '.jar'
at a time, and, on top of that, '.jar's are peculiar about the
order in which they must be packed and signed, so... having a
script to automate this esoteric little process really makes
things nicer.
Here's my 'packer' script:
```
#!/bin/sh
for file in $1
do
echo "Packing $file"
pack200 -r $file
jarsigner $file coolkey
pack200 --modification-time=latest --effort=9
--no-keep-file-order $file.pack.gz $file
done
```
In a directory containing '.jar's that you want to sign, call it
like this: `packer "*.jar"`. You might ask why there need to be
the quotes in there. Honestly, I don't know, and I admit that
this is a
very novice script, and, I also admit that it
would be nicer if the script remembered your passphrases and
didn't ask you for them for each '.jar' being signed, but I'm
actually not interested enough in shell scripts to improve that
aspect of it.... *shrug*
Be sure to modify the script to change "coolkey" to whatever the
name of your keystore from above was!
So... the '.jar's that need to get signed are... all of them. If
so much as a single '.jar' is loaded without being signed, your
applet is going to fail—and they all need to be signed with
the
same signature, too! So run that script on all of the
'.jar's in both the Props and SQL extensions' folders, and on
'NetLogoLite.jar', too. Also, you can/should throw out the old
'NetLogoLite.jar.pack.gz'; '.jar's need to be signed before
they're compressed (and packed before they're signed (see earlier
reference to esotericism)).
Okay, we should now have signed, packed '.jar's. Now, we need to
launch NetLogo with the elevated permissions that having these
signed '.jar's allows us to have. We can't do that with a simple
`<applet>` HTML tag, though. Well, I've sometimes read that
you can use an `<applet>` tag and a custom-made Java
'.policy' file, but I've yet to ever see that work. Instead, I
think we just need to use JNLP files. Resources that I found
useful when setting up my first JNLP-based applet the other night:
one,
another,
yet
another. Regardless, I'll
try to guide you through
the process without you needing to bother with those resources.
So, basically, given your situation, you want to pass in dynamic
data to the applet. To do so, we're going to use Java system
properties. Java system properties are specified for a JNLP-based
applet in the JNLP file. As such, you're going to need a
different JNLP file for each configuration, meaning that you'll
need to dynamically create JNLP files, and then dynamically
generate the HTML that directs the user towards the correct JNLP
file. I'll supply some template code for each of those in a bit.
But, since I have some experience with JNLP files for Java
WebStart, I'll make a recommendation here: have a separate folder
in your applet's directory just for JNLP files, and name each
generated JNLP file as "<UUID>.jnlp", where "<UUID>",
of course, is just some
UUID
that you generate when you go to create the file.
As such, I suggest a folder structure like this:
```
project_root
-<HTML file>
-<NetLogo model file>
-NetLogoLite.jar
-NetLogoLite.jar.pack.gz
-jnlp
--<all of your JNLP files>
-props
--<Props' '.jar's and '.jar.pack.gz's>
-sql
--<SQL's '.jar's and '.jar.pack.gz's>
-<folders for any/all other extensions that you need>
```
My HTML and JNLP templates will expect a directory structure like
the one listed above. If you go with a different structure, you
may need to change the HTML/JNLP accordingly.
For the HTML, it's fairly simple; we just replace the old
`<applet>` tag with some JavaScript that launches the JNLP
as an applet:
```
<script
src=
"http://www.java.com/js/deployJava.js"></script>
<script>
var attributes = {code: 'components.MyApplet', width: 675,
height: 480} ;
var parameters = {jnlp_href: 'jnlp/MyApplet.jnlp'} ;
deployJava.runApplet(attributes, parameters, '1.6');
</script>
```
I don't think that the "MyApplet" in "components.MyApplet" means
much of anything here, but, since I advised naming the JNLPs by
UUID, you're going to want to replace "jnlp/MyApplet.jnlp" with
"jnlp/<UUID>.jnlp". And... that should be the only dynamic
part of rendering the page's HTML. If you don't put your JNLPs in
some 'jnlp' folder, you'll want to change the "jnlp/" in
"jnlp/MyApplet.jnlp" to properly reflect where your JNLPs are.
Now for generating the JNLP. Here's the template:
```
<?xml version="1.0" encoding="UTF-8"?>
<jnlp href="MyApplet.jnlp">
<information>
<title>Props/SQL/Applet Example</title>
<vendor>CCL</vendor>
</information>
<security> <all-permissions/> </security>
<resources>
<property name="jnlp.packEnabled" value="true"/>
<!-- Dynamic data through Java system properties!
-->
<property name="netlogo.data" value="Secret data!"/>
<!-- Application Resources -->
<j2se version="1.6+" />
<jar href="../NetLogoLite.jar" main="true" />
<jar href="../props/props.jar"/>
<jar href="../sql/sql.jar"/>
<jar href="../sql/bonecp-0.7.0.jar"/>
<jar href="../sql/guava-r07.jar"/>
<jar href="../sql/mysql-connector-java-5.1.19.jar"/>
<jar href="../sql/postgresql-9.1-901.jdbc4.jar"/>
<jar href="../sql/slf4j-api-1.5.10.jar"/>
<jar href="../sql/slf4j-simple-1.5.10.jar"/>
</resources>
<applet-desc
name="Props/SQL Applet"
main-class="org.nlogo.lite.Applet"
width="675"
height="480">
<param name="DefaultModel"
value="../MyApplet.nlogo"/>
</applet-desc>
<update check="background"/>
</jnlp>
```
Replace `jnlp \ information \ title`, `jnlp \ information \
vendor`, and `jnlp \
applet-desc.name` with values that are more
representative of your situation.
`<security> <all-permissions/> </security>`:
This is what launches the applet with elevated permissions,
allowing the use of these extensions.
`<property name="netlogo.data" value="Secret data!"/>`: This
makes it so that, if you were to call `props:get "netlogo.data"`
within the NetLogo applet, you should get the value "Secret data!"
back. Change the property name as you see fit, and set the value
dynamically at JNLP-generation time with the data you want to
propagate into NetLogo (I probably don't need to tell you this,
since this data is largely the whole point of everything I'm
saying here). Naturally, you can add virtually as many
`<property />` tags as you'd like, to load in lots of
different values.
`<jnlp href="MyApplet.jnlp">`: This is also something that
needs to be set dynamically by you. Since we don't specify a
`codebase` attribute in this tag, the JNLP's "codebase" is
inferred to be the folder in which the JNLP sits. What is means
is that other URLs are interpreted as being relative the location
the JNLP. Since I advised that JNLPs go in './jnlp', the '.jar'
file paths and the model path should be preceded with "../" (as
shown here). If you go with a different directory structure, or
if you manually set the `codebase` attribute, adjust the paths in
the JNLP accordingly. Also, make sure to change the
"MyApplet.jnlp" in the `href` here to dynamically be
"<UUID>.jnlp", so as to match the actual name of the file.
(Truth be told, I've never really understood the necessity of this
aspect of JNLPs, given how redundant it is.)
And... that should do it.
I hope that helps....