 |
Seek and Deploy 2: The Cookie Jar, Refilled
Posted by evanx on October 31, 2006 at 05:08 PM | Comments (10)
So I've been playing with URLClassLoader, URLConnection, jars within jars, and webservers within, um, Swing apps. All quite Escher'esque.
The article about the demo, is served by the webserver within the demo :)
Actually there is a copy of the "article" here,
and the project page is
cookiejar.dev.java.net.
So we embed a jar within a jar so that we can wrap a
pack200 jar in a real jar. But then the wrapper gets to be like a "splash jar" ie. a splash screen written in java, so we got carte blanche, sweeet!
In this demo, the splash jar uses URLClassLoader to load the "real" jars. We have one embedded jar (containing demo's as in the menu below), and we also preload an external jar eg. the last item in the menu below. It's disabled until that jar is loaded (off jroller.com). Then that menu item becomes enabled, and you can launch it.
In order to use URLClassLoader for this twisted purpose, we embed a webserver, which is what makes
this exercise real fun :)
The code is in webservlet/src.
You can of course run it by checking out the webservlet.dev.java.net project and running the main class cookiejar.CookieJarLoader.
Here is the "raw" CookieJar, ie. a jar file that your browser might be willing to download and run for you with one click?
(webservlet, 150k, executable java5 jar)
The CookieJar pops up the above JFrame as soon as your browser finishes downloading it, and decides to run it using java, woohoo!
If your browser doesn't run jars, then here is the JNLP of the above jar.
(CookieJar, 150k, all-permissions, Java5)
No security... Goddamn, i wish i knew how to sandbox stuff properly?!
Um, er... so what is this 150k jar? Well... it contains a few things. (1) an article, (2) another jar with my old boring dinky demos in it, and (3) a webserver, to serve up (1) and (2).
I must confess, i had a huge amount of fun putting this
twisted demo together! :)
Bookmark blog post: del.icio.us Digg DZone Furl Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment
-
Sorry its broken... gonna need a few minutes...
Posted by: evanx on October 31, 2006 at 05:15 PM
-
seems to be fixed. just don't hit any of the Exit buttons on the demos - cos those do a System.exit() and kill other demo frames (and the webserver) since they use same JVM - rather dispose using the window X
Posted by: evanx on October 31, 2006 at 05:42 PM
-
No security...
Using class loaders from untrusted code is a bit limited. I was running up against these problems earlier this evening.
You can create a class loader with URLClassLoader.newInstance.
You cannot create a class from an arbitrary byte array.
Assuming your code is already in a jar you can't use Class.getResource as a URL in your URLClassLoader, because nested jars are broken.
Applications loaded from a file codebase have some file permissions.
However, you cannot convert a File to a URL as that would give away the working directory.
There's definitely some enhancement work here for the Java SE security (and networking) team...
Posted by: tackline on October 31, 2006 at 06:31 PM
-
You could also have a look at
https://glyph.dev.java.net/hyperjars.html
which uses Pack200 files to provide highly compressed mobile code for Jini applications
Assuming your code is already in a jar you can't use Class.getResource as a URL in your URLClassLoader, because nested jars are broken.
Not if your URL ends with the directory specifier (!/) and it's not that nested jars are broken, but URLClassLoader has a number of issues (including not being able to manage the URL cache, making deploying multiple versions more difficult, but I won't get into that one), and if you don't specify !/ you have to return a single ZipInput Stream to fool URLClassLoader that it's looking at a single Jar File.
However, you cannot convert a File to a URL as that would give away the working directory
I assume your talking File#toURL() here?
Posted by: calum on November 01, 2006 at 02:37 AM
-
Which URL are you talking about? I have this code [full class]
urls.add(DynamicDriverManager.class.getResource(
"chaperon.jar" // i.e. dynamicdriver/chaperon.jar
));
Do you mean changing the string to "chaperon.jar!/"?
For File to URL, I was using file.toURI().toURL() (as File.toURL has broken encoding). Would a manually constructed relative URL work?
Posted by: tackline on November 01, 2006 at 09:24 AM
-
Hi Evan,
This is a really great idea. For games it would be very useful, since they have to download lots of resources & retain the interest of the user. I've posted a link to this page on: javagaming.org
Thanks for making a nice job of this,
Keith
Posted by: commanderkeith on November 02, 2006 at 06:20 AM
-
The menu, the "Run" button, and the "Browser" button never become active. There isn't any obvious failure message. No webserver is available at http://localhost:8005/ The console shows:
FINER:logger:BCommon:loadResourceBytes:272:exiting::(String)/webroot/splash1.html:(Integer)1021
FINER:logger:CookieJarLoader:actionPerformed:271:entering::(String)Next
FINER:logger:BCommon:loadResourceBytes:272:exiting::(String)/webroot/splash2.html:(Integer)2063
FINER:logger:CookieJarLoader:startServer:213:entering::(Boolean)false
FINER:logger:BCommon:loadJar200UrlBytes:303:entering::(String)http://jroller.com/resources/e/evanx/aptcomponent.jar.unsigned.pack.gz.jar
INFO:logger:BCommon:loadJar200UrlBytes:312::(String)http://jroller.com/resources/e/evanx/aptcomponent.jar.unsigned.pack.gz.jar:(Integer)-1
INFO:logger:BServer:putResource:165::(String)/aptcomponent.jar:(Integer)598394
Posted by: coxcu on November 02, 2006 at 08:17 AM
-
The Browser and Run buttons become enabled when the webserver starts. Maybe it can't start on your machine because of ZoneAlarm of something blocking it starting a server on port 8005? That's the only thing i can think of!? cos works on my machine?! Lemme know if you come right or not?!
The other thing one can try is checkout webservlet project, and run within netbeans, use the debugger and stuff and/og add a few logger.info() messages in the server to see what's happening - i'll try to add more debugging messages like that in myself, and also install ZoneAlarm and try with that blocking the port, to make sure the logger and/or exception is made clear
Posted by: evanx on November 03, 2006 at 03:21 AM
-
It's not ZoneAlarm. I run Tomcat and Fit Nesse on my machine without incident.
Posted by: coxcu on November 03, 2006 at 07:15 AM
-
so i fixed a bug which was in the server (BServer's run() method), if it couldn't connect to the port, it was doing a "throw new RuntimeException" but now it's a "handleException(e)" which displays an exception dialog, eg. "Address already in use" eg. if you run it twice.
and fixed another bug that the logger wasn't clearly showing the exception and trace in the console window.
When it connects to the port, it fires an event "serverStarted" on CookieJar, which cause the frame to enable to Browser button and Run button.
If buttons aren't getting enabled, it should mean BServer can't connect() to the server socket ie. 8005 for whatever reason, eg. it is already running, and something is running on that port, or blocking that port. If you look at BServer.java there's not really much to it - connect(), fireStarted() and then accept() connections...
Posted by: evanx on November 06, 2006 at 09:54 AM
|