The JACOB project:a java-com Bridge

Source: Internet
Author: User
Tags event listener wrappers

http://danadler.com/jacob/ What is Jacob?

The "JACOB is a" java-com bridge "allows" to call COM Automation components from JAVA. It uses JNI to make native calls into the COM and Win32 libraries. The JACOB project started in 1999 and are being actively used by thousands of developers. As a Open-source project, it has benefitted from the combined experience to these users, many of whom have made Modificat Ions to the code and submitted them back for inclusion in the project.

The JACOB project has moved to SourceForge.net. Verion 1.14.3 is now available at Sourceforge. If you are are a SourceForge developer and are interested in contributing to the project, please contact the project Administr Ators. The rest of this page is out of Date-please go to Sourceforge for current information and support.

Version 1.7 includes some new features as as a many bug fixes, memory leak plugs, as as as new models for threading a ND object lifetime which the code much robust. The release notes below for details.

This is the background about how the project got started. Release Notes and credits Version 1.7 release Notes and credits Version 1.6 and Previous versions release Notes and credits

Related LinksThe JACOB mailing list is hosted at Yahoo Groups:http://groups.yahoo.com/group/jacob-project.This is the preferred way to get support for JACOB. It also includes an extensive archive. If you are are doing any development with JACOB, please join the list. Massimiliano Bigatti has developed jacobgen-a generator that automatically the JACOB code from Type creates. He no. longer maintains it, but you can get version 0.3 here:jacobgen-0.3 also the samples are here:jacobgen-samples-0.3 Steven Lewis is developing a version of the java2com that supports JACOB code generation. See:http://www.lordjoe.com/java2com/index.html. To find documentation on the com.ms.com package, go to:http://www.microsoft.com/java/download/dl_sdk40.htm and at the bot Tom's the page is a link this says:microsoft SDK for Java 4.0 documentation only. You are should download that file and install it. Then, view sdkdocs.chm and look for "Microsoft Packages Reference". Hopefully, the next release of JACOB would include full Javadoc (volunteers?) ...

Downloads

The JACOB binary distribution (jacobbin_xx.zip) includes: Jacob.jar: a jar file for the Java classes which your MU St Add to your CLASSPATH. The package names replace com.ms with com.jacob (for example com.ms.com.Variant maps to com.jacob.com.Variant. Jacob.dll: a small Win32 dll which you must add to your PATH. samples: provided in Java source and compiled form to demonstrate various features of the product. In particular, a set of wrapper classes for Microsoft®ado are provided as samples.

The source code is available in the JACOB source distribution (Jacobsrc_xx.zip), which includes both the Java and C + + code . The source distribution is a superset to the binary one, so don ' t need both. Version 1.7

Download jacobbin_17.zip Download jacobsrc_17.zip Version 1.6

Download jacobbin_16.zip Download jacobsrc_16.zip License

This is the old JACOB License. The new license is at Sourceforge (the "link above"). Usage and Documentation

Since the Com.jacob classes are intended to being compatible with the microsoft®com.ms classes, it is recommended Ownload the documentation of Microsoft ' s SDK for Java. To find documentation on the com.ms.com package, go to:http://www.microsoft.com/java/download/dl_sdk40.htm and at the bot Tom's the page is a link this says:microsoft SDK for Java 4.0 documentation only. You are should download that file and install it. Then, view sdkdocs.chm and look for "Microsoft Packages Reference". Hopefully, the next release of JACOB would include full Javadoc (volunteers?) ...

The following example uses Microsoft®excel as an Automation server:

Import com.ms.com.*;

Import com.ms.activex.*; public class Dispatchtest {public static void main (string[] args) {activexcomponent xl = new Activexcomponent ("E Xcel.
    Application ");
    Object XLO = Xl.getobject ();
      try {System.out.println ("version=" +xl.getproperty ("version"));
      System.out.println ("version=" +dispatch.get (XLO, "version"));
      Xl.setproperty ("Visible", New Variant (true));
      Object workbooks = Xl.getproperty ("workbooks"). Todispatch ();
      Object workbook = dispatch.get (workbooks, "Add"). Todispatch ();
      Object sheet = dispatch.get (Workbook, "ActiveSheet"). Todispatch ();
                                  Object a1 = Dispatch.invoke (sheet, Range, Dispatch.get, new object[] {"A1"},
      New Int[1]). Todispatch ();
                                  Object A2 = Dispatch.invoke (Sheet, Range, Dispatch.get, new object[] {"A2"},
      New Int[1]). Todispatch (); Dispatch.put (A1, "Value", "123.456");
      Dispatch.put (A2, "Formula", "=a1*2");
      System.out.println ("A1 from Excel:" +dispatch.get (A1, "Value"));
      System.out.println ("A2 from Excel:" +dispatch.get (A2, "Value"));
      Variant F = new Variant (FALSE);
    Dispatch.call (Workbook, "Close", f);
    catch (Exception e) {e.printstacktrace ();
    finally {Xl.invoke ("Quit", new variant[] {});

 }
  }
}

As it stands, the code would only compile with JVC (Microsoft's compiler) and only run under JVIEW (Microsoft ' s VM). However, if you have the JACOB distribution installed, then your can replace the two top lines with:

Import com.jacob.com.*;
Import com.jacob.activex.*;


And now, the can compile this with the any Java compiler and run it using the any Java VM in any Win32 platform. Frequently asked Questions (FAQ)

Massimiliano Bigatti has compiled the Jacob FAQ based on his experience and the discussions in the Jacob Yahoo Group:http ://groups.yahoo.com/group/jacob-project. Implementation

The JACOB implementation of a COM Automation controller is quite different than the one used in the MICROSOFT®JVM. In JACOB, the Com.jacob.com.Dispatch class are the basic building block. This class is used to create the instance of an Automation server. The Com.jacob.activeX.ActiveXComponent class simply extends the Dispatch class to provide compatibility with the way ation servers are created in the MS JVM. The Dispatch class ' s methods are all static for compatibility with the MS class.

The Com.jacob.com.Dispatch constructor takes a String as an argument. If The string contains a colon (': '), then I try to interpret it as a moniker, otherwise, I assume it ' s a ProgID. This means so if you are want to create the CLSID of instead of ProgID, then your should use the Clsid:moniker as The string. I find The Cleaner than manipulating GUID classes in Java.

The implementation of SafeArray ' s reproduces most of the functionality (and some) of the quirks Tation. This is means, for example, that's you have to size the array in the constructor before your fill it with data otherwise you wil L get an error, and the Fromxxxarray methods does not work for multi-dimensional arrays (which are consistent with the Micros OFT®JVM). It would is nice to improve upon this interface, but for now, I put compatibility A.

One extra feature that I couldn ' t resist adding, being that's com.jacob.com.Variant class is java.io.Serializable. This is accomplished the C + + code by using the Variant_usermarshal and Variant_userunmarshal calls from Oaidl. H which are used to serialize a variants to a byte array and back. This feature was reportedly broken on Windows 2000 ... Threads, Applets and security

The original version of JACOB did not handle COM threading issues. This means your had to create and use a COM component in the same thread.

Threading can prove tricky in applets and Servlets. For example, the following code makes sure to initialize the "COM component in the" AWT event thread as opposed to the main Applet thread. If you try to create and initialize the ScriptControl in the Init () method, the subsequent event code would throw a Comfai Lexception. Please read about the "New Threading Model in Version" 1.7 to find out about the many options of handling COM Threading in J Acob.

Import java.awt.event.*;
Import java.applet.*;

Import com.jacob.com.*;
Import com.jacob.activex.*;

public class Apptest extends applets implements ActionListener
{
  TextField in;
  TextField out;
  Button Calc;
  Activexcomponent SC = null;
  Object SControl = null;

  public void init () 
  {
    setlayout (new FlowLayout ());
    Add (in = new TextField ("1+1");
    Add (out = new TextField ("?",));
    Add (Calc = New button ("Calculate"));
    Calc.addactionlistener (this);
  }

  public void actionperformed (ActionEvent ev) 
  {
    if (SC = null) 
    {
      //Create COM component in Event Threa D
      SC = new Activexcomponent ("ScriptControl");
      SControl = Sc.getobject ();
      Dispatch.put (SControl, "Language", "VBScript");
    }
    Use COM component in same thread
    Variant v = dispatch.call (SControl, "Eval", In.gettext ());
    Out.settext (V.tostring ());
  }


In addition to the threading issue, your have to deal with the security restrictions imposed by browsers. If you run this applet in IE5 where the Jacob.jar be in your CLASSPATH, then it'll work, but if the Jacob.jar classes AR E downloaded-you get a security exception. In JDK1.1.6 Appletviewer, this code works as are, but in JDK 1.2.2 Appletviewer, LoadLibrary fails because there are no SECU Rity Descriptor. So far, I couldn ' t get the code to run in Netscape 4.6. COM Object Lifetime

Version 1.7 introduces a new model for COM Object lifetime, please see:com object lifetime in JACOB. Wrappers

I have included a sample directory called ADO. In which Directrory are a set of wrappers for ADO which are source-code equivalent to those produced by the Microsoft®jact Ivex tool. The following excerpt shows how the Connection, Command and Recordset objects interact:

  Create connection and command objects and use them
  //To get a recordset public
  static void GetCommand (String c On, String query
  {
     System.out.println ("Command+connection-> Recordset");
     Connection C = new Connection ();
     C.setconnectionstring (con);
     C.open ();
     Command comm = new command ();
     Comm.setactiveconnection (c);
     Comm.setcommandtype (commandtypeenum.adcmdtext);
     Comm.setcommandtext (query);
     Recordset rs = comm. Execute ();
     Printrs (RS);
     C.close ();
  }

In this release, the wrappers are generated by hand, but, and the related links section above to some 3rd party WRA Pper generators for JACOB. Events

I wanted to support events in the the "I", but delegating COM events to a proper Java interface is too much work fo R this timeframe. So, the current implementation departs from the microsoft®implementation. This would, hopefully, is changed in the future to follow Beans event rules.

The current model was conceptually similar to the Visual Basic WithEvents construct. Basically, I provide a class called com.jacob.com.DispatchEvents which has a constructor that takes a source object (of Ty PE com.jacob.com.Dispatch) and a target object (of any type). The source object is queried a for it IConnectionPointContainer interface and I attempt to obtain a iconnectionpoint for I TS Default source interface (which I obtain from IProvideClassInfo). At the same time, I also create a mapping of DISPID's for the default source interface to the actual method names. I then use the "method" names to get Jmethodid handles from the target Java object. all event methods currently must have the same signature:one argument which are a Java array of variants, and a VO ID return type.

The dependency on IProvideClassInfo means this Type Library for the component must exist if your want to support events . The following example shows the Microsoft®scriptcontrol as an In-proc server, and catch the Error and Timeout Events which it generates:

Version 1.7 also includes code to read the type library directly from the ProgID. This is makes it possible to work and all Microsoft Office application events, as as the IE5 events. For an example the Samples/test/ietest.java example.

Import com.jacob.com.*;

    public class Scripttest {public static void main (String args[]) {system.runfinalizersonexit (true);
    String lang = "VBScript";
    Dispatch SControl = new Dispatch ("ScriptControl");
    Dispatch.put (SControl, "Language", Lang);
    Dispatch.put (SControl, "Allowui", New Variant (true));
    Instantiate an event target object errevents te = new errevents ();
    Hook it up to the SControl source dispatchevents de = new Dispatchevents (SControl, TE); Run an expression from the command line System.out.println ("eval (" +args[0]+ ") =" + Dispatch
  . Call (SControl, "Eval", Args[0]);  }//This are the event interface class Errevents {public void Error (variant[] args) {System.out.println ("Java
  Callback for error! ");}
  public void Timeout (variant[] args) {System.out.println ("Java Callback for timeout!"); } >java Scripttest ' Now () ' eval (now) = 10/5/99 11:07:43 AM >java scripttesT ' () Now () ' Java callback for error!

 Eval (() now ()) = null
Non-default Interfaces

Once you have a Dispatch object, you can navigate to the other interfaces of a COM object by calling Queryinterafce. The argument is a IID string in the format: "{9bf24410-b2e0-11d4-a695-00104bff3241}". You are typically get this string from the IDL file (it's called UUID in there). Any interface your try to use must is derived from IDispatch. The following example shows can be used. The full example (including the ATL COM object) is in the Samples\test\atl directory.

Import com.jacob.com.*;

Import com.jacob.activex.*;

    Class Multiface {public static void main (string[] args) {system.runfinalizersonexit (true);
    activexcomponent MF = new Activexcomponent ("Multiface.face");  try {//I am now dealing with the default interface (IFACE1) dispatch.put (MF, "Face1name", New Variant ("Hello
      Face1 "));

      System.out.println (Dispatch.get (MF, "Face1name")); Get to IFace2 through the IID Dispatch F2 = MF.
      QueryInterface ("{9bf24410-b2e0-11d4-a695-00104bff3241}");
      I am now dealing with IFace2 dispatch.put (F2, "Face2nam", New Variant ("Hello Face2"));

      System.out.println (Dispatch.get (F2, "Face2nam")); Get to IFace3 through the IID Dispatch f3 = MF.
      QueryInterface ("{9bf24411-b2e0-11d4-a695-00104bff3241}");
      I am now dealing with IFace3 Dispatch.put (F3, "Face3name", New Variant ("Hello Face3"));

    System.out.println (Dispatch.get (F3, "Face3name")); catch (Exceptione) {e.printstacktrace ();

 }
  }
}
Limitations Since We do not modify the underlying VM, JACOB cannot does any magic with casting. So to the moment, it does not support any form of custom interfaces. The event model (Java catching COM events) in the "is not compatible" with either the Beans model or the WFC model. The "current model allows" to "pass" Java object as a COM event listener and its methods are invoked by reflection . This release does not include a reverse bridge. Therefore, you can ' t wrap complex Java objects and send them to COM method calls. All inputs must resolve to Variant objects. My theory is that a reverse bridge requires much more code, and so should reside in a separate DLL. I have the code for a skeleton for a reverse bridge-if anyone be interested in working on it. I have a reverse bridge as lower priority, because Sun already provides one as part of the Java PLUG-IN. This release does not provide any support for hosting graphical ActiveX controls inside of Java components. Testing:this RElease has not been tested as rigorously as I would like. Please have a bugs or fix any for you find! Platform and VM testing:i have only tested in NT4SP5 with Sun ' s JDK 1.1.6 and JDK 1.2.2 VM ' s and Microsoft ' s Java vm (Bui LD 3182). Support

The JACOB mailing list is hosted at Yahoo Groups:http://groups.yahoo.com/group/jacob-project. However, due to severe limitations of the Yahoo Groups software it is getting inordinate amounts of spam and has been Discontinued. Please use the "SourceForge" link at the "Top" page for any support requests. Contributions

You are are encouraged to suggest modifications to the code of the JACOB project. Please refer to the "SourceForge link at the" "This page and follow the submission rules of SourceForge.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.