merged R-1_9 release tag against the root-B-1_9

This commit is contained in:
clay_shooter
2005-02-26 21:32:27 +00:00
parent ebb1eddb69
commit bcf7bb0f85
132 changed files with 7134 additions and 4068 deletions

11
.cvsignore Normal file
View File

@@ -0,0 +1,11 @@
jacob.dll
jacob.jar
jacobdll.jar
*.zip
RELEASE.txt
.project
.classpath
compilation_tools.properties
version.properties
release

View File

@@ -1,28 +0,0 @@
For documentation see: http://users.rcn.com/danadler/jacob/
The java code is in com\jacob\*.
The C++ code is in .\jni.
To build, run:
nmake -f makefile
That will first compile the JAVA files and build the JAR file, and
then compile the C++ code and build the DLL.
Building the jni:
The following are hardcoded into the makefile, so you may have to
change it. I developed this with the C++ compiler and ATL version
that ship with VC++ 6.0, so I'm not sure if different versions will
work.
I have compiled this against JDK 1.1.6 and 1.2.2 as well as Microsoft
SDK for Java 3.2 as the JDK setting.
DEST_DIR is a destination directory into which to copy the final DLL.
JDK = d:\j2sdk1.4.2_06
DEST_DIR = d:\jacob
MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98

View File

@@ -1,114 +0,0 @@
<h1>What's New in JACOB 1.8</H1>
<ul>
<li>
<b>Move To SourceForge</b>
The project is not housed at
<a href="http://sourceforge.net/projects/jacob-project/">Sourceforge.net</a>.
</li>
<li>
<b>Licensing Change</b>
All limitations on commercial use of JACOB have been removed and it
is now being developed under a BSD license at
<a href="http://sourceforge.net/projects/jacob-project/">Sourceforge.net</a>.
</li>
<li>
<b>Compiled with Java 1.4.2</b>
Version 1.8 was compiled with JSEE 1.4.2 and fixes the compilation bug
that was remnant of compilation with JDK 1.1.
</li>
<li>
<b>Baseline For Change</b>
This version is the baseline for the first CVS checkin and we encourage
people to start contributing to the project with this version.
</li>
</ul>
<li>
<h1>What's New in JACOB 1.7</H1>
<ul>
<li>
<b>Explicit COM Threading Model Support:</b>
See a detailed discussion of
<a href="JacobThreading.html">COM Apartments in JACOB</a>
</li>
<li>
<b>New COM Object Lifetime model:</b>
See a detailed discussion of
<a href="JacobComLifetime.html">COM Object Lifetime in JACOB</a>.
</li>
<li>
<b>Improved Event Handling:</b>
Thanks to code contributed by
<a href="mailto:n.o.bouvin@daimi.au.dk">
Niels Olof Bouvin</a>
and <a href="mailto:jehoej@daimi.au.dk">Henning Jae</a> JACOB 1.7 can
read the type information of a Connection Point interface by looking
it up in the registry. This makes it possible to use events with IE as
well as office products.
</li>
<li>
<b>Improved Dispatch:</b>
Error messages from Invoke failures are now printed out as well as
allowing the passing in of arguments to a Get method.
</li>
<li>
<b>EnumVariant Implementation:</b>
Makes it easier to iterate over COM collections. Thanks to code
contributed by
<a href="mailto:Thomas.Hallgren@eoncompany.com">Thomas Hallgren</a>.
</li>
<li>
<b>SafeArray leaks:</b>
SafeArrays were not being properly freed prior to version 1.7, many
other memory leaks were fixed as well.
</li>
<li>
<b>Visual Studio Project:</b>
For those who want to debug: vstudio/jacob. At the moment all the
native code is replicated there from the jni directory...
</li>
</ul>
<H1>Related Links</H1>
<ul>
<li>
The JACOB mailing list is hosted at yahoo groups:
<a href="http://groups.yahoo.com/group/jacob-project">
http://groups.yahoo.com/group/jacob-project</a>.
<b>This is the preferred way to get support for JACOB</b>. It also
includes an extensive archive. If you are doing any development with
JACOB, please join the list.
<li>
Massimiliano Bigatti has developed
<a href="http://www.bigatti.it/projects/jacobgen/">
Jacobgen - a generator that automatically creates JACOB code from
Type Libraries</a>
</li>
<li>
Steven Lewis is developing a version of Java2Com that supports JACOB
code generation. See:
<a href="http://www.lordjoe.com/Java2Com/index.html">
http://www.lordjoe.com/Java2Com/index.html</a>.
<li>
To find documentation on the com.ms.com package, go to:
<a href="http://www.microsoft.com/java/download/dl_sdk40.htm">
http://www.microsoft.com/java/download/dl_sdk40.htm</a>
and at the bottom of the page is a link that says:
Microsoft SDK for Java 4.0 Documentation Only. You should download
that file and install it. Then, view sdkdocs.chm and look for
"Microsoft Packages Reference". Hopefully, the next release of
JACOB will include full javadoc (volunteers?)...
</li>

267
build.xml Normal file
View File

@@ -0,0 +1,267 @@
<?xml version="1.0"?>
<!-- ======================================================================
Feb 4, 2005 1:23:05 PM
Ant build file for JACOB.
Tested on Eclipse 3.0.0 and Ant 1.6.1, with MS Visual C++ 6.0
Eclipse users are pretty lucky. This works with the version of ANT
that comes with Eclipse 3.0.1 (maybe 3.0.0). The whole project
can be built inside eclipse.
If you do not have a C++ environment check out the following sites
http://msdn.microsoft.com/visualc/vctoolkit2003/
http://www.eclipse.org/cdt/
http://eclipsewiki.editme.com/InstallingCDTWithMSVisualC
====================================================================== -->
<project name="jacob" default="default" basedir=".">
<property file="compilation_tools.properties" />
<!-- =v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=v=
YOU MUST define a file named compilation_tools.properties
and looking like this:
JDK=D:/J2SDK-1_4_2
MSDEVDIR=C:/Program Files/Microsoft Visual Studio/VC98
version=1.9
DO NOT check this file into source control as the values are specific
to YOUR environment.
the version.properties file is now completely autogenerated
=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^=^ -->
<property name="application.title" value="JACOB : Java COM Bridge" />
<property name="application.vendor" value="http://jacob-project.sourceforge.net, created by Dan Adler (http://danadler.com)" />
<property name="install.dir" value="${basedir}/release" />
<property name="jacob_java.src" value="${basedir}/src" />
<property name="jacob_java.samples" value="${basedir}/samples" />
<property name="jacob_java.unittest" value="${basedir}/unittest" />
<property name="jacob_java.bin" value="${install.dir}" />
<property name="jacob_cpp.src" value="${basedir}/jni" />
<property name="jacob_cpp.bin" value="${install.dir}/jni" />
<property name="jacob.jar" value="${install.dir}/jacob.jar" />
<property name="jacob.dll" value="${install.dir}/jacob.dll" />
<property name="compiler" value="${MSDEVDIR}\bin\cl.exe" />
<property name="linker" value="${MSDEVDIR}\bin\link.exe" />
<!-- =================================
target: default
================================= -->
<target name="default" depends="createDirectoryStructure,jacob_java_jar_bin,jacob_c_dll">
<echo message="Jacob ${version} build ${build.iteration} : finished on ${build.date}" />
</target>
<!-- ======================================================================
Writes out a version file to be included in the jar
================================================================== -->
<target name="IncrementBuildNumber">
<propertyfile file="version.properties">
<entry key="version" type="string" value="${version}" />
<entry key="build.iteration" type="int" operation="+" value="1" pattern="00" />
<entry key="build.date" type="date" value="now" operation="=" pattern="dd-MMMM-yyyy HH:mm:ss" />
</propertyfile>
<property file="version.properties" />
</target>
<!-- ======================================================================
Create the necessary directory structure (does nothing if it
already there)
================================================================== -->
<target name="createDirectoryStructure">
<mkdir dir="${jacob_java.bin}"/>
<mkdir dir="${jacob_cpp.bin}"/>
<mkdir dir="${install.dir}"/>
</target>
<!-- ======================================================================
Compare the date/time of the jacob JAR against that
of the jacob java source
================================================================== -->
<target name="jacob_java_jar_check">
<uptodate property="jarUpToDate" targetfile="${jacob.jar}">
<srcfiles dir="${jacob_java.src}">
<include name="com/**/*.java" />
</srcfiles>
<!-- Check the build file itself as well -->
<srcfiles file="${basedir}/build.xml" />
</uptodate>
<echo message="jacob_java_jar_check result: ${jarUpToDate}" />
</target>
<!-- ======================================================================
Compile the java files
Relies on ant recognizing when a file needs to be compiled
================================================================== -->
<target name="jacob_java_compile" depends="createDirectoryStructure,IncrementBuildNumber">
<echo>Building java classes...</echo>
<javac srcdir="${jacob_java.src}"
destdir="${jacob_java.bin}"
listfiles="true" debug="on" fork="yes" />
<echo>Building java sample classes...</echo>
<javac srcdir="${jacob_java.samples}"
destdir="${jacob_java.bin}"
excludes="com/jacob/samples/servlet/**/*.java"
listfiles="true" debug="on" fork="yes" />
<echo>Building java test classes...</echo>
<javac srcdir="${jacob_java.unittest}"
destdir="${jacob_java.bin}"
listfiles="true" debug="on" fork="yes" />
</target>
<!-- ======================================================================
Package the classes into a JAR.
Put version.propertes into the jar file so getJacobVersion() can find it
================================================================== -->
<target name="jacob_java_jar_bin" depends="createDirectoryStructure,jacob_java_compile,jacob_java_jar_check,IncrementBuildNumber" unless="jarUpToDate">
<echo>Removing old jars</echo>
<delete file="${jacob.jar}" />
<echo>Packaging java classes...</echo>
<jar destfile="${jacob.jar}" basedir="${jacob_java.bin}" update="false">
<exclude name="**/CVS" />
<exclude name="com/**/*Test.class"/>
<exclude name="com/jacob/samples/**"/>
<include name="com/**/*.class" />
<include name="version.properties" />
<manifest>
<attribute name="Built-By" value="${user.name}" />
<section name="com.jacob">
<attribute name="Specification-Title" value="${application.title}" />
<attribute name="Specification-Vendor" value="${application.vendor}" />
<attribute name="Implementation-Title" value="${application.title} Java libraries" />
<attribute name="Implementation-Version" value="${version} build ${build.iteration} on ${build.date}" />
</section>
</manifest>
</jar>
</target>
<!-- ======================================================================
Compare the date/time of the jacob DLL against that
of the jacob cpp source
================================================================== -->
<target name="jacob_c_check">
<uptodate property="dllUpToDate" targetfile="${jacob.dll}">
<srcfiles dir="${jacob_cpp.src}">
<include name="*.cpp" />
<include name="*.h" />
</srcfiles>
<!-- Check the build file itself as well -->
<srcfiles file="${basedir}/build.xml" />
</uptodate>
<echo message="jacob_c_check result: ${dllUpToDate}" />
</target>
<!-- ======================================================================
Compile the c source files.
================================================================== -->
<target name="jacob_c_compile" depends="createDirectoryStructure,jacob_c_check,IncrementBuildNumber" unless="dllUpToDate">
<echo>Clean up the target folders and file, for safety</echo>
<delete file="${jacob_cpp.bin}/**/*.*" />
<echo>Compiling C++ classes</echo>
<apply executable="${compiler}" dir="${jacob_cpp.bin}" parallel="false" verbose="true" failonerror="true">
<arg value="-c" />
<arg value="/nologo" />
<!-- optimize build for speed. (is this VC specific? -->
<arg value="/O2" />
<arg value="-I" />
<arg value="${JDK}\include" />
<arg value="-I" />
<arg value="${JDK}\include\win32" />
<arg value="-I" />
<arg value="${MSDEVDIR}\Include" />
<arg value="-I" />
<arg value="${MSDEVDIR}\ATL\Include" />
<fileset dir="${jacob_cpp.src}">
<include name="*.cpp" />
</fileset>
</apply>
</target>
<!-- ======================================================================
Link the obj files into a DLL.
================================================================== -->
<target name="jacob_c_dll" depends="createDirectoryStructure,jacob_c_check,jacob_c_compile" unless="dllUpToDate">
<echo>Clean up the target folders and file, for safety</echo>
<delete file="${jacob.dll}" />
<echo>Creating jacob.dll</echo>
<apply executable="${linker}" dir="${jacob_cpp.bin}" parallel="true" verbose="true" failonerror="true">
<arg value="/nologo" />
<arg value="/dll" />
<arg value="/version:${version}" />
<arg value="/out:${jacob.dll}" />
<arg value="/libpath:${MSDEVDIR}/lib" />
<srcfile />
<arg value="${JDK}\lib\jvm.lib" />
<arg value="oleaut32.lib" />
<arg value="ole32.lib" />
<arg value="uuid.lib" />
<arg value="kernel32.lib" />
<arg value="shell32.lib" />
<arg value="user32.lib" />
<fileset dir="${jacob_cpp.bin}">
<include name="*.obj" />
</fileset>
</apply>
</target>
<!-- ======================================================================
Use this target to create javadoc from com.jacob.*
================================================================== -->
<target name="javadoc">
<defaultexcludes add="**/*Test*"/>
<javadoc
packagenames="com.jacob/**"
sourcepath="${jacob_java.src}"
destdir="${jacob_java.bin}/docs/api"
author="true"
version="true"
use="true"
windowtitle="Jacob API Docs">
<doctitle><![CDATA[<h1>Java Com Bridge (Jacob)</h1>]]></doctitle>
<bottom><![CDATA[<i>See Jacob-project on Sourceforge for more info</i>]]></bottom>
<tag name="todo" scope="all" description="To do:" />
<group title="Jacob COM" packages="com.jacob.com/**"/>
<group title="Higher Level Active X" packages="com.jacob.activeX/**"/>
<link offline="true" href="http://java.sun.com/j2se/1.4.2/docs/api/" packagelistLoc="C:\tmp"/>
<link href="http://java.sun.com/j2se/1.4.2/docs/api/"/>
</javadoc>
<defaultexcludes default="true"/>
</target>
<!-- ======================================================================
Use this target to package all the files for a release
================================================================== -->
<target name="PackageRelease" depends="createDirectoryStructure,jacob_c_dll,jacob_java_jar_bin,javadoc">
<echo>Packaging release...</echo>
<zip
destfile="${install.dir}/jacob_${version}.zip">
<exclude name="**/CVS" />
<exclude name="**/*.obj" />
<exclude name="**/*.class" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="LICENSE.* version.properties" />
<zipfileset dir="${install.dir}" prefix="jacob_${version}" includes="jacob.jar jacob.dll"/>
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="docs/**" />
<zipfileset dir="${install.dir}" prefix="jacob_${version}" includes="docs/**"/>
</zip>
<zip
destfile="${install.dir}/jacob_${version}_src.zip">
<exclude name="**/CVS" />
<exclude name="**/*.obj" />
<exclude name="**/*.class" />
<exclude name="**/*.dll" />
<exclude name="**/*.exp" />
<exclude name="**/*.jar" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="src/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="docs/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="jni/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="samples/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="unittest/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="vstudio/**" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="build.xml, RELEASE.txt" />
<zipfileset dir="${basedir}" prefix="jacob_${version}" includes="LICENSE.* version.properties" />
</zip>
</target>
</project>

View File

@@ -1,88 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.activeX;
import com.jacob.com.*;
/**
* This class simulates com.ms.activeX.ActiveXComponent only as it used for
* creating Dispatch objects
*/
public class ActiveXComponent extends Dispatch {
/**
* @param progid
*/
public ActiveXComponent(String progid) {
super(progid);
}
/**
* @return actually returns this bject
*/
public Object getObject() {
return this;
}
/**
* @param name
* @param args
* @return Variant result of the invoke
*/
public Variant invoke(String name, Variant[] args) {
return Dispatch.callN(this, name, args);
}
/**
* @param name property name
* @return Variant value of property
*/
public Variant getProperty(String name) {
return Dispatch.get(this, name);
}
/**
* @param name
* @param arg
*/
public void setProperty(String name, Variant arg) {
Dispatch.put(this, name, arg);
}
/**
* @see com.jacob.com.Dispatch#finalize()
*/
protected void finalize() {
super.finalize();
}
static {
System.loadLibrary("jacob");
}
}

View File

@@ -1,589 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.com;
import java.lang.reflect.Array;
/**
* Object represents MS level dispatch object. You're going to live here
* a lot
*/
public class Dispatch extends JacobObject
{
/**
* This is public because Dispatch.cpp knows its name and accesses
* it directly to get the disptach id. You really can't rename
* it or make it private
*/
public int m_pDispatch;
/** program Id passed in by ActiveX components in their constructor */
private String programId = null;
public static final int LOCALE_SYSTEM_DEFAULT = 2048;
public static final int Method = 1;
public static final int Get = 2;
public static final int Put = 4;
public static final int PutRef = 8;
public static final int fdexNameCaseSensitive = 1;
public static final int DISPID_UNKNOWN = -1;
public static final int DISPID_VALUE = 0;
public static final int DISPID_PROPERTYPUT = -3;
public static final int DISPID_NEWENUM = -4;
public static final int DISPID_EVALUATE = -5;
public static final int DISPID_CONSTRUCTOR = -6;
public static final int DISPID_DESTRUCTOR = -7;
public static final int DISPID_COLLECT = -8;
public static final int DISPID_AUTOSIZE = -500;
public static final int DISPID_BACKCOLOR = -501;
public static final int DISPID_BACKSTYLE = -502;
public static final int DISPID_BORDERCOLOR = -503;
public static final int DISPID_BORDERSTYLE = -504;
public static final int DISPID_BORDERWIDTH = -505;
public static final int DISPID_DRAWMODE = -507;
public static final int DISPID_DRAWSTYLE = -508;
public static final int DISPID_DRAWWIDTH = -509;
public static final int DISPID_FILLCOLOR = -510;
public static final int DISPID_FILLSTYLE = -511;
public static final int DISPID_FONT = -512;
public static final int DISPID_FORECOLOR = -513;
public static final int DISPID_ENABLED = -514;
public static final int DISPID_HWND = -515;
public static final int DISPID_TABSTOP = -516;
public static final int DISPID_TEXT = -517;
public static final int DISPID_CAPTION = -518;
public static final int DISPID_BORDERVISIBLE = -519;
public static final int DISPID_APPEARANCE = -520;
public static final int DISPID_MOUSEPOINTER = -521;
public static final int DISPID_MOUSEICON = -522;
public static final int DISPID_PICTURE = -523;
public static final int DISPID_VALID = -524;
public static final int DISPID_READYSTATE = -525;
public static final int DISPID_REFRESH = -550;
public static final int DISPID_DOCLICK = -551;
public static final int DISPID_ABOUTBOX = -552;
public static final int DISPID_CLICK = -600;
public static final int DISPID_DBLCLICK = -601;
public static final int DISPID_KEYDOWN = -602;
public static final int DISPID_KEYPRESS = -603;
public static final int DISPID_KEYUP = -604;
public static final int DISPID_MOUSEDOWN = -605;
public static final int DISPID_MOUSEMOVE = -606;
public static final int DISPID_MOUSEUP = -607;
public static final int DISPID_ERROREVENT = -608;
public static final int DISPID_READYSTATECHANGE = -609;
public static final int DISPID_AMBIENT_BACKCOLOR = -701;
public static final int DISPID_AMBIENT_DISPLAYNAME = -702;
public static final int DISPID_AMBIENT_FONT = -703;
public static final int DISPID_AMBIENT_FORECOLOR = -704;
public static final int DISPID_AMBIENT_LOCALEID = -705;
public static final int DISPID_AMBIENT_MESSAGEREFLECT = -706;
public static final int DISPID_AMBIENT_SCALEUNITS = -707;
public static final int DISPID_AMBIENT_TEXTALIGN = -708;
public static final int DISPID_AMBIENT_USERMODE = -709;
public static final int DISPID_AMBIENT_UIDEAD = -710;
public static final int DISPID_AMBIENT_SHOWGRABHANDLES = -711;
public static final int DISPID_AMBIENT_SHOWHATCHING = -712;
public static final int DISPID_AMBIENT_DISPLAYASDEFAULT = -713;
public static final int DISPID_AMBIENT_SUPPORTSMNEMONICS = -714;
public static final int DISPID_AMBIENT_AUTOCLIP = -715;
public static final int DISPID_AMBIENT_APPEARANCE = -716;
public static final int DISPID_AMBIENT_CODEPAGE = -725;
public static final int DISPID_AMBIENT_PALETTE = -726;
public static final int DISPID_AMBIENT_CHARSET = -727;
public static final int DISPID_AMBIENT_TRANSFERPRIORITY = -728;
// map args based on msdn doc
protected static Variant obj2variant(Object o) {
if (o == null)
return new Variant();
if (o instanceof Variant)
return (Variant) o;
if (o instanceof Integer)
return new Variant(((Integer) o).intValue());
if (o instanceof String)
return new Variant((String) o);
if (o instanceof Boolean)
return new Variant(((Boolean) o).booleanValue());
if (o instanceof Double)
return new Variant(((Double) o).doubleValue());
if (o instanceof Float)
return new Variant(((Float) o).floatValue());
if (o instanceof SafeArray)
return new Variant((SafeArray) o);
if (o instanceof Dispatch) {
Variant v = new Variant();
v.putObject((Dispatch) o);
return v;
}
// automatically convert arrays using reflection
Class c1 = o.getClass();
SafeArray sa = null;
if (c1.isArray()) {
int len1 = Array.getLength(o);
Object first = Array.get(o, 0);
if (first.getClass().isArray()) {
int max = 0;
for (int i = 0; i < len1; i++) {
Object e1 = Array.get(o, i);
int len2 = Array.getLength(e1);
if (max < len2) {
max = len2;
}
}
sa = new SafeArray(Variant.VariantVariant, len1, max);
for (int i = 0; i < len1; i++) {
Object e1 = Array.get(o, i);
for (int j = 0; j < Array.getLength(e1); j++) {
sa.setVariant(i, j, obj2variant(Array.get(e1, j)));
}
}
} else {
sa = new SafeArray(Variant.VariantVariant, len1);
for (int i = 0; i < len1; i++) {
sa.setVariant(i, obj2variant(Array.get(o, i)));
}
}
return new Variant(sa);
}
throw new ClassCastException("cannot convert to Variant");
}
/**
* same as above, for an array
* @param o
* @return Variant[]
*/
protected static Variant[] obj2variant(Object[] o) {
Variant vArg[] = new Variant[o.length];
for (int i = 0; i < o.length; i++) {
vArg[i] = obj2variant(o[i]);
}
return vArg;
}
/**
* zero argument constructor that sets the dispatch pointer to 0
*/
public Dispatch() {
m_pDispatch = 0;
}
/**
* Constructor that calls createInstance with progid. This is the
* constructor used by the ActiveXComponent
*
* @param requestedProgramId
*/
public Dispatch(String requestedProgramId) {
programId = requestedProgramId;
createInstance(requestedProgramId);
}
/**
* return a different interface by IID string
*
* @param iid
* @return Dispatch a disptach that matches ??
*/
public native Dispatch QueryInterface(String iid);
/**
* Constructor that only gets called from JNI
*
* @param pDisp
*/
protected Dispatch(int pDisp) {
m_pDispatch = pDisp;
}
/**
* native call createIstnace only used by the constructor with the same parm
* type could this be private?
*
* @param progid
*/
protected native void createInstance(String progid);
/**
* returns the program id if an activeX component created this
* otherwise it returns null. This was added to aid in debugging
* @return the program id an activeX component was created against
*/
public String getProgramId(){
return programId;
}
/**
* call this to explicitly release the com object before gc
*/
public native void release();
/**
* not implemented yet
*
* @param disp
* @param name
* @param val
* @throws ClassCastException
* because???
*/
public static void put_Casesensitive(Object disp, String name, Object val) {
throw new ClassCastException("not implemented yet");
}
// eliminate _Guid arg
public static void invokeSubv(Object disp, String name, int dispID,
int lcid, int wFlags, Variant[] vArg, int[] uArgErr) {
invokev(disp, name, dispID, lcid, wFlags, vArg, uArgErr);
}
public static void invokeSubv(Object disp, String name, int wFlags,
Variant[] vArg, int[] uArgErr) {
invokev(disp, name, 0, LOCALE_SYSTEM_DEFAULT, wFlags, vArg, uArgErr);
}
public static void invokeSubv(Object disp, int dispID, int wFlags,
Variant[] vArg, int[] uArgErr) {
invokev(disp, null, dispID, LOCALE_SYSTEM_DEFAULT, wFlags, vArg,
uArgErr);
}
public static Variant callN_CaseSensitive(Object disp, String name,
Object[] values) {
throw new ClassCastException("not implemented yet");
}
public static void callSubN(Object disp, String name, Object[] args) {
invokeSubv(disp, name, Method | Get, obj2variant(args),
new int[args.length]);
}
public static void callSubN(Object disp, int dispID, Object[] args) {
invokeSubv(disp, dispID, Method | Get, obj2variant(args),
new int[args.length]);
}
public static int getIDOfName(Object disp, String name) {
int ids[] = getIDsOfNames(disp, LOCALE_SYSTEM_DEFAULT,
new String[] { name });
return ids[0];
}
// eliminated _Guid argument
public static native int[] getIDsOfNames(Object disp, int lcid,
String[] names);
// eliminated _Guid argument
public static int[] getIDsOfNames(Object disp, String[] names) {
return getIDsOfNames(disp, LOCALE_SYSTEM_DEFAULT, names);
}
public static Variant callN(Object disp, String name, Object[] args) {
return invokev(disp, name, Method | Get, obj2variant(args),
new int[args.length]);
}
public static Variant callN(Object disp, int dispID, Object[] args) {
return invokev(disp, dispID, Method | Get, obj2variant(args),
new int[args.length]);
}
public static Variant invoke(Object disp, String name, int dispID,
int lcid, int wFlags, Object[] oArg, int[] uArgErr) {
return invokev(disp, name, dispID, lcid, wFlags, obj2variant(oArg),
uArgErr);
}
public static Variant invoke(Object disp, String name, int wFlags,
Object[] oArg, int[] uArgErr) {
return invokev(disp, name, wFlags, obj2variant(oArg), uArgErr);
}
public static Variant invoke(Object disp, int dispID, int wFlags,
Object[] oArg, int[] uArgErr) {
return invokev(disp, dispID, wFlags, obj2variant(oArg), uArgErr);
}
public static Variant call(Object disp, String name) {
return callN(disp, name, new Variant[0]);
}
public static Variant call(Object disp, String name, Object a1) {
return callN(disp, name, new Object[] { a1 });
}
public static Variant call(Object disp, String name, Object a1, Object a2) {
return callN(disp, name, new Object[] { a1, a2 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3) {
return callN(disp, name, new Object[] { a1, a2, a3 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3, Object a4) {
return callN(disp, name, new Object[] { a1, a2, a3, a4 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5) {
return callN(disp, name, new Object[] { a1, a2, a3, a4, a5 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6) {
return callN(disp, name, new Object[] { a1, a2, a3, a4, a5, a6 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7) {
return callN(disp, name, new Object[] { a1, a2, a3, a4, a5, a6, a7 });
}
public static Variant call(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
return callN(disp, name,
new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 });
}
public static Variant call(Object disp, int dispid) {
return callN(disp, dispid, new Variant[0]);
}
public static Variant call(Object disp, int dispid, Object a1) {
return callN(disp, dispid, new Object[] { a1 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2) {
return callN(disp, dispid, new Object[] { a1, a2 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3) {
return callN(disp, dispid, new Object[] { a1, a2, a3 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4) {
return callN(disp, dispid, new Object[] { a1, a2, a3, a4 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5) {
return callN(disp, dispid, new Object[] { a1, a2, a3, a4, a5 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6) {
return callN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7) {
return callN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7 });
}
public static Variant call(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
return callN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7,
a8 });
}
public static void put(Object disp, String name, Object val) {
invoke(disp, name, Put, new Object[] { val }, new int[1]);
}
public static void put(Object disp, int dispid, Object val) {
invoke(disp, dispid, Put, new Object[] { val }, new int[1]);
}
// removed _Guid argument
public static native Variant invokev(Object disp, String name, int dispID,
int lcid, int wFlags, Variant[] vArg, int[] uArgErr);
public static Variant invokev(Object disp, String name, int wFlags,
Variant[] vArg, int[] uArgErr) {
if (!(disp instanceof Dispatch))
throw new ClassCastException("Dispatch object expected");
return invokev(disp, name, 0, LOCALE_SYSTEM_DEFAULT, wFlags, vArg,
uArgErr);
}
public static Variant invokev(Object disp, String name, int wFlags,
Variant[] vArg, int[] uArgErr, int wFlagsEx) {
if (!(disp instanceof Dispatch))
throw new ClassCastException("Dispatch object expected");
// do not implement IDispatchEx for now
return invokev(disp, name, 0, LOCALE_SYSTEM_DEFAULT, wFlags, vArg,
uArgErr);
}
public static Variant invokev(Object disp, int dispID, int wFlags,
Variant[] vArg, int[] uArgErr) {
if (!(disp instanceof Dispatch))
throw new ClassCastException("Dispatch object expected");
return invokev(disp, null, dispID, LOCALE_SYSTEM_DEFAULT, wFlags, vArg,
uArgErr);
}
// removed _Guid argument
public static void invokeSub(Object disp, String name, int dispid,
int lcid, int wFlags, Object[] oArg, int[] uArgErr) {
invokeSubv(disp, name, dispid, lcid, wFlags, obj2variant(oArg), uArgErr);
}
public static void invokeSub(Object disp, String name, int wFlags,
Object[] oArg, int[] uArgErr) {
invokeSub(disp, name, 0, LOCALE_SYSTEM_DEFAULT, wFlags, oArg, uArgErr);
}
public static void invokeSub(Object disp, int dispid, int wFlags,
Object[] oArg, int[] uArgErr) {
invokeSub(disp, null, dispid, LOCALE_SYSTEM_DEFAULT, wFlags, oArg,
uArgErr);
}
public static void callSub(Object disp, String name) {
callSubN(disp, name, new Object[0]);
}
public static void callSub(Object disp, String name, Object a1) {
callSubN(disp, name, new Object[] { a1 });
}
public static void callSub(Object disp, String name, Object a1, Object a2) {
callSubN(disp, name, new Object[] { a1, a2 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3) {
callSubN(disp, name, new Object[] { a1, a2, a3 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3, Object a4) {
callSubN(disp, name, new Object[] { a1, a2, a3, a4 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5) {
callSubN(disp, name, new Object[] { a1, a2, a3, a4, a5 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6) {
callSubN(disp, name, new Object[] { a1, a2, a3, a4, a5, a6 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7) {
callSubN(disp, name, new Object[] { a1, a2, a3, a4, a5, a6, a7 });
}
public static void callSub(Object disp, String name, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
callSubN(disp, name, new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 });
}
public static void callSub(Object disp, int dispid) {
callSubN(disp, dispid, new Object[0]);
}
public static void callSub(Object disp, int dispid, Object a1) {
callSubN(disp, dispid, new Object[] { a1 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2) {
callSubN(disp, dispid, new Object[] { a1, a2 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3) {
callSubN(disp, dispid, new Object[] { a1, a2, a3 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4) {
callSubN(disp, dispid, new Object[] { a1, a2, a3, a4 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5) {
callSubN(disp, dispid, new Object[] { a1, a2, a3, a4, a5 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6) {
callSubN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7) {
callSubN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7 });
}
public static void callSub(Object disp, int dispid, Object a1, Object a2,
Object a3, Object a4, Object a5, Object a6, Object a7, Object a8) {
callSubN(disp, dispid, new Object[] { a1, a2, a3, a4, a5, a6, a7, a8 });
}
public static Variant get(Object disp, String name) {
return invokev(disp, name, Get, new Variant[0], new int[0]);
}
public static Variant get(Object disp, int dispid) {
return invokev(disp, dispid, Get, new Variant[0], new int[0]);
}
public static void putRef(Object disp, String name, Object val) {
invoke(disp, name, PutRef, new Object[] { val }, new int[1]);
}
public static void putRef(Object disp, int dispid, Object val) {
invoke(disp, dispid, PutRef, new Object[] { val }, new int[1]);
}
public static Variant get_CaseSensitive(Object disp, String name) {
throw new ClassCastException("not implemented yet");
}
static {
System.loadLibrary("jacob");
}
protected void finalize() {
//System.out.println("Dispatch finalize start");
if (m_pDispatch != 0)
release();
//System.out.println("Dispatch finalize end");
}
}

View File

@@ -1,75 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.com;
/**
* ???
*/
public class DispatchEvents extends JacobObject {
int m_pConnPtProxy = 0;
/**
* @param src
* @param sink
*/
public DispatchEvents(Dispatch src, Object sink) {
init(src, sink);
}
/**
* @param src
* @param sink
* @param progId
*/
public DispatchEvents(Dispatch src, Object sink, String progId) {
init2(src, sink, progId);
}
// hook up a connection point proxy object
// event methods on the sink object will be called
// by name with a signature of <name>(Variant[] args)
protected native void init(Dispatch src, Object sink);
protected native void init2(Dispatch src, Object sink, String progId);
// call this to explicitly release the com object before gc
public native void release();
protected void finalize() {
//System.out.println("DispatchEvents finalize start");
if (m_pConnPtProxy != 0)
release();
//System.out.println("DispatchEvents finalize end");
}
static {
System.loadLibrary("jacob");
}
}

View File

@@ -1,52 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.com;
/**
* All COM object created by JACOB extend this class so that we can
* automatically release them when the thread is detached from COM - if we leave
* it to the finalizer it will call the release from another thread, which may
* result in a segmentation violation.
*/
public class JacobObject {
/**
* Standard constructor
*/
public JacobObject() {
ROT.addObject(this);
}
/**
*
*/
public void release() {
// currently does nothing
}
}

View File

@@ -1,92 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.com;
import java.util.Hashtable;
import java.util.Vector;
/**
* The Running Object Table (ROT) maps each thread to a vector of all the
* JacobObjects that were created in that thread. It always operates on the
* current thread so all the methods are static and they implicitly get the
* current thread. Conceptually, this is similar to the ThreadLocal class of
* Java 1.2 but we are also supporting Java 1.6 The clearObjects method is used
* to release all the COM objects created by Jacob in the current thread prior
* to uninitializing COM for that thread. If we leave this job to the garbage
* collector, then finalize might get called from a separate thread which is not
* initialized for COM, and also the component itself may have been freed.
*/
public abstract class ROT {
private static Hashtable rot = new Hashtable();
protected static void addThread() {
String t_name = Thread.currentThread().getName();
if (rot.contains(t_name))
return;
Vector v = new Vector();
rot.put(t_name, v);
}
protected static void clearObjects() {
String t_name = Thread.currentThread().getName();
Vector v = (Vector) rot.get(t_name);
if (v != null) {
while (!v.isEmpty()) {
JacobObject o = (JacobObject) v.elementAt(0);
//System.out.println(t_name + "
// release:"+o+"->"+o.getClass().getName());
if (o != null)
o.release();
v.removeElementAt(0);
}
rot.remove(t_name);
}
}
protected static void addObject(JacobObject o) {
String t_name = Thread.currentThread().getName();
//System.out.println(t_name + " add:"+o+"->"+o.getClass().getName());
Vector v = (Vector) rot.get(t_name);
if (v == null) {
// this thread has not been initialized as a COM thread
// so make it part of MTA for backwards compatibility
ComThread.InitMTA(false);
addThread();
v = (Vector) rot.get(t_name);
}
if (v != null) {
v.addElement(o);
}
}
static {
System.loadLibrary("jacob");
}
}

View File

@@ -1,372 +0,0 @@
/*
* Copyright (c) 1999-2004 Sourceforge JACOB Project.
* All rights reserved. Originator: Dan Adler (http://danadler.com).
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Redistributions in any form must be accompanied by information on
* how to obtain complete source code for the JACOB software.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.jacob.com;
/**
* The multi-format data type used for all call backs and most
* communications between Java and COM
*/
public class Variant extends JacobObject implements java.io.Serializable
{
int m_pVariant = 0;
public static final short VariantEmpty = 0;
public static final short VariantNull = 1;
public static final short VariantShort = 2;
public static final short VariantInt = 3;
public static final short VariantFloat = 4;
public static final short VariantDouble = 5;
public static final short VariantCurrency = 6;
public static final short VariantDate = 7;
public static final short VariantString = 8;
public static final short VariantDispatch = 9;
public static final short VariantError = 10;
public static final short VariantBoolean = 11;
public static final short VariantVariant = 12;
public static final short VariantObject = 13;
public static final short VariantByte = 17;
public static final short VariantTypeMask = 4095;
public static final short VariantArray = 8192;
public static final short VariantByref = 16384;
public native int toInt();
public native double toDate();
public native boolean toBoolean();
public native EnumVariant toEnumVariant();
public native void getNull();
public native void putNull();
public native Variant cloneIndirect();
public native double toDouble();
public native long toCurrency();
// superceded by SafeArray
public void putVariantArray(Variant[] in)
{
throw new ComFailException("Not implemented");
}
// superceded by SafeArray
public Variant[] getVariantArray()
{
throw new ComFailException("Not implemented");
}
// superceded by SafeArray
public void putByteArray(Object in)
{
throw new ComFailException("Not implemented");
}
public native void putShortRef(short in);
public native void putIntRef(int in);
public native void putDoubleRef(double in);
public native void putDateRef(double in);
public native void putStringRef(String in);
public native short getShortRef();
public native int getIntRef();
public native void putShort(short in);
public native short getShort();
public native double getDoubleRef();
public native double getDateRef();
public native String getStringRef();
// superceded by SafeArray
public Object toCharArray()
{
throw new ComFailException("Not implemented");
}
public native void VariantClear();
public native Dispatch toDispatch();
public native Object clone();
public native String toString();
public native int getInt();
public native double getDate();
public native void putInt(int in);
public native void putDate(double in);
public native byte toByte();
public Object getDispatch() { return toDispatch(); }
public void putDispatch(Object in) { putObject(in); }
public native boolean getBoolean();
public native byte getByte();
public native void putBoolean(boolean in);
public native void putByte(byte in);
public native int toError();
public Object toObject()
{
return toDispatch();
}
public native void getEmpty();
public native void putEmpty();
public native int getError();
public native void putError(int in);
public native double getDouble();
public Object getObject()
{
return toDispatch();
}
public native void putCurrency(long in);
public native void putObject(Object in);
public native void putDouble(double in);
public native long getCurrency();
public native void putFloatRef(float in);
public native void putCurrencyRef(long in);
public native void putErrorRef(int in);
public native void putBooleanRef(boolean in);
public void putObjectRef(Object in)
{
putObject(in);
}
public native void putByteRef(byte in);
public native String getString();
public native void putString(String in);
public native float getFloatRef();
public native long getCurrencyRef();
public native int getErrorRef();
public native boolean getBooleanRef();
public native Object getObjectRef();
public native byte getByteRef();
public native float toFloat();
/**
* By default toSafeArray makes a deep copy due to the fact
* that this Variant owns the embedded SafeArray and will
* destroy it when it gc's
*/
public SafeArray toSafeArray()
{
return toSafeArray(true);
}
public native SafeArray toSafeArray(boolean deepCopy);
public native void putSafeArrayRef(SafeArray in);
public native void putSafeArray(SafeArray in);
public native void noParam();
// superceded by SafeArray
public void putCharArray(Object in)
{
throw new ComFailException("Not implemented");
}
public native float getFloat();
public native void putFloat(float in);
public void putDispatchRef(Object in) { putDispatch(in); }
public Object getDispatchRef() { return getDispatch(); }
// superceded by SafeArray
public void putVariantArrayRef(Variant[] in)
{
throw new ClassCastException("Not implemented");
}
// superceded by SafeArray
public Variant[] getVariantArrayRef()
{
throw new ClassCastException("Not implemented");
}
public native void changeType(short in);
public void changeType(int in)
{
changeType((short)in);
}
public Object toScriptObject() { return toDispatch(); }
public Variant()
{
init();
putEmpty();
}
public Variant(int in)
{
init();
putInt(in);
}
public Variant(double in)
{
init();
putDouble(in);
}
public Variant(boolean in)
{
init();
putBoolean(in);
}
public Variant(String in)
{
init();
putString(in);
}
public Variant(SafeArray in,boolean fByRef)
{
init();
if (fByRef) {
putSafeArrayRef(in);
} else {
putSafeArray(in);
}
}
public Variant(Object in)
{
this(in, false);
}
public Variant(Object o,boolean fByRef)
{
init();
if (o == null) {
putEmpty();
} else if (o instanceof Integer) {
if (fByRef) putIntRef(((Integer)o).intValue());
else putInt(((Integer)o).intValue());
} else if (o instanceof String) {
if (fByRef) putStringRef((String)o);
else putString((String)o);
} else if (o instanceof Boolean) {
if (fByRef) putBooleanRef(((Boolean)o).booleanValue());
else putBoolean(((Boolean)o).booleanValue());
} else if (o instanceof Double) {
if (fByRef) putDoubleRef(((Double)o).doubleValue());
else putDouble(((Double)o).doubleValue());
} else if (o instanceof Float) {
if (fByRef) putFloatRef(((Float)o).floatValue());
else putFloat(((Float)o).floatValue());
} else if (o instanceof SafeArray) {
if (fByRef) putSafeArrayRef((SafeArray)o);
else putSafeArray((SafeArray)o);
} else {
if (fByRef) putObjectRef(o); else putObject(o);
}
}
//weird constructors
public Variant(int in,int in1)
{
throw new ComFailException("Not implemented");
}
public Variant(int in,boolean in1)
{
throw new ComFailException("Not implemented");
}
public Variant(int in,double in1)
{
throw new ComFailException("Not implemented");
}
public Variant(int in,Object in1)
{
throw new ComFailException("Not implemented");
}
public native short getvt();
public native short toShort();
// call this to explicitly release the com object before gc
public native void release();
protected native void init();
protected void finalize()
{
//System.out.println("Variant finalize start:"+m_pVariant);
if (m_pVariant != 0) release();
//System.out.println("Variant finalize end");
}
// superceded by SafeArray
public Variant[] toVariantArray()
{
throw new ClassCastException("Not implemented");
}
// superceded by SafeArray
public Object toByteArray()
{
throw new ClassCastException("Not implemented");
}
static {
System.loadLibrary("jacob");
}
// serialization support
private void writeObject(java.io.ObjectOutputStream oos)
{
try {
Save(oos);
} catch (Exception e) {
e.printStackTrace();
}
}
private void readObject(java.io.ObjectInputStream ois)
{
try {
Load(ois);
} catch (Exception e) {
e.printStackTrace();
}
}
// is the variant null or empty or error or null disp
public native boolean isNull();
public native void Save(java.io.OutputStream os)
throws java.io.IOException;
public native void Load(java.io.InputStream is)
throws java.io.IOException;
}

View File

@@ -7,7 +7,7 @@ xmlns="http://www.w3.org/TR/REC-html40">
<meta name=ProgId content=Word.Document>
<meta name=Generator content="Microsoft Word 11">
<meta name=Originator content="Microsoft Word 11">
<link rel=File-List href="EventsAndCallBacks_files/filelist.xml">
<link rel=File-List href="EventCallbacks_files/filelist.xml">
<title>Jacob can register Java classes for MS application events or callbacks</title>
<!--[if gte mso 9]><xml>
<o:OfficeDocumentSettings>
@@ -75,6 +75,38 @@ div.Section1
mso-level-number-position:left;
margin-left:42.0pt;
text-indent:-24.0pt;}
@list l0:level2
{mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level3
{mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level4
{mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level5
{mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level6
{mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level7
{mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level8
{mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l0:level9
{mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1
{mso-list-id:1316765558;
mso-list-type:hybrid;
@@ -85,6 +117,38 @@ div.Section1
mso-level-number-position:left;
margin-left:42.0pt;
text-indent:-24.0pt;}
@list l1:level2
{mso-level-tab-stop:1.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level3
{mso-level-tab-stop:1.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level4
{mso-level-tab-stop:2.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level5
{mso-level-tab-stop:2.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level6
{mso-level-tab-stop:3.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level7
{mso-level-tab-stop:3.5in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level8
{mso-level-tab-stop:4.0in;
mso-level-number-position:left;
text-indent:-.25in;}
@list l1:level9
{mso-level-tab-stop:4.5in;
mso-level-number-position:left;
text-indent:-.25in;}
ol
{margin-bottom:0in;}
ul
@@ -124,48 +188,48 @@ is:</p>
<p class=MsoPlainText><o:p>&nbsp;</o:p></p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>1)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>Application thread creates an instance of the
event handler and registers it with Jacob</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>2)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The application continues on doing other work.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>3)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>Some time later, the MS application takes some
action and initiates the event callback.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>4)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The Java VM receives the event and spins up a
new thread to handle it.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>5)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The Jacob <span class=SpellE>EventProxy</span>
in the <span class=SpellE>dll</span> is called by the VM.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>6)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The Jacob <span class=SpellE>EventProxy</span>
creates Variant objects to handle the parameters of the passed in event.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>7)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The Jacob <span class=SpellE>EventProxy</span>
@@ -173,7 +237,7 @@ uses reflection to map the event name to a method name with the exact same
name.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l1 level1 lfo1;tab-stops:list 42.0pt'><![if !supportLists]><span
l1 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>8)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The Jacob <span class=SpellE>EventProxy</span>
@@ -214,60 +278,66 @@ class loader of the event handler class.</p>
<p class=MsoPlainText><o:p>&nbsp;</o:p></p>
<p class=MsoPlainText>The Jacob <span class=SpellE>EventProxy</span> class has
been modified (off of the 1.8 tree) so that it takes a two step approach to towards
fixing these problems.</p>
been modified (off of the 1.8 tree) so that it takes a two step approach to
towards fixing these problems.</p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span><span
style='mso-tab-count:1'>      </span></p>
<p class=MsoPlainText><span style='mso-tab-count:2'>            </span></p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l0 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
l0 level1 lfo4;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>1)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>The <span class=SpellE>EventProxy</span>
constructor now accepts an extra object, an instance of the Variant class.<span
style='mso-spacerun:yes'>  </span>This gives the <span class=SpellE>EventProxy</span>
a way to get to the Variant class and thus to its <span class=SpellE>classloader</span>.
All of the callers of the constructor have been modified to pass a Variant
object to the <span class=SpellE>EventProxy</span> without programmer
intervention.</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l0 level1 lfo4;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>2)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]><span class=SpellE>EventProxy</span> first
attempts to locate the Variant class using <span class=SpellE>FindClass</span>()</p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l0 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>2)<span
l0 level1 lfo4;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>3)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>Failing that, it looks to see if the event
callback object implements <span class=SpellE><span class=GramE>getVariantClass</span></span><span
class=GramE>(</span>) that returns the <span class=SpellE>Variant.class</span>
object.<span style='mso-spacerun:yes'>  </span>If so, it uses that class to
create variants for the callback parameters.</p>
</span></span></span><![endif]>Failing that, it looks to see if a variant
object had been passed in. If so, it calls <span class=GramE>class(</span>) and
goes from there.<span style='mso-spacerun:yes'>  </span></p>
<p class=MsoPlainText style='margin-left:42.0pt;text-indent:-24.0pt;mso-list:
l0 level1 lfo2;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>3)<span
l0 level1 lfo4;tab-stops:list 42.0pt'><![if !supportLists]><span
style='mso-fareast-font-family:"Courier New"'><span style='mso-list:Ignore'>4)<span
style='font:7.0pt "Times New Roman"'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span></span></span><![endif]>If all that fails, it logs a message and then
fails in the spectacular fashion of the previous versions.</p>
<p class=MsoPlainText><o:p>&nbsp;</o:p></p>
<p class=MsoPlainText>This means developers can receive call back events in JWS
other Java launching programs by implementing <span class=SpellE><span
class=GramE>getVariantClass</span></span><span class=GramE>(</span>) on all of
their classes that receive Microsoft Events.<span style='mso-spacerun:yes'> 
</span>The <span class=SpellE><span class=GramE>getVariantClass</span></span><span
class=GramE>(</span>) method has the added benefit of providing a spot for the
thread <span class=SpellE>classloader</span> to be set:</p>
<p class=MsoPlainText>Developers can receive call back events in JWS other Java
launching programs without implementing any additional code.<span
style='mso-spacerun:yes'>  </span>They should be aware that their callback
methods may need to set the class <span class=GramE>loader.:</span></p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span>Public Class <span
class=SpellE><span class=GramE>getVariantClass</span></span><span class=GramE>(</span>){</p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span>Public xxx <span
class=SpellE><span class=GramE>someHandler</span></span><span class=GramE>(</span>Variant[]
<span class=SpellE>foo</span>){</p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span><span
style='mso-tab-count:1'>      </span><span class=SpellE><span class=GramE>Thread.currentThread</span></span><span
<p class=MsoPlainText><span style='mso-tab-count:2'>            </span><span
class=SpellE><span class=GramE>Thread.currentThread</span></span><span
class=GramE>(</span>).<span class=SpellE>setContextClassLoader</span>(</p>
<p class=MsoPlainText><span style='mso-tab-count:3'>                  </span><span
class=SpellE><span class=GramE>this.getClass</span></span><span class=GramE>(</span>).<span
class=SpellE>getClassLoader</span>());</p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span><span
style='mso-tab-count:1'>      </span><span class=GramE>return</span> <span
class=SpellE>Variant.class</span></p>
<p class=MsoPlainText><span style='mso-tab-count:2'>            </span>// do
something</p>
<p class=MsoPlainText><span style='mso-tab-count:1'>      </span>}</p>
@@ -276,6 +346,8 @@ class=SpellE>Variant.class</span></p>
<p class=MsoPlainText>There may still be a dual event queue issue in JWS
applications that needs to be looked at.</p>
<p class=MsoPlainText><o:p>&nbsp;</o:p></p>
</div>
</body>

69
docs/HowToBuild.txt Normal file
View File

@@ -0,0 +1,69 @@
(2/2005)
To build and run:
Unpack the source archive or check the files out of CVS into d:\jacob
Install the following tools
Microsfot Visual Studio, a stripped down version is available from the MS web site.
Eclipse from www.eclipse.org.
Java jdk 1.4 (this was built using 1.4.2.06)
The following configuration was used by most of the development team:
JDK = d:\j2sdk1.4.2_06
DEST_DIR = d:\jacob
MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98
This project has been converted completely over to ANT. You can
run ANT from inside of eclipse or from the command line.
The ant process is driven off of a configuration file
compilation_tools.properties. Instructions on the information required
in that file are contained in build.xml in the root directory.
Ant, via build.xml will do the following with teh default target.
Build the Java code
Build the jni code
create the dll
create jar file
The package target creates the
javadoc and
zip files
ECLIPSE
Eclipse users will have to do some minor tweaks to their project if they
want to use the integrated build process. This is because the unit
tests are com.jacob.com files located in the unittest directory while
the jacob files themselves are in com.jacob.com off the root directory.
(Eventually the the jacob files will be moved to src)
Eclipse automatically adds the whole project as a source directory
Remove the root of the project from the build path
Add folders samples, src and unittest to the build path
Exclude *.txt from each of the newly added folders.
A couple of the samples require a J2EE library in order to compile. This
means you'll have to add a J2EE jar file to your classpath. This
isn't a problem when using ANT because the Servlet examples are excluded
from the build.
--- old instructions for makefiles that no longer exist --
To build:
Run VCVARS32 to set up your MS Visual C++ environment
cd d:\jacob
nmake
(from dan)I developed this with the C++ compiler and ATL version
that ship with VC++ 6.0, so I'm not sure if different versions will
work.
This is currently designed to compile against JDK 1.4.2. The future
of the Microsoft SDK is in doubt so support may be discontinued
in the future.
The java code is in com\jacob\*.
The C++ code is in .\jni.

View File

@@ -1,51 +1,51 @@
<H1>COM Object Lifetime in JACOB</H1>
<p>
<H2>introduction</H2>
<p>
JACOB Version 1.7 implements a new
<a href="JacobThreading.html">Threading Model</a> that is more
compatible with COM apartments. There is also an incompatibility
between the Java object lifetime model and that of COM objects.
COM Objects live and die by their reference count, whereas Java
objects are collected by the Garbage Collector (GC) based on algortihms
that are hidden from the user.
<H2>COM Object Lifetime in JACOB Prior to Version 1.7</H2>
<p>
In version 1.6 and earlier, JACOB objects which wrapped COM objects
had <code>finalize()</code> methods that would call a native
<code>release</code> method which would call a COM <code>Release</code>.
<p>
This has many problems. For one thing, the GC may take a long time to
kick in and resource consumption may grow. However, the more problematic
issue is that finalizers are called from a separate thread, and, as was
discussed in the <a href="JacobThreading.html">Threading Model</a>
document, this can result in COM errors if the object is running in an
STA. Even if the object is running in an MTA, the finalizer may decide
to run after we have terminated the thread that holds the component, in
which case we would get fatal errors and crashes.
<H2>COM Object Lifetime in JACOB in Version 1.7</H2>
<p>
In Version 1.7, all JACOB objects which wrap COM objects extend
<code>com.jacob.com.JacobObject</code>. This object has some special
code to register itself with a <code>com.jacob.com.ROT</code> object
which represents a Running Object Table (ROT). This table maps a
Thread to the set of JacobObjects created in that thread. Therefore,
when you call <code>ComThread.Release()</code>, the ROT checks whether
that thread has created any objects, and these objects are released
by calling their native <code>release</code> method (which is public).
<p>
This lifetime management method ties the lifecycle to the thread's
lifecycle rather than the GC. The JacobObject's still have finalizers,
but they will typically not perform the native <code>release</code>
since that has already been called. The native <code>release</code>
methods were written such that you can call them multiple times without
worrying - since they zero out the native pointer when called the first
time.
<p>
If you choose to call <code>release</code> methods on your objects
yourself, that is allowed. In that case, when the thread is released
the release calls will be no-ops.
<p>
It becomes important for you to call <code>ComThread.Release()</code>
on any thread before you allow it to exit, otherwise you may get
some random crashes later on in your code.
<H1>COM Object Lifetime in JACOB</H1>
<p>
<H2>introduction</H2>
<p>
JACOB Version 1.7 implements a new
<a href="JacobThreading.html">Threading Model</a> that is more
compatible with COM apartments. There is also an incompatibility
between the Java object lifetime model and that of COM objects.
COM Objects live and die by their reference count, whereas Java
objects are collected by the Garbage Collector (GC) based on algortihms
that are hidden from the user.
<H2>COM Object Lifetime in JACOB Prior to Version 1.7</H2>
<p>
In version 1.6 and earlier, JACOB objects which wrapped COM objects
had <code>finalize()</code> methods that would call a native
<code>release</code> method which would call a COM <code>Release</code>.
<p>
This has many problems. For one thing, the GC may take a long time to
kick in and resource consumption may grow. However, the more problematic
issue is that finalizers are called from a separate thread, and, as was
discussed in the <a href="JacobThreading.html">Threading Model</a>
document, this can result in COM errors if the object is running in an
STA. Even if the object is running in an MTA, the finalizer may decide
to run after we have terminated the thread that holds the component, in
which case we would get fatal errors and crashes.
<H2>COM Object Lifetime in JACOB in Version 1.7</H2>
<p>
In Version 1.7, all JACOB objects which wrap COM objects extend
<code>com.jacob.com.JacobObject</code>. This object has some special
code to register itself with a <code>com.jacob.com.ROT</code> object
which represents a Running Object Table (ROT). This table maps a
Thread to the set of JacobObjects created in that thread. Therefore,
when you call <code>ComThread.Release()</code>, the ROT checks whether
that thread has created any objects, and these objects are released
by calling their native <code>release</code> method (which is public).
<p>
This lifetime management method ties the lifecycle to the thread's
lifecycle rather than the GC. The JacobObject's still have finalizers,
but they will typically not perform the native <code>release</code>
since that has already been called. The native <code>release</code>
methods were written such that you can call them multiple times without
worrying - since they zero out the native pointer when called the first
time.
<p>
If you choose to call <code>release</code> methods on your objects
yourself, that is allowed. In that case, when the thread is released
the release calls will be no-ops.
<p>
It becomes important for you to call <code>ComThread.Release()</code>
on any thread before you allow it to exit, otherwise you may get
some random crashes later on in your code.

View File

@@ -1,410 +1,410 @@
<H1>COM Apartments in JACOB</H1>
<p>
<H2>introduction</H2>
<p>
The COM model for Threading differs from the Java model.
In COM, each component can declare whether or not it support
multi-threading.
You can find some basic information about COM threading at:
<p>
<a href="http://www.execpc.com/~gopalan/com/com_threading.html">
http://www.execpc.com/~gopalan/com/com_threading.html</a>
<p>
<a href="www.microsoft.com/msj/0297/apartment/apartment.htm">
www.microsoft.com/msj/0297/apartment/apartment.htm</a>
<p>
<a href="http://www.cswl.com/whiteppr/white/multithreading.html">
http://www.cswl.com/whiteppr/white/multithreading.html
</a>
<p>
The term <b>Single Threaded Apartment (STA)</b> refers to a thread
where all COM objects created in that thread are
single-threaded. This can manifest itself in two ways:
<br>
Either all calls into that component are made from the same thread
that created the component
<br>
OR any call that is made from another thread gets serialized by COM.
This serialization of calls is done by using a Windows message loop and
posting messages to a hidden window (I'm not kidding). The way COM
achieves this is by requiring any other thread to make calls through
a local Proxy object rather than the original object (more on this
when we discuss the JACOB DispatchProxy class).
<p>
What does this mean for a Java application? If you are using a component
that declares itself as <b>ThreadingModel "Apartment"</b> (you can
find this out by looking in the registry under its CLSID), and you plan
to create, use and destroy this component in one thread - then you are
following the rules of an STA and you can declare the thread as an
STA thread.
<p>
On the other hand, if you need to make method calls from another thread
(e.g. in a servlet) then you have a few choices. Either you
create the component in its own STA, by extending
<code>com.jacob.com.STA</code>, and use the
<code>com.jacob.com.DispatchProxy</code> class to pass the Dispatch
pointer between threads, or you can declare your thread as an MTA
thread. In that case, COM will make
the cross-thread calls into the STA that is running your component.
If you create an Apartment threaded component in the MTA,
COM will automatically create an STA for you and put your
component in there, and then marshall all the calls.
<p>
This brings us to the notion of a <b>Main STA</b>. COM requires that
if there is any Apartment threaded component in your application, then
the first STA created is tagged as the <b>Main STA</b>. COM uses the
Main STA to create all the Apartment threaded components that are
created from an MTA thread. The problem is that if you have already
created an STA, then COM will pick that as the Main STA, and if you
ever exit that thread - the whole application will exit.
<H2>COM Threads in JACOB Prior to Version 1.7</H2>
<p>
Up until version 1.7 of JACOB, there was only one model available
in JACOB:
<ul>
<li>
Before version 1.6: All threads were automatically initialized as STAs.
</li>
<li>
In version 1.6: All threads were automatically initialized as MTAs.
</li>
</ul>
<p>
The reason for the change in default was that tagging a Java thread
as an STA can cause problems. Any Java Swing application, as well as
servlets and applets need to be able to make calls from multiple
threads. If you try to make COM method calls across STA threads - it
will fail!
<p>
In most cases, the default chosen by JACOB 1.6 (MTA) works fine, however
there are some notable exceptions that have caused people grief. One
such exception is in the case of MAPI. It turns out that if you try to
create a MAPI object from an MTA thread - it simply fails and exits.
This has caused some people to recompile JACOB 1.6 back with the STA
default.
<p>
There is another problem with MTA threads: when you are using Apartment
threaded components, we already noted that COM will create the
components in the Main STA. If one doesn't exist, COM will create it.
However, this means that <b>all</b> Apartment threaded components will
be created in the <b>same STA</b>. This creates a bottleneck, and a
dependency between unrelated components. Also, if that STA exits, then
all components are destroyed and the application will likely crash.
<H2>COM Threads in JACOB Version 1.7</H2>
<p>
In Version 1.7 we have added finer grained control to allow the
Java programmer to control how COM creates its components.
Unfortunately, this means that you need to have a pretty good
understanding of the dark and mystical subject of COM Apartments.
There are a few different cases you need to consider:
<H3>Default</H3>
<p>
If you simply run code that was created in Version 1.6 and ignore
the COM threading issue, then you will get the same behavior as in 1.6:
Each java thread will be an MTA thread, and all Apartment threaded
components will be created by COM in its own Main STA. This typically
works for most applications (exceptions noted above).
<H3>Create Your Own Apartment</H3>
<p>
To declare an MTA thread use the following template:
<br>
<pre>
<code>
ComThread.InitMTA();
...
...
ComThread.Release();
</pre>
</code>
<br>
If you want JACOB to create its own Main STA (rather than having COM
choose an STA for you), then you should use:
<br>
<code>
<pre>
Thread 1:
ComThread.InitMTA(true); // a true tells JACOB to create a Main STA
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In this case, you can also create the Main STA explicitly:
<br>
<code>
<pre>
ComThread.startMainSTA();
...
...
Thread 1:
ComThread.InitMTA();
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In the latter case, all Apartment threaded components will be created in
JACOB's main STA. This still has all the problems of components
sharing the same Main STA and creating a bottleneck. To avoid that,
you can also create STA threads yourself:
<br>
<code>
<pre>
ComThread.startMainSTA();
...
...
Thread 1:
ComThread.InitSTA();
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In this example, thread 1 is an STA and thread 2 is an MTA. You could
omit the call to ComThread.startMainSTA(), but if you do, then COM will
make the first STA your main one, and then if you exit that thread,
the application will crash.
<p>
Actually, Thread 1 is <i>almost</i> an STA. It's lacking a windows
message loop. So, this type of STA is fine as long as you are creating
a component and using it in the same thread, and not makind event
callbacks.
<H3>JACOB's STA Class</H3>
<p>
If you want to create an true STA where you can create a component and
then let other threads call methods on it, then you need a windows
message loop. JACOB provides a class called:
<code>com.jacob.com.STA</code> which does exactly this.
<code>
<pre>
public class com.jacob.com.STA extends java.lang.Thread
{
public com.jacob.com.STA();
public boolean OnInit(); // you override this
public void OnQuit(); // you override this
public void quit(); // you can call this from ANY thread
}
</pre>
</code>
<p>
The STA class extends
<code>java.lang.Thread</code> and it provides you with two methods
that you can override: <code>OnInit</code> and <code>OnQuit</code>.
These methods are called from the thread's <code>run</code> method
so they will execute in the new thread. These methods allow you to
create COM components (Dispatch objects) and release them.
To create an STA, you subclass it and override the OnInit.
<p>
The <code>quit</code> method is the <b>only</b> other method that
can be called from any thread. This method uses the Win32 function
<code>PostThreadMessage</code> to force the STA's windows message loop
to exit, thereby terminating the thread.
<p>
You will then need to make calls into the component that is running
in the STA thread. If you simply try to make calls from another thread
on a Dispatch object created in the STA thread, you will get a COM
Exception. For more details see:
<a href="http://www.develop.com/effectivecom">
Don Box 'Effective COM' Rule 29</a>: Don't Access raw
interface pointers across apartment boundaries.
<H3>The DispatchProxy Class</H3>
Since you cannot call methods directly on a Dispatch object created
in another STA JACOB provides a method for the class that created
the Dispatch object to marshal it to your thread. This is done via
the <code>com.jacob.com.DispatchProxy</code> class.
<code>
<pre>
public class DispatchProxy extends JacobObject {
public DispatchProxy(Dispatch);
public Dispatch toDispatch();
public native void release();
public void finalize();
}
</code>
</pre>
<p>
This class works as follows: the thread that created the Dispatch
object constructs an instance of DispatchProxy(Dispatch) with the
Dispatch as a parameter. This instance can then be accessed from
another thread, which will invoke its <code>toDispatch</code> method
proxy as if it were local to your thread. COM will do the inter-thread
marshalling transparently.
<p>
The following example is part of samples/test/ScriptTest2.java in the
JACOB distribution. It shows how you can create the ScriptControl
in one STA thread and make method calls on it from another:
<code>
<pre>
import com.jacob.com.*;
import com.jacob.activeX.*;
class ScriptTest2 extends STA
{
public static ActiveXComponent sC;
public static Dispatch sControl = null;
public static DispatchProxy sCon = null;
public boolean OnInit()
{
try
{
System.out.println("OnInit");
System.out.println(Thread.currentThread());
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
// sCon can be called from another thread
sCon = new DispatchProxy(sControl);
Dispatch.put(sControl, "Language", lang);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public void OnQuit()
{
System.out.println("OnQuit");
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitSTA();
ScriptTest2 script = new ScriptTest2();
Thread.sleep(1000);
// get a thread-local Dispatch from sCon
Dispatch sc = sCon.toDispatch();
// call a method on the thread-local Dispatch obtained
// from the DispatchProxy. If you try to make the same
// method call on the sControl object - you will get a
// ComException.
Variant result = Dispatch.call(sc, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
script.quit();
System.out.println("called quit");
} catch (ComException e) {
e.printStackTrace();
}
finally
{
ComThread.Release();
}
}
}
</pre>
</code>
<p>
You can try to modify the <code>Dispatch.call</code> invocation in
the main thread to use <code>sControl</code> directly, and you will see
that it fails. Notice that once we construct the ScriptTest2 object
in the main thread, we sleep for a second to allow the other thread
time to initialize itself.
<p>
The STA thread calls <code>sCon = new DispatchProxy(sControl);</code>
to save a global reference to the DispatchProxy that represents the
<code>sControl</code> object. The main thread then calls:
<code>Dispatch sc = sCon.toDispatch();</code> to get a local Dispatch
proxy out of the DispatchProxy object.
<p>
At most <b>one(!)</b>
thread can call toDispatch(), and the call can be made only once.
This is because a IStream object is used to pass the proxy, and
it is only written once and closed when you read it.
If you need multiple threads to access a Dispatch pointer, then
create that many DispatchProxy objects. For more details please
refer to the Don Box reference above.
<H3>Recommended Procedure</H3>
<ul>
<li>
It is recommended that you always allow JACOB to manage the main STA
rather than letting COM create one on its own or tag one of yours.
</li>
<li>
Declare an STA thread using ComThread.InitSTA()
if all your
method calls for that component are going to come from the same thread.
</li>
<li>
If you want an STA thread that allows other threads to call into it,
use the <code>com.jacob.com.STA</code> class as outlined above.
</li>
<li>
If you have a COM component that declares its ThreadingModel as
"Free" or "Both", then use the MTA.
</li>
<li>
In most cases, if you need to make method calls from multiple threads,
you can simply
use MTA threads, and allow COM to create the components in
the Main STA. You should only create your own STA's and DispatchProxy
if you understand COM well enough to know when the MTA solution
will fail or have other shortcomings.
<p>
There are 3 examples in the samples/test directory that demonstrate
these cases:
<p>
ScriptTest.java - creates an STA for the ScriptControl component and
runs all its method calls from that STA.
<p>
ScriptTest2.java - creates a separate STA thread, and makes
method calls into the component from another thread using DispatchProxy.
<p>
ScriptTest3.java - creates a separate MTA thread, and makes method
calls into the component from another MTA thread. This is simpler
than ScriptTest2 for most applications.
<p>
<h3>Default Threading Model</h3>
If you create a new thread, and don't call
<code>ComThread.InitSTA()</code> or <code>ComThread.InitMTA()</code>
on it, then the first time your java code creates a JacobObject, it
will try to register itself with the ROT, and when it sees that the
current thread is not initialized, it will initialize it as MTA.
This means that the code to do this is no longer inside the native
jni code - it is now in the <code>com.jacob.com.ROT</code> class.
For more details on the ROT, see the
<a href="JacobComLifetime.html">Object Lifetime</a> document.
<H1>COM Apartments in JACOB</H1>
<p>
<H2>introduction</H2>
<p>
The COM model for Threading differs from the Java model.
In COM, each component can declare whether or not it support
multi-threading.
You can find some basic information about COM threading at:
<p>
<a href="http://www.execpc.com/~gopalan/com/com_threading.html">
http://www.execpc.com/~gopalan/com/com_threading.html</a>
<p>
<a href="www.microsoft.com/msj/0297/apartment/apartment.htm">
www.microsoft.com/msj/0297/apartment/apartment.htm</a>
<p>
<a href="http://www.cswl.com/whiteppr/white/multithreading.html">
http://www.cswl.com/whiteppr/white/multithreading.html
</a>
<p>
The term <b>Single Threaded Apartment (STA)</b> refers to a thread
where all COM objects created in that thread are
single-threaded. This can manifest itself in two ways:
<br>
Either all calls into that component are made from the same thread
that created the component
<br>
OR any call that is made from another thread gets serialized by COM.
This serialization of calls is done by using a Windows message loop and
posting messages to a hidden window (I'm not kidding). The way COM
achieves this is by requiring any other thread to make calls through
a local Proxy object rather than the original object (more on this
when we discuss the JACOB DispatchProxy class).
<p>
What does this mean for a Java application? If you are using a component
that declares itself as <b>ThreadingModel "Apartment"</b> (you can
find this out by looking in the registry under its CLSID), and you plan
to create, use and destroy this component in one thread - then you are
following the rules of an STA and you can declare the thread as an
STA thread.
<p>
On the other hand, if you need to make method calls from another thread
(e.g. in a servlet) then you have a few choices. Either you
create the component in its own STA, by extending
<code>com.jacob.com.STA</code>, and use the
<code>com.jacob.com.DispatchProxy</code> class to pass the Dispatch
pointer between threads, or you can declare your thread as an MTA
thread. In that case, COM will make
the cross-thread calls into the STA that is running your component.
If you create an Apartment threaded component in the MTA,
COM will automatically create an STA for you and put your
component in there, and then marshall all the calls.
<p>
This brings us to the notion of a <b>Main STA</b>. COM requires that
if there is any Apartment threaded component in your application, then
the first STA created is tagged as the <b>Main STA</b>. COM uses the
Main STA to create all the Apartment threaded components that are
created from an MTA thread. The problem is that if you have already
created an STA, then COM will pick that as the Main STA, and if you
ever exit that thread - the whole application will exit.
<H2>COM Threads in JACOB Prior to Version 1.7</H2>
<p>
Up until version 1.7 of JACOB, there was only one model available
in JACOB:
<ul>
<li>
Before version 1.6: All threads were automatically initialized as STAs.
</li>
<li>
In version 1.6: All threads were automatically initialized as MTAs.
</li>
</ul>
<p>
The reason for the change in default was that tagging a Java thread
as an STA can cause problems. Any Java Swing application, as well as
servlets and applets need to be able to make calls from multiple
threads. If you try to make COM method calls across STA threads - it
will fail!
<p>
In most cases, the default chosen by JACOB 1.6 (MTA) works fine, however
there are some notable exceptions that have caused people grief. One
such exception is in the case of MAPI. It turns out that if you try to
create a MAPI object from an MTA thread - it simply fails and exits.
This has caused some people to recompile JACOB 1.6 back with the STA
default.
<p>
There is another problem with MTA threads: when you are using Apartment
threaded components, we already noted that COM will create the
components in the Main STA. If one doesn't exist, COM will create it.
However, this means that <b>all</b> Apartment threaded components will
be created in the <b>same STA</b>. This creates a bottleneck, and a
dependency between unrelated components. Also, if that STA exits, then
all components are destroyed and the application will likely crash.
<H2>COM Threads in JACOB Version 1.7</H2>
<p>
In Version 1.7 we have added finer grained control to allow the
Java programmer to control how COM creates its components.
Unfortunately, this means that you need to have a pretty good
understanding of the dark and mystical subject of COM Apartments.
There are a few different cases you need to consider:
<H3>Default</H3>
<p>
If you simply run code that was created in Version 1.6 and ignore
the COM threading issue, then you will get the same behavior as in 1.6:
Each java thread will be an MTA thread, and all Apartment threaded
components will be created by COM in its own Main STA. This typically
works for most applications (exceptions noted above).
<H3>Create Your Own Apartment</H3>
<p>
To declare an MTA thread use the following template:
<br>
<pre>
<code>
ComThread.InitMTA();
...
...
ComThread.Release();
</pre>
</code>
<br>
If you want JACOB to create its own Main STA (rather than having COM
choose an STA for you), then you should use:
<br>
<code>
<pre>
Thread 1:
ComThread.InitMTA(true); // a true tells JACOB to create a Main STA
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In this case, you can also create the Main STA explicitly:
<br>
<code>
<pre>
ComThread.startMainSTA();
...
...
Thread 1:
ComThread.InitMTA();
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In the latter case, all Apartment threaded components will be created in
JACOB's main STA. This still has all the problems of components
sharing the same Main STA and creating a bottleneck. To avoid that,
you can also create STA threads yourself:
<br>
<code>
<pre>
ComThread.startMainSTA();
...
...
Thread 1:
ComThread.InitSTA();
...
...
ComThread.Release();
...
Thread 2:
ComThread.InitMTA();
...
...
ComThread.Release();
...
...
ComThread.quitMainSTA();
</pre>
</code>
<br>
In this example, thread 1 is an STA and thread 2 is an MTA. You could
omit the call to ComThread.startMainSTA(), but if you do, then COM will
make the first STA your main one, and then if you exit that thread,
the application will crash.
<p>
Actually, Thread 1 is <i>almost</i> an STA. It's lacking a windows
message loop. So, this type of STA is fine as long as you are creating
a component and using it in the same thread, and not makind event
callbacks.
<H3>JACOB's STA Class</H3>
<p>
If you want to create an true STA where you can create a component and
then let other threads call methods on it, then you need a windows
message loop. JACOB provides a class called:
<code>com.jacob.com.STA</code> which does exactly this.
<code>
<pre>
public class com.jacob.com.STA extends java.lang.Thread
{
public com.jacob.com.STA();
public boolean OnInit(); // you override this
public void OnQuit(); // you override this
public void quit(); // you can call this from ANY thread
}
</pre>
</code>
<p>
The STA class extends
<code>java.lang.Thread</code> and it provides you with two methods
that you can override: <code>OnInit</code> and <code>OnQuit</code>.
These methods are called from the thread's <code>run</code> method
so they will execute in the new thread. These methods allow you to
create COM components (Dispatch objects) and release them.
To create an STA, you subclass it and override the OnInit.
<p>
The <code>quit</code> method is the <b>only</b> other method that
can be called from any thread. This method uses the Win32 function
<code>PostThreadMessage</code> to force the STA's windows message loop
to exit, thereby terminating the thread.
<p>
You will then need to make calls into the component that is running
in the STA thread. If you simply try to make calls from another thread
on a Dispatch object created in the STA thread, you will get a COM
Exception. For more details see:
<a href="http://www.develop.com/effectivecom">
Don Box 'Effective COM' Rule 29</a>: Don't Access raw
interface pointers across apartment boundaries.
<H3>The DispatchProxy Class</H3>
Since you cannot call methods directly on a Dispatch object created
in another STA JACOB provides a method for the class that created
the Dispatch object to marshal it to your thread. This is done via
the <code>com.jacob.com.DispatchProxy</code> class.
<code>
<pre>
public class DispatchProxy extends JacobObject {
public DispatchProxy(Dispatch);
public Dispatch toDispatch();
public native void release();
public void finalize();
}
</code>
</pre>
<p>
This class works as follows: the thread that created the Dispatch
object constructs an instance of DispatchProxy(Dispatch) with the
Dispatch as a parameter. This instance can then be accessed from
another thread, which will invoke its <code>toDispatch</code> method
proxy as if it were local to your thread. COM will do the inter-thread
marshalling transparently.
<p>
The following example is part of samples/test/ScriptTest2.java in the
JACOB distribution. It shows how you can create the ScriptControl
in one STA thread and make method calls on it from another:
<code>
<pre>
import com.jacob.com.*;
import com.jacob.activeX.*;
class ScriptTest2 extends STA
{
public static ActiveXComponent sC;
public static Dispatch sControl = null;
public static DispatchProxy sCon = null;
public boolean OnInit()
{
try
{
System.out.println("OnInit");
System.out.println(Thread.currentThread());
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
// sCon can be called from another thread
sCon = new DispatchProxy(sControl);
Dispatch.put(sControl, "Language", lang);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public void OnQuit()
{
System.out.println("OnQuit");
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitSTA();
ScriptTest2 script = new ScriptTest2();
Thread.sleep(1000);
// get a thread-local Dispatch from sCon
Dispatch sc = sCon.toDispatch();
// call a method on the thread-local Dispatch obtained
// from the DispatchProxy. If you try to make the same
// method call on the sControl object - you will get a
// ComException.
Variant result = Dispatch.call(sc, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
script.quit();
System.out.println("called quit");
} catch (ComException e) {
e.printStackTrace();
}
finally
{
ComThread.Release();
}
}
}
</pre>
</code>
<p>
You can try to modify the <code>Dispatch.call</code> invocation in
the main thread to use <code>sControl</code> directly, and you will see
that it fails. Notice that once we construct the ScriptTest2 object
in the main thread, we sleep for a second to allow the other thread
time to initialize itself.
<p>
The STA thread calls <code>sCon = new DispatchProxy(sControl);</code>
to save a global reference to the DispatchProxy that represents the
<code>sControl</code> object. The main thread then calls:
<code>Dispatch sc = sCon.toDispatch();</code> to get a local Dispatch
proxy out of the DispatchProxy object.
<p>
At most <b>one(!)</b>
thread can call toDispatch(), and the call can be made only once.
This is because a IStream object is used to pass the proxy, and
it is only written once and closed when you read it.
If you need multiple threads to access a Dispatch pointer, then
create that many DispatchProxy objects. For more details please
refer to the Don Box reference above.
<H3>Recommended Procedure</H3>
<ul>
<li>
It is recommended that you always allow JACOB to manage the main STA
rather than letting COM create one on its own or tag one of yours.
</li>
<li>
Declare an STA thread using ComThread.InitSTA()
if all your
method calls for that component are going to come from the same thread.
</li>
<li>
If you want an STA thread that allows other threads to call into it,
use the <code>com.jacob.com.STA</code> class as outlined above.
</li>
<li>
If you have a COM component that declares its ThreadingModel as
"Free" or "Both", then use the MTA.
</li>
<li>
In most cases, if you need to make method calls from multiple threads,
you can simply
use MTA threads, and allow COM to create the components in
the Main STA. You should only create your own STA's and DispatchProxy
if you understand COM well enough to know when the MTA solution
will fail or have other shortcomings.
<p>
There are 3 examples in the samples/test directory that demonstrate
these cases:
<p>
ScriptTest.java - creates an STA for the ScriptControl component and
runs all its method calls from that STA.
<p>
ScriptTest2.java - creates a separate STA thread, and makes
method calls into the component from another thread using DispatchProxy.
<p>
ScriptTest3.java - creates a separate MTA thread, and makes method
calls into the component from another MTA thread. This is simpler
than ScriptTest2 for most applications.
<p>
<h3>Default Threading Model</h3>
If you create a new thread, and don't call
<code>ComThread.InitSTA()</code> or <code>ComThread.InitMTA()</code>
on it, then the first time your java code creates a JacobObject, it
will try to register itself with the ROT, and when it sees that the
current thread is not initialized, it will initialize it as MTA.
This means that the code to do this is no longer inside the native
jni code - it is now in the <code>com.jacob.com.ROT</code> class.
For more details on the ROT, see the
<a href="JacobComLifetime.html">Object Lifetime</a> document.

344
docs/WhatsNew.html Normal file
View File

@@ -0,0 +1,344 @@
<h1>What's New in JACOB 1.9</H1>
<ul>
<li>
<b>Event Callbacks</b>
<ul>
<li>Variant parameters can now be modified by the receiver to be passed
back to the COM caller </li>
<li>Callbacks can now be received when running in JWS other launchers where
JACOB.jar is not in the system classloader's path.</li>
</ul>
</li>
<li>
<b>Dispatch API Clarifications</B>
<ul>
<li>All static method's first parameters have been more strongly typed
to the Dispatch class, rather than Object. This may call for code
changes in the cases of code that just asigned Dispatch objects
to variables of type Object rather than Dispatch or one of its subclasses </li>
</ul>
</li>
<li>
<b>Dispatch subclasses are now supported with pointer modifying constructor</b>
<ul>
<li>Dispatch and ActiveXComponent now includes a constructor to be used by Dispatch subclasses
that swaps the pointers around. This eliminates the need for every Dispatch subclass
to have a constructor that swapped and nulled out the pointers to the COM layer.
All samples have updated to use the new api </li>
</ul>
</li>
<li>
<b>ActiveXComponent has been upgraded</b><ul>
<li>ActiveXComponent methods return ActiveXComponets </li>
<li>Methods have been added to the ActiveXComponents to retrieve
parameters as Dispatch objects or ActiveX components. The
Script Tests have been updated to show the same programs in Dispatch
format or ActiveXComponentFormat </li>
</ul>
</li>
<li>
<b>Memory Management</b>
<ul>
<li>Beta test option that lets an application use automatic object object
removal through the use of weak reference hash maps in the ROT class.&nbsp; The
default behavior of manual release via the COMThread class has been retained as
the default behavior.&nbsp; Developers can test automatic memory collection by
using the command line option <i>-Dcom.JACOB.autogc=true</i> </li>
</ul>
</li>
<li>
<b>JNI Changes</b>
<ul>
<li>Erroneous Array dimension checking fixed for certain boolean set and get functions
</li>
<li>Alternative method for finding Variant class for callbacks in JWS
or other application lanchers where the system classloader does not
know about JACOB classes. </li>
<li>Unicode is supported for putString and putStringRef</li>
<li>EventProxy zeros out the com object reference in the Variant objects
that are created by EventProxy so that they are not double released,
by both the Java VM and calling code from the COM side. The caller
is supposed to be responsible for releasing the memory it created.
This fix only applies to Variants created in callbacks. </li>
</ul>
</li>
<li>
<b>Logging Additions</b><ul>
<li>Debugging logging to standard out for JACOB can be turned on by using the
command line option <i>-Dcom.JACOB.debug=true</i></li>
</ul>
</li>
<li>
<b>Visual Studio</b><ul>
<li>The VisualStudio directory in the CVS repository will be removed in the next
release</li>
</ul>
</li>
<li>
<b>Documentation</b><ul>
<li>API documentation via Javadoc&nbsp; is now being generated for all classes.</li>
<li>The development team is looking for help in upgrading the quality of the
class documentation</li>
</ul>
</li>
<li>
<b>Build Changes</b>
<ul>
<li>A static method has been added to JacobObject that returns the build version</li>
<li>The project is now being built using ANT.&nbsp; Most of the developers are
running this from inside of Eclipse</li>
<li>All makefiles have been purged</li>
</ul>
<h2>Tracked Changes</h2>
<table border="0" cellpadding="0" cellspacing="0" style="border-collapse: collapse" bordercolor="#111111" width="100%">
<tr>
<td width="100%" colspan="2"><b>Bugs</b></td>
</tr>
<tr>
<td width="13%">1116101</td>
<td width="87%">jacob-msg 0284 : Access Violation while garbage collecting</td>
</tr>
<tr>
<td width="13%">1114159</td>
<td width="87%">Problem with COM Error Trapping in JACOB DLL</td>
</tr>
<tr>
<td width="13%">1113610</td>
<td width="87%">Bad error check in SafeArray.cpp</td>
</tr>
<tr>
<td width="13%">1066698</td>
<td width="87%">Minor Memory leak in Dispatch.cpp</td>
</tr>
<tr>
<td width="13%">1065533</td>
<td width="87%">Problem with unicode conversion</td>
</tr>
<tr>
<td width="13%">1053871</td>
<td width="87%">solution for memory leak in 1.7</td>
</tr>
<tr>
<td width="13%">1053870</td>
<td width="87%">JACOB0msg 2019 - Safe Array</td>
</tr>
<tr>
<td width="13%">1053866</td>
<td width="87%">getHResult only returns 80020009</td>
</tr>
<tr>
<td width="13%">960646</td>
<td width="87%">But in SafeArray:: getBoolean for 2D arrays</td>
</tr>
<tr>
<td width="13%">&nbsp;</td>
<td width="87%">&nbsp;</td>
</tr>
<tr>
<td width="100%" colspan="2"><b>Patches</b></td>
</tr>
<tr>
<td width="13%">1115187</td>
<td width="87%">EventCallbacks fail w/Variant ClassNotFoundException in JWS</td>
</tr>
<tr>
<td width="13%">1105915</td>
<td width="87%">Fix for event handling memory corruption</td>
</tr>
<tr>
<td width="13%">1090104</td>
<td width="87%">Weak Reference in teh ROT</td>
</tr>
<tr>
<td width="13%">1068544</td>
<td width="87%">in/out parameter support for event handlers</td>
</tr>
<tr>
<td width="13%">981540</td>
<td width="87%">jre 1.4.2 fix as patch</td>
</tr>
<tr>
<td width="13%">&nbsp;</td>
<td width="87%">&nbsp;</td>
</tr>
<tr>
<td width="100%" colspan="2"><b>Feature Requests</b></td>
</tr>
<tr>
<td width="13%">1049390</td>
<td width="87%">static Version information</td>
</tr>
<tr>
<td width="13%">1049224</td>
<td width="87%">Javadocs or at least script to generate it</td>
</tr>
<tr>
<td width="13%">1049158</td>
<td width="87%">API to get ProgId of ActiveXComponent</td>
</tr>
<tr>
<td width="13%">&nbsp;</td>
<td width="87%">&nbsp;</td>
</tr>
</table>
</li>
</ul>
<h1>What's New in JACOB 1.8</H1>
<ul>
<li>
<b>Move To SourceForge</b>
The project is not housed at
<a href="http://sourceforge.net/projects/jacob-project/">Sourceforge.net</a>.
</li>
<li>
<b>Licensing Change</b>
All limitations on commercial use of JACOB have been removed and it
is now being developed under a BSD license at
<a href="http://sourceforge.net/projects/jacob-project/">Sourceforge.net</a>.
</li>
<li>
<b>Compiled with Java 1.4.2</b>
Version 1.8 was compiled with JSEE 1.4.2 and fixes the compilation bug
that was remnant of compilation with JDK 1.1.
</li>
<li>
<b>Baseline For Change</b>
This version is the baseline for the first CVS checkin and we encourage
people to start contributing to the project with this version.
</li>
</ul>
<li>
<h1>What's New in JACOB 1.7</H1>
<ul>
<li>
<b>Explicit COM Threading Model Support:</b>
See a detailed discussion of
<a href="JacobThreading.html">COM Apartments in JACOB</a>
</li>
<li>
<b>New COM Object Lifetime model:</b>
See a detailed discussion of
<a href="JacobComLifetime.html">COM Object Lifetime in JACOB</a>.
</li>
<li>
<b>Improved Event Handling:</b>
Thanks to code contributed by
<a href="mailto:n.o.bouvin@daimi.au.dk">
Niels Olof Bouvin</a>
and <a href="mailto:jehoej@daimi.au.dk">Henning Jae</a> JACOB 1.7 can
read the type information of a Connection Point interface by looking
it up in the registry. This makes it possible to use events with IE as
well as office products.
</li>
<li>
<b>Improved Dispatch:</b>
Error messages from Invoke failures are now printed out as well as
allowing the passing in of arguments to a Get method.
</li>
<li>
<b>EnumVariant Implementation:</b>
Makes it easier to iterate over COM collections. Thanks to code
contributed by
<a href="mailto:Thomas.Hallgren@eoncompany.com">Thomas Hallgren</a>.
</li>
<li>
<b>SafeArray leaks:</b>
SafeArrays were not being properly freed prior to version 1.7, many
other memory leaks were fixed as well.
</li>
<li>
<b>Visual Studio Project:</b>
For those who want to debug: vstudio/JACOB. At the moment all the
native code is replicated there from the jni directory...
</li>
</ul>
<H1>Related Links</H1>
<ul>
<li>
The JACOB mailing list is hosted at yahoo groups:
<a href="http://groups.yahoo.com/group/jacob-project">
http://groups.yahoo.com/group/JACOB-project</a>.
<b>This is the preferred way to get support for JACOB</b>. It also
includes an extensive archive. If you are doing any development with
JACOB, please join the list.
<li>
Massimiliano Bigatti has developed
<a href="http://www.bigatti.it/projects/jacobgen/">
JACOBgen - a generator that automatically creates JACOB code from
Type Libraries</a>
</li>
<li>
Steven Lewis is developing a version of Java2Com that supports JACOB
code generation. See:
<a href="http://www.lordjoe.com/Java2Com/index.html">
http://www.lordjoe.com/Java2Com/index.html</a>.
<li>
To find documentation on the com.ms.com package, go to:
<a href="http://www.microsoft.com/java/download/dl_sdk40.htm">
http://www.microsoft.com/java/download/dl_sdk40.htm</a>
and at the bottom of the page is a link that says:
Microsoft SDK for Java 4.0 Documentation Only. You should download
that file and install it. Then, view sdkdocs.chm and look for
"Microsoft Packages Reference". Hopefully, the next release of
JACOB will include full javadoc (volunteers?)...</li>

3
docs/todo.txt Normal file
View File

@@ -0,0 +1,3 @@
1. Make everything check the current thread's mta-ness
2. Write more documentation
3. Get someone to help write the Javadoc

BIN
jacob.dll

Binary file not shown.

BIN
jacob.jar

Binary file not shown.

4
jni/.cvsignore Normal file
View File

@@ -0,0 +1,4 @@
jacob.dll
jacob.lib
jacob.exp

View File

@@ -410,9 +410,22 @@ JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
// check for error and display a somewhat verbose error message
if (!SUCCEEDED(hr)) {
const char *nm = env->GetStringUTFChars(name, NULL);
char *buf = CreateErrorMsgFromInfo(hr, &excepInfo, nm);
env->ReleaseStringUTFChars(name, nm);
// two buffers that may have to be freed later
char *buf = NULL;
char *dispIdAsName = NULL;
// this method can get called with a name or a dispatch id
// we need to handle both SF 1114159
if (name != NULL){
const char *nm = env->GetStringUTFChars(name, NULL);
buf = CreateErrorMsgFromInfo(hr, &excepInfo, nm);
env->ReleaseStringUTFChars(name, nm);
} else {
dispIdAsName = new char[256];
// get the id string
itoa (dispID,dispIdAsName,10);
//continue on mostly as before
buf = CreateErrorMsgFromInfo(hr,&excepInfo,dispIdAsName);
}
// jacob-msg 3696 - SF 1053866
if(hr == DISP_E_EXCEPTION)
@@ -429,6 +442,7 @@ JNIEXPORT jobject JNICALL Java_com_jacob_com_Dispatch_invokev
ThrowComFail(env, buf, hr);
if (buf) delete buf;
if (dispIdAsName) delete dispIdAsName;
return NULL;
}

View File

@@ -72,7 +72,10 @@ void putProxy(JNIEnv *env, jobject arg, EventProxy *ep)
* Signature: (LDispatch;Ljava/lang/Object;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
(JNIEnv *env, jobject _this, jobject src, jobject sink, jstring _progid)
(JNIEnv *env,
jobject _this, jobject src,
jobject sink, jobject protoVariant,
jstring _progid)
{
USES_CONVERSION;
// find progid if any
@@ -104,10 +107,11 @@ JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
return;
}
HRESULT hr = pCPC->FindConnectionPoint(eventIID, &pCP);
DWORD dwEventCookie;
// VC++ 6.0 compiler realiized we weren't using this variable
//DWORD dwEventCookie;
if (SUCCEEDED(hr))
{
EventProxy *ep = new EventProxy(env, sink, pCP, eventIID, mNames, mIDs, n_EventMethods);
EventProxy *ep = new EventProxy(env, sink, protoVariant, pCP, eventIID, mNames, mIDs, n_EventMethods);
// need to store ep on _this, in case it gets collected
putProxy(env, _this, ep);
} else {
@@ -121,9 +125,9 @@ JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
* Signature: (LDispatch;Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init
(JNIEnv *env, jobject _this, jobject src, jobject sink)
(JNIEnv *env, jobject _this, jobject src, jobject sink, jobject protoVariant)
{
Java_com_jacob_com_DispatchEvents_init2(env,_this,src,sink,NULL);
Java_com_jacob_com_DispatchEvents_init2(env,_this,src,sink, protoVariant, NULL);
}
/*

View File

@@ -13,7 +13,7 @@ extern "C" {
* Signature: (LDispatch;Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init
(JNIEnv *, jobject, jobject, jobject);
(JNIEnv *, jobject, jobject, jobject, jobject);
/*
* Class: DispatchEvents
@@ -21,7 +21,7 @@ JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init
* Signature: (LDispatch;Ljava/lang/Object;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_jacob_com_DispatchEvents_init2
(JNIEnv *, jobject, jobject, jobject, jstring);
(JNIEnv *, jobject, jobject, jobject, jobject, jstring);
/*
* Class: DispatchEvents

View File

@@ -28,34 +28,44 @@
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "EventProxy.h"
#include "Variant.h"
// hook myself up as a listener for delegate
EventProxy::EventProxy(JNIEnv *env, jobject aSinkObj,
EventProxy::EventProxy(JNIEnv *env,
jobject aSinkObj,
jobject aVariantObj,
CComPtr<IConnectionPoint> pConn,
IID eid, CComBSTR mName[], DISPID mID[], int mNum) :
IID eid,
CComBSTR mName[],
DISPID mID[],
int mNum) :
// initialize some variables
m_cRef(0), pCP(pConn),
eventIID(eid), MethNum(mNum), MethName(mName),
MethID(mID), JMethID(NULL), javaSinkClass(NULL),
variantClassMethod(NULL)
MethID(mID), JMethID(NULL),
javaSinkClass(NULL)
{
// don't really need the variant object but we keep a reference
// anyway
javaSinkObj = env->NewGlobalRef(aSinkObj);
if (env->ExceptionOccurred()) { env->ExceptionDescribe();}
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
javaVariantObj = env->NewGlobalRef(aVariantObj);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
// we need this to attach to the event invocation thread
env->GetJavaVM(&jvm);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
AddRef();
HRESULT hr = pCP->Advise(this, &dwEventCookie);
if (SUCCEEDED(hr)) {
// create a mapping from the DISPID's to jmethodID's by using
// the method names I extracted from the classinfo
JMethID = new jmethodID[MethNum];
javaSinkClass = env->GetObjectClass(javaSinkObj);
if (javaSinkClass == NULL){ printf("can't figure out java sink class"); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
variantClassMethod = env->GetMethodID(javaSinkClass, "getVariantClass", "()Ljava/lang/Class;");
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (variantClassMethod == NULL) { printf("variantClassMethod == null\n"); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
const char *method;
for(int i=0;i<MethNum;i++)
@@ -69,6 +79,7 @@ EventProxy::EventProxy(JNIEnv *env, jobject aSinkObj,
// if the user didn't implement all the methods
env->ExceptionClear();
}
} else {
ThrowComFail(env, "Advise failed", hr);
}
@@ -85,10 +96,10 @@ EventProxy::~EventProxy()
#else
jvm->AttachCurrentThread((void**)&env, NULL);
#endif
env->DeleteGlobalRef(javaSinkObj);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
if (MethNum) {
delete [] MethName;
delete [] MethID;
@@ -125,7 +136,8 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
LCID lcid, unsigned short wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
HRESULT hr;
//Visual C++ 6.0 recognized this as an unused variable
//HRESULT hr;
jmethodID meth = 0;
JNIEnv *env = NULL;
@@ -146,29 +158,32 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
{
// attach to the current running thread
#ifdef JNI_VERSION_1_2
jvm->AttachCurrentThread((void **)&env, jvm);
#else
jvm->AttachCurrentThread((void**)&env, NULL);
#endif
jvm->AttachCurrentThread((void **)&env, jvm);
#else
jvm->AttachCurrentThread((void**)&env, NULL);
#endif
// get variant class
jclass vClass;
jclass vClass = NULL;
// do this in a JACOB 1.8 backwards compatable way
// this succeeds if the class was loaded from the bootstrap class loader
vClass = env->FindClass("com/jacob/com/Variant");
//vClass = env->FindClass("com/jacob/com/Variant");
// this is guarenteed to work so there really isn't any need for the line above
// but I don't want to bust anything so we leave it in
// the following code exists to support launchers like JWS where jacob isn't
// in the system classloader so we wouldn't be able to create a variant class
if (vClass == NULL){
// see if our call back class implements our "special" method
if (variantClassMethod != NULL){
jobject variantFound = env->CallObjectMethod(javaSinkObj, variantClassMethod);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (variantFound == NULL) { printf("variantFound == null\n"); }
vClass = (jclass)variantFound;
} else {
// dang they didn't. lets tell the user they are having a bad day
printf("We're going to fail now in a way that is probably pretty ugly");
// there will be a stored up exception if FindClass failed so lets clear it
if (env->ExceptionOccurred()) { env->ExceptionClear(); }
//printf("using variant class passed in via constructor\n");
jclass javaVariantClass = env->GetObjectClass(javaVariantObj);
if (javaVariantClass == NULL){ printf("can't figure out java Variant class"); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
vClass = javaVariantClass;
if (vClass == NULL){
printf("This application is probably running from a launcher where system class loader knows not Jacob\n");
printf("The call back class does not implement 'Class getVariantClass()' that we can use to work around this\n");
printf("And for some reason we couldn't find the variant class from the passed in variant\n");
}
}
@@ -176,16 +191,16 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
int num = pDispParams->cArgs;
// and the constructor
jmethodID vCons = env->GetMethodID(vClass, "<init>", "()V");
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
// make an array of them
jobjectArray varr = env->NewObjectArray(num, vClass, 0);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
int i,j;
for(i=num-1,j=0;i>=0;i--,j++)
{
// construct a java variant holder
jobject arg = env->NewObject(vClass, vCons);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
// get the empty variant from it
VARIANT *va = extractVariant(env, arg);
// copy the value
@@ -193,11 +208,11 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
// put it in the array
env->SetObjectArrayElement(varr, j, arg);
env->DeleteLocalRef(arg);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
}
// call the method
env->CallVoidMethod(javaSinkObj, meth, varr);
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); }
if (env->ExceptionOccurred()) { env->ExceptionDescribe(); env->ExceptionClear();}
// Begin code from Jiffie team that copies parameters back from java to COM
@@ -820,6 +835,7 @@ STDMETHODIMP EventProxy::Invoke(DISPID dispID, REFIID riid,
}
zeroVariant(env, arg);
env->DeleteLocalRef(arg);
}
// End code from Jiffie team that copies parameters back from java to COM

View File

@@ -59,7 +59,7 @@ private:
DWORD dwEventCookie; // connection point cookie
jobject javaSinkObj; // the java object to delegate calls
jclass javaSinkClass; // the java class of the object
jmethodID variantClassMethod; // the method on the javaSinkObj that will return the Variant class
jobject javaVariantObj; // a variant object passed in so we can find Variant later
IID eventIID; // the interface iid passed in
int MethNum;
@@ -70,9 +70,14 @@ private:
public:
// constuct with a global JNI ref to a sink object
// to which we will delegate event callbacks
EventProxy(JNIEnv *jenv, jobject aSinkObj,
EventProxy(JNIEnv *jenv,
jobject aSinkObj,
jobject aVariantObj,
CComPtr<IConnectionPoint> pConn,
IID eventIID, CComBSTR *mName, DISPID *mID, int mNum);
IID eventIID,
CComBSTR *mName,
DISPID *mID,
int mNum);
~EventProxy();
// IUnknown methods

View File

@@ -99,13 +99,12 @@ SAFEARRAY *copySA(SAFEARRAY *psa)
VARIANT v1, v2;
VariantInit(&v1);
VariantInit(&v2);
VariantInit(&v2);
V_VT(&v1) = VT_ARRAY | vt;
V_ARRAY(&v1) = psa;
VariantCopy(&v2, &v1);
SAFEARRAY *sa = V_ARRAY(&v2);
VariantInit(&v2); // make sure it's not owned by this variant
VariantClear(&v2);
VariantInit(&v1);
VariantClear(&v1);
@@ -1719,8 +1718,8 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setString__IILjava_lang_Stri
ThrowComFail(env, "safearray object corrupted", -1);
return;
}
if (SafeArrayGetDim(sa) != 1) {
ThrowComFail(env, "safearray is not 1D", -1);
if (SafeArrayGetDim(sa) != 2) {
ThrowComFail(env, "safearray is not 2D", -1);
return;
}
VARTYPE vt;
@@ -2035,8 +2034,8 @@ JNIEXPORT jboolean JNICALL Java_com_jacob_com_SafeArray_getBoolean__II
ThrowComFail(env, "safearray object corrupted", -1);
return NULL;
}
if (SafeArrayGetDim(sa) != 1) {
ThrowComFail(env, "safearray is not 1D", -1);
if (SafeArrayGetDim(sa) != 2) {
ThrowComFail(env, "safearray is not 2D", -1);
return NULL;
}
VARTYPE vt;
@@ -2110,10 +2109,10 @@ JNIEXPORT void JNICALL Java_com_jacob_com_SafeArray_setBoolean__IIZ
ThrowComFail(env, "safearray object corrupted", -1);
return;
}
if (SafeArrayGetDim(sa) != 1) {
ThrowComFail(env, "safearray is not 1D", -1);
if (SafeArrayGetDim(sa) != 2) {
ThrowComFail(env, "safearray is not 2D", -1);
return;
}
}
VARTYPE vt;
SafeArrayGetVartype(sa, &vt);
long idx[2] = {i,j};

View File

@@ -91,6 +91,25 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_init
env->SetIntField(_this, jf, (unsigned int)v);
}
/*
* Class: com_jacob_com_Variant
* Method: zeroVariant
* Signature: ()V
*
* This should only be used on variant objects created by teh
* com layer as part of a call through EventProxy.
* This zeros out the variant pointer in the Variant object
* so that the calling COM program can free the memory.
* instead of both the COM program and the Java GC doing it.
*/
void zeroVariant(JNIEnv *env, jobject _this)
{
jclass clazz = env->GetObjectClass(_this);
jfieldID jf = env->GetFieldID(clazz, VARIANT_FLD, "I");
env->SetIntField(_this, jf, (unsigned int)0);
}
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Save
(JNIEnv *env, jobject _this, jobject outStream)
{
@@ -351,6 +370,7 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putDateRef
}
}
// SF 1065533 added unicode support
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putStringRef
(JNIEnv *env, jobject _this, jstring s)
{
@@ -358,21 +378,15 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putStringRef
if (v) {
VariantClear(v); // whatever was there before
// need to convert to C-style char buffer
jclass strcls = env->FindClass("java/lang/String");
jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
int len = env->GetArrayLength(ba);
jbyte* buf = (jbyte*)alloca(len + 1);
env->GetByteArrayRegion(ba, 0, len, buf);
buf[len] = '\0';
CComBSTR bs((char*)buf);
const jchar *cStr = env->GetStringChars(s,NULL);
CComBSTR bs(cStr);
BSTR *pbs = (BSTR *)CoTaskMemAlloc(sizeof(BSTR));
bs.CopyTo(pbs);
V_VT(v) = VT_BSTR|VT_BYREF;
V_BSTRREF(v) = pbs;
}
env->ReleaseStringChars(s,cStr); }
}
JNIEXPORT jshort JNICALL Java_com_jacob_com_Variant_getShortRef
@@ -858,6 +872,7 @@ JNIEXPORT jstring JNICALL Java_com_jacob_com_Variant_getString
return NULL;
}
// SF 1065533 added unicode support
JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putString
(JNIEnv *env, jobject _this, jstring s)
{
@@ -866,18 +881,13 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_putString
VariantClear(v); // whatever was there before
V_VT(v) = VT_BSTR;
// get C-style byte array
jclass strcls = env->FindClass("java/lang/String");
jmethodID getBytes = env->GetMethodID(strcls, "getBytes", "()[B");
jbyteArray ba = (jbyteArray)env->CallObjectMethod(s, getBytes);
int len = env->GetArrayLength(ba);
jbyte* buf = (jbyte*)alloca(len + 1);
env->GetByteArrayRegion(ba, 0, len, buf);
buf[len] = '\0';
const jchar *cStr = env->GetStringChars(s,NULL);
CComBSTR bs(cStr);
CComBSTR bs((char*)buf);
V_VT(v) = VT_BSTR;
V_BSTR(v) = bs.Copy();
env->ReleaseStringChars(s,cStr);
}
}

View File

@@ -607,6 +607,19 @@ JNIEXPORT void JNICALL Java_com_jacob_com_Variant_Load
JNIEXPORT jboolean JNICALL Java_com_jacob_com_Variant_isNull
(JNIEnv *, jobject);
/*
* Class: com_jacob_com_Variant
* Method: zeroVariant
* Signature: ()V
*
* This should only be used on variant objects created by teh
* com layer as part of a call through EventProxy.
* This zeros out the variant pointer in the Variant object
* so that the calling COM program can free the memory.
* instead of both the COM program and the Java GC doing it.
*/
void zeroVariant (JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,51 +0,0 @@
JDK = d:\j2sdk1.4.2_06
DEST_DIR = d:\jacob_18
MSDEVDIR = d:\apps\\"Microsoft Visual Studio"\VC98
JDK_INC = -I$(JDK)\include -I$(JDK)\include\win32
JDK_LIB = $(JDK)\lib\jvm.lib
MS_INC = -I$(MSDEVDIR)\Include -I$(MSDEVDIR)\ATL\Include
SYS_LIB = oleaut32.lib ole32.lib uuid.lib kernel32.lib shell32.lib user32.lib
OPT = /O2
CC = cl $(OPT) $(JDK_INC) $(MS_INC)
OBJFILES = stdafx.obj util.obj EventProxy.obj Variant.obj Dispatch.obj SafeArray.obj DispatchEvents.obj ComThread.obj EnumVariant.obj STA.obj DispatchProxy.obj
all: jacob.dll
cp jacob.dll $(DEST_DIR)
jacob.dll: $(OBJFILES)
link /dll /out:jacob.dll $(OBJFILES) $(JDK_LIB) $(SYS_LIB)
stdafx.obj: stdafx.cpp *.h
$(CC) -c stdafx.cpp
util.obj: util.cpp *.h
$(CC) -c util.cpp
EventProxy.obj: EventProxy.cpp *.h
$(CC) -c EventProxy.cpp
Variant.obj: Variant.cpp *.h
$(CC) -c Variant.cpp
Dispatch.obj: Dispatch.cpp *.h
$(CC) -c Dispatch.cpp
SafeArray.obj: SafeArray.cpp *.h
$(CC) -c SafeArray.cpp
DispatchEvents.obj: DispatchEvents.cpp *.h
$(CC) -c DispatchEvents.cpp
ComThread.obj: ComThread.cpp *.h
$(CC) -c ComThread.cpp
EnumVariant.obj: EnumVariant.cpp *.h
$(CC) -c EnumVariant.cpp
STA.obj: STA.cpp *.h
$(CC) -c STA.cpp
DispatchProxy.obj: DispatchProxy.cpp *.h
$(CC) -c DispatchProxy.cpp

View File

@@ -5,6 +5,5 @@ extern "C" {
IDispatch *extractDispatch(JNIEnv *env, jobject arg);
SAFEARRAY *extractSA(JNIEnv *env, jobject arg);
void setSA(JNIEnv *env, jobject arg, SAFEARRAY *sa, int copy);
SAFEARRAY *copySA(SAFEARRAY *psa)
SAFEARRAY *copySA(SAFEARRAY *psa);
}

View File

@@ -1,18 +0,0 @@
JAVAC = d:\j2sdk1.4.2_06\bin\javac -O
JAR = d:\j2sdk1.4.2_06\bin\jar -cvf jacob.jar
COM_DIR = com\jacob\com
ACX_DIR = com\jacob\activeX
all: java jni
rm -f jacobSrc_18.zip jacobBin_18.zip
jar -cvf jacobSrc_18.zip .
jar -cvf jacobBin_18.zip jacob.dll jacob.jar LICENSE.TXT README.TXT samples
java: jacob.jar
$(JAVAC) $(COM_DIR)\*.java $(ACX_DIR)\*.java
$(JAR) $(COM_DIR)\*.class $(ACX_DIR)\*.class
jni: jni\jacob.dll
cd jni
nmake -f makefile all
cd ..\

View File

@@ -1,88 +1,88 @@
- ADO Wrapper for JACOB - Copyright 1999, Dan Adler
This sample shows how to generate more strongly typed wrapper classes
for the JACOB automation classes. These are pure java classes which
extend com.jacob.com.Dispatch and delegate all the methods to the
unedrlying IDispatch pointer. This methodology is similar to the way
MFC does automation wrappers, rather than using the @com directives
to invisibly delegate the calls, as the Microsoft VM does.
The ADO wrappers in this directory are not a part of the JACOB
distribution, however, they demonstrate the preferred way to create
wrappers around the core functionality. The wrappers included here are
not a complete set, but they could easily be extended to provide all
the functionality of the com.ms.wfc.data classes.
The code in test.java demonstrates two ways to get a Recordset
from SQL Server. In this case, I query for the authors in the 'pubs'
database once by opening a Recordset object directly, and once by
using the Command and Connection objects. The same code, using the WFC
wrappers can be found in ms\testms.java in case you want to compare
the performace. You can run the test.java demo in the MS VM as well.
The constructor of the wrapper is used to create an instance.
For example, the user can write:
Connection c = new Connection();
The code for the Connection constructor is shown here:
public Connection()
{
super("ADODB.Connection");
}
it simply delegates to the com.jacob.com.Dispatch constructor which
takes a ProgID.
Since I don't have a tool like JACTIVEX yet to create the wrappers
automatically from the type library, I created them by hand by using
the JACTIVEX'ed version as a starting point, and replacing the @com
calls with delegated calls to JACOB classes. A simple PERL program
could probably be used to automate this step.
In order to return strongly typed wrappers from method calls, I had to
create a special constructor which constructs the wrapper class instance
and copies over the IDispatch pointer. This is because I can't cast a
java Dispatch object to a super class object.
For example, the Command class has a method like this:
public Connection getActiveConnection();
Ideally, I would like the wrapper code to say:
public Connection getActiveConnection()
{
// this doesn't work
return (Connection)Dispatch.get(this, "ActiveConnection").toDispatch());
}
Thereby wrapping the returned Dispatch pointer in a Connection object.
But, since I can't cast in this way, I use the following construct:
public Connection getActiveConnection()
{
// this works
return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
}
Which uses a special constructor inserted into the Connection class:
/**
* This constructor is used instead of a case operation to
* turn a Dispatch object into a wider object - it must exist
* in every wrapper class whose instances may be returned from
* method calls wrapped in VT_DISPATCH Variants.
*/
public Connection(Dispatch d)
{
// take over the IDispatch pointer
m_pDispatch = d.m_pDispatch;
// null out the input's pointer
d.m_pDispatch = 0;
}
I have to add this constructor to any class whose instances I want
to return from wrapped calls.
- ADO Wrapper for JACOB - Copyright 1999, Dan Adler
This sample shows how to generate more strongly typed wrapper classes
for the JACOB automation classes. These are pure java classes which
extend com.jacob.com.Dispatch and delegate all the methods to the
unedrlying IDispatch pointer. This methodology is similar to the way
MFC does automation wrappers, rather than using the @com directives
to invisibly delegate the calls, as the Microsoft VM does.
The ADO wrappers in this directory are not a part of the JACOB
distribution, however, they demonstrate the preferred way to create
wrappers around the core functionality. The wrappers included here are
not a complete set, but they could easily be extended to provide all
the functionality of the com.ms.wfc.data classes.
The code in test.java demonstrates two ways to get a Recordset
from SQL Server. In this case, I query for the authors in the 'pubs'
database once by opening a Recordset object directly, and once by
using the Command and Connection objects. The same code, using the WFC
wrappers can be found in ms\testms.java in case you want to compare
the performace. You can run the test.java demo in the MS VM as well.
The constructor of the wrapper is used to create an instance.
For example, the user can write:
Connection c = new Connection();
The code for the Connection constructor is shown here:
public Connection()
{
super("ADODB.Connection");
}
it simply delegates to the com.jacob.com.Dispatch constructor which
takes a ProgID.
Since I don't have a tool like JACTIVEX yet to create the wrappers
automatically from the type library, I created them by hand by using
the JACTIVEX'ed version as a starting point, and replacing the @com
calls with delegated calls to JACOB classes. A simple PERL program
could probably be used to automate this step.
In order to return strongly typed wrappers from method calls, I had to
create a special constructor which constructs the wrapper class instance
and copies over the IDispatch pointer. This is because I can't cast a
java Dispatch object to a super class object.
For example, the Command class has a method like this:
public Connection getActiveConnection();
Ideally, I would like the wrapper code to say:
public Connection getActiveConnection()
{
// this doesn't work
return (Connection)Dispatch.get(this, "ActiveConnection").toDispatch());
}
Thereby wrapping the returned Dispatch pointer in a Connection object.
But, since I can't cast in this way, I use the following construct:
public Connection getActiveConnection()
{
// this works
return new Connection(Dispatch.get(this, "ActiveConnection").toDispatch());
}
Which uses a special constructor inserted into the Connection class:
/**
* This constructor is used instead of a case operation to
* turn a Dispatch object into a wider object - it must exist
* in every wrapper class whose instances may be returned from
* method calls wrapped in VT_DISPATCH Variants.
*/
public Connection(Dispatch d)
{
// take over the IDispatch pointer
m_pDispatch = d.m_pDispatch;
// null out the input's pointer
d.m_pDispatch = 0;
}
I have to add this constructor to any class whose instances I want
to return from wrapped calls.

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
// Enum: CommandTypeEnum

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;
public class Field extends Dispatch

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;
public class Fields extends Dispatch

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;
public class Recordset extends Dispatch

View File

@@ -1,4 +1,4 @@
package samples.ado;
package com.jacob.samples.ado;
import com.jacob.com.*;
public class test

View File

@@ -1,8 +1,8 @@
<title>Applet Test (1.1)</title>
<h1>Applet Test (1.1)</h1>
<hr>
<applet code=AppTest.class width=400 height=400>
</applet>
<hr>
<a href="AppTest.java">The source.</a>
<br>
<title>Applet Test (1.1)</title>
<h1>Applet Test (1.1)</h1>
<hr>
<applet code=AppTest.class width=400 height=400>
</applet>
<hr>
<a href="AppTest.java">The source.</a>
<br>

View File

@@ -1,4 +1,4 @@
package samples.applet;
package com.jacob.samples.applet;
import java.awt.*;
import java.awt.event.*;
@@ -16,7 +16,7 @@ public class AppTest extends Applet implements ActionListener
TextField out;
Button calc;
ActiveXComponent sC = null;
Object sControl = null;
Dispatch sControl = null;
/**
* startup method

View File

@@ -1,4 +1,4 @@
package samples.servlet;
package com.jacob.samples.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
@@ -44,7 +44,7 @@ public class JacobScript extends javax.servlet.http.HttpServlet
String expr = (String)req.getParameter("expr");
// make sure we have a session
HttpSession session = req.getSession(true);
Object sControl = null;
Dispatch sControl = null;
if (session.isNew())
{
// initialize the control and store it on the session
@@ -56,7 +56,7 @@ public class JacobScript extends javax.servlet.http.HttpServlet
}
else
{
sControl = session.getValue("control");
sControl = (Dispatch)session.getValue("control");
}
Variant result = Dispatch.call(sControl, "Eval", expr);
// display a form

View File

@@ -1,44 +1,44 @@
This sample runs in Weblogic 5.1 as a servlet.
1. Compile this file (make sure you have jdk1.2 installed or the
javax.servlet.* classes in your classpath).
2. Make sure the weblogic policy file allows native access. The easiest
way is to replace the contents with this:
grant codeBase "file:d:/weblogic/-" {
permission java.security.AllPermission;
};
grant codeBase "file:/c:/classes/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
grant {
permission java.security.AllPermission;
};
3. Add the servlet to the weblogic.properties file:
weblogic.httpd.register.JacobScript=JacobScript
4. Either add your CLASSPATH to weblogic.classpath in startWebLogic.cmd
or copy the com directory into weblogic/myserver/servletclasses
5. Copy the jacob/samples/servlet/* into weblogic/myserver/servletclasses
6. Start weblogic
7. Type the url: http://localhost:7001/JacobScript into the browser
(If you run on port 7001)
8. Enter a VBScript expression like:
1+2
Now
"hello" & " world"
etc.
and watch the MS Script control (which you must have installed)
evaluate and return the result.
This sample runs in Weblogic 5.1 as a servlet.
1. Compile this file (make sure you have jdk1.2 installed or the
javax.servlet.* classes in your classpath).
2. Make sure the weblogic policy file allows native access. The easiest
way is to replace the contents with this:
grant codeBase "file:d:/weblogic/-" {
permission java.security.AllPermission;
};
grant codeBase "file:/c:/classes/-" {
permission java.security.AllPermission;
};
grant codeBase "file:${java.home}/lib/ext/-" {
permission java.security.AllPermission;
};
grant {
permission java.security.AllPermission;
};
3. Add the servlet to the weblogic.properties file:
weblogic.httpd.register.JacobScript=JacobScript
4. Either add your CLASSPATH to weblogic.classpath in startWebLogic.cmd
or copy the com directory into weblogic/myserver/servletclasses
5. Copy the jacob/samples/servlet/* into weblogic/myserver/servletclasses
6. Start weblogic
7. Type the url: http://localhost:7001/JacobScript into the browser
(If you run on port 7001)
8. Enter a VBScript expression like:
1+2
Now
"hello" & " world"
etc.
and watch the MS Script control (which you must have installed)
evaluate and return the result.

View File

@@ -1,4 +1,4 @@
package samples.test;
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;

View File

@@ -1,40 +1,40 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class DispatchTest
{
public static void main(String[] args)
{
ComThread.InitSTA();
ActiveXComponent xl = new ActiveXComponent("Excel.Application");
Object xlo = xl.getObject();
try {
System.out.println("version="+xl.getProperty("Version"));
System.out.println("version="+Dispatch.get(xlo, "Version"));
Dispatch.put(xlo, "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[] {});
ComThread.Release();
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class DispatchTest
{
public static void main(String[] args)
{
ComThread.InitSTA();
ActiveXComponent xl = new ActiveXComponent("Excel.Application");
Dispatch xlo = xl.getObject();
try {
System.out.println("version="+xl.getProperty("Version"));
System.out.println("version="+Dispatch.get(xlo, "Version"));
Dispatch.put(xlo, "Visible", new Variant(true));
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
Dispatch workbook = Dispatch.get(workbooks,"Add").toDispatch();
Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();
Dispatch a1 = Dispatch.invoke(sheet, "Range", Dispatch.Get,
new Object[] {"A1"},
new int[1]).toDispatch();
Dispatch 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[] {});
ComThread.Release();
}
}
}

View File

@@ -1,4 +1,4 @@
package samples.test;
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
@@ -14,8 +14,9 @@ class IETest
{
public static void main(String[] args)
{
int delay = 5000; // msec
ActiveXComponent ie = new ActiveXComponent("clsid:0002DF01-0000-0000-C000-000000000046");
Object ieo = ie.getObject();
Dispatch ieo = ie.getObject();
try {
Dispatch.put(ieo, "Visible", new Variant(true));
Dispatch.put(ieo, "AddressBar", new Variant(true));
@@ -28,9 +29,9 @@ class IETest
optional.noParam();
Dispatch.call(ieo, "Navigate", new Variant("http://www.danadler.com/jacob"));
try { Thread.sleep(5000); } catch (Exception e) {}
try { Thread.sleep(delay); } catch (Exception e) {}
Dispatch.call(ieo, "Navigate", new Variant("http://groups.yahoo.com/group/jacob-project"));
try { Thread.sleep(5000); } catch (Exception e) {}
try { Thread.sleep(delay); } catch (Exception e) {}
} catch (Exception e) {
e.printStackTrace();
} finally {

View File

@@ -1,4 +1,4 @@
package samples.test;
package com.jacob.samples.test;
/**
* JACOB Outlook sample contributed by
@@ -22,14 +22,14 @@ public class Outlook {
}
private static void recurseFolders(int iIndent, Object o) {
private static void recurseFolders(int iIndent, Dispatch o) {
if (o == null) return;
Object oFolders = Dispatch.get(o, "Folders").toDispatch();
Dispatch oFolders = Dispatch.get(o, "Folders").toDispatch();
// System.out.println("oFolders=" + oFolders);
if (oFolders == null) return;
Object oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch();
Dispatch oFolder = Dispatch.get(oFolders, "GetFirst").toDispatch();
do {
Object oFolderName = Dispatch.get(oFolder, "Name");
if (null == oFolderName) {
@@ -52,10 +52,10 @@ public class Outlook {
try {
System.out.println("version="+axOutlook.getProperty("Version"));
Object oOutlook = axOutlook.getObject();
Dispatch oOutlook = axOutlook.getObject();
System.out.println("version="+Dispatch.get(oOutlook, "Version"));
Object oNameSpace = axOutlook.getProperty("Session").toDispatch();
Dispatch oNameSpace = axOutlook.getProperty("Session").toDispatch();
System.out.println("oNameSpace=" + oNameSpace);
recurseFolders(0, oNameSpace);

View File

@@ -1,57 +1,47 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* In this case the component is created and used in the same thread
* and it's an Apartment Threaded component, so we call InitSTA.
*/
class ScriptTest
{
public static void main(String args[]) throws Exception
{
ComThread.InitSTA(true);
DispatchEvents de = null;
Dispatch sControl = null;
try {
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
errEvents te = new errEvents();
de = new DispatchEvents(sControl, te);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
// call it twice to see the objects reused
result = Dispatch.call(sControl, "Eval", args[0]);
// call it 3 times to see the objects reused
result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
ComThread.quitMainSTA();
}
}
}
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 error!");
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* In this case the component is created and used in the same thread
* and it's an Apartment Threaded component, so we call InitSTA.
*/
class ScriptTest
{
public static void main(String args[]) throws Exception
{
ComThread.InitSTA(true);
DispatchEvents de = null;
Dispatch sControl = null;
try {
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sControl, te);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
// call it twice to see the objects reused
result = Dispatch.call(sControl, "Eval", args[0]);
// call it 3 times to see the objects reused
result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
ComThread.quitMainSTA();
}
}
}

View File

@@ -1,98 +1,98 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* This example demonstrates how to make calls between
* two different STA's.
* First, to create an STA, you need to extend the STA class
* and override its OnInit() method. This method will be called
* in the STA's thread so you can use it to create your COM
* components that will run in that STA.
* If you then try to call methods on those components from other
* threads (STA or MTA) - this will fail.
* You cannot create a component in an STA and call its methods
* from another thread.
* You can use the DispatchProxy to get a proxy to any Dispatch
* that lives in another STA. This object has to be created in the
* STA that houses the Dispatch (in this case it's created in the
* OnInit method). Then, another thread can call the toDispatch()
* method of DispatchProxy to get a local proxy. At most ONE (!)
* thread can call toDispatch(), and the call can be made only once.
* This is because a IStream object is used to pass the proxy, and
* it is only written once and closed when you read it.
* If you need multiple threads to access a Dispatch pointer, then
* create that many DispatchProxy objects.
*/
class ScriptTest2 extends STA
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static Dispatch sControl = null;
public static DispatchProxy sCon = null;
public boolean OnInit()
{
try
{
System.out.println("OnInit");
System.out.println(Thread.currentThread());
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
// sCon can be called from another thread
sCon = new DispatchProxy(sControl);
Dispatch.put(sControl, "Language", lang);
errEvents te = new errEvents();
de = new DispatchEvents(sControl, te);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public void OnQuit()
{
System.out.println("OnQuit");
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitSTA();
ScriptTest2 script = new ScriptTest2();
Thread.sleep(1000);
// get a thread-local Dispatch from sCon
Dispatch sc = sCon.toDispatch();
// call a method on the thread-local Dispatch obtained
// from the DispatchProxy. If you try to make the same
// method call on the sControl object - you will get a
// ComException.
Variant result = Dispatch.call(sc, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
script.quit();
System.out.println("called quit");
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* This example demonstrates how to make calls between
* two different STA's.
* First, to create an STA, you need to extend the STA class
* and override its OnInit() method. This method will be called
* in the STA's thread so you can use it to create your COM
* components that will run in that STA.
* If you then try to call methods on those components from other
* threads (STA or MTA) - this will fail.
* You cannot create a component in an STA and call its methods
* from another thread.
* You can use the DispatchProxy to get a proxy to any Dispatch
* that lives in another STA. This object has to be created in the
* STA that houses the Dispatch (in this case it's created in the
* OnInit method). Then, another thread can call the toDispatch()
* method of DispatchProxy to get a local proxy. At most ONE (!)
* thread can call toDispatch(), and the call can be made only once.
* This is because a IStream object is used to pass the proxy, and
* it is only written once and closed when you read it.
* If you need multiple threads to access a Dispatch pointer, then
* create that many DispatchProxy objects.
*/
class ScriptTest2 extends STA
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static Dispatch sControl = null;
public static DispatchProxy sCon = null;
public boolean OnInit()
{
try
{
System.out.println("OnInit");
System.out.println(Thread.currentThread());
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
// sCon can be called from another thread
sCon = new DispatchProxy(sControl);
Dispatch.put(sControl, "Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sControl, te);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public void OnQuit()
{
System.out.println("OnQuit");
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitSTA();
ScriptTest2 script = new ScriptTest2();
Thread.sleep(1000);
// get a thread-local Dispatch from sCon
Dispatch sc = sCon.toDispatch();
// call a method on the thread-local Dispatch obtained
// from the DispatchProxy. If you try to make the same
// method call on the sControl object - you will get a
// ComException.
Variant result = Dispatch.call(sc, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
script.quit();
System.out.println("called quit");
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
}
}
}

View File

@@ -0,0 +1,96 @@
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* This example demonstrates how to make calls between
* two different STA's.
* First, to create an STA, you need to extend the STA class
* and override its OnInit() method. This method will be called
* in the STA's thread so you can use it to create your COM
* components that will run in that STA.
* If you then try to call methods on those components from other
* threads (STA or MTA) - this will fail.
* You cannot create a component in an STA and call its methods
* from another thread.
* You can use the DispatchProxy to get a proxy to any Dispatch
* that lives in another STA. This object has to be created in the
* STA that houses the Dispatch (in this case it's created in the
* OnInit method). Then, another thread can call the toDispatch()
* method of DispatchProxy to get a local proxy. At most ONE (!)
* thread can call toDispatch(), and the call can be made only once.
* This is because a IStream object is used to pass the proxy, and
* it is only written once and closed when you read it.
* If you need multiple threads to access a Dispatch pointer, then
* create that many DispatchProxy objects.
*/
class ScriptTest2ActiveX extends STA
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static DispatchProxy sCon = null;
public boolean OnInit()
{
try
{
System.out.println("OnInit");
System.out.println(Thread.currentThread());
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
// sCon can be called from another thread
sCon = new DispatchProxy(sC);
sC.setProperty("Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sC, te);
return true;
}
catch (Exception e)
{
e.printStackTrace();
return false;
}
}
public void OnQuit()
{
System.out.println("OnQuit");
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitSTA();
ScriptTest2ActiveX script = new ScriptTest2ActiveX();
Thread.sleep(1000);
// get a thread-local Dispatch from sCon
ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch());
// call a method on the thread-local Dispatch obtained
// from the DispatchProxy. If you try to make the same
// method call on the sControl object - you will get a
// ComException.
Variant result = sc.invoke("Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
script.quit();
System.out.println("called quit");
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
}
}
}

View File

@@ -1,68 +1,68 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* Here we create the ScriptControl component in a separate MTA thread
* and then call the Eval method from the main thread. The main thread
* must also be an MTA thread. If you try to create it as an STA
* then you will not be able to make calls into a component running
* in another thread.
*/
class ScriptTest3 extends Thread
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static Dispatch sControl = null;
public static boolean quit = false;
public void run()
{
try
{
ComThread.InitMTA();
System.out.println("OnInit");
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
errEvents te = new errEvents();
de = new DispatchEvents(sControl, te);
System.out.println("sControl="+sControl);
while (!quit) sleep(100);
ComThread.Release();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("worker thread exits");
}
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitMTA();
ScriptTest3 script = new ScriptTest3();
script.start();
Thread.sleep(1000);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
System.out.println("setting quit");
script.quit = true;
} catch (ComException e) {
e.printStackTrace();
}
finally
{
System.out.println("main done");
ComThread.Release();
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* Here we create the ScriptControl component in a separate MTA thread
* and then call the Eval method from the main thread. The main thread
* must also be an MTA thread. If you try to create it as an STA
* then you will not be able to make calls into a component running
* in another thread.
*/
class ScriptTest3 extends Thread
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static Dispatch sControl = null;
public static boolean quit = false;
public void run()
{
try
{
ComThread.InitMTA();
System.out.println("OnInit");
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sControl, te);
System.out.println("sControl="+sControl);
while (!quit) sleep(100);
ComThread.Release();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("worker thread exits");
}
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitMTA();
ScriptTest3 script = new ScriptTest3();
script.start();
Thread.sleep(1000);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
System.out.println("setting quit");
ScriptTest3.quit = true;
} catch (ComException e) {
e.printStackTrace();
}
finally
{
System.out.println("main done");
ComThread.Release();
}
}
}

View File

@@ -0,0 +1,66 @@
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* Here we create the ScriptControl component in a separate MTA thread
* and then call the Eval method from the main thread. The main thread
* must also be an MTA thread. If you try to create it as an STA
* then you will not be able to make calls into a component running
* in another thread.
*/
class ScriptTest3ActiveX extends Thread
{
public static ActiveXComponent sC;
public static DispatchEvents de = null;
public static boolean quit = false;
public void run()
{
try
{
ComThread.InitMTA();
System.out.println("OnInit");
String lang = "VBScript";
sC = new ActiveXComponent("ScriptControl");
sC.setProperty("Language", lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sC, te);
System.out.println("sControl="+sC);
while (!quit) sleep(100);
ComThread.Release();
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
System.out.println("worker thread exits");
}
}
public static void main(String args[]) throws Exception
{
try {
ComThread.InitMTA();
ScriptTest3ActiveX script = new ScriptTest3ActiveX();
script.start();
Thread.sleep(1000);
Variant result = sC.invoke("Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
System.out.println("setting quit");
ScriptTest3ActiveX.quit = true;
} catch (ComException e) {
e.printStackTrace();
}
finally
{
System.out.println("main done");
ComThread.Release();
}
}
}

View File

@@ -0,0 +1,46 @@
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
/**
* In this case the component is created and used in the same thread
* and it's an Apartment Threaded component, so we call InitSTA.
*/
class ScriptTestActiveX
{
public static void main(String args[]) throws Exception
{
ComThread.InitSTA(true);
DispatchEvents de = null;
try {
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
sC.setProperty("Language",lang);
ScriptTestErrEvents te = new ScriptTestErrEvents();
de = new DispatchEvents(sC, te);
Variant result;
result = sC.invoke("Eval",args[0]);
// call it twice to see the objects reused
result = sC.invoke("Eval",args[0]);
// call it 3 times to see the objects reused
result = sC.invoke("Eval",args[0]);
System.out.println("eval("+args[0]+") = "+ result);
} catch (ComException e) {
e.printStackTrace();
}
finally
{
Integer I = null;
for(int i=1;i<1000000;i++)
{
I = new Integer(i);
}
System.out.println(I);
ComThread.Release();
ComThread.quitMainSTA();
}
}
}

View File

@@ -0,0 +1,19 @@
package com.jacob.samples.test;
import com.jacob.com.Variant;
/**
* Extracted from ScriptTest so everyone can see this
*/
public class ScriptTestErrEvents {
public void Error(Variant[] args)
{
System.out.println("java callback for error!");
}
public void Timeout(Variant[] args)
{
System.out.println("java callback for error!");
}
}

View File

@@ -1,67 +1,67 @@
// Face.cpp : Implementation of CMultiFaceApp and DLL registration.
#include "stdafx.h"
#include "MultiFace.h"
#include "Face.h"
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP Face::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IFace1,
&IID_IFace2,
&IID_IFace3,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP Face::get_Face1Name(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name1;
return S_OK;
}
STDMETHODIMP Face::put_Face1Name(BSTR newVal)
{
// TODO: Add your implementation code here
name1 = newVal;
return S_OK;
}
STDMETHODIMP Face::get_Face2Nam(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name2;
return S_OK;
}
STDMETHODIMP Face::put_Face2Nam(BSTR newVal)
{
// TODO: Add your implementation code here
name2 = newVal;
return S_OK;
}
STDMETHODIMP Face::get_Face3Name(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name3;
return S_OK;
}
STDMETHODIMP Face::put_Face3Name(BSTR newVal)
{
// TODO: Add your implementation code here
name3 = newVal;
return S_OK;
}
// Face.cpp : Implementation of CMultiFaceApp and DLL registration.
#include "stdafx.h"
#include "MultiFace.h"
#include "Face.h"
/////////////////////////////////////////////////////////////////////////////
//
STDMETHODIMP Face::InterfaceSupportsErrorInfo(REFIID riid)
{
static const IID* arr[] =
{
&IID_IFace1,
&IID_IFace2,
&IID_IFace3,
};
for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
{
if (InlineIsEqualGUID(*arr[i],riid))
return S_OK;
}
return S_FALSE;
}
STDMETHODIMP Face::get_Face1Name(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name1;
return S_OK;
}
STDMETHODIMP Face::put_Face1Name(BSTR newVal)
{
// TODO: Add your implementation code here
name1 = newVal;
return S_OK;
}
STDMETHODIMP Face::get_Face2Nam(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name2;
return S_OK;
}
STDMETHODIMP Face::put_Face2Nam(BSTR newVal)
{
// TODO: Add your implementation code here
name2 = newVal;
return S_OK;
}
STDMETHODIMP Face::get_Face3Name(BSTR *pVal)
{
// TODO: Add your implementation code here
*pVal = name3;
return S_OK;
}
STDMETHODIMP Face::put_Face3Name(BSTR newVal)
{
// TODO: Add your implementation code here
name3 = newVal;
return S_OK;
}

View File

@@ -1,63 +1,63 @@
// Face.h: Definition of the Face class
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
#define AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// Face
class Face :
public IDispatchImpl<IFace1, &IID_IFace1, &LIBID_MULTIFACELib>,
public IDispatchImpl<IFace2, &IID_IFace2, &LIBID_MULTIFACELib>,
public IDispatchImpl<IFace3, &IID_IFace3, &LIBID_MULTIFACELib>,
public ISupportErrorInfo,
public CComObjectRoot,
public CComCoClass<Face,&CLSID_Face>
{
// IFace1
private:
CComBSTR name1;
// IFace2
CComBSTR name2;
// IFace3
CComBSTR name3;
public:
Face() {}
BEGIN_COM_MAP(Face)
COM_INTERFACE_ENTRY2(IDispatch, IFace1)
COM_INTERFACE_ENTRY(IFace1)
COM_INTERFACE_ENTRY(IFace2)
COM_INTERFACE_ENTRY(IFace3)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
//DECLARE_NOT_AGGREGATABLE(Face)
// Remove the comment from the line above if you don't want your object to
// support aggregation.
DECLARE_REGISTRY_RESOURCEID(IDR_Face)
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
public:
STDMETHOD(get_Face3Name)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face3Name)(/*[in]*/ BSTR newVal);
STDMETHOD(get_Face2Nam)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face2Nam)(/*[in]*/ BSTR newVal);
STDMETHOD(get_Face1Name)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face1Name)(/*[in]*/ BSTR newVal);
};
#endif // !defined(AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
// Face.h: Definition of the Face class
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
#define AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "resource.h" // main symbols
/////////////////////////////////////////////////////////////////////////////
// Face
class Face :
public IDispatchImpl<IFace1, &IID_IFace1, &LIBID_MULTIFACELib>,
public IDispatchImpl<IFace2, &IID_IFace2, &LIBID_MULTIFACELib>,
public IDispatchImpl<IFace3, &IID_IFace3, &LIBID_MULTIFACELib>,
public ISupportErrorInfo,
public CComObjectRoot,
public CComCoClass<Face,&CLSID_Face>
{
// IFace1
private:
CComBSTR name1;
// IFace2
CComBSTR name2;
// IFace3
CComBSTR name3;
public:
Face() {}
BEGIN_COM_MAP(Face)
COM_INTERFACE_ENTRY2(IDispatch, IFace1)
COM_INTERFACE_ENTRY(IFace1)
COM_INTERFACE_ENTRY(IFace2)
COM_INTERFACE_ENTRY(IFace3)
COM_INTERFACE_ENTRY(ISupportErrorInfo)
END_COM_MAP()
//DECLARE_NOT_AGGREGATABLE(Face)
// Remove the comment from the line above if you don't want your object to
// support aggregation.
DECLARE_REGISTRY_RESOURCEID(IDR_Face)
// ISupportsErrorInfo
STDMETHOD(InterfaceSupportsErrorInfo)(REFIID riid);
public:
STDMETHOD(get_Face3Name)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face3Name)(/*[in]*/ BSTR newVal);
STDMETHOD(get_Face2Nam)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face2Nam)(/*[in]*/ BSTR newVal);
STDMETHOD(get_Face1Name)(/*[out, retval]*/ BSTR *pVal);
STDMETHOD(put_Face1Name)(/*[in]*/ BSTR newVal);
};
#endif // !defined(AFX_FACE_H__9BF24413_B2E0_11D4_A695_00104BFF3241__INCLUDED_)

View File

@@ -1,72 +1,72 @@
// MultiFace.cpp : Implementation of DLL Exports.
// Note: Proxy/Stub Information
// To build a separate proxy/stub DLL,
// run nmake -f MultiFaceps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "MultiFace.h"
#include "MultiFace_i.c"
#include "Face.h"
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Face, Face)
END_OBJECT_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_MULTIFACELib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}
// MultiFace.cpp : Implementation of DLL Exports.
// Note: Proxy/Stub Information
// To build a separate proxy/stub DLL,
// run nmake -f MultiFaceps.mk in the project directory.
#include "stdafx.h"
#include "resource.h"
#include <initguid.h>
#include "MultiFace.h"
#include "MultiFace_i.c"
#include "Face.h"
CComModule _Module;
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_Face, Face)
END_OBJECT_MAP()
/////////////////////////////////////////////////////////////////////////////
// DLL Entry Point
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
if (dwReason == DLL_PROCESS_ATTACH)
{
_Module.Init(ObjectMap, hInstance, &LIBID_MULTIFACELib);
DisableThreadLibraryCalls(hInstance);
}
else if (dwReason == DLL_PROCESS_DETACH)
_Module.Term();
return TRUE; // ok
}
/////////////////////////////////////////////////////////////////////////////
// Used to determine whether the DLL can be unloaded by OLE
STDAPI DllCanUnloadNow(void)
{
return (_Module.GetLockCount()==0) ? S_OK : S_FALSE;
}
/////////////////////////////////////////////////////////////////////////////
// Returns a class factory to create an object of the requested type
STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)
{
return _Module.GetClassObject(rclsid, riid, ppv);
}
/////////////////////////////////////////////////////////////////////////////
// DllRegisterServer - Adds entries to the system registry
STDAPI DllRegisterServer(void)
{
// registers object, typelib and all interfaces in typelib
return _Module.RegisterServer(TRUE);
}
/////////////////////////////////////////////////////////////////////////////
// DllUnregisterServer - Removes entries from the system registry
STDAPI DllUnregisterServer(void)
{
return _Module.UnregisterServer(TRUE);
}

View File

@@ -1,12 +1,12 @@
// stdafx.cpp : source file that includes just the standard includes
// stdafx.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
#ifdef _ATL_STATIC_REGISTRY
#include <statreg.h>
#include <statreg.cpp>
#endif
#include <atlimpl.cpp>
// stdafx.cpp : source file that includes just the standard includes
// stdafx.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
#ifdef _ATL_STATIC_REGISTRY
#include <statreg.h>
#include <statreg.cpp>
#endif
#include <atlimpl.cpp>

View File

@@ -1,27 +1,27 @@
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#if !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
#define AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define STRICT
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#define _ATL_APARTMENT_THREADED
#include <atlbase.h>
//You may derive a class from CComModule and use it if you want to override
//something, but do not change the name of _Module
extern CComModule _Module;
#include <atlcom.h>
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED)
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently,
// but are changed infrequently
#if !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_)
#define AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#define STRICT
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0400
#endif
#define _ATL_APARTMENT_THREADED
#include <atlbase.h>
//You may derive a class from CComModule and use it if you want to override
//something, but do not change the name of _Module
extern CComModule _Module;
#include <atlcom.h>
//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
#endif // !defined(AFX_STDAFX_H__9BF24406_B2E0_11D4_A695_00104BFF3241__INCLUDED)

View File

@@ -1,18 +1,18 @@
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by MultiFace.rc
//
#define IDS_PROJNAME 100
#define IDS_FACE_DESC 101
#define IDR_Face 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 201
#define _APS_NEXT_COMMAND_VALUE 32768
#define _APS_NEXT_CONTROL_VALUE 201
#define _APS_NEXT_SYMED_VALUE 103
#endif
#endif
//{{NO_DEPENDENCIES}}
// Microsoft Developer Studio generated include file.
// Used by MultiFace.rc
//
#define IDS_PROJNAME 100
#define IDS_FACE_DESC 101
#define IDR_Face 102
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 201
#define _APS_NEXT_COMMAND_VALUE 32768
#define _APS_NEXT_CONTROL_VALUE 201
#define _APS_NEXT_SYMED_VALUE 103
#endif
#endif

View File

@@ -1,4 +1,4 @@
package samples.test.atl;
package com.jacob.samples.test.atl;
import com.jacob.com.*;
import com.jacob.activeX.*;

View File

@@ -1,14 +1,14 @@
This example demonstrates how to access multiple interfaces.
To run it, chdir to MultiFace\Debug and run:
regsvr32 MultiFace.dll
Then, run (in this dir):
java MultiFace
As you can see from MultiFace\MultiFace.idl - there are 3 interfaces.
By default JACOB attaches to the default interface.
The file MultiFace.java shows how to use the new Dispatch.QueryInterface
to get access to the other interfaces.
This example demonstrates how to access multiple interfaces.
To run it, chdir to MultiFace\Debug and run:
regsvr32 MultiFace.dll
Then, run (in this dir):
java MultiFace
As you can see from MultiFace\MultiFace.idl - there are 3 interfaces.
By default JACOB attaches to the default interface.
The file MultiFace.java shows how to use the new Dispatch.QueryInterface
to get access to the other interfaces.

View File

@@ -1,38 +1,38 @@
package samples.test;
import com.jacob.com.*;
/*
* This example uses the MathTest sample VB COM DLL under
* the MathProj directory
*/
class math
{
public static void main(String[] args)
{
System.runFinalizersOnExit(true);
Dispatch test = new Dispatch("MathTest.Math");
testEvents te = new testEvents();
DispatchEvents de = new DispatchEvents(test, te);
System.out.println(Dispatch.call(test, "Add", new Variant(1), new Variant(2)));
System.out.println(Dispatch.call(test, "Mult", new Variant(2), new Variant(2)));
Variant v = Dispatch.call(test, "Mult", new Variant(2), new Variant(2));
// this should return false
System.out.println("v.isNull="+v.isNull());
v = Dispatch.call(test, "getNothing");
// these should return nothing
System.out.println("v.isNull="+v.isNull());
System.out.println("v.toDispatch="+v.toDispatch());
}
}
class testEvents {
public void DoneAdd(Variant[] args)
{
System.out.println("DoneAdd called in java");
}
public void DoneMult(Variant[] args)
{
System.out.println("DoneMult called in java");
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
/*
* This example uses the MathTest sample VB COM DLL under
* the MathProj directory
*/
class math
{
public static void main(String[] args)
{
System.runFinalizersOnExit(true);
Dispatch test = new Dispatch("MathTest.Math");
testEvents te = new testEvents();
DispatchEvents de = new DispatchEvents(test, te);
System.out.println(Dispatch.call(test, "Add", new Variant(1), new Variant(2)));
System.out.println(Dispatch.call(test, "Mult", new Variant(2), new Variant(2)));
Variant v = Dispatch.call(test, "Mult", new Variant(2), new Variant(2));
// this should return false
System.out.println("v.isNull="+v.isNull());
v = Dispatch.call(test, "getNothing");
// these should return nothing
System.out.println("v.isNull="+v.isNull());
System.out.println("v.toDispatch="+v.toDispatch());
}
}
class testEvents {
public void DoneAdd(Variant[] args)
{
System.out.println("DoneAdd called in java");
}
public void DoneMult(Variant[] args)
{
System.out.println("DoneMult called in java");
}
}

View File

@@ -1,41 +1,41 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class sa_dispatch
{
public static void main(String args[])
{
System.runFinalizersOnExit(true);
try {
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
Dispatch sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
// wrap the script control in a variant
Variant v = new Variant(sControl);
// create a safe array of type dispatch
SafeArray sa = new SafeArray(Variant.VariantDispatch, 1);
// put the variant in the array
sa.setVariant(0, v);
// take it back out
Variant v2 = sa.getVariant(0);
Dispatch d = v2.toDispatch();
// make sure you can call eval on it
result = Dispatch.call(d, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
} catch (ComException e) {
e.printStackTrace();
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class sa_dispatch
{
public static void main(String args[])
{
System.runFinalizersOnExit(true);
try {
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
Dispatch sControl = (Dispatch)sC.getObject();
Dispatch.put(sControl, "Language", lang);
Variant result = Dispatch.call(sControl, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
// wrap the script control in a variant
Variant v = new Variant(sControl);
// create a safe array of type dispatch
SafeArray sa = new SafeArray(Variant.VariantDispatch, 1);
// put the variant in the array
sa.setVariant(0, v);
// take it back out
Variant v2 = sa.getVariant(0);
Dispatch d = v2.toDispatch();
// make sure you can call eval on it
result = Dispatch.call(d, "Eval", args[0]);
System.out.println("eval("+args[0]+") = "+ result);
} catch (ComException e) {
e.printStackTrace();
}
}
}

View File

@@ -1,58 +1,58 @@
package samples.test;
import com.jacob.com.*;
class sa_test
{
public static void main(String[] args)
{
System.runFinalizersOnExit(true);
SafeArray sa = new SafeArray(Variant.VariantVariant, 3);
sa.fromShortArray(new short[] {1,2,3});
System.out.println("sa short="+sa);
int[] ai = sa.toIntArray();
for(int i=0;i<ai.length;i++) {
System.out.println("toInt="+ai[i]);
}
double[] ad = sa.toDoubleArray();
for(int i=0;i<ad.length;i++) {
System.out.println("toDouble="+ad[i]);
}
sa.fromIntArray(new int[] {100000,200000,300000});
System.out.println("sa int="+sa);
ai = sa.toIntArray();
for(int i=0;i<ai.length;i++) {
System.out.println("toInt="+ai[i]);
}
ad = sa.toDoubleArray();
for(int i=0;i<ad.length;i++) {
System.out.println("toDouble="+ad[i]);
}
Variant av[] = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromDoubleArray(new double[] {1.5,2.5,3.5});
System.out.println("sa double="+sa);
sa.fromFloatArray(new float[] {1.5F,2.5F,3.5F});
System.out.println("sa float="+sa);
sa.fromBooleanArray(new boolean[] {true, false, true, false});
System.out.println("sa bool="+sa);
av = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromCharArray(new char[] {'a','b','c','d'});
System.out.println("sa char="+sa);
sa.fromStringArray(new String[] {"hello", "from", "java", "com"});
System.out.println("sa string="+sa);
av = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromVariantArray(new Variant[] {
new Variant(1), new Variant(2.3), new Variant("hi")});
System.out.println("sa variant="+sa);
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
class sa_test
{
public static void main(String[] args)
{
System.runFinalizersOnExit(true);
SafeArray sa = new SafeArray(Variant.VariantVariant, 3);
sa.fromShortArray(new short[] {1,2,3});
System.out.println("sa short="+sa);
int[] ai = sa.toIntArray();
for(int i=0;i<ai.length;i++) {
System.out.println("toInt="+ai[i]);
}
double[] ad = sa.toDoubleArray();
for(int i=0;i<ad.length;i++) {
System.out.println("toDouble="+ad[i]);
}
sa.fromIntArray(new int[] {100000,200000,300000});
System.out.println("sa int="+sa);
ai = sa.toIntArray();
for(int i=0;i<ai.length;i++) {
System.out.println("toInt="+ai[i]);
}
ad = sa.toDoubleArray();
for(int i=0;i<ad.length;i++) {
System.out.println("toDouble="+ad[i]);
}
Variant av[] = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromDoubleArray(new double[] {1.5,2.5,3.5});
System.out.println("sa double="+sa);
sa.fromFloatArray(new float[] {1.5F,2.5F,3.5F});
System.out.println("sa float="+sa);
sa.fromBooleanArray(new boolean[] {true, false, true, false});
System.out.println("sa bool="+sa);
av = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromCharArray(new char[] {'a','b','c','d'});
System.out.println("sa char="+sa);
sa.fromStringArray(new String[] {"hello", "from", "java", "com"});
System.out.println("sa string="+sa);
av = sa.toVariantArray();
for(int i=0;i<av.length;i++) {
System.out.println("toVariant="+av[i]);
}
sa.fromVariantArray(new Variant[] {
new Variant(1), new Variant(2.3), new Variant("hi")});
System.out.println("sa variant="+sa);
}
}

View File

@@ -1,61 +1,61 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
public class safearray
{
public static void main(java.lang.String[] args)
{
System.runFinalizersOnExit(true);
ActiveXComponent xl = new ActiveXComponent("Excel.Application");
try {
Object cell;
Object cellstart;
Object cellstop;
SafeArray sAProdText;
Object workbooks = xl.getProperty("Workbooks").toDispatch();
System.out.println("have workbooks");
Object workbook = Dispatch.call(workbooks, "Open", "d:\\jacob_15\\samples\\test\\jacobtest.xls").toDispatch();
System.out.println("Opened File - jacobtest.xls\n");
Object sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();
cell = Dispatch.invoke(sheet,"Range",Dispatch.Get,new Object[] {"A1:D1000"},new int[1]).toDispatch();
System.out.println("have cell:"+cell);
sAProdText = Dispatch.get(cell,"Value").toSafeArray();
System.out.println("sa: dim="+sAProdText.getNumDim());
System.out.println("sa: start row="+sAProdText.getLBound(1));
System.out.println("sa: start col="+sAProdText.getLBound(2));
System.out.println("sa: end row="+sAProdText.getUBound(1));
System.out.println("sa: end col="+sAProdText.getUBound(2));
int i;
int lineNumber=1;
boolean stringFound = true;
int n = 0;
for(lineNumber=1; lineNumber < 1000; lineNumber++)
{
for (i = 1 ; i < 4 ; i++ ) {
System.out.println((n++) + " " + lineNumber+" "+i+" " +sAProdText.getString(lineNumber,i));
/*
if (sAProdText.getString(lineNumber,i).compareTo("aaaa") != 0 ) {
System.out.println("Invalid String in line " + lineNumber + " Cell " + i + " Value = " + sAProdText.getString(lineNumber,i));
stringFound = false;
}
}
if (stringFound) {
System.out.println("Valid Strings in line " + lineNumber);
lineNumber++;
}
*/
}
}
Dispatch.call(workbook, "Close");
System.out.println("Closed File\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
xl.invoke("Quit", new Variant[] {});
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
public class safearray
{
public static void main(java.lang.String[] args)
{
System.runFinalizersOnExit(true);
ActiveXComponent xl = new ActiveXComponent("Excel.Application");
try {
Dispatch cell;
Dispatch cellstart;
Dispatch cellstop;
SafeArray sAProdText;
Dispatch workbooks = xl.getProperty("Workbooks").toDispatch();
System.out.println("have workbooks");
Dispatch workbook = Dispatch.call(workbooks, "Open", "d:\\jacob_15\\samples\\test\\jacobtest.xls").toDispatch();
System.out.println("Opened File - jacobtest.xls\n");
Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch();
cell = Dispatch.invoke(sheet,"Range",Dispatch.Get,new Object[] {"A1:D1000"},new int[1]).toDispatch();
System.out.println("have cell:"+cell);
sAProdText = Dispatch.get(cell,"Value").toSafeArray();
System.out.println("sa: dim="+sAProdText.getNumDim());
System.out.println("sa: start row="+sAProdText.getLBound(1));
System.out.println("sa: start col="+sAProdText.getLBound(2));
System.out.println("sa: end row="+sAProdText.getUBound(1));
System.out.println("sa: end col="+sAProdText.getUBound(2));
int i;
int lineNumber=1;
boolean stringFound = true;
int n = 0;
for(lineNumber=1; lineNumber < 1000; lineNumber++)
{
for (i = 1 ; i < 4 ; i++ ) {
System.out.println((n++) + " " + lineNumber+" "+i+" " +sAProdText.getString(lineNumber,i));
/*
if (sAProdText.getString(lineNumber,i).compareTo("aaaa") != 0 ) {
System.out.println("Invalid String in line " + lineNumber + " Cell " + i + " Value = " + sAProdText.getString(lineNumber,i));
stringFound = false;
}
}
if (stringFound) {
System.out.println("Valid Strings in line " + lineNumber);
lineNumber++;
}
*/
}
}
Dispatch.call(workbook, "Close");
System.out.println("Closed File\n");
} catch (Exception e) {
e.printStackTrace();
} finally {
xl.invoke("Quit", new Variant[] {});
}
}
}

View File

@@ -1,18 +1,18 @@
package samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class speed
{
public static void main(String args[])
{
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
Object sControl = sC.getObject();
Dispatch.put(sControl, "Language", lang);
for(int i=0;i<10000;i++) {
Dispatch.call(sControl, "Eval", "1+1");
}
}
}
package com.jacob.samples.test;
import com.jacob.com.*;
import com.jacob.activeX.*;
class speed
{
public static void main(String args[])
{
String lang = "VBScript";
ActiveXComponent sC = new ActiveXComponent("ScriptControl");
Dispatch sControl = sC.getObject();
Dispatch.put(sControl, "Language", lang);
for(int i=0;i<10000;i++) {
Dispatch.call(sControl, "Eval", "1+1");
}
}
}

Some files were not shown because too many files have changed in this diff Show More