Operating System - OpenVMS
1753907 Members
8653 Online
108810 Solutions
New Discussion юеВ

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

 
SOLVED
Go to solution
Richard J Maher
Trusted Contributor

Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Hi,

Any advice regarding problems/solutions to the following requirements-specification would be appreciated.

a) I want to implement an Asynchronous I/O strategy between my Java Applet's TCP/IP Socket and my JavaScript anonymous function instances. (So that they fulfill the role of "Asynchronous System Traps - ASTs" or "Asynchronous Call-backs")

b) My JavaScript will call an Applet method to perform synchronous writes to the Socket and I plan to have a separate thread constantly reading for responses.

c) I don't want to lock up the browser EDT while I'm waiting for a Read to complete and have previously used a single-thread and the Socket Timeout method as a sort of delayed poll which let user events/clicks through every "n" seconds. What I want to do this time is use the separate thread to invoke JSObject.call() for each message received. No problem with using a static JavaScript function (I've done so successfully with async UDP messages) but, as there may be many messages received per message sent and there is no restriction on additional messages/requests (or message types) being sent before all messages/responses for a prior message have been read, I was hoping to use closures and anonymous function instances to preserve and pass message-specific parameters to asynchronous read-completion routine/callback.

d) The good news is the requests will be on a single connection-oriented Socket and will be processed on a FIFO basis, so storing parameter objects in an JavaScript/Java Array certainly seems doable. (I'd pass a serial number with the outgoing message and check it against what we're expecting to read next and use push() and shift() to manage the Array)

e) I have to admit to being a bit bamboozled as to whether Java has received the function instance by reference, and once the JS function's local variable that passed the reference to Java has RETURNed (or that local variable re-assigned) and nobody on the avaScript side is left referencing that instance of the function, that the garbage-collector might clean-up the function even though my Applet would be expecting to call it some time in the future.

f) Even if longevity was assured, stuffed if I know of a method that would deserialize the function (or function reference) so that it could accompany the outgoing message to the remote 3GL routine and come back in a reply and
be serialized into a useful form. As a procedural guy at heart, to me it looks like a great case for malloc, pointer, free but hopefully someone can show me the optimal OO way of achieving this.

g) Would the performance of a JavaScript Array that acts like a queue and gets fed from the tail and diminished from the head, degrade over time? (At least with an Array I could use a static/named JS function and keep it simple.)

I guess the first thing I should've asked is has anyone done this or have an example? It is my understanding that Async i/o would appear to be "new" in Java 7 and if that is the case then I'm guessing there's a definite requirement but perhaps no historic solution at present?

Cheers Richard Maher

"Richard Maher" wrote in message
news:gpf5mv$nf3$1@news-01.bur.connect.com.au...
> Hi,
>
> I replaced the pilot-error: -
> public void javaMethod (String jsNum, String jsFunc) {
> with
> public void javaMethod (String jsNum, Object jsFunc) {
>
> and it seems to be giving me a bit more. Sorry for the distraction.
>
> Cheers Richard Maher
>
> "Richard Maher" wrote in message
> news:gpevll$jcd$1@news-01.bur.connect.com.au...
> > Hi,
> >
> > Using netscape.javascript.JSObject (LiveConnect) I want/need to pass a
> > Function Reference to my Java Applet so that it can either call that
> > directly, or pass it to a static JavaScript function that will then
> redirect
> > the call to the appropriate anonymous function that formed a closure.
> >
> > Please forgive me if the terminology is not strictly correct, but I hope
> you
> > can still understand what I'm trying to do.
> >
> > I thought the second argument to JSObject.call could be an array of
> Strings
> > *or* Objects but trying to get a JavaScript object (or a
reference/pointer
> > to it) to survive the Java Applet membrane (without some sort of
> > serialize/deserialize) is proving difficult. Am I missing something
> obvious?
> > Does anyone have a small example I can look at?
> >
> > Maybe it's as easy as the first argument to JSObject.call can be a
> > JavaScript VARiable? I'll give it a go. . .
> >
> > Cheers Richard Maher
> >
> > //This is called from the "onload" event
> > function load() {
> > myFunc = setClosure();
> > myFunc();
> > chan = document.getElementById("AnonCallApplet");
> > return;
> > }
> > // This is called from the Applet
> > function jsMethod(javaInt, javaFunc) {
> > alert('Integer ' + javaInt);
> > alert('JavaFunc ' + javaFunc.toString());
> > javaFunc();
> > return;
> > }
> >
> > function setClosure() {
> > var lclNum = 0;
> > return function(){
> > lclNum++;
> > alert("lclNum = " + lclNum);
> > }
> > }
> > // This is called by some user-driven event (onchange, onclick. . ).
> > function callApplet() {
> > alert(myFunc.toString());
> > chan.javaMethod(step, myFunc)
> > return true;
> > }
> >
> > //Here's the Applet
> >
> > import java.applet.Applet;
> > import java.io.IOException;
> > import netscape.javascript.JSObject;
> > import netscape.javascript.JSException;
> >
> > public class AnonCallApplet extends Applet {
> >
> > private JSObject browser;
> > private static int sumNum = 0;
> > private int addNum;
> >
> > public void init(){
> > try {
> > browser = JSObject.getWindow(this); }
> > catch (netscape.javascript.JSException e) {
> > e.printStackTrace(); }
> > catch (Exception e) {
> > e.printStackTrace(); }
> > }
> >
> > public void javaMethod (String jsNum, String jsFunc) {
> >
> > addNum = Integer.parseInt(jsNum);
> >
> > sumNum += addNum;
> > Object args[] = {(Object)new Integer(sumNum), (Object)jsFunc};
> > try {
> > browser.call("jsMethod", args);}
> > catch (JSException e){
> > System.out.println("Error when calling jsMethod()"); }
> > }
> >
> > public void destroy() {
> > super.destroy();
> > }
> > }
13 REPLIES 13
Bojan Nemec
Honored Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Richard,

First, I have no direct experience with this argument. Reading your post I have read some about JSObject.

If I am correct, all JavaScript objects are wrapped with the JSObject when they are passed to Java methods. So before calling the Applet method wrap all your functions in a single object (AJAX does the same) and pass this object to the Applet method.

a) Probably the best way (as you just say) is to have a separate thread to do the work.

b) Simplier it will be to have an Applet which will do both (reading and writing). Construct the JavaScript object. Put in it all the data you need and the methods to retreive this data and all the methods to process the response (AST/s). So you can call them from the Applet (the name/s of this function/s must be known to the Applet, then call the JSObject.call method to retreive/set/callback). Use this object as a message to your Applet. (in yours example "public void javaMethod (String jsNum, String jsFunc)" will probably be "public void javaMethod (JSObject request)").

c) If you have more than one response you probably know which response belong to the specific request and when you are finished by this request. Simply remember the request (probably a simple Hashtable can do all the work) and use it until you have some responses.

d) On the Java side (java >= 1.5) look at the java.util.concurent package. It has some objects for implementing queues which works between threads. LinkedBlockingQueue for example. You can "put" objects in one thread and "take" them out in another thread. The synchronizing and waiting for objects is part of the LinkedBlockingQueue.

e) Probably the JSObject which wrapp the JavaScript object will take the reference. If this is not true and the object can be garbage-collected put this object in an array so JavaScript will reference the object and when you are finished remove it from the array.

f) See b). See some references on JavaScript classes/objects and prototypes which are very flexible and in same time very strange. You can add data to functions and also functions to functions...

g) I dont know and it probably depends on the used browser.


Probably an example should be in this place.
OK a simplified one.
JavaScript:

function MyMessage ()
{
this.data = "";
}
// somewhere in the code

var msg = new MyMessage ();
msg.data = "something you want to pass as message";
msg.callback = function (response) {Alert (response);}
// I ommit the creation of the applet you already know how to do this
applet.insertMessage (msg);

Java Applet:

public class MyApplet extends Applet implements Runnable
{
LinkedBlockingQueue queue;
// constructors and initialization simplified!!!
public void init ()
{
queue = new LinkedBlockingQueue();
Thread thread = new Thread (this);
thread.start ();
}
public void insertMessage (JSObject message)
{
queue.put (message);
}
public void run ()
{
for (;;)
{
JSObject message = queue.take ();
String data = message.getMember ("data");
// do something with that data
String newData = doSomething (data);
Object [] args = new Object[1];
args[0] = newData;
message.call ("callback" , args);
}
}
}

As I say this example is simplified. No imports, exception handling, constructors and much more.

Bojan
Richard J Maher
Trusted Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Hi Bojan,

Thanks for the reply.

This started out mainly as me trying to use JavaScript closures and anonymous functions as a quasi-malloc.

Some of the problems are: -
1) You can't get a worthwhile (to a VMS 3GL routine) handle on them
2) There are grave doubts about them no longer being referenced and being garbage-collection candidates
3) I really wished they'd work as I think they're really really sexy!

See attached for a tiny example of what I'd hope to achieve with closures and emulating ASTs + Parameters.

Enter something in one of the fields and move off to the other one to see the results. (Try multi-tab and multi-browser instance as well)

Anyway we are where we are as probably best followed at: -
http://groups.google.com/group/comp.lang.java.programmer/browse_frm/thread/06e807a645ea8e78#
(Sorry for the multi-posting)

But to answer some of your points: -

> If I am correct, all JavaScript objects
> are wrapped with the JSObject when they
> are passed to Java methods.

Really?

> before calling the Applet method wrap all
> your functions in a single object (AJAX
> does the same) and pass this object to the
> Applet method.

That was the plan but who'd maintain a reference to it? That's where I came to the Array solution like you (but on the JavaScript side instead)

>(in yours example "public void javaMethod
> (String jsNum, String jsFunc)" will
> probably be "public void javaMethod
> (JSObject request)").

Well spotted - changed in the attached.

> c) If you have more than one response you
> probably know which response belong to the
> specific request and when you are finished
> by this request. Simply remember the
> request (probably a simple Hashtable can
> do all the work) and use it until you have
> some responses.

I can rely on FIFO so it makes things a bit easier.

> e) Probably the JSObject which wrapp the
> JavaScript object will take the reference.
> If this is not true and the object can be
> garbage-collected put this object in an
> array so JavaScript will reference the
> object and when you are finished remove it
> from the array.

Bummer, eh.

Hold on! Looking at your example, I think I understand you now. Are you saying: -

a) Don't have to reference any objects or closures on the JavaScript side 'cos Java will honour the complex Object and it will be maintained in the Java LinkedList?
b) We somehow add/append a ID/SerialNumber or whatever to check against incoming replies?
c) That a variable function name (also sent/returned with the messages) is then called with the Complex Object and the message body as it's parameters?
d) That function can reference a further internal callback if need be?
e) Everyone's a winner; chickens for dinner?

Sounds good! I'm off to sleep on it - Thanks!

Cheers Richard Maher

PS. I think we're still stuck with no one on the JS side referencing any of these lovely complex objects and no gurantee of their longevity? Any takers?
Bojan Nemec
Honored Contributor
Solution

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Richard,

Wrote a simple working (?) example. Stil no exception handling etc...
In the example you can get some ansawers to your questions. I tested it in IE6 FF 2 and Chrome.
It works with one shared thread between tabs/windows. The messages are stored in a JavaScript local array to prevent the garbage-colector.
Two different JavaScript functions for inserting messages. Both can have multiple parameters but only one has local parameters (see comments in the applet).
It is up to you to write communication, serializing and deserializing to and from the host. One option is to convert all parameters n strings send them thru the socket and on the other side convert them in what you need and viceversa (lib$cvt_dx_dx is your friend).

Bojan
Richard J Maher
Trusted Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Hi Bojan,

Once again you're a bloody marvel! What a fabulous illustration of wrapping a complex JavaScript object up in JSObject as an alternative/extension to just using what's returned from JSObject.getWindow(). I have to admit to scratching my head for a while trying to work out how in this instance "this" resolved to the MessageObject (taken from the queue) when it was being referenced in the JavaScript functions replaceValue() and showResponse(). Now I know what you were talking about; very informative and very useful!

Ok a few questions/issues if I may: -

1) It didn't work for me with FireFox 2.0.0.4. In the Java console I get "null" when you're trying to println(message) (Normally in IE6 I get [object Object] 'cos you forgot to toString() it :-) BTW, nothing in the FF Error console to help.

2) Are you using "File" or "Web-Server" URLs? The reason I ask is that for some reason, with IE6, I get separate JVMs when I use IIS URLs, as opposed to File URLs where the JVM is shared. I see the same behaviour with my other example so it's not specific to your code. Can you (or anyone) test with IE7 and multi-tabs?

3) Not sure what the JavaScript function Array().slice is doing for you in MessageObject.done() Going by the name "done" and it's position in the logic I'm guessing this is where you're finished processing the message and are ready to remove it from the array. The problem is that my understanding of slice() is that it doesn't do that. Anyway, it looks like you don't have any issues with JavaScript Array() performance degradation over time?

4) This is a biggie but more philisopical: Why are you creating a separate Worker thread for (what will be) outgoing Socket messages/writes? I too intend to have a separate thread but for a single Reader (that will read the socket and dispatch the message to the appropriate JSObject) but I was planning on using the Socket itself (ok, perhaps the BufferedWriter) as a natural queueing mechanism. Do you see problems/disadvantages in this approach? Yes, I will have to do my own synchronizing, but is there anything else. I had hoped to say that each browser/tab writing directly to the Socket had the advantage that the number of bytes written can be checked immediately but BufferedWriter methods are void and if an IOException is raised then you pretty much want to shutdown all access; so the jury's out.

I don't like using Arrays/Queues/LinkedLists at all and am only doing it in JS to up the reference and keep the GC at bay. I am also lucky that my messages are FIFO and I can fall-over if the response received does not match the message serial number that I'm expecting. But trying to keep two arrays and the outgoing messages in sync is surely over-complicating the process?

Thanks again!

Cheers Richard Maher
Bojan Nemec
Honored Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Richard,

1) My appologies for FF. When I was writing the example I manged it to work in IE6 and Crome but not in FF. Yust in the middle of writing my previous post I tryed again in FF and it begin to work. Today it does not work. However this is just an example, for a real Applet there is much more work.

2) The applet and html is served by an Apache server on a Linux machine. Sorry have no IE7 installed.

3) I just misread the slice reference. The intention was to remove the object. So the "done" method must be rewritten and probably the two call functions. One option is to search the first free slot in the array and in done just set the reference to null. On the other hand I am prety shure that this step is not needed and the JSObject keeps the reference. Look at this link:

http://www.docjar.com/html/api/netscape/javascript/JSObject.java.html

It is not much but see the description of the finalize method.

4) I create a separate worker to test yours idea of one single thread doing all IO. Doing both writing and reading from this thread seems to me a more simple solution than do writes in one and reads in another thread. All exceptions can be signaled by a special JavaScript object method say onError () and you have all in one thread so you can shutdown the socket and do all other house keeping without some interthread comunication.

The LinkedBlockingQueue is used only to simplify the inter thread communication. The queue will probably be empty in most cases.
I also do not like Arrays in 3GL languages because of static size. So I use Queues which are double linked lists. This comes from the old VAX days and VAX macro which has instructions for queues. VMS operating system hardly relayes on queues. Abbout the second (JavaScript) array se 3). I am prety shure there is no need to have any reference to keep the GC at bay. The reference is the JSObject and when it will be finalized the reference will disapear.

Bojan
Bojan Nemec
Honored Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Found some more references that JSObject keeps the JavaScript reference. This is true for gecko/mozilla based browsers. See this source:

http://xulrunner-1.9.sourcearchive.com/documentation/1.9~a8/jsj__JSObject_8c-source.html

and the description of JSRemoveRootRT:

https://developer.mozilla.org/en/SpiderMonkey/JSAPI_Reference/JS_RemoveRootRT

The first link is to the xulrunner source but I found it in the firefox source which is identical (or much similar) to the one from xulrunner. Search for finalize in the code.

Bojan
Richard J Maher
Trusted Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Hi Bojan,

God I like you! Not only do you go out of your way to answer my questions, and reference supporting documentation, but you also answer the questions that I haven't worked out I should be asking yet. I won't keep going on about it but I am most appreciative of your help! (And also that of other contibutors and lurkers here and at COV and HP)

Anyway, back to your latest post: -

It is absolutely fantastic news about JSObject [re/main]taining a JavaScript reference on the object; this stuff just keeps getting better and better!

1) No problem with the bug in FF, I do appreciate it's a quick demo. (Although, in absence of anything in the Error Console as to why the JObject wasn't formed, if you want to tell me what's wrong with it then that'd be fine also :-)

Great to see you've got it working on Chrome. Last I saw it didn't yet support Java Sockets :-( Do you know if that's changed?

2) WRT IE6, are you getting one JVM per browser instance? Do you have "Java Console" switched on in your browser settings? (With File URLs I get one JVM for all Browser instances, with web-server URLs I get a 1:1 ratio. This behaviour appears specific to applets containing "static" variables) Just noticed I am running Java 1.6.0_01 so I guessing there may have been some bug-fixes in the last 12 months. Can one of you lurkers please try this with TABs on IE7?

3) This is a water-shed moment in the design! Ok, so now the question flips to "How do we get rid of the JSObject-wrapped JavaScript object when we're finished with it?" My guess is just "MessageObject = null;" and let the GC sort it out; anything more appropriate? Looks like the finalize() method is protected and there's no special destroy(), so will setting these complex objects to null when we're finished with them be enough to flag them for clean-up in both Java and JavaScript?

4) This is not really important and probably more a matter of preference, but let me point out that in my design I would only have one additional thread "Reader" all the writing would be done in the intrinsic browser/applet threads. If I understand your example correctly, you would either have to have 2 additional threads (a Writer and a Reader) *or* you would delay the sending of the next message(s) over the network until you have received all the responses from the previous message. Is that not correct? If it is then not only is Network latency an issue but competition is fierce on the server-side with many other Sockets stuffing messages down to be processed. First come, first served.

*) Would the relative perfomance of JSObject.[get/set]Member() be better than defining JavaScript "getter and setter" functions for any properties that Java needs to obtain from the complex JavaSCript object by JSObject.Call() them? I plan to have a MessageSeqNum property that will be set when the message is sent down the network and compared when the response(s) come back.

This is all great stuff! Why can't VMS can be a bigger part of it? Does no one else get as excited as me about the opportunities here?

a) SUN completely revamps Applet Support with Java 6 (Seperate Applet thread)
b) JNLP deployment of Applets and multi-version JVM instantiation support
c) Microsoft/Silverlight introduces Socket support
d) Adobe/Flex proposes a standard for Cross-Domain policy-file Socket suport
e) SUN/Java also introduces Cross-Domain policy files for Sockets
f) HTML5 people are working on intrinsic html WebSocket support
g) VMS released with full IPsec support (and INETd is free)
h) Adobe FABridge lets you opt for Java Socket over Flex
i) Java for Android (Java the iPhone yet?)

Why can't VMS back-end all of these amazing offerings instead of having its user-community condemned to Green-Screens and FTP? Dear God in heaven, what more does one man have to do? Are they really going to continue to ignore any form of merit-based project funding until there's some poorly performing Linux freeware version of Tier3 available so they can pay some half-trained gibbon to port it over to VMS?

Cheers Richard Maher

PS. I will respond to your other reply soon. It just takes me a bit longer to process the information than you :-)
Bojan Nemec
Honored Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Richard,

1) This will probably take to much time to me. So its up to you to debug and see why its not working. As I said in one moment all works OK. And one more thing, in FF3 it not work. There are some problems with mayscript and scriptable parameters of the Applet.
Abbout Chrome. I was testing it in IE6 and when it was working I simply run Chrome. I have no experience with it.

2) In IE6 I have open two windows and it seems that it shares the the JVM instance. Java 1.6.0_10.

3) The MessageObject is instantiated as a local var in the two supporting functions. So when the function returns they are dereferenced and ready for the GC. The reference is held by the JSObject. The finalize method of the JSObject is called from the Java GC.
Abbout "MessageObject = null;". You should not do this. The MessageObject is the class and will probably be reused for other calls. With the "new MessageObject()" we create new instances of this class. It is similar to Java classes and objects.

4) My intention was to do write/read in the same thread. OK you are right the writes and reads are not simultaneus.
It will be interesant to see what do you plan to have on the VMS side. I supposed that you will have a program which will read the message do the work and write the ansawer in a read/compute/write loop.

To have simultaneus write and read, you can modify the example logic with:
public void insertMessage (JSObject message)
{
// for outputStream is meant a static output stream to the socket.
synchronized(outputStream)
{
// assign the message number
worker.insertMessage(message);
// do the writes
}
}
and in the dispatchMessage (the name is no more appropriate it should be something like readMessage) method do the reads.

*) To be tested. It could be done with the JSObject.[get/set]Member() and will probably be faster. When I wrote in OO languages I always have getters and setters for the properties so I can override them when subclassing.

I wrote a simple http server for VMS about 4 jears ago. It was a project for one of my customers and works as a simple TCP/IP service (Yes I know it is slow and consuming) but it was written COBOL programmer friendly. From that day the customer write all his programs as web pages and no more as terminal applications.

I think there is a lack of support for that kind of applications in VMS. Yes there are many ports from open source but all that is C oriented. Nothing contrary to C and open source but on VMS you need also the support for other languages and VMS standards (descriptors etc...). An example:
Say we have a subprogram which takes the value of a numeric parameter from the http request.
1 name pic x(10).
1 stringval pic x(10).
1 numval pic s9(5)v9(2).

string "NUMBER" X"00" delimited by size into name.
call "getParameter" using request name stringval giving stat.

Now you have to parse the value to get the numeric value and probably you have to strip the ending null character because this was written for C. Time consuming for the programer and the program became unreadable.

If the software is VMS oriented we can wrote it in this way:

1 numval pic s9(5)v9(2).

call "getNumericParameter" using request
by descriptor "NUMBER" numval giving stat.

Bojan
Richard J Maher
Trusted Contributor

Re: Java and JavaScript Asynchronous i/o, Garbage Collection, Funtion Instance references

Hi Bojan,

1) Look mate, you're just not tryin'. If you've got time-management and priority issues then I suggest you get'em sorted :-)

Nah no worries, I've got more than enough to get on with and at least with FireFox there's FireBug and a decent Error Console.

2) Interesting; must be me.

3) Good tip thanks! I wasn't aware of the Object Re-use potential and thought I'd be speeding up the clean-up and avoiding any leaks.

4) "It will be interesant to see what do you plan to have on the VMS side."
Which rock have you been hiding under? For examples, please try: -

http://manson.vistech.net/t3$examples/demo_client_web.html
(Enter an "*" in the queuename and hit the green button)

or (one that uses Flex charting): -

http://manson.vistech.net/t3$examples/demo_client_flex.html
(Just hit "GO")

Username: TIER3_DEMO
Password: QUEUE

All (slightly out of date) Java/COBOL source code is available at: -
http://manson.vistech.net/t3$examples/

The format and content of data that goes up and down the network is specified by the individual application, and you can put any language that adheres to the VMS procedure calling standard on the server side. (Just 6 routines!)

These examples have the following restrictions: -

1) A Socket and Network Connection is bound closely to each web-page/frame-set
2) If you change pages and come back you have to log in again
3) All blocking-socket interaction takes place within the scope of the browser's, or Applet's (after Java6), EDT. I use setSoTimeout() as a polling-mitigator so the thread can be freed up every "n" seconds to service events.

What I want to do now is get around these restrictions by firstly having a separate thread read the responses and then "callback" in the appropriate Window, and secondly go the whole-hog and allow the user to flit from page to "unrelated" page but remember them when the come back again. (No cookies, Session IDs, Session-hijacking, etc from that poorly-performing, context-devoid, load of bollocks HTTP!)

Pretty sexy eh?

Ok, admittedly on the server-side I won't go back to the Socket for another client request until the last response message has been sent (for that particular exchange/association/RPC) but when I do go back, if the next message is queued up for processing at the server-end then the AST will be triggered immediately.

Cheers Richard Maher

BTW, I too provide a simple/lightweight HTTP server (Applet Uploader) so that sites that use an OS other than VMS to host their main Web-Servers can still grab their Applets from the VMS codebase blisteringly fast.