If you are dying to be given a more realistic example, turn your attention towards Netscape. The problem that Netscape faces is no less menacing than the one that the hypothetical Mother faces in the above analogy. Netscape has three components that ref use to work with each other due to the language barrier that is prevalent between them. Netscape can work ever so well with C/C++ (in the form of plug- in DLLs), Java and of course, its baby, Java Script. But, these children refuse to say a meaningful word to each other. If used in conjunction with one another, the three are capable of performing miracles, but they simply refuse to talk. So what does Netscape do? Netscape took up a seemingly impossible challenge and after months of hard work and con centrated effort, gave the world a new concept in computer programming. LiveConnect.
LiveConnect promises to revolutionize the way these three different entities interact with each other over and beyond the Internet. It will act as a sort of a middle man or intermediary who will take instructions from one entity, translate and deliver it to the other entity in a form that the other understands. Since Java Script can already talk to Java, the main language problems lie between the Netscape Plugins (written in C/C++) and Java. With so many incompatibilities between these languages, the co ncept holds promise.
Before you launch on this trip...
The technology involved here is fairly complicated, so we suggest that you proceed onto this journey only if you are proficient in Java, Java Script and Netscape Plugins (in C/C++). If you are totally in the dark about any one of these three, we strongly recommend that you bookmark this page and go to our main page to check out our relevant tutorials. Only when you are somewhat confident about these topics should you attempt this tutorial. We're serious about this. This stuff still has us confused, so do n't lose heart if you don't get it the first time.
Before LiveConnect - The Dark Ages
The problem before Live Connect was quite interesting (and frustrating, to those who were exposed to it). Netscape could process HTML pages. HTML was powerful, but not in the same terms as a programming language would be expected to be. To add more pow er to their already popular HTML, Netscape introduced a product called Live Script. The effect that Live Script had on HTML was similar to the effect that steroids have on an athlete. Powered on by the Live Script, which pumped life into it, HTML came o n stronger than was expected. Live Script underwent a renaming ceremony and became known the world over as Java Script. Java Script, as Live Script now came to be known, was, basically, a programming language. It could understand HTML and brought more life and intelligence to the pages. Whenever Netscape Navigator (or any other browser) would encounter Java Script instructions, it would simply call the Java Script Interpreter, which would then decipher the code. Java Scri! pt was unique in the sense that it had pre- created objects which understood HTML. So, for example, you could use the object history, to perform a certain function, which could be to go back one page (i.e., history go (-1)). This, when encountered, caus ed the browser to perform the specified action.
As suggested earlier, Java Script was Netscape's baby and Netscape could do anything to it. But, the problem was that nobody could touch Java.
Java looks and behaves a lot like C++ and holds on to many concepts used by the latter. Even though it has its shortcomings (Who doesn't???), it's a revolutionary product that is all set to change the way we think. Even before we realized it, Java recei ved a positive response from both, the market and the media.
When we use the command line Java compiler, Javac, we convert our source code into a .class file. It is this .class file which has the capability to whiz down the Internet and execute on your machine, since the code to execute a Java applet is already p resent in the Netscape Navigator. Nothing really stops Netscape from going to Sun Microsystems and licensing their Java compiler. If they did that (as they indeed have), the browser's HTML compiler would have to work overtime, but could easily invoke th e Java Script interpreter on encountering Java Script and upon finding Java code, it could call the Java compiler, convert it into a class file and execute it. So, in a sense, Java and Java Script could reside in the same HTML document.
YIPPEE!!!!
Of course, before you put on your best suit and pull out your finest wine, just answer a couple of questions that do arise out of this situation...
The answer is pretty straight forward. Java Script and the original Java classes (Moz3_0.zip)are built into Netscape, so, they can be merged and called as one; your own classes don't really come into the picture. So, that solves a part of the problem. ( Did I hear you call for the wine???)
Let us, for some time, wander away from the problems associated with Java and Java Script, and focus our attention on the third man who promises to be no less a problem than the other two put together- Netscape plug- ins, written only in C/C++. (All those holding the key to writing DLLs in other languages are requested to E- mail us on this issue)
A plugin is a .dll, which (being a .dll) is programming language neutral. A .dll has more to do with the operating system, than the programming language, for example, the Macintosh doesn't use .dlls. (You would probably recall that a plug- in is a conven ient method of letting other programs execute code and understand formats that your program is not educated to. If you are confused, I'd suggest that you skim through our tutorial on this topic first). A plugin is simply a modified .dll. A plugin adds new capabilities to old software. Using plugins, Netscape and Microsoft let other companies create compatible software for their products. Obviously, a plug- in is not only a fantastic idea, but also a very powerful one.
Fortunately (or unfortunately), when it comes to plugins, there is only one flavor, Netscape's. Software developers the world over breathed a collective sigh of relief, when Microsoft announced that their browser would be Netscape plugin compatible. In a plugin, you set the functions that Netscape can call to extend its capabilities. This is truly the essence of a plugin, i.e., it is simply a set of retrievable dynamic functions. Another point to be noted, is that a plugin not only offers its functions to Netscape, but at the same time, is also capable of calling functions from Netscape. It is a two way street. This is the crucial difference between a .dll and a plugin, because a .dll cannot call code from the application that uses it.
It is indeed a trivial task to convert a program into a plugin and that's why so many of them are floating around in the ether of cyberspace. There are only superficial differences between a .dll and a plugin, so anyone who knows how to write .dll's can comfortably switch over to writing Netscape Plugins. This, in effect, means that the power associated with the Netscape plug- ins is almost unlimited. The only point to be remembered is that these plug- ins are written primarily in C/C++, which, though, easily interfaceable with the Netscape Navigator, are almost impossible to interface with Java and Java Script.
The problem, thus, was this. Netscape navigator dealt with three different entities, namely Java, Java Script and the plug- ins written in C/C++. Java Script could be used only from HTML pages. Java could communicate only with other programs written in Java; C/C++ could communicate only with other material originating from the C/C++ programmer's desk. There was a communication gap that existed between any two of these entities. When all appeared dark and gloomy, Netscape gave us their most promising product- Live Connect!!!
LiveConnect - What is it that we are looking at???
Even though the name does not say much, the product itself is quite good. LiveConnect promises to let Java, Java Script and .dll's written in C/C++ talk to each other. Now the basic problem is that the creators of these languages never really meant for th em to talk to each other. Java and Java Script do manage somehow, but C/C++ is totally out of the picture. There was no way that you could copy Java code and paste it in a C/C++ program, and expect smooth, efficient operation. Similarly, it would be sill y to expect that C/C++ code would run flawlessly when pasted into a Java program.
As mentioned earlier, Java understands only Objects. One of the problems with having Objects is that new ones keep cropping up all the time, so a way must be found to inform Java about these new Objects when and if they are made available. It is for thi s purpose that the developers at Sun gave us the import statement. By using this function, we can 'import' new Objects into Java as and when we like. However, any code you bring in has to be compiled into a class file first. This means that Netscape now has to write code in the Java programming language, compile it, create a class which Java can understand, create an Object that looks like Java Script .... and on and on and on! Sounds like a lot of hard work? Well, definitely, it was. But, after hours of hard work, Netscape, in its infinite wisdom, introduced the finished code- LiveConnect.
Since there are three major players in this drama (Java, Java Script and Netscape plug- ins), we have six possible communication options. Netscape has removed two of these by making it impossible for Java Script to communicate with plugins. However, this means that Java can converse with a plugin and vice versa and Java Script can communicate with Java and vice versa. So, for Java Script to converse with plugins, we have to go through Java. But, hey, if everybody can get talking even to this level, Live Connect deserves more than just a first glance.
LiveConnect bears a striking resemblance to the MFC classes. It is both a collection of functions and a set of rules and regulations. It makes fast and superficially uncomplicated communication possible between C/C++, Java and Java Script. Like most new s oftware, it offers this simplicity only through its own uncompromising complexity. (Confused ?! You're not the only one!!) Hang in long enough, and we'll make your problems melt away.
Since C/C++ plug- ins refuse to understand Java, Netscape has no choice but to give you functions, contained in a library file (JRT3321.lib); This file then becomes the buffer between the Plugin and Java. This library file contains functions that begin w ith JRI_ and are an integral part of LiveConnect . So much for maling C/C++ understand Java. The rest of LiveConnect deals with Java's interactions with a plugin.
Really, the problem seems almost out of our hair. One could say that LiveConnect has been divided into two equally important halves, one written in Java and the other in C/C++. There is a part of LiveConnect that is written in C/C++ and interfaces other C/C++ code with Java and Java Script. (This takes care of two more communication options) At the same time, the remaining communication channels are covered comfortably by the part of Live Connect that is written in Java and dedicatedly co-ordinates th e interface between Java programs and the powerful DLLs. (This, basically, means that Java can now interface easily with C/C++, since almost all DLLs are written in these two languages!!! Of course, it also means that C/C++ can now, easily, interface wit h Java. Is this good, or what?)
Now a simple example to get our concepts straight and our brains rolling...
Program 1
a1.htm
<html> <head> <script language="JavaScript"> function it() { java.lang.System.err.println("Hello"); } </script> </head> <body> <center> <h1> Test </h1> <hr> </center> <form> <input type=button onclick="it()" value=Click me, please !!> </form> </body> </html>
This is quite a simple program, but let us quickly examine it all the same.
In this program, we're calling Java code from Java Script . Now, we should remember that when I say Java code, I mean the original Java SDK, not the code residing in applets I have written.
Now in this first example, we have an input, of the type 'button', where the value of the button is "Click me, please !!" ( just so that it's irresistible!! ). When this snippet of code is run, a button with the label "Click me, please !!" will appear on the screen. When you click on the button, the event onclick is called and it in turn will call the 'it' function. Doing this, displays nothing on the screen, but if you go to the Java console, you will see a cheerful little 'Hello' printed across the win dow. (You would, of course, recall that since we are using .err, the output 'Hello' will obviously be sent to the Java console)
What we've done is directly call a Java class named System. System is a static object, having a member named err, which in turn contains another member named println. So whatever you type in here will be teleported directly over to the Java Console ( in Netscape ).
As promised, this program was actually quite simple. But, obviously, we are made for sterner stuff. Why don't we try out something just a little juicier.
Onwards ....
Program 2
a1.htm
We are well aware that Java Script has typeless variables. But, in this program, we've broken up our function it() into two lines. We've said, var s = java.lang.System. This implies that s, a Java Script variable, is now an object which represents the S ystem. So instead of using the object System , we can simply type in s.err.println to send output to the Java Console.<html> <head> <script language="JavaScript"> function it() { var s = java.lang.System; s.err.println("Hello"); } </script> </head> <body> <center> <h1>Test </h1> <hr> </center> <form> <input type=button onclick="it()" value=good> </form> </body> </html>
<html> <script language="JavaScript"> function it() { var s = new java.awt.Frame("bye"); s.show(); var s = java.lang.System; s.err.println("hello"); } </script> <body> <center> <h1>Test </h1> <hr> </center> <form> <input type=button onclick="it()" value=good> </form> </body> </html>
Program 4
AviTest.java
import java.awt.*; import java.applet.Applet; public class AviTest extends Applet { public void it() { Frame g = new Frame("aaa"); g.show(); } }
<html> <head> <script language="JavaScript"> </script> </head> <body> <center> <h1>Test </h1> <hr> <applet name=avi code=AviTest.class width=400 height=30 > </applet> </center> <form> <input type=button onclick="document.avi.it()" value=good> </form> </body> </html>
AviTest1.javaimport java.awt.*; import java.applet.Applet; public class AviTest extends Applet { public void it() { Frame g = new Frame("aaa"); g.show(); } }
import java.awt.*; import java.applet.Applet; public class AviTest1 extends Applet { public void it1() { Frame g = new Frame("bbb"); g.show(); } }
a1.htm
<html> <head> <script language="JavaScript"> </script> </head> <body> <center> <h1>Test </h1> <hr> <applet name=avi code=AviTest.class width=400 height=30 > <applet name=avi1 code=AviTest1.class width=400 height=30 > </applet> </center> <form> <input type=button onclick="document.avi.it()" value=good> <input type=button onclick="document.avi1.it1()" value=good1> </form> </body> </html>
import java.awt.*; import java.applet.Applet; import netscape.javascript.JSObject; public class AviTest2 extends Applet { mmm l; public void it() { Frame g = new Frame("aaa"); g.show(); } public void init() { setLayout(new BorderLayout()); add("Center", l = new mmm(getDocument())); l.enable(); } public static void main(String args[]) { Frame f = new Frame("AviTest"); AviTest2 aviTest = new AviTest2(); aviTest.init(); f.add("Center", aviTest); f.resize(300, 30); f.show(); } public JSObject getDocument() { JSObject a = (JSObject)JSObject.getWindow(this); JSObject b = (JSObject)a.getMember("document"); return b; } } class mmm extends Panel { Button play; JSObject d; public mmm(JSObject doc) { d = doc; add(play = new Button("Play")); } public boolean action(Event ev, Object arg) { if (ev.target instanceof Button) { AviTest2 v = (AviTest2)d.getMember("avi"); v.it(); } return true; } }
<html> <head> <script language="JavaScript"> </script> </head> <body> <center> <h1>Test </h1> <hr> <applet name=avi code=AviTest2.class width=400 height=30 mayscript> </applet> <hr> <hr> </center> <form> </form> </body> </html>
a1.htmimport java.awt.*; import java.applet.Applet; import netscape.javascript.JSObject; public class AviTest3 extends Applet { mmm l; public void it() { Frame g = new Frame("aaa"); g.show(); } public void init() { setLayout(new BorderLayout()); add("Center", l = new mmm(zzz())); l.enable(); } public static void main(String args[]) { Frame f = new Frame("AviTest"); AviTest3 aviTest = new AviTest3(); aviTest.init(); f.add("Center", aviTest); f.resize(300, 30); f.show(); } public JSObject zzz() { JSObject a = (JSObject)JSObject.getWindow(this); return a; } } class mmm extends Panel { Button play; JSObject d; public mmm(JSObject doc) { d = doc; add(play = new Button("Play")); } public boolean action(Event ev, Object arg) { if (ev.target instanceof Button) { String a[]; a = new String[1]; a[0]="hello"; d.call("confirm",a); } return true; } }
<html> <head> <script language="JavaScript"> </script> </head> <body> <center> <h1>Test </h1> <hr> <applet name=avi code=AviTest3.class width=400 height=30 mayscript> </applet> <hr> <hr> </center> <form> </form> </body> </html>
npshell.cpp
a1.htm#include <windows.h> #include <string.h> #include <stdio.h> #include "jri.h" #include "npapi.h" #include "npupp.h" NPError NP_LOADDS NPP_NewStream(NPP instance,NPMIMEType type,NPStream *stream, NPBool seekable, uint16 *stype) { stream->pdata = instance->pdata; *stype = NP_ASFILE; return NPERR_NO_ERROR; } void NP_LOADDS NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname){ } int32 STREAMBUFSIZE = 0X0FFFFFFF; int32 NP_LOADDS NPP_WriteReady(NPP instance, NPStream *stream) { return STREAMBUFSIZE; } int32 NP_LOADDS NPP_Write(NPP instance, NPStream *stream, int32 offset, int32 len, void *buffer) { return len;} NPError NP_LOADDS NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason) { return NPERR_NO_ERROR;} void NP_LOADDS NPP_Print(NPP instance, NPPrint* printInfo){} NPNetscapeFuncs* g_pNavigatorFuncs = NULL; BOOL WINAPI DllEntryPoint( HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { return TRUE;} NPError NPP_Initialize(void) { return NPERR_NO_ERROR;} NPError WINAPI NP_Shutdown() { return NPERR_NO_ERROR;} void NPP_Shutdown(void){} NPError NP_LOADDS NPP_New(NPMIMEType pluginType,NPP instance,uint16 mode,int16 argc, char* argn[], char* argv[],NPSavedData* saved) { return NPERR_NO_ERROR;} NPError NP_LOADDS NPP_Destroy(NPP instance, NPSavedData** save) { return NPERR_NO_ERROR;} static NPPluginFuncs* g_pluginFuncs; NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs) { pFuncs->version = (NP_VERSION_MAJOR<<8)|NP_VERSION_MINOR; pFuncs->newp = NPP_New; pFuncs->destroy = NPP_Destroy; pFuncs->setwindow = NPP_SetWindow; pFuncs->newstream = NPP_NewStream; pFuncs->destroystream = NPP_DestroyStream; pFuncs->asfile = NPP_StreamAsFile; pFuncs->writeready = NPP_WriteReady; pFuncs->write = NPP_Write; pFuncs->print = NPP_Print; pFuncs->event = NULL; /// reserved g_pluginFuncs = pFuncs; return NPERR_NO_ERROR; } JRIMethodThunk S = {(JRIMethodThunkType)0,"onStop","()V"}; JRIMethodThunk O={(JRIMethodThunkType)0,"getObserver","()LAviObserver;"}; char aa[100]; FARPROC _pfnDefault; NPP i; LRESULT CALLBACK PluginWndProc(HWND w, UINT x, WPARAM y, LPARAM z) { if ( x == WM_LBUTTONDOWN) { void * javaAviInst; const JRINativeInterface** env; javaAviInst =(void *) g_pNavigatorFuncs->getJavaPeer(i); env = g_pNavigatorFuncs->getJavaEnv(); void * o = (*env)->CallMethod(env,javaAviInst,&O).r; sprintf(aa,"env %p o %p javaclass %p",env,o,javaAviInst); if (o) (*env)->CallMethod(env, o, &S); MessageBox(0,aa,aa,0); } return CallWindowProc(_pfnDefault, w,x,y,z); } NPError NP_LOADDS NPP_SetWindow(NPP instance, NPWindow* window) { if (!window) return NPERR_GENERIC_ERROR; if (!instance) return NPERR_INVALID_INSTANCE_ERROR; if (!window->window) return NPERR_NO_ERROR; i = instance; _pfnDefault=(FARPROC)::SetWindowLong(window->window, GWL_WNDPROC,(LONG)PluginWndProc); return NPERR_NO_ERROR; } NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs) { g_pNavigatorFuncs = pFuncs; JRIEnv* env = g_pNavigatorFuncs->getJavaEnv();; clazz=(java_lang_Class*)JRI_FindClass(env,"AviPlayer"); struct java_lang_Class*clazz=(java_lang_Class*)(*env)-> FindClass(env,"AviPlayer"); JRIGlobal * a = (*env)->NewGlobalRef(env, clazz); g_pluginFuncs->javaClass = a; sprintf(aa,"javaclass %p..",a); MessageBox(0,aa,aa,0); return NPERR_NO_ERROR;; }
AviTest.java<html> <body> <applet name=controller code=AviTest.class width=400 height=30 mayscript></applet> <embed name=avi SRC="m0oooj9l.avi" WIDTH=100 HEIGHT=100> <hr> <form> <input type=button onclick="document.avi.advise(document.controller)" value=sonal> </form> </body> </html>
AviPlayer.javaimport AviObserver; import AviPlayer; import java.awt.Frame; import java.applet.Applet; import netscape.javascript.JSObject; public class AviTest extends Applet implements AviObserver{ public void onStop() { Frame s = new Frame("hello"); s.show(); } }
import netscape.plugin.Plugin; import AviObserver; public class AviPlayer extends Plugin { private AviObserver observer; public AviObserver getObserver() { return observer; } public boolean advise(AviObserver o) { observer = o; return true; } } interface AviObserver { public void onStop(); }